简介: CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀
专题四:Android15快速自定义与集成音效实战课 🚀
专题五:Android15音频策略实战课 🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉
🌻1.前言
本篇目的:理解
av_dump_format()如何读取AVFormatContext中的容器、流和元数据信息,并通过FFmpeg输入流程观察它输出的格式摘要。
打开媒体文件并获取流信息后,程序通常需要确认输入容器、时长、码率和各路音视频参数。av_dump_format()把这些信息写入FFmpeg日志,便于开发者检查探测结果。它只负责打印,不负责探测媒体、解码数据或改变流参数。
#mermaid-svg-V9d7W8glGQRdFg4H{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-V9d7W8glGQRdFg4H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-V9d7W8glGQRdFg4H .error-icon{fill:#552222;}#mermaid-svg-V9d7W8glGQRdFg4H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V9d7W8glGQRdFg4H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V9d7W8glGQRdFg4H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V9d7W8glGQRdFg4H .marker.cross{stroke:#333333;}#mermaid-svg-V9d7W8glGQRdFg4H svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V9d7W8glGQRdFg4H p{margin:0;}#mermaid-svg-V9d7W8glGQRdFg4H .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-V9d7W8glGQRdFg4H .cluster-label text{fill:#333;}#mermaid-svg-V9d7W8glGQRdFg4H .cluster-label span{color:#333;}#mermaid-svg-V9d7W8glGQRdFg4H .cluster-label span p{background-color:transparent;}#mermaid-svg-V9d7W8glGQRdFg4H .label text,#mermaid-svg-V9d7W8glGQRdFg4H span{fill:#333;color:#333;}#mermaid-svg-V9d7W8glGQRdFg4H .node rect,#mermaid-svg-V9d7W8glGQRdFg4H .node circle,#mermaid-svg-V9d7W8glGQRdFg4H .node ellipse,#mermaid-svg-V9d7W8glGQRdFg4H .node polygon,#mermaid-svg-V9d7W8glGQRdFg4H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-V9d7W8glGQRdFg4H .rough-node .label text,#mermaid-svg-V9d7W8glGQRdFg4H .node .label text,#mermaid-svg-V9d7W8glGQRdFg4H .image-shape .label,#mermaid-svg-V9d7W8glGQRdFg4H .icon-shape .label{text-anchor:middle;}#mermaid-svg-V9d7W8glGQRdFg4H .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-V9d7W8glGQRdFg4H .rough-node .label,#mermaid-svg-V9d7W8glGQRdFg4H .node .label,#mermaid-svg-V9d7W8glGQRdFg4H .image-shape .label,#mermaid-svg-V9d7W8glGQRdFg4H .icon-shape .label{text-align:center;}#mermaid-svg-V9d7W8glGQRdFg4H .node.clickable{cursor:pointer;}#mermaid-svg-V9d7W8glGQRdFg4H .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-V9d7W8glGQRdFg4H .arrowheadPath{fill:#333333;}#mermaid-svg-V9d7W8glGQRdFg4H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-V9d7W8glGQRdFg4H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-V9d7W8glGQRdFg4H .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V9d7W8glGQRdFg4H .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-V9d7W8glGQRdFg4H .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V9d7W8glGQRdFg4H .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-V9d7W8glGQRdFg4H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-V9d7W8glGQRdFg4H .cluster text{fill:#333;}#mermaid-svg-V9d7W8glGQRdFg4H .cluster span{color:#333;}#mermaid-svg-V9d7W8glGQRdFg4H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-V9d7W8glGQRdFg4H .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-V9d7W8glGQRdFg4H rect.text{fill:none;stroke-width:0;}#mermaid-svg-V9d7W8glGQRdFg4H .icon-shape,#mermaid-svg-V9d7W8glGQRdFg4H .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V9d7W8glGQRdFg4H .icon-shape p,#mermaid-svg-V9d7W8glGQRdFg4H .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-V9d7W8glGQRdFg4H .icon-shape .label rect,#mermaid-svg-V9d7W8glGQRdFg4H .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V9d7W8glGQRdFg4H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-V9d7W8glGQRdFg4H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-V9d7W8glGQRdFg4H :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入媒体文件
AVFormatContext
探测容器和流信息
av_dump_format
FFmpeg日志中的格式摘要
🌻2.应用场景和用法
2.1查看容器和流信息
av_dump_format()适合放在输入探测或输出封装配置之后,用来检查FFmpeg当前掌握的格式信息。
| 场景 | 调用时机 | 观察内容 |
|---|---|---|
| 输入文件探测 | avformat_find_stream_info()成功后 |
输入格式、时长、码率和流参数 |
| 多轨媒体分析 | 流信息探测后 | 音视频流编号、编码类型和时间基 |
| 输出封装检查 | 输出流和封装器配置完成后 | 输出格式及输出流参数 |
| 定位媒体信息异常 | 打开文件或协商参数后 | 上下文中实际存在的信息是否符合预期 |
函数将摘要写入FFmpeg日志系统,常见级别为AV_LOG_INFO。日志级别或回调配置会影响信息是否显示。
2.2函数原型与参数
c
void
av_dump_format (AVFormatContext *ic,
int index,
const char *url,
int is_output);
| 参数 | 含义 |
|---|---|
ic |
已填充输入或输出信息的AVFormatContext |
index |
日志中显示的文件或输出上下文编号 |
url |
输出摘要中显示的媒体地址或文件名 |
is_output |
为0表示输入,为非0表示输出 |
函数没有返回值,也不接管AVFormatContext的所有权。输入场景需要先打开媒体并探测流信息;输出场景应在输出格式和流信息已经准备后调用。它与相邻接口的分工如下:
| 接口 | 职责 |
|---|---|
avformat_open_input() |
打开输入并识别输入格式 |
avformat_find_stream_info() |
读取数据以补充流信息 |
av_dump_format() |
把当前上下文中的格式信息写入日志 |
avformat_close_input() |
关闭输入并释放输入上下文 |
🌻3.调用流程剖析
3.1从格式上下文读取信息
av_dump_format()根据is_output选择上下文中的输入格式或输出格式名称,再通过av_log()打印文件方向、编号和URL。
输入场景会额外打印时长、起始时间和码率。函数随后遍历章节、节目和普通流,并调用内部的流格式输出逻辑整理各流信息。输出摘要来自当前AVFormatContext及其关联的流参数,因此调用时机很重要:如果流探测尚未完成,摘要中就可能缺少信息。
#mermaid-svg-1yI0PfSJHKpisJhq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1yI0PfSJHKpisJhq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1yI0PfSJHKpisJhq .error-icon{fill:#552222;}#mermaid-svg-1yI0PfSJHKpisJhq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1yI0PfSJHKpisJhq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1yI0PfSJHKpisJhq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1yI0PfSJHKpisJhq .marker.cross{stroke:#333333;}#mermaid-svg-1yI0PfSJHKpisJhq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1yI0PfSJHKpisJhq p{margin:0;}#mermaid-svg-1yI0PfSJHKpisJhq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1yI0PfSJHKpisJhq .cluster-label text{fill:#333;}#mermaid-svg-1yI0PfSJHKpisJhq .cluster-label span{color:#333;}#mermaid-svg-1yI0PfSJHKpisJhq .cluster-label span p{background-color:transparent;}#mermaid-svg-1yI0PfSJHKpisJhq .label text,#mermaid-svg-1yI0PfSJHKpisJhq span{fill:#333;color:#333;}#mermaid-svg-1yI0PfSJHKpisJhq .node rect,#mermaid-svg-1yI0PfSJHKpisJhq .node circle,#mermaid-svg-1yI0PfSJHKpisJhq .node ellipse,#mermaid-svg-1yI0PfSJHKpisJhq .node polygon,#mermaid-svg-1yI0PfSJHKpisJhq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1yI0PfSJHKpisJhq .rough-node .label text,#mermaid-svg-1yI0PfSJHKpisJhq .node .label text,#mermaid-svg-1yI0PfSJHKpisJhq .image-shape .label,#mermaid-svg-1yI0PfSJHKpisJhq .icon-shape .label{text-anchor:middle;}#mermaid-svg-1yI0PfSJHKpisJhq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1yI0PfSJHKpisJhq .rough-node .label,#mermaid-svg-1yI0PfSJHKpisJhq .node .label,#mermaid-svg-1yI0PfSJHKpisJhq .image-shape .label,#mermaid-svg-1yI0PfSJHKpisJhq .icon-shape .label{text-align:center;}#mermaid-svg-1yI0PfSJHKpisJhq .node.clickable{cursor:pointer;}#mermaid-svg-1yI0PfSJHKpisJhq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1yI0PfSJHKpisJhq .arrowheadPath{fill:#333333;}#mermaid-svg-1yI0PfSJHKpisJhq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1yI0PfSJHKpisJhq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1yI0PfSJHKpisJhq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1yI0PfSJHKpisJhq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1yI0PfSJHKpisJhq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1yI0PfSJHKpisJhq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1yI0PfSJHKpisJhq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1yI0PfSJHKpisJhq .cluster text{fill:#333;}#mermaid-svg-1yI0PfSJHKpisJhq .cluster span{color:#333;}#mermaid-svg-1yI0PfSJHKpisJhq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1yI0PfSJHKpisJhq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1yI0PfSJHKpisJhq rect.text{fill:none;stroke-width:0;}#mermaid-svg-1yI0PfSJHKpisJhq .icon-shape,#mermaid-svg-1yI0PfSJHKpisJhq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1yI0PfSJHKpisJhq .icon-shape p,#mermaid-svg-1yI0PfSJHKpisJhq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1yI0PfSJHKpisJhq .icon-shape .label rect,#mermaid-svg-1yI0PfSJHKpisJhq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1yI0PfSJHKpisJhq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1yI0PfSJHKpisJhq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1yI0PfSJHKpisJhq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 传入格式上下文和方向
选择输入或输出格式
打印文件与容器信息
遍历章节和节目
逐流整理编码与时间基
通过av_log输出摘要
3.2它不负责探测或校验媒体
av_dump_format()只根据传入上下文中已有的数据生成日志。它不会调用输入探测过程,也不会判断媒体能否完整解码,更不会保证日志显示的参数一定符合应用预期。
排查时应先确认avformat_open_input()和avformat_find_stream_info()的返回值,再观察摘要。如果输入信息未探测完成,优先检查探测流程;如果摘要内容与预期不同,则检查输入文件、流选择和上下文状态。
🌻4.实战案例
4.1打开输入并探测流信息
示例接收媒体路径作为命令行参数。调用av_dump_format()前,先通过avformat_open_input()打开文件,再通过avformat_find_stream_info()补充流信息。
4.2打印输入格式摘要
探测成功后,将输入上下文、文件编号、媒体路径和输入方向传给av_dump_format()。示例使用avformat_close_input()释放输入上下文。
4.3完整代码
c
#include <libavformat/avformat.h>
#include <stdio.h>
int
main (int argc, char *argv[])
{
AVFormatContext *format_context = NULL;
int ret;
if (argc < 2) {
fprintf (stderr, "请提供媒体文件路径\n");
return 1;
}
/* 打开输入文件并读取容器信息 */
ret = avformat_open_input (
&format_context,
argv[1],
NULL,
NULL);
if (ret < 0) {
fprintf (stderr, "无法打开输入文件\n");
return 1;
}
/* 探测音视频流参数,再打印完整摘要 */
ret = avformat_find_stream_info (format_context, NULL);
if (ret < 0) {
fprintf (stderr, "无法获取流信息\n");
avformat_close_input (&format_context);
return 1;
}
/* is_output为0,表示当前上下文用于输入 */
av_dump_format (format_context, 0, argv[1], 0);
/* 释放输入上下文及其关联资源 */
avformat_close_input (&format_context);
return 0;
}
🌻5.总结
av_dump_format()根据AVFormatContext当前已有的输入或输出信息生成格式摘要日志,不负责打开媒体、探测流或解码数据。