FFmpeg源码分析:avcodec_register_all()注册编解码器

FFmpeg的avcodec_register_all()用于注册编解码器,FFmpeg4.0版本以前是调用该方法,运行期把所有编译的编解码器添加到链表。但是FFmpeg4.0版本以后,改为编译期自动生成编解码数组,还有解析器数组。

在APIChanges文档中有说明,FFmpeg4.0版本以后,avcodec_register_all()等方法已经过时,添加av_codec_iterate()、av_parser_iterate()来迭代遍历,API改动如下:

2018-02-06 - 36c85d6e77 - lavc 58.10.100 - avcodec.h
  Deprecate use of avcodec_register(), avcodec_register_all(),
  av_codec_next(), av_register_codec_parser(), and av_parser_next().
  Add av_codec_iterate() and av_parser_iterate().

一、注册AVCodec 

avcodec_register_all()的代码实现在libavcodec/allcodecs.c中,代码如下:

#if FF_API_NEXT

static AVOnce av_codec_next_init = AV_ONCE_INIT;

static void av_codec_init_next(void)
{
    AVCodec *prev = NULL, *p;
    void *i = 0;
    while ((p = (AVCodec*)av_codec_iterate(&i))) {
        if (prev)
            prev->next = p;
        prev = p;
    }
}

av_cold void avcodec_register(AVCodec *codec)
{
    ff_thread_once(&av_codec_next_init, av_codec_init_next);
}

AVCodec *av_codec_next(const AVCodec *c)
{
    ff_thread_once(&av_codec_next_init, av_codec_init_next);

    if (c)
        return c->next;
    else
        return (AVCodec*)codec_list[0];
}

void avcodec_register_all(void)
{
    ff_thread_once(&av_codec_next_init, av_codec_init_next);
}

#endif

与av_register_all()一样,调用ff_thread_once单例线程进行注册,只执行一次。av_codec_init_next()方法主要调用av_codec_iterate()迭代遍历,我们来看下av_codec_iterate方法实现:

static void av_codec_init_static(void)
{
    for (int i = 0; codec_list[i]; i++) {
        if (codec_list[i]->init_static_data)
            codec_list[i]->init_static_data((AVCodec*)codec_list[i]);
    }
}

const AVCodec *av_codec_iterate(void **opaque)
{
    uintptr_t i = (uintptr_t)*opaque;
    const AVCodec *c = codec_list[i];

    ff_thread_once(&av_codec_static_init, av_codec_init_static);

    if (c)
        *opaque = (void*)(i + 1);

    return c;
}

主要是for循环从codec_list数组取出AVCodec,该数组是编译期自动生成,保存在libavcodec/codec_list.c中:

static const AVCodec * const codec_list[] = {
    &ff_aac_encoder,
    &ff_opus_encoder,
    &ff_flv_decoder,
    &ff_h264_decoder,
    &ff_hevc_decoder,
    &ff_mjpeg_decoder,
	&ff_mp3_decoder,
    &ff_mpeg4_decoder,
	&ff_vp8_decoder,
	&ff_vp9_decoder,
    NULL };

可以看到,生成的codec_list数组是不完整的,是由编译脚本指定--enable-encoder或者--enable-decoder,开启特定的编解码器。而这些编解码器来自libavcodec/allcodecs.c中声明的全局变量(有删减):

extern AVCodec ff_flv_encoder;
extern AVCodec ff_flv_decoder;
extern AVCodec ff_h264_decoder;
extern AVCodec ff_hevc_decoder;
extern AVCodec ff_mpeg4_encoder;
extern AVCodec ff_mpeg4_decoder;
extern AVCodec ff_msmpeg4v1_decoder;
extern AVCodec ff_msmpeg4v2_encoder;
extern AVCodec ff_msmpeg4v2_decoder;
extern AVCodec ff_msmpeg4v3_encoder;
extern AVCodec ff_msmpeg4v3_decoder;
extern AVCodec ff_vp8_decoder;
extern AVCodec ff_vp9_decoder;
extern AVCodec ff_wmv1_encoder;
extern AVCodec ff_wmv1_decoder;
extern AVCodec ff_wmv2_encoder;
extern AVCodec ff_wmv2_decoder;
extern AVCodec ff_wmv3_decoder;

