当前位置: 首页 > news >正文

音视频开发9 FFmpeg 解复用框架--如何将一个影音文件(mp4文件/wav文件) 最终播放起来

一,播放器框架

二 常用音视频术语

容器/文件(Conainer/File): 即特定格式的多媒体文件, 比如mp4、flv、mkv等。
媒体流(Stream): 表示时间轴上的一段连续数据,如一 段 声音数据 、一段 视频数据 或一段 字幕数据 ,可以是压缩 的,也可以是非压缩的,压缩的数据需要关联特定的编解 码器(有些码流音频他是纯PCM)。一般对于 一个 mp4文件, 通过解复用器,就可以将mp4中的 视频流和 音频流,甚至字符流都分离出来。 
数据帧/数据包(Frame/Packet): 通常,一个媒体流是 由大量的数据帧组成的,对于压缩数据, 帧对应着编解码 器的最小处理单元 ,分属于不同媒体流的数据帧交错存储 于容器之中。
一般来说,压缩后的数据,我们认为是packet
解码后的数据,我们认为是frame的概念。
帧对应着编解码 器的最小处理单元 这句话的理解如下:
对于视频,一个frame实际上就是一张图片了
对于音频,一个frame,对于 aac 是1024个采样点为一帧,mp3 则是1152个采样点为一帧。
编解码器: 编解码器是以帧为单位实现压缩数据和原始数 据之间的相互转换的。

三 常用概念-复用器

四 常用概念-编解码器

五 FFmpeg库简介

FFMPEG有8个常用库:
AVUtil :核心工具库,下面的许多其他模块都会依赖该库做一些基本的音 视频处理操作。
AVFormat :文件格式和协议库,该模块是最重要的模块之一,封装了 Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透 明的。
AVCodec :编解码库,封装了Codec层,但是有一些Codec是具备自己的 License的,FFmpeg是不会默认添加像 libx264、FDK-AAC 等库的,但是 FFmpeg就像一个平台一样,可以将其他的第三方的Codec以插件的方式 添加进来,然后为开发者提供统一的接口。
AVFilter :音视频滤镜库,该模块提供了包括音频特效和视频特效的处理, 在使用FFmpeg的API进行编解码的过程中,直接使用该模块为音视频数 据做特效处理是非常方便同时也非常高效的一种方式。
AVDevice :输入输出设备库,比如,需要编译出播放声音或者视 频的工具ffplay,就需要确保该模块是打开的,同时也需要SDL的 预先编译,因为该设备模块播放声音与播放视频使用的都SDL库。
SwrRessample :该模块可用于 音频重采样 ,可以对数字音频进行 声道数、数据格式、采样率 等多种基本信息的转换。
SWScale :该模块是将图像进行格式转换的模块,比如,可以将 YUV的数据转换为RGB的数据,缩放尺寸由1280*720变为800*480。
PostProc :该模块可用于进行后期处理,当我们使用AVFilter的时 候需要打开该模块的开关,因为Filter中会使用到该模块的一些基 础函数。

六 FFmpeg函数简介

av_register_all():注册所有组件,4.0已经弃用

avdevice_register_all()对设备进行注册,比如V4L2等。

        
#include <libavdevice/avdevice.h>/*** Initialize libavdevice and register all the input and output devices.*/
void avdevice_register_all(void);

avformat_network_init();初始化网络库以及网络加密协议相关 的库(比如openssl)

#include <libavformat/avformat.h>int avformat_network_init(void);

七 FFmpeg函数简介-封装格式相关

avformat_alloc_context();负责申请一个AVFormatContext 结构的内存,并进行简单初始化

#include <libavformat/avformat.h>/*** Allocate an AVFormatContext.* avformat_free_context() can be used to free the context and everything* allocated by the framework within it.*/
AVFormatContext *avformat_alloc_context(void);## AVFormatContext:它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体, 	

其中比较重要的几个如下解释:

