链接:https://trac.ffmpeg.org/

docs:FFmpeg

在这里插入图片描述
FFmpeg 是一个强大的多媒体框架,旨在处理媒体处理的各个阶段。

它就像一个数字媒体工厂,包含以下部门:打包/解包(容器处理)、
转译/压缩(编解码器处理)、管理原始视频帧压缩数据包
连接输入/输出源(输入输出访问)、执行编辑和特效(过滤与处理)、
保持所有内容的同步性(时间与速率管理),并提供灵活定制(配置选项)。

概览

在这里插入图片描述

章节列表

  1. 输入输出访问
  2. 容器处理
  3. 压缩媒体数据包
  4. 原始媒体帧
  5. 编解码器处理
  6. 过滤与处理
  7. 时间与速率管理
  8. 配置选项

第一章:输入输出访问

欢迎来到FFmpeg的第一章~

在FFmpeg能够执行诸如转换视频或提取音频等酷炫操作之前,它需要从某处获取多媒体数据并将其发送到另一处。这个首要关键步骤由FFmpeg的输入输出访问层处理。

可将输入输出访问视为连接FFmpeg与外部世界的"管道系统"。

就像房屋需要管道来进出水一样,FFmpeg需要一种方式来输入输出视频、音频和其他数据。该层提供了处理数据流的标准化方式,无论数据是来自计算机本地文件、网络视频流,甚至是网络摄像头等实时捕获设备。

如果没有这种抽象层,FFmpeg将需要完全不同的代码来读取本地.mp4文件(与从网站下载视频或从麦克风捕获相比)。输入输出访问层隐藏了这些差异,提供了一致的接口。

让我们从一个常见用例开始:将视频文件从一种格式转换为另一种格式。假设您有一个名为input.mp4的视频文件,希望另存为output.avi

在命令行中使用ffmpeg工具(底层使用FFmpeg库)时,通常执行如下操作:

ffmpeg -i input.mp4 output.avi

从输入输出角度分析此命令:

  • -i input.mp4:告知FFmpeg使用input.mp4作为输入源,-i选项是标准输入文件或URL指定参数
  • output.avi:指定输出目标,FFmpeg将其识别为文件名并准备写入数据

在此简单命令中,FFmpeg的输入输出访问层负责:

  1. 打开input.mp4进行读取
  2. 分块读取input.mp4数据
  3. 打开output.avi进行写入
  4. 将处理后的数据写入output.avi

-f选项(-format缩写)可显式指定输入输出格式,这对于没有明确头部的原始视频数据等输入尤为重要:

ffmpeg -f rawvideo -video_size 640x480 -pixel_format yuv420p -i input.yuv output.mp4

此处-f rawvideo告知FFmpeg将input.yuv视为原始视频数据,因为.yuv文件本身不包含尺寸或像素格式等格式信息。输入输出层仍负责打开和读取文件,但需要这些额外参数(-video_size, -pixel_format)来理解读取数据的结构。

因此,输入输出访问层的核心职责是获取字节输入发送字节输出

内部机制:管道系统

当运行ffmpeg -i input.mp4 output.avi时,FFmpeg如何处理文件读取?

FFmpeg使用称为协议(或URLProtocol)的组件来了解如何与不同类型数据源和目的地交互。

当提供input.mp4时,FFmpeg识别其为本地文件,内部通常视为file://input.mp4 URL。

随后FFmpeg查找能处理file:// URL的"协议处理器"——即file协议。同理,output.avi也由file协议处理写入。

这些协议处理器抽象了底层细节

FFmpeg主引擎只需要求输入输出层"打开此URL"、“读取数据”、“写入数据"或"关闭URL”,相应协议处理器执行实际工作,无论是调用文件系统函数、发起网络请求还是与设备驱动交互。

FFmpeg I/O处理流程:

在这里插入图片描述

  • FFmpeg告知输入输出层打开目标,输入输出层使用正确协议(如本例的file协议)与外部资源交互。
  • 随后FFmpeg循环请求输入数据并提供输出数据直至完成,最终关闭所有资源。

超越本地文件:多样化数据源与目的地

输入输出访问层的强大之处在于其通过统一方式处理多种不同类型数据源和目的地的能力。