/* audio codecs */
extern AVCodec ff_aac_encoder;
extern AVCodec ff_aac_decoder;
extern AVCodec ff_ac3_encoder;
extern AVCodec ff_ac3_decoder;
extern AVCodec ff_amrnb_decoder;
extern AVCodec ff_amrwb_decoder;
extern AVCodec ff_ape_decoder;
extern AVCodec ff_eac3_encoder;
extern AVCodec ff_eac3_decoder;
extern AVCodec ff_flac_encoder;
extern AVCodec ff_flac_decoder;
extern AVCodec ff_mp3_decoder;
extern AVCodec ff_opus_encoder;
extern AVCodec ff_opus_decoder;
extern AVCodec ff_truehd_encoder;
extern AVCodec ff_truehd_decoder;
extern AVCodec ff_vorbis_encoder;
extern AVCodec ff_vorbis_decoder;
extern AVCodec ff_wmav1_encoder;
extern AVCodec ff_wmav1_decoder;
extern AVCodec ff_wmav2_encoder;
extern AVCodec ff_wmav2_decoder;

/* PCM codecs */
extern AVCodec ff_pcm_alaw_encoder;
extern AVCodec ff_pcm_alaw_decoder;
extern AVCodec ff_pcm_mulaw_encoder;
extern AVCodec ff_pcm_mulaw_decoder;
extern AVCodec ff_pcm_s8_encoder;
extern AVCodec ff_pcm_s8_decoder;
extern AVCodec ff_pcm_s16le_encoder;
extern AVCodec ff_pcm_s16le_decoder;
extern AVCodec ff_pcm_s16le_planar_encoder;
extern AVCodec ff_pcm_s16le_planar_decoder;
extern AVCodec ff_pcm_s24le_encoder;
extern AVCodec ff_pcm_s24le_decoder;
extern AVCodec ff_pcm_s32le_encoder;
extern AVCodec ff_pcm_s32le_decoder;
extern AVCodec ff_pcm_s64le_encoder;
extern AVCodec ff_pcm_s64le_decoder;
extern AVCodec ff_pcm_u8_encoder;
extern AVCodec ff_pcm_u8_decoder;

/* ADPCM codecs */
extern AVCodec ff_adpcm_ima_wav_encoder;
extern AVCodec ff_adpcm_ima_wav_decoder;
extern AVCodec ff_adpcm_ms_encoder;
extern AVCodec ff_adpcm_ms_decoder;

/* subtitles */
extern AVCodec ff_ssa_encoder;
extern AVCodec ff_ssa_decoder;
extern AVCodec ff_ass_encoder;
extern AVCodec ff_ass_decoder;
extern AVCodec ff_movtext_encoder;
extern AVCodec ff_movtext_decoder;
extern AVCodec ff_pgssub_decoder;
extern AVCodec ff_sami_decoder;
extern AVCodec ff_srt_encoder;
extern AVCodec ff_srt_decoder;
extern AVCodec ff_subrip_encoder;
extern AVCodec ff_subrip_decoder;
extern AVCodec ff_ttml_encoder;
extern AVCodec ff_webvtt_encoder;
extern AVCodec ff_webvtt_decoder;