typedef struct AVFormatContext {const AVClass *av_class;   // 一个类,用于保存指向父对象的链接,用于日志记录struct AVInputFormat *iformat;  // 用于指定输入文件的格式以及文件读取的操作函数struct AVOutputFormat *oformat; // 用于指定输出文件的格式以及文件写入的操作函数void *priv_data;            // 指向 AVFormatContext(容器上下文)的私有数据AVIOContext *pb;            // 用于读取和写入媒体数据的 I/O 上下文int nb_streams;             // 流的数量,包括音频、视频、字幕等AVStream **streams;         // 指向 AVStream 结构体的指针,用于存储所有流的信息char *filename;             // 用于存储文件名的字符串int64_t start_time, duration;// 媒体文件的起始时间戳和持续时间int64_t bit_rate;           // 比特率,以 bit/s 计算uint8_t *buffer;            // 用于暂存数据的缓冲区int buffer_size;            // 缓冲区的大小
} AVFormatContext;AVFormatContext 结构体的各个成员变量的作用详见以下介绍。成员变量介绍AVClass *av_class: 一个类,用于保存指向父对象的链接,用于日志记录;
AVClass是FFmpeg中libavutil库中的一个结构体,用于在FFmpeg中实现类及其对象的日志和调试功能。AVClass提供了一种标准的方式来管理类及其对象,在不同的库和插件之间提供了统一的日志记录和调试接口。AVInputFormat *iformat:用于指定输入文件的格式以及文件读取的操作函数;
AVOutputFormat *oformat: 用于指定输出文件的格式以及文件写入的操作函数;void *priv_data: 指向 AVFormatContext(容器上下文)的私有数据;
priv_data成员可以用于存储和传递特定协议下使用的私有数据,常见的使用场景是实现自定义输入或输出协议。AVIOContext *pb:用于读取和写入媒体数据的 I/O 上下文;
AVIOContext 是libavformat库中一个表示访问媒体文件的I/O环境的结构体。它封装了对媒体文件的读取和写入操作,提供了和具体I/O操作系统相关的操作的抽象接口,实现了独立于实际操作系统的媒体文件访问接口。int nb_streams: 流的数量,包括音频、视频、字幕等;
AVStream **streams:指向 AVStream 结构体的指针,用于存储所有流的信息;
AVStream是FFmpeg中libavformat库中的一个数据结构,用于表示媒体文件中的一个音频或视频流。在FFmpeg中,一个媒体文件通常包含多个音视频流,每个流对应着媒体文件中的一个轨道。AVStream通过存储音视频流的各种属性信息,方便解码和编码,对于多媒体处理和视频编辑有着至关重要的作用。
AVStream包含了一个媒体流的所有基本信息,如类型、编解码器、时间戳、时长、帧率、码率等等。常用的成员变量有:
char *filename: 用于存储文件名的字符串;int64_t start_time: 媒体文件的起始时间戳;
int64_t duration: 媒体文件的持续时间;
int64_t bit_rate: 比特率,以 bit/s 计算;
uint8_t *buffer: 用于暂存数据的缓冲区;
int buffer_size: 缓冲区的大小。

avformat_free_context();释放该结构里的所有东西以及该 结构本身

#include <libavformat/avformat.h>/*** Free an AVFormatContext and all its streams.* @param s context to free*/
void avformat_free_context(AVFormatContext *s);

avformat_open_input();打开输入视频文件

在avformat_alloc_context()方法中,我们申请了一个avformatcontext,这个context中现在只有框架,没有实际的内容。
/*** Open an input stream and read the header. The codecs are not opened.* The stream must be closed with avformat_close_input().** @param ps       Pointer to user-supplied AVFormatContext (allocated by*                 avformat_alloc_context). May be a pointer to NULL, in*                 which case an AVFormatContext is allocated by this*                 function and written into ps.*                 Note that a user-supplied AVFormatContext will be freed*                 on failure.* @param url      URL of the stream to open.* @param fmt      If non-NULL, this parameter forces a specific input format.*                 Otherwise the format is autodetected.* @param options  A dictionary filled with AVFormatContext and demuxer-private*                 options.*                 On return this parameter will be destroyed and replaced with*                 a dict containing options that were not found. May be NULL.** @return 0 on success, a negative AVERROR on failure.** @note If you want to use custom IO, preallocate the format context and set its pb field.*/
int avformat_open_input(AVFormatContext **ps, const char *url,const AVInputFormat *fmt, AVDictionary **options);

avformat_close_input(); 关闭解复用器。关闭后就不再需要 使用avformat_free_context 进行释放。
avformat_find_stream_info() :获取 音视频 文件信息
av_read_frame(); 读取 音视频 ,这里更加合理的命令应该是av_read_packet();因为这里读取的并不是yuv或者pcm的frame数据,而是打包了的h264或者aac数据,是一包数据,但是由于ffmpeg历史原因,这里一直是av_read_frame();
avformat_seek_file(); 定位文件
av_seek_frame(): 定位文件

