音视频开发9 FFmpeg 解复用框架说明,重要API说明

一,播放器框架

二 常用音视频术语

容器/文件(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_close_input();关闭解复用器。关闭后就不再需要 使用avformat_free_context 进行释放。

/**
 * Close an opened input AVFormatContext. Free it and all its contents
 * and set *s to NULL.
 */
void avformat_close_input(AVFormatContext **s);

avformat_open_input();打开媒体文件并获取媒体文件信息的函数

在前面,调用 avformat_alloc_context()方法中,我们申请了一个avformatcontext,这个context中现在只有框架,没有实际的内容。
avformat_open_input 方法的目的就是打开一个媒体文件,并将媒体文件信息,都存储在这个avformatcontext 中,
在打开这个文件的时候,我们当然要指定存储到那个 avformatcontext中,因此有了第一个参数,也是由于要给这个avformatcontext存储值,在c语言的语法中,第一个参数就是传递指针 ,又因为avformat_alloc_context 返回的本来就是一个 avformatcontext *,因此第一个参数就是 avformatcontext**
第二个参数是要打开的音影文件,或者媒体文件的URL。
第三个参数是可以指定该文件 用什么具体的 媒体文件输入格式 (AVInputFormat )来解析,一般设置为NULL,设置为NULL的意思是,根据文件的扩展名 自动 选择输入格式
如果我们自己填写了这个参数,那么这个参数会对  avformatcontext 中 的 iformat起作用。参见 结构体  avformatcontext  中的说明
    /**
     * The input container format.
     *
     * Demuxing only, set by avformat_open_input().
     */
    const struct AVInputFormat *iformat;
第四个参数:todo,这个怎么理解,有啥用?
avformat_open_input() 函数是用于打开媒体文件并获取媒体文件信息的函数,该函数定义在libavformat/avformat.h中。


该函数的参数含义如下:

ps:AVFormatContext结构体的指针。该参数用于存储打开的媒体文件的信息。当该函数成功返回时,AVFormatContext结构体中将存储媒体文件的相关信息。
url:要打开的媒体文件的URL。可以是本地文件路径,也可以是HTTP URL或其他协议的URL。
fmt:AVInputFormat结构体的指针,用于指定媒体文件的格式。如果该参数为NULL,则根据文件扩展名自动选择输入格式。
options:AVDictionary结构体的指针,用于传递打开媒体文件时的选项。



/**
 * 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_find_stream_info():获取音视频文件信息

当我们打开一个文件后,就应该将这个文件

avformat_find_stream_info()函数是用于获取媒体文件中每个音视频流的详细信息的函数,包括解码器类型、采样率、声道数、码率、关键帧等信息。该函数定义在libavformat/avformat.h中。
函数原型为:

int avformat_find_stream_info(AVFormatContext *fmt_ctx, AVDictionary **options);

该函数的参数含义如下:

fmt_ctx:AVFormatContext结构体指针,表示媒体文件的格式上下文,其中包含已经打开的媒体文件的信息和媒体文件中每个音视频流的信息。
options:AVDictionary结构体指针,用于传递选项。目前已经不使用,传NULL即可。

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(): 关闭解码器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/652546.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据整理的Compact流程 (二)|OceanBase数据转储合并技术解读(二)

上篇文章《数据整理的Compact流程 &#xff08;一&#xff09;&#xff5c;OceanBase数据转储合并技术解读&#xff08;二&#xff09;》中&#xff0c;有讲解到&#xff0c;在OceanBase数据库中&#xff0c;当MemTable写满时&#xff0c;将其下刷到Mini SSTable的过程包含两个…

「小明赠书活动」第四期《Java开发坑点解析:从根因分析到最佳实践》

目录 ⭐️ 赠书 - 《Java开发坑点解析&#xff1a;从根因分析到最佳实践》 参 加 活 动 方 式 见 文 末 ⭐️内容简介 -《Java开发坑点解析&#xff1a;从根因分析到最佳实践》 ⭐️阅读建议 -《Java开发坑点解析&#xff1a;从根因分析到最佳实践》 ⭐️《Java开发坑…

CSS 介绍及用法,常用属性

一、CSS介绍 A. 简介 CSS全称&#xff1a;全称为层叠样式表&#xff08;Cascading Style Sheets&#xff09;&#xff0c;是一种用于描述网页外观和格式的计算机语言。CSS可以使网页的布局更加丰富和多样化&#xff0c;并且可以将样式信息与网页内容分离&#xff0c;使得网…

C语言——基于stm32G030的温湿度传感器项目实验

一、功能要求&#xff1a; 设备自检功能&#xff1a; 设备上电自检&#xff08;检查传感器采集是否正常&#xff0c; DHT11有存在响应&#xff0c; 可以自检使用&#xff0c; &#xff09;自检通过后&#xff0c;由串口打印设备状态信息。 自动控制功能&#xff1a; 进入自动控…

python连接FTP服务器:[WinError 10054] 远程主机强迫关闭了一个现有连接

一、原始报错信息 pythonProcess finished with exit code -1073740791 (0xC0000409) 这个报错信息&#xff0c;太过于笼统&#xff0c;是分析不出代码出了什么问题的。 二、打印详细报错信息 在服务器相关可能报错的地方&#xff0c;进行报错信息追踪&#xff1a; import …

如何在OrangePi AIpro智能小车上实现安全强化学习算法

随着人工智能和智能移动机器人的广泛应用&#xff0c;智能机器人的安全性和高效性问题受到了广泛关注。在实际应用中&#xff0c;智能小车需要在复杂的环境中自主导航和决策&#xff0c;这对算法的安全性和可靠性提出了很高的要求。传统的强化学习算法在处理安全约束时存在一定…

SpringBoot搭建OAuth2

背景 前几天自己从零开始的搭建了CAS 服务器&#xff0c;结果差强人意&#xff08;反正是成功了&#xff09;。这几天&#xff0c;我躁动的心又开始压抑不住了&#xff0c;没错&#xff0c;我盯上OAuth2了&#xff0c;大佬们都说OAuth2比CAS牛批&#xff0c;我就想知道它有多牛…

Elasticsearch不删原有jdk8导致的系列安装和启动问题

以前在空机器直接装elasticsearch&#xff0c;没有遇到什么问题。今天在现有JDK上安装&#xff0c;遇到的问题记录一下&#xff1a; 1. JDK的环境变量配置与我原有的不一致报如下错误&#xff1a; [estestZK-DES-I root]$ /usr/elasticsearch/bin/elasticsearch could not fi…

SSL函数01-数组函数Array Functions

一、数组的初始化 SSL中&#xff0c;数组下标从1开始&#xff01; 1-1、不知道数组的长度 :DECLARE a6; a6 : {}; Aadd(a6,a); Aadd(a6,b); Aadd(a6,c); 当用a : {}创建一个数组的时候&#xff0c;不可以用a[1] 值&#xff0c;来赋值&#xff01; 1-2、知道数组的长度 方式一…

【录用案例】2天录用!提交可录,沾边即可!

本周投稿推荐 SSCI • 2区社科类&#xff0c;3.0-4.0&#xff08;录用友好&#xff09; EI • 计算机工程生物医学等&#xff08;2天录用&#xff09; CNKI • 3天内初审录用&#xff0c;随即出版&#xff08;急录友好&#xff09; SCI&EI • 4区生物医学类&#x…

数据链路层 + NAT技术

数据链路层&#xff1a;负责设备之间的数据帧的传送和识别。 一、以太网 以太网的帧格式 如何分离报头和有效数据&#xff1f; 报头是固定长度的 如何将数据交给上层协议&#xff1f; 通过类型&#xff0c;如果是0800&#xff0c;则交给IP协议&#xff0c;如果是0806&#xf…

JavaScript正则表达式

一、介绍 正则表达式是用于匹配字符串中字符组合的模式。在javascript中&#xff0c;正则表达式也是对象。通常用来查找、替换那些符合正则表达式的文本&#xff0c;许多语言都支持正则表达式。 正则表达式的作用&#xff1a; 表单验证&#xff08;匹配&#xff09;、过滤敏感…

筛斗数据提取:解锁信息宝藏的关键步骤

在数字化时代&#xff0c;数据已成为推动社会进步和企业发展的关键要素。然而&#xff0c;数据本身并不直接产生价值&#xff0c;其价值在于我们如何从中提取有用的信息。数据提取&#xff0c;作为解锁信息宝藏的关键步骤&#xff0c;对于任何希望从海量数据中获取洞察力和竞争…

十四天学会Vue——Vue核心(理论+实战)上篇(第一天)

一、Vue核心&#xff08;上篇&#xff09; 热身tops&#xff1a;选取开发模式 ①用于开发模式 我们只需要知道 我们是开发模式&#xff0c;开发模式他会跟你提示代码出现错误的地方以及出错原因&#xff0c;而生产模式比较简洁。 ②用于生产模式 1.1 new Vue()实例 了解Vue&a…

人脸识别——筛选与删除重复或近似重复数据提高人脸识别的精确度

1. 概述 人脸识别研究通常使用从网上收集的人脸图像数据集&#xff0c;但这些数据集可能包含重复的人脸图像。为了解决这个问题&#xff0c;我们需要一种方法来检测人脸图像数据集中的重复图像&#xff0c;并提高其质量。本文介绍了一种检测人脸图像数据集中重复图像的方法。该…

有趣的css - 双开门按钮

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是一个双开门的按钮&#xff0c;交互效果比较强&#xff0c;但是实现很简单&#xff0c;快学起来吧。 最新文章通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html 代码cs…

充电宝哪家好用推荐?买什么充电宝性价比高?2024年充电宝排行榜

说实话&#xff0c;我其实是个手机重度使用者&#xff0c;买过的充电宝也有无数款了&#xff0c;每次手机没电的时候插座都离得不是特别近&#xff0c;不是要下床充电就是要固定在一个位置充电感觉怪麻烦的&#xff0c;但是有了充电宝后可以在床上玩手机都不用担心手机没电&…

惯性测量单元M-G366PDG提供低误差系数的解决方案

人形机器人、自动驾驶的快速发展&#xff0c;促成了惯性测量单元(IMU)的爆火市场。据相关研究报告统计&#xff0c;IMU全球市场规模从2018年的99.94亿美元增加至2021年的135.95亿美元预计2027年将达到222.53亿美元&#xff0c;2021年至2027年复合增长率达8.56%。而由于智能技术…

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

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

免费,Python蓝桥杯等级考试真题--第13级(含答案解析和代码)

Python蓝桥杯等级考试真题–第13级 一、 选择题 答案&#xff1a;C 解析&#xff1a;正向下标由0开始&#xff0c;下标3代表第四个元素&#xff0c;故答案为C。 答案&#xff1a;A 解析&#xff1a;range&#xff08;0,4&#xff09;的取前不取后&#xff0c;元组的符号是小括…