除本地文件外,FFmpeg还能读写:

  • 网络流媒体:HTTP、RTMP、RTSP、TCP、UDP等,只需提供不同URL:

    ffmpeg -i http://example.com/video.mp4 output.avi
    ffmpeg -i input.mp4 rtmp://publish.example.com/app/streamkey
    

    此类情况使用httprtmp等专用协议,详见FFmpeg文档协议选项。

  • 捕获/播放设备:摄像头、麦克风、屏幕捕获、视频/音频卡,通过操作系统特定的设备名或URL访问:

    ffmpeg -f video4linux2 -i /dev/video0 output.mp4 # Linux摄像头
    ffmpeg -f dshow -i video="集成摄像头":audio="麦克风" output.mp4 # Windows摄像头+麦克风
    

    使用设备特定的输入输出处理器(参见输入设备和输出设备)。

  • 标准输入/输出(管道):通过stdin读取、stdout写入,实现命令行工具链式调用:

    cat input.ts | ffmpeg -i pipe:0 output.mp4 # 从stdin读取
    ffmpeg -i input.mp4 -f avi pipe:1 | ffplay pipe:0 # 写入stdout
    

    通常使用pipefd协议。

核心思想保持不变:FFmpeg通过输入输出层获取原始数据字节,无需关心字节获取方式(通过各种上层协议的制定,实现了很好的抽象),只需确保可读写。


🎢协议解析结构体:AVIOContext与自定义数据源处理

在这里插入图片描述

AVIOContext 与 URLProtocol

  • AVIOContext 是 FFmpeg 中用于抽象 I/O 操作的核心结构体,负责数据的读写缓冲和协议处理。

  • 它通过 URLProtocol 实现与具体协议(如文件、HTTP、RTMP等)的交互。

URLProtocol 是协议实现的接口,定义了一组标准函数(如打开、读取、写入、关闭等)。每种协议(如 file、http)需要实现自己的 URLProtocol 实例

协作流程

AVIOContext 初始化时绑定一个 URLProtocol

当用户通过 AVIOContext 读写数据时,AVIOContext 会调用对应 URLProtocol 的函数。

例如,读取 HTTP 数据时:

  1. AVIOContext 处理缓冲状态管理
  2. 实际网络请求由 HTTP 协议的 URLProtocol 实现完成。

联系

  • AVIOContext 是上层抽象,提供统一的 I/O 接口。
  • URLProtocol 是底层实现,处理具体协议的细节。
  • 开发者通常只需操作 AVIOContext,无需直接调用 URLProtocol。

FFmpeg支持多种协议(HTTP、RTMP、RTSP、文件等)的多媒体数据获取。其协议解析模块通过三个核心结构体实现灵活的数据处理:

在这里插入图片描述

核心结构体解析

1. AVIOContext

头文件libavformat/avio.h
https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/avio.h

关键字段

  • buffer:数据缓冲区
  • buffer_size:缓冲区容量
  • pos:当前读取偏移量
  • opaque:指向用户数据或URLContext
  • read_packet/write_packet读写回调函数

缓冲区关系
在这里插入图片描述

2. URLContext

典型实现(以RTP协议为例):

typedef struct RTPContext 
{URLContext *rtp_hd, *rtcp_hd;int ttl;int buffer_size;// ...其他协议特定字段
} RTPContext;const URLProtocol ff_rtp_protocol = 
{.name = "rtp",.url_open = rtp_open,.url_read = rtp_read,.priv_data_size = sizeof(RTPContext),// ...其他回调函数
};

3. URLProtocol

作为协议实现的基类,定义标准操作接口:

  • url_open:建立协议连接
  • url_read/url_write:数据读写
  • priv_data_size:协议私有数据大小

URLProtocol是FFMPEG操作文件的结构(包括文件,网络数据流等等),包括open、close、read、write、seek等操作。

定义了协议相关的回调函数,类似于url协议的虚函数定义

也类似门面模式,具体的回调函数的方法实现在ff_rtp_protocol等具体的对象中。

  • 门面模式通过一个统一的高层接口简化复杂子系统调用,像前台接待一样隐藏内部细节

应用场景

标准协议处理

使用avformat_open_input即可完成:

AVFormatContext *fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, "rtsp://example.com/stream", NULL, NULL);

自定义数据源处理

当需要处理以下特殊场景时需直接操作AVIOContext:

  1. 内存数据源
