سؤال

أقوم بفك تشفير الفيديو عبر libavcodec باستخدام الكود التالي:

//Open input file
if(avformat_open_input(&ctx, filename, NULL, NULL)!=0)
    return FALSE; // Couldn't open file
if(avformat_find_stream_info(ctx, NULL)<0)
    return FALSE; // Couldn't find stream information
videoStream = -1;
//find video stream
for(i=0; i<ctx->nb_streams; i++)
{       
    if((ctx->streams[i])->codec->codec_type==AVMEDIA_TYPE_VIDEO)
    {
        videoStream=i;
        break;
    }
}
if (videoStream == -1)
    return FALSE; // Didn't find a video stream
video_codec_ctx=ctx->streams[videoStream]->codec;
//find decoder
video_codec=avcodec_find_decoder(video_codec_ctx->codec_id);
if(video_codec==NULL)
    return FALSE; // Codec not found
if(avcodec_open(video_codec_ctx, video_codec)<0)
    return -1; // Could not open codec
video_frame=avcodec_alloc_frame();
scaled_frame=avcodec_alloc_frame();
static struct SwsContext *img_convert_ctx; 
if(img_convert_ctx == NULL) 
{
      int w = video_codec_ctx->width;
      int h = video_codec_ctx->height;
      img_convert_ctx = sws_getContext(w, h, 
                        video_codec_ctx->pix_fmt, 
                        w, h, dst_pix_fmt, SWS_BICUBIC, 
                        NULL, NULL, NULL);
      if(img_convert_ctx == NULL) {
        fprintf(stderr, "Cannot initialize the conversion context!\n");
        return FALSE;
      }
}
while(b_play) 
{
    if (av_read_frame(ctx, &packet) < 0)
    {
        break;
    }
    if(packet.stream_index==videoStream) {
    // Decode video frame   
        avcodec_decode_video2(video_codec_ctx, video_frame, &frameFinished,
                         &packet);
        // Did we get a video frame?
        if(frameFinished) 
        {
            if (video_codec_ctx->pix_fmt != dst_pix_fmt)
            {                       
                if (video_codec_ctx->pix_fmt != dst_pix_fmt)            
                     sws_scale(img_convert_ctx, video_frame->data, 
                              video_frame->linesize, 0, 
                              video_codec_ctx->height, 
                              scaled_frame->data, scaled_frame->linesize);              
            }           
        }
}
av_free_packet(&packet);
}

تعمل التعليمات البرمجية بشكل صحيح، ولكن من الضروري تحويل كل إطار إلى التنسيق المطلوب.هل من الممكن ضبط تنسيق البكسل لفك التشفير للحصول على التنسيق الصحيح بدون sws_scale؟

شكرا جزيلا على إجاباتك.

هل كانت مفيدة؟

المحلول

ffmpegAVCodec تحدد كل مثيلات (كائنات "المصنع" لوحدة فك الترميز الثابتة) مصفوفة من تنسيقات البكسل التي تدعمها، وتنتهي بالقيمة -1.

ال AVCodecContext (مثيل وحدة فك الترميز) تحتوي الكائنات على مؤشر وظيفة رد اتصال يسمى get_format:إنه مؤشر دالة في هذا الهيكل.

يتم استدعاء وظيفة رد الاتصال هذه، في مرحلة ما أثناء تهيئة برنامج الترميز، باستخدام التابع AVCodec مصفوفة كائن المصنع من التنسيقات المدعومة، ومن المفترض أن يختار رد الاتصال أحد التنسيقات من تلك المصفوفة (نوعًا ما مثل "اختر بطاقة، أي بطاقة") ويعيد تلك القيمة.التنفيذ الافتراضي لهذا get_format رد الاتصال هو وظيفة تسمى avcodec_default_get_format.(تم تثبيت هذا avcodec_get_context_defaults2).تنفذ هذه الوظيفة الافتراضية منطق "اختيار التنسيق" بكل بساطة:فهو يختار العنصر الأول من المصفوفة الذي ليس تنسيق بكسل للأجهزة فقط.

إذا كنت تريد أن يعمل برنامج الترميز بتنسيق بكسل مختلف، فما يمكنك فعله هو تثبيت برنامج الترميز الخاص بك get_format رد الاتصال في كائن السياق.ومع ذلك، يجب أن يُرجع رد الاتصال إحدى القيم الموجودة في المصفوفة (مثل الاختيار من القائمة).لا يمكن إرجاع قيمة تعسفية.سيدعم برنامج الترميز فقط التنسيقات التي يحددها في المصفوفة.

انتقل إلى مجموعة التنسيقات المتاحة واختر الأفضل.إذا كنت محظوظًا، فهذا هو بالضبط ما تريده بالفعل و sws_scale لن تحتاج الوظيفة إلى تحويل تنسيق البكسل.(إذا لم تطلب، بالإضافة إلى ذلك، تغيير حجم الصورة أو اقتصاصها، فيجب أن يتعرف sws_scale على أن التحويل أمر مستحيل.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top