懒人李冰

记录我的生活、学习

FFMPEG 源码分析:avcodec_open2

avcodec_open2函数实现的功能为利用给定的AVCodec结构初始化AVCodecContext结构。

函数声明

avcodec_open2的声明如下:

1
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

函数参数说明:

  • avctx:需要初始化的context.
  • codec:
  • options:
  • 返回值:如果返回0,正确。失败则返回负数。

该函数利用给定的AVCodec结构初始化AVCodecContext结构,在使用该函数之前,AVCodecContext 必须已经用avcodec_alloc_context3()函数分配出来。

AVCodec结构在使用该函数之前,由avcodec_find_decoder_by_nameavcodec_find_encoder_by_name avcodec_find_decoderavcodec_find_encoder提前得到。

注意,在正式解码之前(比如使用avcodec_decode_video2()之前),必须调用avcodec_open2函数。

函数使用示例

示例代码如下:

1
2
3
4
5
6
7
8
9
10
avcodec_register_all();
av_dict_set(&opt, "b", "2.5M", 0);
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if(!codec)
    exit(1);

context = avcodec_alloc_context3(codec);

if(avcodec_open2(context, codec, opts) < 0)
    exit(1);

函数源码分析

avcodec_open2的逻辑非常简单,首先是进行一些参数检测、之后调动AVCodec的init函数。大概步骤如下:

  • 各种函数参数检测。
  • 各种结构体分配内存。
  • 将输入的AVDictionary形式的选项设置到AVCodecContext
  • 其他一些零散的查,检查输入参数是否符合编码器的要求。
  • 调用AVCodec的init函数初始化具体的解码器。

此处重点分析调用AVCodec的init函数处。 以 HEVC 解码器为例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
AVCodec ff_hevc_decoder = {
    .name                  = "hevc",
    .long_name             = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"),
    .type                  = AVMEDIA_TYPE_VIDEO,
    .id                    = AV_CODEC_ID_HEVC,
    .priv_data_size        = sizeof(HEVCContext),
    .priv_class            = &hevc_decoder_class,
    .init                  = hevc_decode_init,
    .close                 = hevc_decode_free,
    .decode                = hevc_decode_frame,
    .flush                 = hevc_decode_flush,
    .update_thread_context = hevc_update_thread_context,
    .init_thread_copy      = hevc_init_thread_copy,
    .capabilities          = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                             AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
    .profiles              = NULL_IF_CONFIG_SMALL(profiles),
};

其中 init 函数定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static av_cold int hevc_decode_init(AVCodecContext *avctx)
{
    HEVCContext *s = avctx->priv_data;
    int ret;

    ff_init_cabac_states();

    avctx->internal->allocate_progress = 1;

    ret = hevc_init_context(avctx);
    if (ret < 0)
        return ret;

    s->enable_parallel_tiles = 0;
    s->picture_struct = 0;

    if(avctx->active_thread_type & FF_THREAD_SLICE)
        s->threads_number = avctx->thread_count;
    else
        s->threads_number = 1;

    if (avctx->extradata_size > 0 && avctx->extradata) {
        ret = hevc_decode_extradata(s);
        if (ret < 0) {
            hevc_decode_free(avctx);
            return ret;
        }
    }

    if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1)
            s->threads_type = FF_THREAD_FRAME;
        else
            s->threads_type = FF_THREAD_SLICE;

    return 0;
}