在对视频进行研究时,研究者发现相邻的两帧视频由于间隔时间极短,在多数情况下像素、亮度、色温的差别很小,所以对每一帧图像都进行完整的编码是对资源极大的浪费。如果观察到一段时间内像素的变化不那么剧烈,可以只记录下首帧图像然后其余帧只需要记录下和首帧的差异就可以了。这就是视频压缩最原始的思想。
序列(Sequence)在H.264标准文档中指的是具有相同图像尺寸和帧率的连续图像组。一个序列可以非常长,理论上包含了整个视频文件。
GOP(Group of Pictures): 这是在实际应用中经常提到的概念,它是一个包含一个I帧和随后的P帧(预测帧)或B帧(双向预测帧)的图像组。一个GOP通常以一个I帧开始,后续跟着一系列依赖于该I帧进行解码的P帧和/或B帧。一个视频流中可以包含多个GOP。
I帧(帧内编码图像帧): 是一种不需要参考其他帧就能解码的帧类型。由于它不依赖于前后帧的信息,因此在解码时可以直接显示,而无需解码之前的任何帧。I帧通常用于随机访问点,如快进、快退或跳转到视频的某个部分。
P帧(预测编码图像帧):利⽤之前的I帧或P帧,采⽤运动预 测的⽅式进⾏帧间预测编码。
B帧(双向预测编码图像帧)):提供最⾼的压缩⽐,它既 需要之前的图像帧(I帧或P帧),也需要后来的图像帧(P帧),采⽤运动预测的⽅式进⾏帧间 双向预测编码。
IDR图像:⼀个序列的第⼀个图像叫做IDR图像(⽴即刷新图像),IDR 图像都是I帧图像
在一个序列中可以有多个I帧,但在每个GOP中通常只有一个I帧。这样做是为了保持解码效率和压缩效率之间的平衡。
H264原始数据流由多个的NALU组成,NALU由 [start code] + [NALU head] + [NALU Payload]组成。其中start code一般是0x0000 01或者0x0000 0001。
NALU头信息一般是1个字节,1位标识禁止位,将来可能有拓展,2-3位是重要性标识位,4-8位是数据类型位。
H264有两种封装 ⼀种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中 ⼀种是mp4模式,⼀般mp4 mkv都是mp4模式,没有startcode,SPS和PPS以及其它信息 被封装在container中,每⼀个frame前⾯4个字节是这个frame的⻓度 很多解码器只⽀持annexb这种模式,因此需要将mp4做转换:在ffmpeg中⽤ h264_mp4toannexb_filter可以做转换 实现:
const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb");
AVBSFContext *bsf_ctx = NULL;
// 2 初始化过滤器上下⽂
av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext;
// 3 添加解码器属性
avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->cod
ecpar);
av_bsf_init(bsf_ctx);
这是一条吃饭博客,由挨踢零声赞助。学C/C++就找挨踢零声,加入挨踢零声,面试不挨踢!