struct buffer_data {uint8_t *ptr; size_t size;
};static int read_packet(void *opaque, uint8_t *buf, int buf_size) {struct buffer_data *bd = opaque;// 实现自定义读取逻辑
}
  1. 实时流处理(代码示例)
// 创建自定义AVIOContext
avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,0, &bd, &read_packet, NULL, NULL);// 关联到FormatContext
fmt_ctx->pb = avio_ctx;
avformat_open_input(&fmt_ctx, NULL, NULL, NULL);
  1. 加密传输
static int decrypt_packet(void *opaque, uint8_t *buf, int buf_size) {// 解密逻辑实现return decrypt_data(buf, buf_size);
}

示例代码

#include <libavformat/avformat.h>struct buffer_data {uint8_t *ptr;size_t size; 
};static int read_packet(void *opaque, uint8_t *buf, int buf_size) {struct buffer_data *bd = opaque;// 实现内存到缓冲区的拷贝逻辑
}int main() {// 初始化AVFormatContextAVFormatContext *fmt_ctx = avformat_alloc_context();// 创建自定义IO上下文AVIOContext *avio_ctx = avio_alloc_context(av_malloc(4096), 4096, 0, &bd, &read_packet, NULL, NULL);fmt_ctx->pb = avio_ctx;avformat_open_input(&fmt_ctx, NULL, NULL, NULL);// 后续处理流程...
}

运行测试前置条件:

sudo apt-get update
sudo apt-get install libavformat-dev libavutil-dev

运行:

gcc -o ffmpeg_buffer_test ffmpeg_buffer_test.c -lavformat -lavutil

在这里插入图片描述

架构设计思想

FFmpeg通过分层设计实现协议处理的灵活性:

  1. 高层接口avformat_open_input封装常规操作
  2. 扩展层AVIOContext提供自定义I/O接入点
  3. 协议实现层URLProtocol定义标准协议接口

这种设计使得开发者既能快速处理标准协议,又能通过自定义AVIOContext实现特殊需求,在易用性和灵活性之间取得平衡。


C语言API:AVIOContext与URLProtocol

对于使用FFmpeg库(libavformat、libavcodec等)的开发人员,输入输出访问层主要通过AVIOContext结构体和URLProtocol相关函数管理。

  • AVIOContext:表示I/O操作上下文,包含读写缓冲区及指向底层I/O函数的指针
  • URLProtocol:定义特定协议处理器,包含协议名("file""http""rtmp")及实现打开、读写、寻址、关闭等操作的函数指针

多数应用不直接操作URLProtocol,而是通过avio_open2等函数为给定URL创建AVIOContext

// API函数使用示例(非完整代码)
AVFormatContext* fmt_ctx = avformat_alloc_context(); // 媒体文件格式上下文
AVIOContext* avio_ctx = NULL; // I/O操作上下文
char* input_url = "input.mp4";
int ret;// 使用avio_open2打开输入URL并创建AVIOContext
ret = avio_open2(&avio_ctx, input_url, AVIO_FLAG_READ, NULL, NULL);
if (ret < 0) {// 错误处理
}fmt_ctx->pb = avio_ctx; // 将AVIOContext关联到格式上下文// ...后续读取数据...
uint8_t buffer[4096];
int bytes_read = avio_read(avio_ctx, buffer, sizeof(buffer));// ...关闭资源...
avio_close(avio_ctx);
// 注意:avio_context_free在关闭后释放AVIOContext本身

该代码段展示了核心函数:

  • avio_open2初始化
  • avio_read/avio_write数据传输
  • avio_close终止操作。

doc/APIchanges文件记录了库接口变更,包含诸多AVIOContext相关更新,例如avio_open2的引入、支持更多参数等。

示例代码如

  • avio_list_dir.c展示了目录协议交互
  • avio_read_callback.c演示了自定义I/O上下文

这些API细节主要面向使用FFmpeg库的开发人员,证实输入输出访问层(AVIOContextURLProtocol)是FFmpeg架构的基础组成部分,专门负责原始数据字节的输入输出。

平时调api,最多用到avio,具体的数据结构和urlprotocol的实现我们并不关心,我们只需要调用,并且能输入和输出数据


总结

本章我们了解到,在FFmpeg解码、编码或处理多媒体数据前,必须首先读取数据,处理完成后写出数据。