/* external libraries */
extern AVCodec ff_aac_at_encoder;
extern AVCodec ff_aac_at_decoder;
extern AVCodec ff_ac3_at_decoder;
extern AVCodec ff_amr_nb_at_decoder;
extern AVCodec ff_eac3_at_decoder;
extern AVCodec ff_mp3_at_decoder;
extern AVCodec ff_libaom_av1_encoder;
extern AVCodec ff_libdav1d_decoder;
extern AVCodec ff_libfdk_aac_encoder;
extern AVCodec ff_libfdk_aac_decoder;
extern AVCodec ff_libmp3lame_encoder;
extern AVCodec ff_libopencore_amrnb_decoder;
extern AVCodec ff_libopencore_amrwb_decoder;
extern AVCodec ff_libopus_encoder;
extern AVCodec ff_libopus_decoder;
extern AVCodec ff_libshine_encoder;
extern AVCodec ff_libspeex_encoder;
extern AVCodec ff_libspeex_decoder;
extern AVCodec ff_libvorbis_encoder;
extern AVCodec ff_libvorbis_decoder;
extern AVCodec ff_libvpx_vp8_encoder;
extern AVCodec ff_libvpx_vp8_decoder;
extern AVCodec ff_libvpx_vp9_encoder;
extern AVCodec ff_libvpx_vp9_decoder;
extern AVCodec ff_libwebp_encoder;
extern AVCodec ff_libx264_encoder;
extern AVCodec ff_libx265_encoder;

/* hwaccel hooks only, so prefer external decoders */
extern AVCodec ff_av1_decoder;
extern AVCodec ff_av1_cuvid_decoder;
extern AVCodec ff_av1_qsv_decoder;
extern AVCodec ff_libopenh264_encoder;
extern AVCodec ff_libopenh264_decoder;
extern AVCodec ff_h264_cuvid_decoder;
extern AVCodec ff_h264_nvenc_encoder;
extern AVCodec ff_h264_omx_encoder;
extern AVCodec ff_h264_qsv_encoder;
extern AVCodec ff_h264_v4l2m2m_encoder;
extern AVCodec ff_h264_vaapi_encoder;
extern AVCodec ff_h264_videotoolbox_encoder;
extern AVCodec ff_hevc_mediacodec_decoder;
extern AVCodec ff_hevc_nvenc_encoder;
extern AVCodec ff_hevc_qsv_encoder;
extern AVCodec ff_hevc_v4l2m2m_encoder;
extern AVCodec ff_hevc_vaapi_encoder;
extern AVCodec ff_hevc_videotoolbox_encoder;
extern AVCodec ff_mp3_mf_encoder;
extern AVCodec ff_mpeg4_cuvid_decoder;
extern AVCodec ff_mpeg4_mediacodec_decoder;
extern AVCodec ff_mpeg4_omx_encoder;
extern AVCodec ff_mpeg4_v4l2m2m_encoder;
extern AVCodec ff_vp9_cuvid_decoder;
extern AVCodec ff_vp9_mediacodec_decoder;
extern AVCodec ff_vp9_qsv_decoder;
extern AVCodec ff_vp9_vaapi_encoder;
extern AVCodec ff_vp9_qsv_encoder;

二、注册AVParser

AVParser是用于解析数据包,使用av_register_codec_parser()进行注册,位于libavcodec/parsers.c,注册函数如下:

#if FF_API_NEXT

static AVOnce av_parser_next_init = AV_ONCE_INIT;

static void av_parser_init_next(void)
{
    AVCodecParser *prev = NULL, *p;
    int i = 0;
    while ((p = (AVCodecParser*)parser_list[i++])) {
        if (prev)
            prev->next = p;
        prev = p;
    }
}

AVCodecParser *av_parser_next(const AVCodecParser *p)
{
    ff_thread_once(&av_parser_next_init, av_parser_init_next);

    if (p)
        return p->next;
    else
        return (AVCodecParser*)parser_list[0];
}

void av_register_codec_parser(AVCodecParser *parser)
{
    ff_thread_once(&av_parser_next_init, av_parser_init_next);
}

#endif

可以看到,av_parser_init_next()调用parser_list数组,while遍历添加到链表。parser_list数组是编译期自动生成,保存在libavcodec/parser_list.c中:

static const AVCodecParser * const parser_list[] = {
    &ff_aac_parser,
    &ff_ac3_parser,
    &ff_av1_parser,
    &ff_flac_parser,
    &ff_gif_parser,
    &ff_h264_parser,
    &ff_hevc_parser,
    &ff_mjpeg_parser,
    &ff_mpeg4video_parser,
    &ff_mpegaudio_parser,
    &ff_mpegvideo_parser,
    &ff_opus_parser,
    &ff_png_parser,
    &ff_vorbis_parser,
    &ff_vp9_parser,
    &ff_webp_parser,
    NULL };

