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

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

博主新书推荐:《Android系统多媒体进阶实战》🚀

Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀

Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀

专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀

专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀

专题四:Android15快速自定义与集成音效实战课 🚀

专题五:Android15音频策略实战课 🚀

专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

🌻1.前言

本篇目的:理解avformat_open_input()如何创建并初始化输入AVFormatContext,分析它如何打开输入、选择解复用器并读取文件头,再通过独立的C程序观察调用结果。

读取媒体文件时,应用首先需要一个能够描述输入源和解复用状态的AVFormatContext。avformat_open_input()负责打开输入并调用对应解复用器读取文件头。它不会替应用打开正式解码流程;缺失的流参数通常由后续的avformat_find_stream_info()探测。
#mermaid-svg-5JZXMcimdW3NFYpx{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-5JZXMcimdW3NFYpx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5JZXMcimdW3NFYpx .error-icon{fill:#552222;}#mermaid-svg-5JZXMcimdW3NFYpx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5JZXMcimdW3NFYpx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5JZXMcimdW3NFYpx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5JZXMcimdW3NFYpx .marker.cross{stroke:#333333;}#mermaid-svg-5JZXMcimdW3NFYpx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5JZXMcimdW3NFYpx p{margin:0;}#mermaid-svg-5JZXMcimdW3NFYpx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5JZXMcimdW3NFYpx .cluster-label text{fill:#333;}#mermaid-svg-5JZXMcimdW3NFYpx .cluster-label span{color:#333;}#mermaid-svg-5JZXMcimdW3NFYpx .cluster-label span p{background-color:transparent;}#mermaid-svg-5JZXMcimdW3NFYpx .label text,#mermaid-svg-5JZXMcimdW3NFYpx span{fill:#333;color:#333;}#mermaid-svg-5JZXMcimdW3NFYpx .node rect,#mermaid-svg-5JZXMcimdW3NFYpx .node circle,#mermaid-svg-5JZXMcimdW3NFYpx .node ellipse,#mermaid-svg-5JZXMcimdW3NFYpx .node polygon,#mermaid-svg-5JZXMcimdW3NFYpx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5JZXMcimdW3NFYpx .rough-node .label text,#mermaid-svg-5JZXMcimdW3NFYpx .node .label text,#mermaid-svg-5JZXMcimdW3NFYpx .image-shape .label,#mermaid-svg-5JZXMcimdW3NFYpx .icon-shape .label{text-anchor:middle;}#mermaid-svg-5JZXMcimdW3NFYpx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5JZXMcimdW3NFYpx .rough-node .label,#mermaid-svg-5JZXMcimdW3NFYpx .node .label,#mermaid-svg-5JZXMcimdW3NFYpx .image-shape .label,#mermaid-svg-5JZXMcimdW3NFYpx .icon-shape .label{text-align:center;}#mermaid-svg-5JZXMcimdW3NFYpx .node.clickable{cursor:pointer;}#mermaid-svg-5JZXMcimdW3NFYpx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5JZXMcimdW3NFYpx .arrowheadPath{fill:#333333;}#mermaid-svg-5JZXMcimdW3NFYpx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5JZXMcimdW3NFYpx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5JZXMcimdW3NFYpx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5JZXMcimdW3NFYpx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5JZXMcimdW3NFYpx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5JZXMcimdW3NFYpx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5JZXMcimdW3NFYpx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5JZXMcimdW3NFYpx .cluster text{fill:#333;}#mermaid-svg-5JZXMcimdW3NFYpx .cluster span{color:#333;}#mermaid-svg-5JZXMcimdW3NFYpx 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-5JZXMcimdW3NFYpx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5JZXMcimdW3NFYpx rect.text{fill:none;stroke-width:0;}#mermaid-svg-5JZXMcimdW3NFYpx .icon-shape,#mermaid-svg-5JZXMcimdW3NFYpx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5JZXMcimdW3NFYpx .icon-shape p,#mermaid-svg-5JZXMcimdW3NFYpx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5JZXMcimdW3NFYpx .icon-shape .label rect,#mermaid-svg-5JZXMcimdW3NFYpx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5JZXMcimdW3NFYpx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5JZXMcimdW3NFYpx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5JZXMcimdW3NFYpx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入URL或自定义IO
avformat_open_input
输入格式与选项
选择解复用器并读取文件头
返回已初始化的AVFormatContext

