1.视频编码原理
2.FFMpeg编码接口和AVPacket结构体详解
2.1ffmpeg编码接口 -编码器+上下文
2.2AVPacket结构体
2.3AVFrame结构体
3.视频播放最简单demo
3.1FFMpeg编码器获取和上下文打开
3.2视频帧创建和测试
1.视频编码原理
1.1 流程:像素格式转换->编码->封装
1.2为什么要编码:像素格式数据过大
采集高速数据,内存:128G内存
硬盘来不及存储:SSD :1s,3G ;PCIE接口 1s,500MB
1.3原始帧AVFrame->压缩帧AVPacket
AVFrame数据大:1s 1G的数据,性能性问题,不能复制。
AVPacket数据小:1080p:1s 1MB 结构清晰
1.4帧内压缩、帧间压缩
图片压缩:bmp->jpg 压缩 找相似点,大小变化不大
视频压缩:视频:保存差异
帧内压缩:只跟关键帧相关
1.5有损压缩、无损压缩
有损压缩:类似数据丢掉 解压后无法与原文件相同。
无损压缩:zip,rar,7z
2.FFMpeg编码接口和AVPacket结构体详解
2.1ffmpeg编码接口 -编码器+上下文

2.2AVPacket结构体
2.3AVFrame结构体

3.视频播放最简单demo
cpp
int main113()
{
// auto codec; 编码器
// auto c; 上下文
// auto frame; 对象+缓冲 编码前
// auto pkt; 对象+缓冲 编码后
// 编码器+上下文
//1.查找+分配空间
auto codec = avcodec_find_encoder(AV_CODEC_ID_H264); //对象返回的是指针
if (!codec) { return -1; }
auto c = avcodec_alloc_context3(codec);
//2.上下文 参数设置 视频宽、高、帧时间、元数据像素格式、编码线程数
c->width = 400;
c->height = 300;
c->time_base = { 1,25 };
c->pix_fmt = AV_PIX_FMT_YUV420P;
c->thread_count = 16;
//3.编码器 参数设置 b帧为0,
c->max_b_frames = 0;
int opt_re = av_opt_set(c->priv_data,"preset","ultrafast",0);//最快速度
opt_re = av_opt_set(c->priv_data,"tune","zerolatency",0); //零延时
//4.打开上下文 返回值==0 OK
int re = avcodec_open2(c, codec, NULL); // 返回值 "打开"!=0表示正确
if (re != 0) { return -1; }
//5.AVFrame -赋值-编码(压缩数据AVPAckage)-写入文件
//5.1AVFrame 创建对象+缓冲(),
//5.11AVFrame设置参数 宽、高、像素格式
auto frame=av_frame_alloc();
frame->width = 400;
frame->height = 300;
frame->format = c->pix_fmt;
int re = av_frame_get_buffer(frame,0); // 返回值 创建"缓冲区"!=0表示错误
if (re != 0) { return -1; }
//5.12 AVPacket 创建对象
auto pkt = av_packet_alloc();
//5.13
string filename;
filename = "400_300_25_preset.h265";
ofstream ofs;
ofs.open(filename, ios::binary); //返回值 ofs ofs.open !表示错误
if (!ofs)
{
cerr << "open " << filename<<" failed!" << endl;
return -1;
}
//ofs.write((char*)pkt->data, pkt->size);
//ofs.close();
/*编码
re=avcodec_send_frame(c,frame);
while (re >= 0)
{
re=avcodec_receive_packet(c,pkt);
if (re < 0) { break; }
ofs.write((char*)pkt->data, pkt->size);
av_packet_unref(pkt);
}*/
for (int i = 0; i < 250; i++)
{
for (int y = 0; y < frame->height;y++)//Y
{
for (int x = 0; x < frame->width; x++)
{
frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
}
}
for (int y = 0; y < frame->height / 2; y++)//UV
{
for (int x = 0; x < frame->width / 2; x++)
{
frame->data[1][y*frame->linesize[1]+x]= 128+x + y + i * 3;
frame->data[2][y*frame->linesize[2]+x]=64+ x + y + i * 3;
}
}
frame->pts = i;
re=avcodec_send_frame(c, frame); //返回值 !=0 表示错误
if (re != 0){ break;}
while (re >= 0)
{
re=avcodec_receive_packet(c, pkt); //返回值
if (re < 0) { break; }
av_packet_unref(pkt);
}
}
ofs.close();
//5.释放对象 AVFrame AVPAckage 编码器上下文
av_packet_free(&pkt);
av_frame_free(&frame);
avcodec_free_context(&c);
return 0;
}