parser_list数组来自parsers.c声明的全局变量(有删减):

extern AVCodecParser ff_aac_parser;
extern AVCodecParser ff_ac3_parser;
extern AVCodecParser ff_av1_parser;
extern AVCodecParser ff_flac_parser;
extern AVCodecParser ff_gif_parser;
extern AVCodecParser ff_h264_parser;
extern AVCodecParser ff_hevc_parser;
extern AVCodecParser ff_mjpeg_parser;
extern AVCodecParser ff_mpeg4video_parser;
extern AVCodecParser ff_mpegaudio_parser;
extern AVCodecParser ff_mpegvideo_parser;
extern AVCodecParser ff_opus_parser;
extern AVCodecParser ff_png_parser;
extern AVCodecParser ff_vorbis_parser;
extern AVCodecParser ff_vp9_parser;
extern AVCodecParser ff_webp_parser;

三、注册AVBitStreamFilter

AVBitStreamFilter用于比特流滤波,提供av_bsf_iterate()来获取指定的滤波器,该方法位于libavcodec/bitstream_filters.c,具体如下:

const AVBitStreamFilter *av_bsf_iterate(void **opaque)
{
    uintptr_t i = (uintptr_t)*opaque;
    const AVBitStreamFilter *f = bitstream_filters[i];

    if (f)
        *opaque = (void*)(i + 1);

    return f;
}

同样地,也是使用数组进行存储。这里使用的是bitstream_filters数组,在编译期自动生成保存于libavcodec/bsf_list.c文件。该数组的滤波器来自bitstream_filters.c声明的全局变量:

extern const AVBitStreamFilter ff_aac_adtstoasc_bsf;
extern const AVBitStreamFilter ff_av1_frame_merge_bsf;
extern const AVBitStreamFilter ff_av1_frame_split_bsf;
extern const AVBitStreamFilter ff_av1_metadata_bsf;
extern const AVBitStreamFilter ff_chomp_bsf;
extern const AVBitStreamFilter ff_dump_extradata_bsf;
extern const AVBitStreamFilter ff_dca_core_bsf;
extern const AVBitStreamFilter ff_eac3_core_bsf;
extern const AVBitStreamFilter ff_extract_extradata_bsf;
extern const AVBitStreamFilter ff_filter_units_bsf;
extern const AVBitStreamFilter ff_h264_metadata_bsf;
extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf;
extern const AVBitStreamFilter ff_h264_redundant_pps_bsf;
extern const AVBitStreamFilter ff_hapqa_extract_bsf;
extern const AVBitStreamFilter ff_hevc_metadata_bsf;
extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf;
extern const AVBitStreamFilter ff_imx_dump_header_bsf;
extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf;
extern const AVBitStreamFilter ff_mjpega_dump_header_bsf;
extern const AVBitStreamFilter ff_mp3_header_decompress_bsf;
extern const AVBitStreamFilter ff_mpeg2_metadata_bsf;
extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf;
extern const AVBitStreamFilter ff_mov2textsub_bsf;
extern const AVBitStreamFilter ff_noise_bsf;
extern const AVBitStreamFilter ff_null_bsf;
extern const AVBitStreamFilter ff_opus_metadata_bsf;
extern const AVBitStreamFilter ff_pcm_rechunk_bsf;
extern const AVBitStreamFilter ff_prores_metadata_bsf;
extern const AVBitStreamFilter ff_remove_extradata_bsf;
extern const AVBitStreamFilter ff_setts_bsf;
extern const AVBitStreamFilter ff_text2movsub_bsf;
extern const AVBitStreamFilter ff_trace_headers_bsf;
extern const AVBitStreamFilter ff_truehd_core_bsf;
extern const AVBitStreamFilter ff_vp9_metadata_bsf;
extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf;
extern const AVBitStreamFilter ff_vp9_superframe_bsf;
extern const AVBitStreamFilter ff_vp9_superframe_split_bsf;

猜你喜欢

转载自blog.csdn.net/u011686167/article/details/121723790
今日推荐