这是输入输出访问层的职责,它通过特定协议处理器为本地文件、网络流和硬件设备等多样化数据源/目的地提供统一处理方式

现在我们理解FFmpeg如何获取原始字节,下一步是解析这些字节

多媒体数据通常封装在容器格式(如MP4MKVAVI)中,这些容器提供结构和元数据。

下一章我们将探讨FFmpeg如何处理这些容器。

容器处理


(抽象和协议的重要性)

统一接口设计 --前文传送:

[xiaozhi-esp32] 应用层(9种state) | 音频编解码层 | 双循环架构

[xiaozhi-esp32] 音频处理 | Display | 纯虚锁的抽象思想

[Subtitle Edit] 字幕数据模型Paragraph | 核心逻辑库(libse)

[shadPS4] 内存管理 | 权限管理 |文件系统 | 挂载和句柄

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/89852.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89852.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89852.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务的编程测评系统2

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言工程创建创建ck-oj创建oj-modules创建具体微服务oj-system推送码云管理员登录逻辑分析docker安装mysqldocker客户端docker desktop安装安装mysqlmysql-plus和数据…

AR智能巡检:电力运维的数字化变革

在电力行业快速发展的当下&#xff0c;传统运维方式已难以满足现代电网对高效、安全的需求。近年来&#xff0c;增强现实&#xff08;AR www.teamhelper.cn &#xff09;技术的兴起为电力巡检带来了全新的解决方案。通过实时数据可视化、远程协作和智能分析&#xff0c;AR技术…

NeRF和3DGS原理详细

NeRF和3DGS一、传统三维表征方法1.1 显示表征1.2 隐式表征二、NeRF&#xff08;Nerual Radiance Field&#xff09;2.1 NeRF场景表示2.2 NeRF训练流程2.3 NeRF体渲染2.4 NeRF位置编码2.5 NeRF体素分层采样&#xff08;Volume Hierarchical Sampling&#xff09;2.6 NeRF网络结构…

035_ClaudeCode_MCP_介绍

035_ClaudeCode_MCP_介绍 摘要 Model Context Protocol&#xff08;MCP&#xff09;是一个开放的标准化协议&#xff0c;专为大型语言模型提供上下文数据而设计。作为Claude Code生态系统的重要组成部分&#xff0c;MCP如同"AI应用程序的USB-C端口"&#xff0c;提供…

Python 程序无法找到 Oracle 的 64 位客户端库 (libclntsh.so)

数据库错误: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help 这个错误表明 Python 程序无法找到…

Kubernetes常用命令总结

文章目录Kubernetes常用命令总结1. 集群管理命令kubectl cluster-infokubectl get nodeskubectl describe node <node-name>kubectl top nodes2. Pod相关命令kubectl get podskubectl get pods -o widekubectl describe pod <pod-name>kubectl logs <pod-name&g…

roboflow使用教程

如何利用roboflow标注自己的训练集、调用开源数据集 官网&#xff1a;Roboflow: Computer vision tools for developers and enterprises&#xff08;国内代理进不去&#xff09; 先注册登陆进去 训练自己的数据集 点击“New Project”,名字按照自己的需求来 我不想写了&am…

IDEA中使用Tomcat两种方式

Catalogue1 集成本地Tomcat2 Tomcat Maven插件&#xff08;推荐&#xff09;1 集成本地Tomcat 将本地Tomcat集成到Idea中&#xff0c;然后进行项目部署即可 点击编辑配置 点击加号 添加local的Tomcat 配置Application Server 可以修改一下Name 至此&#xff0c;配置完成 …

服务器上的文件复制到本地 Windows 系统

在 Windows 上通过 SSH 连接到 Linux 服务器后&#xff0c;如果需要将服务器上的文件复制到本地 Windows 系统&#xff0c;可以使用以下几种方法&#xff1a;方法 1&#xff1a;使用 scp&#xff08;Secure Copy&#xff09;命令 scp&#xff08;基于 SSH 的安全复制&#xff0…

大语言模型置信度增强实战指南

LLM怎么简单增强置信度 在大语言模型(LLM)的应用中,“置信度增强”核心目标是提升模型输出的可靠性(减少错误/幻觉) 并让模型更清晰地表达自身的不确定性(避免“一本正经地胡说”)。常用方式可分为“输出优化”“知识补充”“校准调整”三大类, 一、基于“推理过程优…

