H264编码NALU结构介绍与I帧判断
在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。因此我们平时的每帧数据就是一个NAL单元(SPS与PPS除外)。在实际的H264数据帧中,往往帧前面带有00 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为I帧。
H264关键帧就是I frame。
最简单的办法是找0x65或0x25(I frame启始位),或者去找0x67或0x27(SPS)和0x68或0x28(PPS)后面的完整包。
SPS和PPS后面必然跟着I frame。
帧是组成视频图像的基本单位。关键帧也叫I帧,它是帧间压缩编码里的重要帧;它是一个全帧压缩的编码帧;解码时仅用I帧的数据就可重构完整图像;I帧不需要参考其他画面而生成。视频文件是由多个连续的图片组成。
H264 NALU固定以 0x00 00 00 01为起始,NALU_data部分不会出现这个起始码;在找到下一个起始码之前,当前NALU数据长度不知(参考);
H264 NALU: 00 00 00 01(4字节) | NALU type(1字节) | NALU_data (N字节) | 0x00 00 00 01 |
---|---|---|---|
起始码(4字节) | 类型 | 数据 | 下一个NALU |
NALU_type 1字节,定义为:
1比特 禁止位 | 2比特 重要性指示位 | 5比特 类型 |
---|---|---|
固定为0 | 11 | 1-12 由h264使用 |
常用Nalu_type:
0x67 (0 11 00111) SPS 非常重要 type = 7
0x68 (0 11 01000) PPS 非常重要 type = 8
0x65 (0 11 00101) IDR帧 关键帧 非常重要 type = 5
0x61 (0 11 00001) I帧 重要 type=1 非IDR的I帧 不大常见
0x41 (0 10 00001) P帧 重要 type = 1
0x01 (0 00 00001) B帧 不重要 type = 1
0x06 (0 00 00110) SEI 不重要 type = 6
h264视频数据一帧的起始一般为00 00 00 01(视频首帧)和00 00 01(首帧之外每一帧),然后接下来的一位则表示帧类型,具体判断如下(参考):
/**
* 检测是否是关键帧
* @param buffer 编码后的h264视频数据
*/
public static boolean isKeyFrame(@NonNull byte[] buffer) {
if (buffer.length < 5) {
return false;
}
//00 00 00 01
if (buffer[0] == 0
&& buffer[1] == 0
&& buffer[2] == 0
&& buffer[3] == 1) {
int nalType = buffer[4] & 0x1f;
if (nalType == 0x07 || nalType == 0x05 || nalType == 0x08) {
return true;
}
}
//00 00 01
if (buffer[0] == 0
&& buffer[1] == 0
&& buffer[2] == 1) {
int nalType = buffer[3] & 0x1f;
if (nalType == 0x07 || nalType == 0x05 || nalType == 0x08) {
return true;
}
}
return false;
}
引用文章:
https://blog.csdn.net/weixin_43194037/article/details/103386950
https://blog.csdn.net/u012758497/article/details/113549613
https://blog.csdn.net/dreamxiang68/article/details/7410423
https://blog.csdn.net/bootleader/article/details/122869026