🌻2.应用场景和用法

2.1打开输入并读取容器头部

avformat_open_input()是FFmpeg解复用流程的入口,常见于播放器、转码器、媒体分析工具和流媒体客户端。它根据URL或调用者提供的输入格式建立输入上下文,并让解复用器读取文件头。

一些容器的文件头已经包含音视频流数量、编码格式等信息。另一些格式没有完整头部,或者头部信息不足,调用成功后仍需执行avformat_find_stream_info()补充流参数。

它主要完成输入打开和解复用器初始化,不负责把压缩数据解码成音视频帧,也不保证AVStream中的全部参数已经探测完成。

2.2函数原型与返回语义

函数原型如下:

c 复制代码
int
avformat_open_input (AVFormatContext **ps,
                     const char *url,
                     const AVInputFormat *fmt,
                     AVDictionary **options);
参数 含义
ps AVFormatContext指针的地址;指向NULL时,函数会分配上下文
url 输入URL或文件路径;使用自定义IO时可以传入NULL
fmt 非NULL时强制使用指定的AVInputFormat,否则自动探测
options 输入上下文和解复用器选项;成功返回后保留未识别的选项

返回0表示打开成功,负值表示错误。成功后,调用者通过*ps取得输入上下文,并在使用完成后调用avformat_close_input()释放。

如果调用者预先分配了AVFormatContext,打开失败时该上下文也会被释放,*ps会被设为NULL。传入的options在成功返回时会被替换为未识别选项组成的字典,调用者仍需释放剩余字典。

🌻3.调用流程剖析

3.1分配上下文并选择输入格式

调用时,avformat_open_input()先读取*ps。如果它是NULL,函数调用avformat_alloc_context()创建AVFormatContext。传入了fmt时,函数将其记录为输入格式;否则进入init_input()确定格式。

init_input()根据输入状态选择路径:如果调用者提供了自定义AVIOContext,就使用该IO;如果输入格式已经指定,或格式不需要文件IO,就沿用现有配置;其他情况下先打开输入,再调用探测逻辑识别解复用器。
#mermaid-svg-Y0dsdethi7DSJ8H7{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-Y0dsdethi7DSJ8H7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Y0dsdethi7DSJ8H7 .error-icon{fill:#552222;}#mermaid-svg-Y0dsdethi7DSJ8H7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Y0dsdethi7DSJ8H7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .marker.cross{stroke:#333333;}#mermaid-svg-Y0dsdethi7DSJ8H7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Y0dsdethi7DSJ8H7 p{margin:0;}#mermaid-svg-Y0dsdethi7DSJ8H7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .cluster-label text{fill:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .cluster-label span{color:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .cluster-label span p{background-color:transparent;}#mermaid-svg-Y0dsdethi7DSJ8H7 .label text,#mermaid-svg-Y0dsdethi7DSJ8H7 span{fill:#333;color:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .node rect,#mermaid-svg-Y0dsdethi7DSJ8H7 .node circle,#mermaid-svg-Y0dsdethi7DSJ8H7 .node ellipse,#mermaid-svg-Y0dsdethi7DSJ8H7 .node polygon,#mermaid-svg-Y0dsdethi7DSJ8H7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .rough-node .label text,#mermaid-svg-Y0dsdethi7DSJ8H7 .node .label text,#mermaid-svg-Y0dsdethi7DSJ8H7 .image-shape .label,#mermaid-svg-Y0dsdethi7DSJ8H7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Y0dsdethi7DSJ8H7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .rough-node .label,#mermaid-svg-Y0dsdethi7DSJ8H7 .node .label,#mermaid-svg-Y0dsdethi7DSJ8H7 .image-shape .label,#mermaid-svg-Y0dsdethi7DSJ8H7 .icon-shape .label{text-align:center;}#mermaid-svg-Y0dsdethi7DSJ8H7 .node.clickable{cursor:pointer;}#mermaid-svg-Y0dsdethi7DSJ8H7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .arrowheadPath{fill:#333333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y0dsdethi7DSJ8H7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Y0dsdethi7DSJ8H7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y0dsdethi7DSJ8H7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Y0dsdethi7DSJ8H7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .cluster text{fill:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 .cluster span{color:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 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-Y0dsdethi7DSJ8H7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Y0dsdethi7DSJ8H7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Y0dsdethi7DSJ8H7 .icon-shape,#mermaid-svg-Y0dsdethi7DSJ8H7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y0dsdethi7DSJ8H7 .icon-shape p,#mermaid-svg-Y0dsdethi7DSJ8H7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Y0dsdethi7DSJ8H7 .icon-shape .label rect,#mermaid-svg-Y0dsdethi7DSJ8H7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y0dsdethi7DSJ8H7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Y0dsdethi7DSJ8H7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Y0dsdethi7DSJ8H7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
AVFormatContext与输入参数
分配或复用输入上下文
是否指定输入格式或自定义IO
使用调用者提供的输入配置
打开IO并探测解复用器

