一,播放器框架
二 常用音视频术语
容器/文件(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(): 关闭解码器