八 FFmpeg解码函数简介-解码器相关

avcodec_alloc_context3(): 分配解码器上下文
avcodec_find_decoder(): 根据ID查找解码器
avcodec_find_decoder_by_name(): 根据解码器名字
avcodec_open2(): 打开 码器
avcodec_decode_video2(): 解码一帧视频数据
avcodec_decode_audio4(): 解码一帧音频数据
avcodec_send_packet(): 发送编码数据包
avcodec_receive_frame(): 接收解码后数据
avcodec_free_context(): 释放解码器上下文,包含了 avcodec_close()
avcodec_close(): 关闭解码器

相关文章:

音视频开发9 FFmpeg 解复用框架--如何将一个影音文件(mp4文件/wav文件) 最终播放起来

一&#xff0c;播放器框架 二 常用音视频术语 容器&#xff0f;文件&#xff08;Conainer/File&#xff09;&#xff1a; 即特定格式的多媒体文件&#xff0c; 比如mp4、flv、mkv等。 媒体流&#xff08;Stream&#xff09;&#xff1a; 表示时间轴上的一段连续数据&#xff0…...

vue实现页面渲染时候执行某需求

1. 前言 在之前的项目中&#xff0c;需要实现一个监控token是否过期从而动态刷新token的功能&#xff0c;然而在登录成功后创建的监控器会在浏览器刷新点击或者是通过导航栏输入网址时销毁... 2. 试错 前前后后始过很多方法&#xff0c;在这里就记录一下也许也能为各位读者排…...

Python小游戏——俄罗斯方块

文章目录 项目介绍环境配置代码设计思路1.初始化和导入库&#xff1a;2.定义颜色和屏幕尺寸&#xff1a;3.定义游戏逻辑&#xff1a;4.游戏循环&#xff1a; 源代码效果图 项目介绍 俄罗斯方块游戏是一款经典的益智游戏&#xff0c;玩家通过旋转和移动各种形状的方块&#xff…...

Moto和Inter字节序

inter: 低地址按照start_bit位放低字节依次往高字节填充 MotoLsb: 低地址按照start_bit位放高字节&#xff0c;依次往低字节填充MotoMsb&#xff1a;高字节按照start_bit位放低地址&#xff0c;依次往高字节填充...

外汇天眼:野村证券和Laser Digital与GMO互联网集团合作发行日元和美元稳定币

野村控股和Laser Digital将与GMO互联网集团合作&#xff0c;在日本探索发行日元和美元稳定币。GMO互联网集团的美国子公司GMO-Z.com Trust Company, Inc. 在纽约州金融服务部的监管框架下&#xff0c;在以太坊、恒星币和Solana等主要区块链上发行稳定币。GMO-Z.com Trust Compa…...

Python怎么使用getattr?

getattr() 是 Python 的内置函数&#xff0c;用于获取对象的属性值。它接受三个参数&#xff1a;对象、属性名称以及一个可选的默认值。如果对象具有指定的属性&#xff0c;getattr() 会返回该属性的值&#xff1b;如果对象没有该属性&#xff0c;并且提供了默认值&#xff0c;…...

[算法] 优先算法(三):滑动窗口(上)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …...

[蓝桥杯 2020 省 A1] 超级胶水

一.题目 题目描述 小明有 n 颗石子&#xff0c;按顺序摆成一排。 他准备用胶水将这些石子粘在一起。 每颗石子有自己的重量&#xff0c;如果将两颗石子粘在一起&#xff0c;将合并成一颗新的石子&#xff0c;重量是这两颗石子的重量之和。 为了保证石子粘贴牢固&#xff0…...

读书笔记分享

1.苏格拉底只在需要的时候才索取&#xff0c;那样便能以最少的物质满足自身的要求。他认为每个人都天生体质脆弱&#xff0c;只有在贫乏的环境中才会锻炼地强壮起来。生活中的大多数人认为&#xff0c;奢华才是幸福的生活。无休止的物质积聚&#xff0c;让人们每天生活在一个内…...

考试宝典——软件过程与管理重点知识总结

概论 软件工程三要素 过程方法工具 软件过程的定义 软件过程是用于软件开发及维护的一系列活动、方法及实践。 常见软件过程分类&#xff08;五大类&#xff09; 客户-供应商过程&#xff1a;内部直接影响到客户、外部直接影响开发、向客户交付软件以及软件正确操作与使用的过…...