3.2调用解复用器读取文件头

格式确定后,函数为解复用器分配私有数据,应用选项,再调用AVInputFormat中的read_header()读取容器头部。解复用器可能在这一步创建AVStream并写入部分codecpar参数。

成功后,函数处理文件头中的元数据和附加图片,更新内部流上下文,并把初始化后的AVFormatContext写回*ps。打开失败时则执行清理,释放相关上下文和内部IO资源。
#mermaid-svg-1A7wjNa9n5YoilKm{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-1A7wjNa9n5YoilKm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1A7wjNa9n5YoilKm .error-icon{fill:#552222;}#mermaid-svg-1A7wjNa9n5YoilKm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1A7wjNa9n5YoilKm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1A7wjNa9n5YoilKm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1A7wjNa9n5YoilKm .marker.cross{stroke:#333333;}#mermaid-svg-1A7wjNa9n5YoilKm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1A7wjNa9n5YoilKm p{margin:0;}#mermaid-svg-1A7wjNa9n5YoilKm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1A7wjNa9n5YoilKm .cluster-label text{fill:#333;}#mermaid-svg-1A7wjNa9n5YoilKm .cluster-label span{color:#333;}#mermaid-svg-1A7wjNa9n5YoilKm .cluster-label span p{background-color:transparent;}#mermaid-svg-1A7wjNa9n5YoilKm .label text,#mermaid-svg-1A7wjNa9n5YoilKm span{fill:#333;color:#333;}#mermaid-svg-1A7wjNa9n5YoilKm .node rect,#mermaid-svg-1A7wjNa9n5YoilKm .node circle,#mermaid-svg-1A7wjNa9n5YoilKm .node ellipse,#mermaid-svg-1A7wjNa9n5YoilKm .node polygon,#mermaid-svg-1A7wjNa9n5YoilKm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1A7wjNa9n5YoilKm .rough-node .label text,#mermaid-svg-1A7wjNa9n5YoilKm .node .label text,#mermaid-svg-1A7wjNa9n5YoilKm .image-shape .label,#mermaid-svg-1A7wjNa9n5YoilKm .icon-shape .label{text-anchor:middle;}#mermaid-svg-1A7wjNa9n5YoilKm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1A7wjNa9n5YoilKm .rough-node .label,#mermaid-svg-1A7wjNa9n5YoilKm .node .label,#mermaid-svg-1A7wjNa9n5YoilKm .image-shape .label,#mermaid-svg-1A7wjNa9n5YoilKm .icon-shape .label{text-align:center;}#mermaid-svg-1A7wjNa9n5YoilKm .node.clickable{cursor:pointer;}#mermaid-svg-1A7wjNa9n5YoilKm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1A7wjNa9n5YoilKm .arrowheadPath{fill:#333333;}#mermaid-svg-1A7wjNa9n5YoilKm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1A7wjNa9n5YoilKm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1A7wjNa9n5YoilKm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1A7wjNa9n5YoilKm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1A7wjNa9n5YoilKm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1A7wjNa9n5YoilKm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1A7wjNa9n5YoilKm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1A7wjNa9n5YoilKm .cluster text{fill:#333;}#mermaid-svg-1A7wjNa9n5YoilKm .cluster span{color:#333;}#mermaid-svg-1A7wjNa9n5YoilKm 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-1A7wjNa9n5YoilKm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1A7wjNa9n5YoilKm rect.text{fill:none;stroke-width:0;}#mermaid-svg-1A7wjNa9n5YoilKm .icon-shape,#mermaid-svg-1A7wjNa9n5YoilKm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1A7wjNa9n5YoilKm .icon-shape p,#mermaid-svg-1A7wjNa9n5YoilKm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1A7wjNa9n5YoilKm .icon-shape .label rect,#mermaid-svg-1A7wjNa9n5YoilKm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1A7wjNa9n5YoilKm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1A7wjNa9n5YoilKm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1A7wjNa9n5YoilKm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 已选定AVInputFormat
配置解复用器私有数据
read_header读取容器头部
创建或更新AVStream
返回AVFormatContext

