ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Linux FFmpeg深度解析之av_demuxer_iterate调用流程与实战(十)

Linux FFmpeg深度解析之av_demuxer_iterate调用流程与实战(十)

简介:CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀

人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

点击获取二维码


🍉🍉🍉文章目录🍉🍉🍉

      • 🌻1.前言
      • 🌻2.应用场景和用法
        • 2.1遍历输入格式的应用场景
        • 2.2函数原型与返回语义
      • 🌻3.调用流程剖析
        • 3.1从编译生成的格式列表中返回对象
        • 3.2在查找和探测流程中的位置
      • 🌻4.实战案例
        • 4.1准备输入格式枚举程序
        • 4.2遍历并检查格式描述
        • 4.3完整代码
      • 🌻5.总结

🌻1.前言

本篇目的:理解av_demuxer_iterate()如何遍历当前FFmpeg构建中注册的输入格式,分析迭代状态和返回对象,并通过C程序列出可用的demuxer。

FFmpeg打开媒体时,需要从当前构建可用的输入格式中选择候选项。av_demuxer_iterate()提供逐个遍历这些格式描述对象的接口。

它只负责返回下一个AVInputFormat,不读取媒体数据、不探测文件内容,也不打开输入文件。文件探测和打开由其他API完成。

当前构建的输入格式列表

av_demuxer_iterate

调用者迭代状态

下一个AVInputFormat

格式枚举或后续探测

🌻2.应用场景和用法

2.1遍历输入格式的应用场景

av_demuxer_iterate()适合需要了解或检查当前FFmpeg构建所支持输入格式的场景。

场景使用方式能得到什么
列出可用demuxer循环调用接口,直到返回NULL获取每个AVInputFormat描述对象
检查定制构建遍历并查看格式名称确认目标格式是否包含在当前构建中
按名称查找格式遍历并比较AVInputFormat.name实现类似av_find_input_format()的查找逻辑
自定义探测流程遍历格式并按需调用探测回调获取候选格式,探测逻辑仍由调用者负责

返回列表取决于FFmpeg构建时启用的组件。被配置排除的demuxer不会出现在列表中。调用者不能把“列表里没有”直接解释成媒体类型不受FFmpeg支持,也要考虑当前二进制的构建配置。

2.2函数原型与返回语义

函数原型如下:

constAVInputFormat*av_demuxer_iterate(void**opaque);
参数或返回值含义
opaque由调用者持有的迭代状态指针,开始遍历时必须指向NULL
返回值下一个已注册输入格式的描述对象
返回NULL当前迭代已经结束

最小调用方式如下:

void*iter=NULL;constAVInputFormat*fmt;while((fmt=av_demuxer_iterate(&iter))!=NULL){/* 使用fmt->name、fmt->long_name等描述字段 */}

opaque是接口内部使用的迭代状态。调用者应原样传回,不要解引用、修改或释放它。每次独立遍历都要使用新的状态变量,或在开始前重新设为NULL。

返回的AVInputFormat是FFmpeg注册表中的格式描述对象,类型为const指针。它不是新分配给调用者的对象,不需要释放。接口本身不创建AVFormatContext,也不触发文件读取或格式探测。

相邻接口的职责不同:

接口作用
av_demuxer_iterate()逐个返回已注册输入格式
av_find_input_format()按名称从输入格式中查找对象
av_probe_input_format3()根据探测数据和候选格式计算匹配结果
avformat_open_input()打开输入并创建或使用AVFormatContext

🌻3.调用流程剖析

3.1从编译生成的格式列表中返回对象

FFmpeg构建时会生成demuxer列表。av_demuxer_iterate()把调用者传入的opaque解释为当前遍历位置,再从静态demuxer_list中取出对应的格式描述对象。

核心逻辑如下:

constAVInputFormat*av_demuxer_iterate(void**opaque){staticconstuintptr_tsize=sizeof(demuxer_list)/sizeof(demuxer_list[0])-1;uintptr_ti=(uintptr_t)*opaque;constAVInputFormat*f=NULL;if(i<size){f=demuxer_list[i];}if(f)*opaque=(void*)(i+1);returnf;}

每次成功返回一个格式对象,内部位置就前进一项。列表结束后,函数返回NULL,调用者应结束循环。实际源码还会检查是否注册了libavdevice输入设备列表;如果存在,也可以继续从该列表中返回输入设备格式。使用avdevice_register_all()注册输入设备属于libavdevice的职责,不是av_demuxer_iterate()自动完成的。

是

否

是

否

opaque指向当前迭代位置

读取demuxer_list

当前位置存在格式对象

返回AVInputFormat

更新opaque位置

检查已注册输入设备列表

还有输入格式

返回NULL结束遍历

3.2在查找和探测流程中的位置

av_find_input_format()内部也通过av_demuxer_iterate()遍历格式,再使用格式名称匹配目标项。av_probe_input_format3()则会遍历候选格式,并根据探测数据调用相应格式的探测逻辑,累计匹配分数。

因此,这三个动作处于不同层次:迭代接口提供格式描述对象,查找接口按名称筛选对象,探测接口结合媒体数据判断格式。迭代本身不会判断某个文件究竟是什么格式。

输入格式注册表

av_demuxer_iterate

AVInputFormat候选对象

按名称查找或执行格式探测

得到匹配格式

交给输入打开流程

🌻4.实战案例

4.1准备输入格式枚举程序

程序使用一个初始化为NULL的void *保存迭代状态,并通过av_demuxer_iterate()逐个获取输入格式。每次返回的对象都可读取name和long_name,循环以返回NULL结束。

4.2遍历并检查格式描述

观察两个内容:

  1. 每次调用是否返回一个AVInputFormat对象。
  2. 迭代结束时是否返回NULL,以及遍历期间累计了多少个格式对象。

格式名称来自当前FFmpeg构建中实际生成的列表。若需要同时枚举输入设备,应链接libavdevice并按其接口完成设备注册。

4.3完整代码
#include<libavformat/avformat.h>#include<stdio.h>intmain(void){void*iter=NULL;constAVInputFormat*fmt;unsignedintcount=0;/* 从NULL状态开始,逐个读取当前构建注册的输入格式 */while((fmt=av_demuxer_iterate(&iter))!=NULL){constchar*long_name=fmt->long_name?fmt->long_name:"无描述";/* name是短名称,long_name是可读格式说明 */printf("%-20s %s\n",fmt->name,long_name);count++;}/* count反映本次遍历实际返回的格式对象数量 */printf("demuxer count: %u\n",count);return0;}

🌻5.总结

av_demuxer_iterate()根据调用者保存的迭代状态逐个返回当前构建中注册的AVInputFormat对象,供格式枚举、查找或后续探测流程使用。

返回列表