NLP:人名分类器案例分享

本文目录&#xff1a;一、案例介绍&#xff08;一&#xff09;关于人名分类&#xff08;二&#xff09;人名分类数据预览二、案例步骤&#xff08;一&#xff09;导入工具包&#xff08;二&#xff09;数据预处理1. 获取常用的字符数量2. 国家名种类数和个数3.读数据到内存4.构…

3分钟实战!用DeepSeek+墨刀AI生成智能对话APP原型图

如今&#xff0c;AI生成原型图已经逐渐成为产品经理的一项常用辅助技能&#xff0c;不仅能加快设计进程&#xff0c;还能显著提升前期沟通效率。最近我尝试将大语言模型工具与AI原型工具结合测试&#xff0c;目标是看看是否能生成更高质量的原型页面。直到我使用DeepSeek墨刀AI…

CentOS网络配置与LAMP环境搭建指南

一、CentOS配置网络1、查看网卡名称ifconfig2、找到网卡对应配置文件网卡存放路径 &#xff1a;/etc/sysconfig/network-scriptscd /etc/sysconfig/network-scripts3、修改网卡对应配置文件使用 vi/vim 打开文件&#xff0c;查看以下内容vim ifcfg-ens33将ONBOOTno 改为 ONBOOT…

TinyMCE 富文本编辑器在 vue2 中的使用 @tinymce/tinymce-vue

TinyMCE是一款功能强大、高度可定制的富文本编辑器。官方文档 TinyMCE DOCS tinymce-vue包的版本4及更高版本支持Vue.js 3。但不支持Vue.js 2.x。对于Vue.js 2。X应用程序&#xff0c;使用tinymce-vue版本3。 安装TinyMCE和Vue集成包 npm install tinymce/tinymce-vue3 tiny…

LP-MSPM0G3507学习--04GPIO控制

关键函数&#xff1a; DL_GPIO_readPins(GPIO_Regs* gpio, uint32_t pins):同时读一组端口DL_GPIO_writePins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;同时写一组端口DL_GPIO_setPins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;对指定某组端口的某管脚置高DL_GPIO_cle…

LVS(Linux virtual server)-实现四层负载均衡

一、简介LVS:Linux Virtual Server&#xff0c;负载调度器&#xff0c;内核集成&#xff0c;章文嵩&#xff0c;阿里的四层SLB(Server LoadBalance)是基 于LVSkeepalived实现LVS 官网: http://www.linuxvirtualserver.org/二、LVS运行原理2.1LVS 的集群结构2.2lvs相关概念RS&am…

Kubernetes CNI网络插件性能瓶颈排查与优化实践

Kubernetes CNI网络插件性能瓶颈排查与优化实践 CNI&#xff08;Container Network Interface&#xff09;是 Kubernetes 网络层的核心组件&#xff0c;不同 CNI 插件实现了容器间网络通信、多租户隔离、流量限速等功能。然而在大规模集群或高并发业务场景下&#xff0c;CNI 插…

20250720-6-Kubernetes 调度-nodeName字段,DaemonS_笔记

一、污点与容忍&#xfeff;1. 给节点添加污点&#xfeff;1&#xff09;命令格式基本语法&#xff1a;kubectl taint node [node] keyvalue:[effect]示例&#xff1a;kubectl taint node k8s-node1 gpuyes:NoSchedule操作说明&#xff1a;与打标签命令类似&#xff0c;将"…

微软开源项目 Detours 详细介绍与使用实例分享

目录 1、Detours概述 2、Detours功能特性 3、Detours工作原理 4、Detours应用场景 5、Detours兼容性 6、Detours具体使用方法 7、Detours使用实例 - 使用Detours拦截系统库中的UnhandledExceptionFilter接口,实现对程序异常的拦截 C++软件异常排查从入门到精通系列教程…

研发知识系统选型实战:从 Notion 到 Gitee Wiki 的迭代经验

关键词&#xff1a;知识管理、版本控制、协作编辑、国产平台、研发效能 在日常研发管理中&#xff0c;知识管理平台往往被视为“非核心工具”&#xff0c;但它的好坏直接影响着团队交接效率、文档可用性以及协作深度。过去几年&#xff0c;我们团队先后使用过 Notion、Confluen…