H.264原始码流(又称为“裸流”)是由一个一个的NALU组成的。他们的结构如下图所示。
|NALU|NALU|NALU|....
其中每个NALU之间通过startcode(起始码)进行分隔,起始码分成两种:0x000001(3Byte)或者0x00000001(4Byte)。如果NALU对应的Slice为一帧的开始就用0x00000001,否则就用0x000001。 H.264码流解析的步骤就是首先从码流中搜索0x000001和0x00000001,分离出NALU;然后再分析NALU的各个字段。本文的程序即实现了上述的两个步骤。
H264附录B指明一种简单高效的方案解决解码器分辨每个NAL的起始位置和终止位置-当数据流存储在介质中时,在每个NAL前添加:0x000001
在某些类型的存储介质中,为了寻址方便,要求数据流在长度上对齐,或必须是某个常数的倍数。考虑到这种情况,H264建议在起始码前添加若干字节的0来填充,直到该NAL的长度符合要求。
在这样的机制下,解码器在码流中检测起始码,作为一个NAL的起始标志,当检测到下一个起始码时当前NAL结束。H264规定当检测到0x000000时也可以表征当前NAL的结束,这是因为连着的3个字节的0中任何一个字节的0要么属于起始码,要么是起始码前面的0。
但是如果NAL内部出现了0x000001或0x000000的序列怎么办?解决办法如下:
0x000000------------->0x00000300
0x000001-------------->0x00000301
0x000002-------------->0x00000302
0x000003-------------->0x00000303
就是在0000后面加上03;
有人问:如果原序列中本来就有个0x00000303呢?会不会导致歧义?
答案肯定是不会的,假设原序列:0x00 00 03 03 ....
那么经过转换之后变成: 0x00 00 03 03 03.....
解码之后:0x00 00 03 03
解码之后的数据和原序列一样。所以不用担心产生歧义。 移除H264的NAL防竞争码(0x03)
Network Abstraction Layer,视频数据网络抽样层。
VIdeo Coding Layer, 视频数据编码层。
原始数据比特流,长度不一定是8的倍数,故需要补齐。它是由VCL层产生的。
SODB+trailing bits
算法是如果SODB最后一个字节不对齐,则补1和多个0.
NAL Header(1byte) + RBSP
1、SPS/PPS/Slice Header
2、 常见分析工具
3、 ffmpeg视频编码
对视频压缩特性的描述,Profile越高,就说明采用了越高级的压缩特性
Level是对视频的描述,Level越高,视频的码率、分辨率、fps越高
pic_width_in_mbs_minues1 | 图像宽度包括的宏块个数-1 |
pic_heigh_in_mbs_minus1 | 图像高度包括的宏块个数-1 |
frame_mbs_only_flag | 帧编码还是场编码 (场是隔行扫描、产生两张图) |
frame_cropping_flag | 图像算法需要裁剪 |
frame_crop_left_offset | 减去左侧的偏移量 |
frame_crop_right_offset | 减去右侧的偏移量 |
frame_crop_top_offset | 减去顶部的偏移量 |
frame_crop_bottom_offset | 减去底部的偏移量 |
解码设置缓冲区大小的
解码
framerate = (float)(sps->vui.vui_time_scale)/(float)(sps->vui.vui_num_units_in_tick)/2;
entropy_coding_mode_flag | 熵编码,1表示使用CABAC编码 |
num_slice_groups_minus1 | 分片数量 |
weighted_pred_flag | 在P/SP Slice中开启权重预测 |
weighted_bipred_idc | 在B Slice中加权预测的方法 |
pic_init_qp_minus26/pic_init_qs_minus26 | 初始化量参数,实际参数在Slice header |
chroma_qp_index_offset | 用于计算色度分量的量化参数 |
deblocking_filter_control_present_flag | 表示Slice header中是否存在用于去块滤波器控制的信息 |
constrainged_intra_pred_flag | 若该标识为1,表示I宏块在进行帧内预测时只能使用来自I和SI类型宏块的信息 |
redundant_pic_cnt_preset_flag | 用于表示Slice Header中是否存在redundant_pic_cnt语法元素 |
工具
Elecard Stream Eye
CodecVisa
40 * 16 = 640