穿越时空的工厂之旅:探索可视化三维场景的奥秘

在科技日新月异的今天&#xff0c;我们似乎总是在不断追求着更加高效、智能的生产方式。 传统的工厂管理方式往往依赖于平面图纸、纸质文档和现场巡查&#xff0c;这不仅效率低下&#xff0c;而且容易出错。而三维可视化技术通过3D建模和虚拟现实技术&#xff0c;将工厂内部的各…...

2024年推荐的适合电脑和手机操作的线上兼职副业平台

总是会有人在找寻着线上兼职副业&#xff0c;那么在如今的2024年&#xff0c;互联网提供了诸多方便&#xff0c;无论你是宝妈、大学生、程序员、外卖小哥还是打工族&#xff0c;如果你正在寻找副业机会&#xff0c;那么这篇文章将为你提供一些适合电脑和手机操作的线上兼职副业…...

传感器的静态特性

传感器的静态特性是指传感器在稳态&#xff08;输入量为常量或变化极慢时&#xff09;输入信号作用下&#xff0c;传感器输出与输入信号之间的关系。这种关系一般用曲线、数学表达式或表格来表示。传感器的静态特性是传感器的基本特性之一&#xff0c;其描述了传感器在不考虑迟…...

如果jupyter notebook不能实现网页自动跳转,参考下面的链接

一招搞定Jupyter-notebook命令行打开之后不能自动跳转浏览器_一招搞定jupter notebook命令行打开之后-CSDN博客...

顺序表实现通讯录项目

目录 一.实现功能&#xff1a; 二.文件结构 三.代码实现 1.初始化 2.通讯录的销毁 3.通讯录添加数据 4.通讯录删除数据 5.通讯录的修改 6.展现通讯录数据 7.通讯录查找 四.代码 SeqList.h Contact.h Contact.c test(通讯录).c 一.实现功能&#xff1a; ⾄少能够存…...

【ai】pycharm设置软件仓库编译运行基于langchain的chatpdf

联想笔记本 y9000p创建python工程: 使用langchain支持openai的向量化embedding安装软件包 发现没有openai ,添加软件仓库打开工具窗口 点击设置...

LeetCode:279.完全平方数

class Solution:def numSquares(self, n: int) -> int:dp[i for i in range(n1)]for i in range(2,n1):for j in range(1,int(i**(0.5))1):dp[i]min(dp[i],dp[i-j*j]1)return dp[-1]代码解释 初始化 DP 数组&#xff1a; dp [i for i in range(n1)] 这里&#xff0c;dp[i]…...

Python面试宝典:Python中与ORM技术(对象关系映射)相关的面试笔试题(1000加面试笔试题助你轻松捕获大厂Offer)

Python面试宝典:1000加python面试题助你轻松捕获大厂Offer【第二部分:Python高级特性:第十五章:数据库编程:第二节:ORM技术】 第十五章:数据库编程第二节:ORM技术SQLAlchemyDjango ORMORM技术的优势和劣势python中与ORM技术相关的面试笔试题面试题1面试题2面试题3面试题…...

VUE3+TS+elementplus创建table,纯前端的table

一、前言 开始学习前端&#xff0c;直接从VUE3开始&#xff0c;从简单的创建表格开始。因为自己不是专业的程序员&#xff0c;编程主要是为了辅助自己的工作&#xff0c;提高工作效率&#xff0c;VUE的基础知识并不牢固&#xff0c;主要是为了快速上手&#xff0c;能够做出一些…...

UE驻网失败问题(二)

另一个UE注册失败的问题&#xff0c;具体过程如下&#xff1a; 问题现象如上&#xff0c;UE在这个N48上的小区一直在重复上述过程&#xff0c;收到RRC Setup后就不发RRC Setupcomplete&#xff0c;闭上眼睛也知道大概率是这个RRC Setup的配置有问题。 在问题时间点周围查看&…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

Python学习(8) ----- Python的类与对象

Python 中的类&#xff08;Class&#xff09;与对象&#xff08;Object&#xff09;是面向对象编程&#xff08;OOP&#xff09;的核心。我们可以通过“类是模板&#xff0c;对象是实例”来理解它们的关系。 &#x1f9f1; 一句话理解&#xff1a; 类就像“图纸”&#xff0c;对…...