FFmpeg源码分析:av_register_all()注册封装器与解封装器

FFmpeg中av_register_all()函数用于注册所有muxers、demuxers与protocols。FFmpeg4.0以前是用链表存储muxer/demuxer,FFmpeg4.0以后改为数组存储,并且av_register_all方法已被标记为过时,av_register_input_format和av_register_output_format也被标记为过时。

av_register_all()的声明位于libavformat/avformat.h头文件中,在新版本4.0以后,不需要调用该方法,可以直接使用所有模块。声明如下:

#if FF_API_NEXT
/**
 * Initialize libavformat and register all the muxers, demuxers and
 * protocols. If you do not call this function, then you can select
 * exactly which formats you want to support.
 *
 * @see av_register_input_format()
 * @see av_register_output_format()
 */
attribute_deprecated
void av_register_all(void);

attribute_deprecated
void av_register_input_format(AVInputFormat *format);
attribute_deprecated
void av_register_output_format(AVOutputFormat *format);
#endif

并且在APIChanges文档中也有说明,FFmpeg4.0的部分API改动如下:

2018-04-01 - f1805d160d - lavfi 7.14.100 - avfilter.h
  Deprecate use of avfilter_register(), avfilter_register_all(),
  avfilter_next(). Add av_filter_iterate().

2018-02-06 - 0694d87024 - lavf 58.9.100 - avformat.h
  Deprecate use of av_register_input_format(), av_register_output_format(),
  av_register_all(), av_iformat_next(), av_oformat_next().
  Add av_demuxer_iterate(), and av_muxer_iterate().

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().

文档提到avfilter模块:avfilter_register()、avfilter_register_all()和avfilter_next()已过时,添加av_filter_iterate()来迭代遍历。avformat模块:av_register_input_format()、av_register_output_format()、av_register_all()等已过时,添加av_demuxer_iterate()和av_muxer_iterate()来迭代遍历。avcodec模块:avcodec_register()、avcodec_register_all()、av_register_codec_parser()等已过时,添加av_codec_iterae()和av_parser_iterate()来迭代遍历。

我们主要看下avformat模块的注册函数,位于libavformat/allformats.c文件:

void av_register_all(void)
{
    ff_thread_once(&av_format_next_init, av_format_init_next);
}

void av_register_input_format(AVInputFormat *format)
{
    ff_thread_once(&av_format_next_init, av_format_init_next);
}

void av_register_output_format(AVOutputFormat *format)
{
    ff_thread_once(&av_format_next_init, av_format_init_next);
}

函数体改为运行单例线程,ff_thread_once()位于libavutil/thread.h,代码如下:

#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
......
#define ff_thread_once(control, routine) pthread_once(control, routine)

#else
......

static inline int ff_thread_once(char *control, void (*routine)(void))
{
    if (!*control) {
        routine();
        *control = 1;
    }
    return 0;
}

#endif

ff_thread_once()的函数指针avformat_init_next()也位于libavformat/allformats.c,代码如下:

static void av_format_init_next(void)
{
    AVOutputFormat *prevout = NULL, *out;
    AVInputFormat *previn = NULL, *in;

    ff_mutex_lock(&avpriv_register_devices_mutex);

    for (int i = 0; (out = (AVOutputFormat*)muxer_list[i]); i++) {
        if (prevout)
            prevout->next = out;
        prevout = out;
    }

    if (outdev_list) {
        for (int i = 0; (out = (AVOutputFormat*)outdev_list[i]); i++) {
            if (prevout)
                prevout->next = out;
            prevout = out;
        }
    }

    for (int i = 0; (in = (AVInputFormat*)demuxer_list[i]); i++) {
        if (previn)
            previn->next = in;
        previn = in;
    }

    if (indev_list) {
        for (int i = 0; (in = (AVInputFormat*)indev_list[i]); i++) {
            if (previn)
                previn->next = in;
            previn = in;
        }
    }

    ff_mutex_unlock(&avpriv_register_devices_mutex);
}

这里主要是把muxer_list和demuxer_list数组的元素取出来,添加到链表中。如果有开启avdevice模块,有index_list和outdev_list数组,也添加到链表中。这几个数组都是编译源码后,自动生成,来自allformats.c声明的muxers与demuxers全局变量:

/* (de)muxers */
extern AVInputFormat  ff_aac_demuxer;
extern AVInputFormat  ff_ac3_demuxer;
extern AVOutputFormat ff_ac3_muxer;
extern AVInputFormat  ff_amr_demuxer;
extern AVOutputFormat ff_amr_muxer;
extern AVInputFormat  ff_amrnb_demuxer;
extern AVInputFormat  ff_amrwb_demuxer;
extern AVInputFormat  ff_asf_demuxer;
extern AVOutputFormat ff_asf_muxer;
extern AVInputFormat  ff_av1_demuxer;
extern AVInputFormat  ff_avi_demuxer;
extern AVOutputFormat ff_avi_muxer;
extern AVInputFormat  ff_dash_demuxer;
extern AVOutputFormat ff_dash_muxer;
extern AVInputFormat  ff_eac3_demuxer;
extern AVOutputFormat ff_eac3_muxer;
extern AVInputFormat  ff_flac_demuxer;
extern AVOutputFormat ff_flac_muxer;
extern AVInputFormat  ff_flv_demuxer;
extern AVOutputFormat ff_flv_muxer;
extern AVInputFormat  ff_hls_demuxer;
extern AVOutputFormat ff_hls_muxer;
extern AVOutputFormat ff_ipod_muxer;
extern AVInputFormat  ff_matroska_demuxer;
extern AVOutputFormat ff_matroska_muxer;
extern AVInputFormat  ff_mov_demuxer;
extern AVOutputFormat ff_mov_muxer;
extern AVInputFormat  ff_mp3_demuxer;
extern AVOutputFormat ff_mp3_muxer;
extern AVOutputFormat ff_mp4_muxer;
extern AVInputFormat  ff_ogg_demuxer;
extern AVOutputFormat ff_ogg_muxer;
extern AVInputFormat  ff_rtp_demuxer;
extern AVOutputFormat ff_rtp_muxer;
extern AVInputFormat  ff_rtsp_demuxer;
extern AVOutputFormat ff_rtsp_muxer;
extern AVInputFormat  ff_wav_demuxer;
extern AVOutputFormat ff_wav_muxer;
/* image demuxers */
extern AVInputFormat  ff_image_bmp_pipe_demuxer;
extern AVInputFormat  ff_image_gif_pipe_demuxer;
extern AVInputFormat  ff_image_jpeg_pipe_demuxer;
extern AVInputFormat  ff_image_png_pipe_demuxer;
extern AVInputFormat  ff_image_webp_pipe_demuxer;

muxer_list位于libavformat/muxer_list.c,生成的muxers数组如下(有删减):

static const AVOutputFormat * const muxer_list[] = {
    &ff_ac3_muxer,
    &ff_amr_muxer,
    &ff_asf_muxer,
    &ff_avi_muxer,
    &ff_eac3_muxer,
    &ff_flac_muxer,
    &ff_flv_muxer,
    &ff_gif_muxer,
    &ff_h264_muxer,
    &ff_hevc_muxer,
    &ff_hls_muxer,
    &ff_image2_muxer,
    &ff_ipod_muxer,
    &ff_matroska_muxer,
    &ff_mov_muxer,
    &ff_mp3_muxer,
    &ff_mp4_muxer,
    &ff_mpeg1video_muxer,
    &ff_mpeg2video_muxer,
    &ff_mpegts_muxer,
    &ff_mpjpeg_muxer,
    &ff_ogg_muxer,
    &ff_opus_muxer,
    &ff_wav_muxer,
    &ff_webm_muxer,
    NULL };

demuxer_list位于libavformat/demuxer_list.c,生成的demuxers数组如下(有删减):

static const AVInputFormat * const demuxer_list[] = {
    &ff_aac_demuxer,
    &ff_ac3_demuxer,
    &ff_amr_demuxer,
    &ff_amrnb_demuxer,
    &ff_amrwb_demuxer,
    &ff_asf_demuxer,
    &ff_avi_demuxer,
    &ff_eac3_demuxer,
    &ff_flac_demuxer,
    &ff_flv_demuxer,
    &ff_h264_demuxer,
    &ff_hevc_demuxer,
    &ff_hls_demuxer,
    &ff_image2_demuxer,
    &ff_matroska_demuxer,
    &ff_mov_demuxer,
    &ff_mp3_demuxer,
    &ff_ogg_demuxer,
    &ff_wav_demuxer,
    NULL };

总结avformat模块的注册函数改动,链表存储改为数组存储,在运行期添加muxer与demuxer到链表,改为编译期自动生成保存于数组。

猜你喜欢

转载自blog.csdn.net/u011686167/article/details/121691245