VideoToolbox基本数据结构:
(1)CVPixelBuffer:编码前和解码后的图像数据结构。
(2)CMTime、CMClock和CMTimebase:时间戳相关。时间以64-bit/32-bit的形式出现。
(3)CMBlockBuffer:编码后,结果图像的数据结构。
(4)CMVideoFormatDescription:图像存储方式,编解码器等格式描述。
(5)CMSampleBuffer:存放编解码前后的视频图像的容器数据结构。
1视频压缩知识:
H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:
帧内预测压缩,解决的是空域数据冗余问题。
帧间预测压缩(运动估计与补偿),解决的是时域数据冗徐问题。
整数离散余弦变换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化。
CABAC压缩。
经过压缩后的帧分为:I帧,P帧和B帧:
I帧:关键帧,采用帧内压缩技术。
P帧:向前参考帧,在压缩时,只参考前面已经处理的帧。采用帧音压缩技术。
B帧:双向参考帧,在压缩时,它即参考前而的帧,又参考它后面的帧。采用帧间压缩技术。
除了I/P/B帧外,还有图像序列GOP。
GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧。如下图所示:
2NALU:(H264的码流,H264的实际数据传输)Network Abstract Layer,即网络抽象层
H.264码流在网络中传输时实际是以NALU的形式进行传输的.
H264的码流由NALU单元组成,NALU单元包含视频图像数据和H264的参数信息。其中视频图像数据就是CMBlockBuffer,而H264的参数信息则可以组合成FormatDesc。具体来说参数信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set)
由NALU构成的H264NALUS数据码流(1)提取sps和pps生成format description。
a,每个NALU的开始码是0x00 00 01,按照开始码定位NALU。
b,通过类型信息找到sps和pps并提取,开始码后第一个byte的后5位,7代表sps,8代表pps。
c,CMVideoFormatDescriptionCreateFromH264ParameterSets函数来构建CMVideoFormatDescriptionRef。具体代码可以见demo。
(2)提取视频图像数据生成CMBlockBuffer。
a,通过开始码,定位到NALU。
b,确定类型为数据后,将开始码替换成NALU的长度信息(4 Bytes)。
c,CMBlockBufferCreateWithMemoryBlock接口构造CMBlockBufferRef。具体代码可以见demo。
(3)根据需要,生成CMTime信息。(实际测试时,加入time信息后,有不稳定的图像,不加入time信息反而没有,需要进一步研究,这里建议不加入time信息)
根据上述得到CMVideoFormatDescriptionRef、CMBlockBufferRef和可选的时间信息,使用CMSampleBufferCreate接口得到CMSampleBuffer数据这个待解码的原始的数据。见下图的H264数据转换示意图。
1NALU结构:长度-1byte
NALU结构 NALU HeaderNAL header:
forbidden_zero_bit:forbidden_zero_bit shall be equal to 0.
nal_ref_idc:
用于表示当前NALU的重要性,值越大,越重要.
解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU.
nal_ref_idc不等于0时, NAL unit的内容可能是SPS/PPS/参考图像的片等,nal_ref_idc等于0时,NAL unit的内容可能是非参考图像的片等.
SPS/PPS时,nal_ref_idc不可为0,当某个图像的片的nal_ref_id等于0时,该图像的所有片均应等于0.
1举例来说:
00 00 00 01 06: SEI信息
00 00 00 01 67: 0x67&0x1f = 0x07 :SPS
00 00 00 01 68: 0x68&0x1f= 0x08 :PPS
00 00 00 01 65: 0x65&0x1f= 0x05 :IDR Slice
RBSP
RBSP 序列举例:
3SODB与RBSP:
SODB 数据比特串 -> 是编码后的原始数据.
RBSP 原始字节序列载荷 -> 在原始编码数据的后面添加了 结尾比特。一个 bit“1”若干比特“0”,以便字节对齐。
3NALU架构:
41帧 = n个片
1片 = n个宏块
1宏块 =16x16yuv数据
为什么要设置片呢?
设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。
可以看到上图中,每个图像中,若干宏块(Macroblock)被排列成片。一个视频图像可编程一个或更多个片,每片包含整数个宏块 (MB),每片至少包含一个宏块。
片有一下五种类型:
片 意义
I 片只包含I宏块
P 片包含P和I宏块
B 片包含B和I宏块
SP 片包含P 和/或 I宏块,用于不同码流之间的切换
SI 片一种特殊类型的编码宏块
SPS:
h264文档 7.2章节描述了内存大小描述语法
7.3.2.1.1描述了sps结构
Sequence Parameter Set(序列参数集)
nal_unit_type = 7
包含H.264的profile_idc和level_idc等信息.
还有图像的宽高:
pic_width_in_mbs_minus1:pic_width_in_mbs_minus1 = 21 以宏块(16x16)为单位的值减1
因此,实际的宽为 (21 + 1) * 16 = 352
pic_height_in_map_units_minus1
PPS:
Picture Parameter Set(图像参数集)
SEI:
Supplementary Enhancement Information
level和profile:
profile:
在H.264的SPS中,第一个字节表示profile_idc,根据profile_idc的值可以确定码流符合哪一种档次。判断规律为:
profile_idc = 66 → baseline profile,基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;
profile_idc = 77 → main profile, 进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少);
profile_idc = 88 → extended profile,主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持;
4、High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;
在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一种都由不同的profile_idc表示。
level:
level由level_idc指定,编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数
Level 主要参数:
1如何查看H264码流数据?
h264bitstream: https://sourceforge.net/projects/h264bitstream/files/latest/download
H264Naked:https://github.com/shi-yan/H264Naked 可视化工具,H264Naked既可以识别.264,也可以还别.h264.但是使用live555MediaServer播放RTSP流,live555MediaServer只支持.264后缀。
参考文章:https://www.jianshu.com/p/ea650344bafb
如何查看H264裸流数据?
网友评论