如何在libavcodec中设置解码像素格式? [英] How to set decode pixel format in libavcodec?

查看:112
本文介绍了如何在libavcodec中设置解码像素格式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下代码通过libavcodec解码视频:

I decode video via libavcodec, using the following code:

//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的正确格式?

The code works correctly, but it is necessary to convert each frame to the required format. Is it possible to set the pixel format for decoding to get the correct format without sws_scale?

非常感谢您的回答。

推荐答案

ffmpeg AVCodec 实例(静态解码器工厂对象)各自定义了它们支持的像素格式数组,并以值-1终止。

ffmpeg's AVCodec instances (static decoder "factory" objects) each define an array of pixel formats that they support, terminated by the value -1.

AVCodecContext (解码器实例)对象具有名为 get_format 的回调函数指针:这是该结构中的函数指针。

The AVCodecContext (decoder instance) objects have a callback function pointer called get_format: it is a function pointer in that structure.

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

This callback function is called, at some point in the codec initialization, with the AVCodec factory object's array of supported formats, and the callback is supposed to choose one of the formats from that array (kind of like "pick a card, any card") and return that value. The default implementation of this get_format callback is a function called avcodec_default_get_format. (This is installed avcodec_get_context_defaults2). This default function implements the "pick a format" logic quite simply: it chooses the first element of the array which isn't a hardware-accel-only pixel format.

如果希望编解码器使用其他像素格式,则可以将自己的 get_format 回调安装到上下文对象中。但是,回调必须返回数组中的值之一(例如从菜单中选择)。它不能返回任意值。编解码器将仅支持其在数组中指定的格式。

If you want the codec to work with a different pixel format, what you can do is install your own get_format callback into the context object. However, the callback must return one of the values in the array (like choosing from a menu). It cannot return an arbitrary value. The codec will only support the formats that it specifies in the array.

遍历可用格式的数组并选择最佳格式。如果幸运的话,这正是您真正想要的, sws_scale 函数无需进行像素格式转换。 (此外,如果您不要求缩放或裁剪图片,则sws_scale应该会识别出该转换为noop。)

Walk the array of available formats and pick the best one. If you're lucky, it's the exact one you actually want and the sws_scale function won't have to do pixel format conversion. (If, additionally, you don't request to scale or crop the picture, sws_scale should recognize that the conversion is a noop.)

这篇关于如何在libavcodec中设置解码像素格式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