FFmpeg中的AVFrame结构体是用于存放音视频的原始数据的
也就是音频的 PCM数据
和视频的 YUV数据或者RGB数据
这里记录一下视频帧数据的存放
通过C++的文件IO来对AVFrame读写, 需要了解AVFrame的成员含义, 以及YUV/RGB数据的存放格式
AVFrame的几个重要的成员:
uint8_t *data[AV_NUM_DATA_POINTERS];
用来存放具体的未压缩的数据 ,如 yuv数据 y就存在 data[0]数组 u就存在data[1]数组 v就粗在data[2]数组
音频原始数据也存在这里面
int linesize[AV_NUM_DATA_POINTERS];
字节对齐
一行数据的大小; 在一个800*600的视频帧中, 如果是rgba格式, 那么一行就是 800x4个字节.
如果是yuv420 linesize[0] 就是数据y一行的大小 linesize[1]就是数据u一行的大小, linesize[2]就是数据v一行的大小
int width ;
int height;
图像的宽高
int format;
像素格式
如何将yuv视频文件的一帧放入AVFrame?
1, 分配AVFrame对象空间
AVFrame* frame = av_frame_alloc();
此时分配的frame中的data并没有空间.
2,设定视频帧的信息
frame->width = 400;
frame->height = 300;
frame->format = AV_PIX_FMT_YUV420P;
设定视频帧的 宽为400, 高为300, 像素格式为YUV420P
3, 如果是YUV420P的格式那么就要设定三个linsize, 因为再AVFrame中yuv是存放在三个数组中的
frame->linesize[0] = 400;
frame->linesize[1] = 150;
frame->linesize[2] = 150;
YUV420P一行的Y就是宽度, 一行的U就是宽度的一半, 一行的V是宽度的一半
4,生成AVFrame中的data空间, 并指定对齐方式
av_frame_get_buffer(frame, 0);
第二个参数是0, 表示默认对齐, 此函数执行成功就生成了 AVFrame中的data的数组
5,读取一帧的视频数据
std::ifstream ifs;
ifs.open("yuv.yuv", std::ios::binary);
ifs.read((char*)frame_->data[0],
400 * 300);
ifs.read((char*)frame_->data[1],
400 * 300 / 4);
ifs.read((char*)frame_->data[2],
400 * 300 / 4);
必须要用二进制模式打开, U和V的数据只有Y的1/4的量
这样一帧数据就存放完成了.