2012-03-11 20 views
9

我经由libavcodec的解码视频,使用以下代码:如何在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?

非常感谢您的回答。

回答

14

ffmpegAVCodec实例(静态解码器“工厂”对象)每个都定义了它们支持的像素格式的数组,它们以值-1结尾。

AVCodecContext(解码器实例)对象有一个称为get_format的回调函数指针:它是该结构中的函数指针。

此回调函数在编解码器初始化过程中的某个时刻被AVCodec工厂对象的支持格式数组调用,并且该回调函数应该从该数组中选择一种格式(类似于“拾取卡片,任何卡“)并返回该值。此get_format回调的默认实现是一个名为avcodec_default_get_format的函数。 (这是安装avcodec_get_context_defaults2)。这个默认函数非常简单地实现了“选择格式”逻辑:它选择了数组的第一个元素,它不是一个只有硬件加速度的像素格式。

如果你想编解码器与一个不同的像素格式的工作,你可以做的是安装你自己get_format回调到上下文对象。但是,回调必须返回数组中的某个值(如从菜单中选择)。它不能返回任意值。编解码器将只支持它在数组中指定的格式。

走可用格式的阵列,并挑选最好的一个。如果幸运的话,这是你真正想要的确切一个和sws_scale功能就不必做像素格式转换。 (如果,另外,你不要求缩放或裁剪图片,sws_scale应该认识到,转换是一个空操作。)

+1

附:在重写回调中的位置应该在'avcodec_open'之前。请注意,自从我看了这些东西之后已经有一段时间了。 – Kaz 2012-03-11 11:08:37

+0

谢谢,Kaz! – kochedykov 2012-03-11 16:13:26

相关问题