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_name
avcodec_find_encoder_by_name
avcodec_find_decoder
或avcodec_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 ;
}