RTMP视频数据格式
RTMP视频流格式与FLV很相似,通过查看FLV的格式文档,就能够知道RTMP视频数据应该怎么拼接。
RTMP中的数据就是由FLV的TAG中的数据区构成。
参考 FLV 文件格式
一般情况下,组装的RTMPPacket(RTMPDump中的结构体)为:
视频包.png 视频解码序列包.png
NALU
NALU就是NAL UNIT,nal单元。NAL全称Network Abstract Layer, 即网络抽象层,H.264在网络上传输的结构。一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了 。
我们通过x264编码获得一组或者多组 x264_nal_t
。结合RTMP,我们需要区分的是SPS、PPS、关键帧与普通帧:
enum nal_unit_type_e
{
NAL_UNKNOWN = 0,
NAL_SLICE = 1,
NAL_SLICE_DPA = 2,
NAL_SLICE_DPB = 3,
NAL_SLICE_DPC = 4,
NAL_SLICE_IDR = 5, /* ref_idc != 0 */ //关键帧片
NAL_SEI = 6, /* ref_idc == 0 */
NAL_SPS = 7, //sps片
NAL_PPS = 8, //pps片
NAL_AUD = 9,
NAL_FILLER = 12,
/* ref_idc == 0 for 6,9,10,11,12 */
};
IDR
一段h264视频由N组GOP(group of picture)组成,GOP指的就是画面组,一个GOP是一组连续的画面 。之前的学习中我们知道I帧能够独立解码,而P、B需要参考其他帧。
属于I帧的子集,有一种特殊的I帧,被称之为IDR帧,IDR帧的作用为即时刷新。
GOP.png
上面的这张图片描述的是2组GOP。其他I帧与IDR帧的区别就在于:刷新。当解码器解码帧5的时候,可以跨过帧4参考到帧3,普通I帧不会导致解码器的解码信息数据刷新。而IDR帧则会刷新解码需要的SPS、PPS数据,所以帧8不可能跨帧7参考解码。
H.264数据
往RTMP包中填充的是H.264数据,但不是直接将x264编码出来的数据填充进去。
一段包含了N个图像的H.264裸数据,每个NAL之间由:00 00 00 01 或者 00 00 01进行分割。
每个NALU之间通过startcode(起始码)进行分隔,起始码分成两种:0x000001(3Byte)或者0x00000001(4Byte)。如果NALU对应的Slice为一帧的开始就用0x00000001,否则就用0x000001。
在分割符之后的第一个字节,就是表示这个nal的类型。
- 0x67:sps
- 0x68:pps
- 0x65:IDR
即为上面的
NAL_SLICE_IDR 0x65& 0x1f = 5
NAL_SPS 0x67 & 0x1f = 7,
NAL_PPS 0x68 & 0x1f= 8,
SPS:序列参数集,作用于一系列连续的编码图像。
PPS:图像参数集,作用于编码视频序列中一个或多个独立的图像。
IDR:一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。
SPS 和 PPS 包含了初始化H.264解码器所需要的信息参数。
在将数据加入RTMPPacket的时候是需要去除分割符的。
h264.png
网友评论