AVStream、AVFormatContext
AVStream
AVStream 是 FFmpeg 中用于表示媒体文件中每个流(如视频流、音频流、字幕流等)的数据结构。每个媒体文件通常包含一个或多个流,例如一个视频文件可能包含一个视频流和一个音频流。
AVFormatContext
AVFormatContext 是 FFmpeg 库中的一个核心数据结构,用于表示一个多媒体文件或流的上下文。它包含了文件或流的全局信息以及其中的各个流(如视频流、音频流、字幕流等)的详细信息。这个结构体在处理多媒体文件的过程中起着至关重要的作用,几乎所有与多媒体文件相关的操作都依赖于它。
AVFormatContext 的主要作用
AVFormatContext 是处理多媒体文件的中心,它负责:
管理文件的全局信息:包括文件的格式、持续时间、比特率等。
管理文件中的各个流:如视频流、音频流、字幕流等,每个流的信息都保存在 AVStream 结构中,AVFormatContext 通过一个流数组(streams)来管理这些流。
与多媒体文件的 I/O 操作相关:它包含文件的输入输出上下文,可以通过它来打开、读取、写入文件。
与编解码器交互:它存储了与 ...
AVCodec、AVCodecContext
AVCodec
AVCodec 是 FFmpeg 中用于表示一个编解码器(encoder 或 decoder)的结构体。编解码器是用于对音频、视频、字幕等媒体数据进行编码或解码的核心组件。AVCodec 结构体包含了编解码器的基本信息和功能指针,FFmpeg 通过这个结构体来管理和操作各种编解码器。
AVCodec 结构体的基本介绍
用途:AVCodec 结构体用于描述 FFmpeg 支持的每一个编解码器(如 H.264 解码器、MP3 编码器等)。它既可以表示一个解码器,也可以表示一个编码器。
位置:AVCodec 结构体定义在 libavcodec/avcodec.h 头文件中。
如何使用 AVCodec
AVCodec 结构体通常不会直接使用,而是与 AVCodecContext 一起配合使用。下面是一个简单的使用流程:
查找编解码器:
使用 avcodec_find_decoder() 或 avcodec_find_encoder() 函数查找你需要的编解码器,并获取相应的 AVCodec 指针。
12345AVCodec *codec = avcodec_find ...
ffmpeg库进行解码
代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119/* 这段代码的作用是使用 FFmpeg 库解码 H.264 视频文件。 它读取 H.264 编码的视频文件 test.h264,将数据分割成帧,并将每一帧数据传递给解码器,解码后输出帧格式。*/#include <iostream>#include <fstream>#include <cstring>using namespace std;extern "C" { // 指定函数是C语言函数,函数名不包含重载标注 // ...
编码压缩(I、P、B帧,GOP)
视频为什么需要进行编码压缩
一张为$720\times 480$的图像,用YUV420P的格式来表示,其大小为:$720\times 480\times 1.5$约等于$0.5$MB
如果是$25$帧,$10$分钟的数据量$0.5M\times 10 \times 60\times 25=7500MB \rightarrow 7G$多
视频编码压缩的目的就是降低视频数据大小,方便存储和传输。
图像帧的类型
I帧、P帧和B帧是视频压缩领域中的基础概念,用于提升视频压缩效率、视频质量和视频恢复能力。
I帧能够独立解码,P帧、B帧需要依赖I帧进行解码,如果I帧出现数据丢失,解码就会出现马赛克。
I帧(关键帧)仅由帧内预测的宏块组成。
P帧代表预测帧,除帧内空域预测以外,它还可以通过时域预测来进行压缩。P帧通过使用已经编码的帧进行运动估计。
B帧可以参考在其前后出现的帧,B帧中的B代表双向(Bi-Directional)
【帧内空域】:也叫空间冗余:,像相邻像素之间有较强的相关性,比如一帧图像划分成多个 16x16 的块之后,相邻的块很多时候都有比较明显的相似性。
【时域】:时间 ...
ffmpeg库进行编码
“encode” 是指将原始或解码后的媒体数据(如视频帧或音频样本)转换为一种特定的压缩格式或编码格式。
编码过程将未压缩的媒体数据(如原始的 RGB 图像数据或 PCM 音频数据)转换为压缩格式(如 H.264 视频或 AAC 音频),
以便于存储或传输。
这段代码展示了如何使用 FFmpeg 库进行视频编码。
整个过程包括查找编码器、分配和配置编码器上下文、生成未压缩数据帧、编码数据帧、处理编码后的数据包,并将其写入文件。
通过这种方式,可以将未压缩的视频帧转换为压缩的视频格式(如 H.264 或 H.265),以便于存储和传输。
编码生成一段10秒的h.264视频
【效果展示】
代码
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210 ...
YUV、RGBA相互转换
转化前准备
视频、图片格式介绍
12345678910111213141516171819202122232425262728#define YUV_FILE "400_300_25.yuv"#define RGBA_FILE "800_600_25.rgba"// YUVint width = 400, height = 300;// RGBAint rgb_width = 800, rgb_height = 600;unsigned char *yuv[3] = { 0 };int yuv_linesize[3] = { width, width / 2, width / 2 }; // Y、U、V的每行数量yuv[0] = new unsigned char[width * height]; // Y的数量yuv[1] = new unsigned char[width * height / 4]; // U的数量yuv[2] = new unsigned char[width * height ...
IO文件操作
打开文件,Open
123std::ifstream yuv_file;yuv_file.open("400_300_25.yuv", std::ios::binary);
第二个参数_Mode默认值为 ios_base::in,表示以只读模式打开文件。常见的模式包括:
ios_base::in:以输入(读)模式打开文件。
ios_base::out:以输出(写)模式打开文件。
ios_base::binary:以二进制模式打开文件。
ios_base::app:以追加模式打开文件,写入的内容会追加到文件末尾。
ios_base::trunc:如果文件存在,则在打开时将其长度截断为 0(通常与 ios_base::out 一起使用)。
ios_base::ate:在打开文件时定位到文件末尾。
移动文件,seekg
123std::ifstream yuv_file;yuv_file.seekg(0, ios::end);
seekg 是 C++ 标准库中用于操作输入文件流(如 std::ifstream)位置的成员函数。seekg 的功能是将文件流的“读指针”移 ...
控制视频播放速度(使用Sleep函数)
总体思路:在主函数中初始化SDL,读取文件,将数据交给线程Main,在线程Main中,通过while循环,以及用户设置的fps,根据fps的计算,读取数据进入View()函数中进行处理。
主函数
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061SDLQtRGB::SDLQtRGB(QWidget *parent) : QWidget(parent){ ui.setupUi(this); // 打开yuv文件 yuv_file.open("400_300_25.yuv", std::ios::binary); // 拿到文件大小 yuv_file.seekg(0, ios::end); // 移到文件结尾 file_size = yuv_file.tellg(); // 文件指针位置,获取文件大小 yuv_file.seekg(0, ios::beg); ...
AVFrame介绍
AVFrame介绍
AVFrame 是 FFmpeg 库中用于存储音视频数据帧的核心结构体。它在处理视频解码、编码、滤镜以及其他音视频处理任务时非常重要。AVFrame 可以表示原始的未压缩音频或视频数据。
AVFrame 的作用:
视频帧:在处理视频时,AVFrame 用于存储解码后的原始视频帧,每个帧包括像素数据、分辨率、格式、时间戳等信息。
音频帧:在处理音频时,AVFrame 用于存储解码后的原始音频数据,包括音频样本、通道布局、采样率等信息。
AVFrame 的结构:
AVFrame 是一个复杂的结构体,包含了大量与音视频数据相关的字段。以下是一些主要字段的介绍:
数据和缓冲区相关:
AV_NUM_DATA_POINTERS是 FFmpeg 库中的一个宏定义,它定义了用于指向数据平面的指针数组的大小。一般被定义为 8,这意味着数据指针数组 data[AV_NUM_DATA_POINTERS] 可以存储多达 8 个指向不同数据平面的指针。
uint8_t *data[AV_NUM_DATA_POINTERS]:指向存储数据的指针数组。对于视频,data[0] ...
视频、图片格式
YUV格式
YUV:"Y"表示明亮度(Luminance或Luma),也就是灰阶值,"U"和"V"表示的则是色度(Chrominance或Chroma)
为什么压缩数据一般采用YUV格式
与熟知RGB类似,YUV也是一种颜色编码方法,它是指将亮度参量(Y:Luminance或Luma)和色度参量(UV:Chrominance或Chroma)分开进行表示的像素编码格式
这样分开的好处就是不但可以避免相互干扰,没有UV信息一样可以显示完整的图像因而解决了彩色电视与黑白电视的兼容问题;还可以降低色度的采样率而不会对图像质量影响太大,降低了视屏信号传输时对频宽(带宽)的要求。
Y共用一组UV分量
YUV具体格式
YUV444
表示$4:4:4$的YUV取样。
每个像素都有独立的Y、U、V分量。
每一个像素Y占一个字节,U占一个字节,V占一个字节,因此每个像素占:
$$1 (Y)×8 bits+1 (U)×8 bits+1 (V)×8 bits=24 bits/pixel (bpp)$$
以$2\times 2$像素的图像为例
...