avformat_open_input()成功返回后,输入已打开且文件头已处理,但解码器尚未由应用打开。需要补充流信息时再调用avformat_find_stream_info();需要读取压缩数据时使用av_read_frame()。

🌻4.实战案例

4.1准备输入参数

程序从命令行取得媒体文件路径,将AVFormatContext初始化为NULL,让avformat_open_input()负责分配上下文。示例不指定输入格式和选项,因此使用自动格式探测。

4.2打开输入并检查上下文

调用成功后检查iformat和nb_streams,确认解复用器已经选择、文件头阶段得到的流信息已经写入上下文。这里不调用avformat_find_stream_info(),以便单独观察打开接口的职责范围。

4.3完整代码
c 复制代码
#include <libavformat/avformat.h>
#include <libavutil/error.h>
#include <stdio.h>

static void
print_av_error (int error_code)
{
  char error_text[AV_ERROR_MAX_STRING_SIZE];

  av_strerror (error_code, error_text, sizeof (error_text));
  fprintf (stderr, "FFmpeg error: %s\n", error_text);
}

int
main (int argc, char *argv[])
{
  AVFormatContext *format_context = NULL;
  int ret;

  if (argc < 2) {
    fprintf (stderr, "Usage: %s <input>\n", argv[0]);
    return 1;
  }

  /* 由FFmpeg自动分配上下文并探测输入格式 */
  ret = avformat_open_input (
      &format_context,
      argv[1],
      NULL,
      NULL);

  if (ret < 0) {
    print_av_error (ret);
    /* 打开失败时,format_context由接口清理并置为NULL */
    avformat_close_input (&format_context);
    return 1;
  }

  /* 文件头已读取,检查解复用器和当前可见的流数量 */
  if (format_context->iformat != NULL) {
    printf ("demuxer: %s\n", format_context->iformat->name);
  }
  printf ("streams from header: %u\n", format_context->nb_streams);

  /* 释放输入上下文及FFmpeg内部打开的输入IO */
  avformat_close_input (&format_context);

  return 0;
}

🌻5.总结

avformat_open_input()负责打开输入、确定解复用器并读取文件头,返回初始化后的AVFormatContext,但不负责应用侧的音视频解码。

相关推荐
分布式存储与RustFS1 小时前
把 LSM 引擎直接架在对象存储上:slatedb 能不能跑在 RustFS 上?
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
深圳恒讯1 小时前
国外云服务器部署企业官网,怎样确定配置、IP 与后续扩容方案?
运维·服务器·tcp/ip
java_logo2 小时前
Docker 部署 Excalidraw:轻松搭建手绘风格白板
运维·docker·容器·excalidraw·白板·轩辕镜像
吹什么轩2 小时前
linux系统复习:Ext 文件系统(一个文件在磁盘上到底长什么样)
linux·运维·服务器
吹什么轩2 小时前
linux系统复习:全景串联
linux·运维·服务器
m0_547486662 小时前
《Ubuntu Linux操作系统与实验教程》全套PPT课件2026
linux·ubuntu·操作系统
Elastic 中国社区官方博客2 小时前
5 分钟内将 56 页扫描文档转化为带引用的答案:面向搜索无法读取的文档的检索增强生成流水线
大数据·运维·人工智能·elasticsearch·搜索引擎·信息可视化·全文检索
John_Hui2 小时前
第 1 篇:VMware 安装 Ubuntu 24.04.3 Server
linux·运维·ubuntu
kyle~2 小时前
C++ 原子操作、内存模型与无锁并发编程
linux·开发语言·c++·操作系统