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

2023-10-31

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到链表,改为编译期自动生成保存于数组。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FFmpeg源码分析:av_register_all()注册封装器与解封装器 的相关文章

随机推荐

  • MBA-day13 逻辑学 模态推理(可能与必然的推理)

    1 基本概念 模态判断 是反应事物的可能性或必然性的判断 根据判断所反应的事物的可能性还是必然性 可以把模态判断分为可能判断与必然判断 模态命题 可能命题 必然命题 可能肯定命题 可能否定命题 必然肯定命题 必然否定命题 2 模态判断的负判
  • 第63讲:Python编程案例之猴子吃桃

    文章目录 1 需求描述以及分析 2 递推方式实该该程序 3 递归方式实现该程序 1 需求描述以及分析 需求描述 猴子第一天摘了若干个桃子 第一天吃了若干个桃子中的一半 觉得不过瘾 又多吃了一个 第二天早上又将第一天剩下的桃子吃了一半 并且也
  • IDEA中修改workspace.xml内容,保存后自动被删除

    最近在做一个SpringBoot的分布式项目 由于项目里面有多个启动器 每次查找启动类文件来启动服务效率就很低 于是想到用Run Dashboard来管理启动类 由于是新的电脑装的IDEA没有自动开启这个工具 因此需要手动开启一下 开启方式
  • 【Docker】安装Presto连接Hive、mysql、oracle、postgresql、SQL server等7种类型数据库

    目录 1 简介 2 下载安装 1 下载镜像 2 下载presto客户端jar文件 3 将hadoop配置拷贝到容器 4 新增hive properties配置文件 5 重启容器 在linux命令行下 3 测试连接 4 其他类型数据库配置连接
  • Java 两点经纬度计算距离和角度

    角度 计算两点对于正北方向的朝向角度 0 360 param start format latitude 30 longitude 120 param end private static double bearing List
  • UEFI入门必读的12本书

    作者简介 罗冰 系统安全 特别是物理隔离领域 专家 主导开发网络隔离卡 双网隔离机 国产隔离系统 单向光传输等各类安全产品 拥有十几项发明和实用新型专利 致力于UEFI技术的研究 实践和推广 在CSDN和知乎上设有 UEFI开发探索 专栏
  • UE4(unreal engine4)蒙太奇动画删除不想要的帧数

    UE4系列文章目录 文章目录 UE4系列文章目录 前言 一 问题原因 二 具体操作步骤 前言 UE4 unreal engine4 蒙太奇动画删除不想要的帧数 当我们在UE4中导入一个fbx骨骼动画 当我们想要截取动画中某些不想用的帧时 点
  • 软件版本号命名规范_产品版本命名的规范与规则

    上一篇文章我们对产品的版本迭代的方法进行了一些总结 本篇文章我会针对产品的版本命名 验收 发布这三个层面 来总结一下我自己的想法 希望能对大家有所帮助 01 产品版本命名的规范与规则 1 1 版本命名规范 软件版本号由主版本号 次版本号 修
  • springboot后台获取不到前台Vue日期问题解决

    一 实体类字段写法如下 JsonFormat pattern yyyy MM dd timezone GMT 8 private Date sendTime Vue使用element ui写法
  • 4.2、Flink任务怎样读取文件中的数据

    目录 1 前言 2 readTextFile 已过时 不推荐使用 3 readFile 已过时 不推荐使用 4 fromSource FileSource 推荐使用 1 前言 思考 读取文件时可以设置哪些规则呢 1 文件的格式 txt cs
  • (二)程序语言设计基础

    目录 1 程序设计语言概述 1 1 基本概念 1 1 1 低级语言和高级语言 1 1 2 编译程序和解释程序 1 1 3 程序设计语言的定义 1 1 4 程序设计语言的分类 1 2 程序设计语言的基本成分 1 2 1 数据成分 1 2 2
  • 2022最新android设备uuid、udid使用教程​

    前言 udid UDID是Unique Device Identifier的缩写 中文意思是设备唯一标识 uuid UUID是Universally Unique Identifier的缩写 中文意思是通用唯一识别码 简言之 udid对应某
  • elasticsearch 中text与keyword的区别

    创建索引 PUT ellis mappings properties name type text fields keyword type keyword ignore above 256 age type long 我们可以看到name类
  • VBA常用语法

    最近接触了一下VBA编程 才知道Excel还能编程 而且还如此强大 真的是惊呆了 话不多说 先了解一下VBA常用的语法吧 1 基础语法 高级for循环 Function deleteArrayByIndex list As String D
  • oracle获取随机记录

    oracle获取随机记录 select from select from ford car order by dbms random value where rownum lt 1001
  • 【vision transformer】DETR原理及代码详解(三)

    transformer 端到端目标检测DETR项目实践及代码详解 Paddle Detr git PaddleViT object detection DETR at develop BR IDL PaddleViT GitHub 数据集及
  • Redis SDS简单动态字符串

    结构体定义 本质上说就是用C语言来实现基本的面向对象 来对底层的字符串进行表示 方便上层使用 为调用者减少负担 typedef char sds struct sdshdr int len int free char buf 举例常用操作
  • 搭建JMeter分布式测试环境

    分布式测试概述 现在我们来了解如何使用多台机器来执行压力测试 也就是所谓的分布式测试 当我们模拟大量的并发虚拟用户时 比如我们要起10万 100万甚至更多的并发用户时 一台负载机器可能就满足不了我们需要的用户量 此时 就需要使用多台主机搭建
  • Git入门--自定义标签

    忽略特殊文件 忽略某些文件时 需要编写 gitignore gitignore文件本身要放到版本库里 并且可以对 gitignore做版本管理 配置别名 git config global alias co checkout 用co来代替c
  • FFmpeg源码分析:av_register_all()注册封装器与解封装器

    FFmpeg中av register all 函数用于注册所有muxers demuxers与protocols FFmpeg4 0以前是用链表存储muxer demuxer FFmpeg4 0以后改为数组存储 并且av register