H264
单元
NAL单元包括对应于视频编码的NAL头信息、原始字节序列负荷。
SODB:最原始的编码数据,无任何附加数据。
RBSP:在SODB的基础上增加了结尾比特(bit值为1)并用0按字节补位对齐。
EBSP:在RBSP的基础上增加了防止伪起始码字节(0x03)。在编码的时候每遇到两个字节(连续)的0,就插入一个字节0x03,以便和起始码相区别,解码时,则将相应的0x03删除掉。所以有时候NAL单元有可能是NAL头+EBSP组成
帧
帧名 | 帧头 | 功能 |
---|---|---|
SPS | 00 00 00 01 67 | SPS和PPS是用来初始化解码器的,没有,视频数据无法解析 |
PPS | 00 00 00 01 68 | SPS和PPS是用来初始化解码器的,没有,视频数据无法解析 |
SEI | 00 00 01 06 | 描述信息 |
I 帧 | 00 00 00 01 65 | 关键帧:底画 |
P帧 | 00 00 00 01 61 | 补充帧:在底画上的修修改改 |
RTP荷载H264
FU-A 单元分片
- FU-A头包含1字节NAL头,1字节的分片单元头。
- S: 开始标识位,FU荷载为NAL的起始分片
- E: 结束标识位,FU荷载为NAL的结束分片
- R: 保留位,必须设置为0,
- 打包时,H264帧头(如00 00 00 01 65),前面的00 * 01去掉,最后一字节标识(65),存储在NAL头的前三位(F,NRI)与分片单元头的后5位中(FU header Type)
TCP传输
TCP 为字节流传输,需要添加间隔帧RTSP Interleaved Frame,对包进行分割
PS
PS格式
首条数据结构:PS Header + PS System Header + PSM + PESV(Header + Payload)
非首条数据结构:PS Header + PESV(Header + Payload)
包定义
定义太多,没整理,当字典用吧
PS Header:00 00 01 ba
program_mux_rate:速率值字段,占位22bit,正整数,表示P-STD接收此字段所在包的PS流的速率;这个值以每秒50字节作为单位;禁止0值;
Marker_bit:标记字段,占位1bit,固定为’1’;
stuffing_byte:填充字段,长度由pack_stuffing_length确定;
PS System Header:00 00 01 bb
header_length:头部长度字段,占位16bit,表示此字段之后的系统首部字节长度;
rate_bound:整数值,占位22bit,为一个大于或等于PS流所有PS包中的最大program_mux_rate值的整数;解码器用来判断是否可以对整个流进行解码;
audio_bound:占位6bit;取值范围0到32间整数;大于或等于同时进行解码处理的PS流中的音频流的最大数目;
fixed_flag:占位1bit;置位1表示固定比特率操作,置位0则为可变比特率操作;
CSPS_flag:CSPS标志位,占位1bit;置位1表示此PS流满足标准的限制;
system_audio_lock_flag:占位1bit,表示音频采样率和系统目标解码器的system_clock_frequency之间有一特定常数比例关系;
system_video_lock_flag:占位1bit,表示视频帧速率和system_clock_frequency之间有一特定常数比例关系;
video_bound:整数,占位5bit,取值范围0到16;大于或等于同时进行解码处理的PS流中的视频流的最大数目;
stream_id :占位8bit,判断视频流或音频流;
PSM:00 00 01 bc
program_stream_map_length:占位16bit;表示此字段之后PSM的总长度,最大值为1018(0x3FA);
current_next_indicator:标识符,占位1bit;置位1表示当前PSM是可用的,置位0则表示当前PSM不可以;
program_stream_map_version:版本字段,占位5bit;表示PSM的版本号,取值范围1到32,随着PSM定义的改变循环累加;若current_next_indicator == 1,表示当前PSM的版本号,若current_next_indicator == 0,表示下一个PSM的版本号;
elementary_stream_map_length:长度字段,占位16bit;表示在这个PSM中所有ES流信息的总长度;
stream_type:类型字段,占位8bit;表示原始流ES的类型;可以判断PS打包的流编码类型;MPEG-4 视频流: 0x10;H.264 视频流: 0x1B;SVAC 视频流: 0x80;G.711 音频流: 0x90;G.722.1 音频流: 0x92;G.723.1 音频流: 0x93; G.729 音频流: 0x99; SVAC音频流: 0x9B;
elementary_stream_id:流ID字段,占位8bit;表示此ES流所在PES分组包头中的stream_id字段的值;其中0x(C0~DF)指音频,0x(E0~EF)为视频;
PES 包(Header + Body):00 00 01 e0
PES_packet_length :PES分组长度字段,16位字段,指出了PES分组中跟在该字段后的字节数目。
PES_scrambling_control :PES加扰控制字段,2位字段,表示PES分组有效负载的加扰方式。
PES_priority :PES优先级字段,1位字段,指示PES分组中有效负载的优先级。
Copyright:版权字段,1位字段。置’1’时表示相关PES分组有效负载的材料受到版权保护。当值为’0’时,没有定义该材料是否受到版权保护。
original_or_copy:原始或拷贝字段,1位字段。置’1’时表示相关PES分组有效负载的内容是原始的;值为’0’表示相关PES分组有效负载的内容是一份拷贝。
DSM_trick_mode_flag :DSM特技方式标志字段,1位标志。置’1’时表示有8位特技方式字段;值为’0’表示没有该字段。
additional_copy_info_flag:附加版权信息标志字段,1位标志。置’1’时表示有附加拷贝信息字段;值为’0’表示没有该字段。
例子
00 00 01 ba 代表 PS 包的开始。第 10 个字节 fe,对应着二进制数据的 1111 1110它的后三位为 110 为十进制的 6,即接下来的六个字节是扩展内容。
00 00 01 bb是PS System Header 部分。System Header 当且仅当数据包为第一个数据包时才存在。之后紧邻的 00 12 两个字节表示 System Header 的长度,即为 18 个字节。在 header_length 后共有 6 个字节的数据,之后就是 stream_id 字段, system_id 值为 e0,可知本 PS 流为视频流。它是 3 个字节一循环,下一个循环 system_id 字节值为 c0,为音频流,之后出现了 bd,这个是海康私有流的标识,bf 也是海康的私有数据。
00 00 01 bc是本段数据的类型 program_stream_map,即 PSM。之后的两个字段为 header 的长度,00 5e 十进制的 94,自 00 5e 后,跳过两个字段的固定内容,就到了两个字节的 program_stream_info_length,其值为 00 24,说明其后跟着的 descriptor 共占 36 字节。跳过 36 字节后,接下来的值 00 30 为 element_stream_map_length(基本流映射长度),也就是 48 字节,它表示接下来的 48 字节都是用来描述原始流信息的。
进入原始流描述的第一次循环,第一个字节 stream_type 值为 1b 。根据 GB28181 的定义可知为 H.264 编码,之后的 e0 表示其为视频流。再之后的 00 1c 代表接下来描述占用 28 字节。接着循环下去,接下来的字段 91 和 c0,代表着其为音频流, 00 0c 代表接下来描述占用 12 字节,最后就是 CRC_32,4个字节。
00 00 01 e0表示是一个视频流,再之后的 FF C6 表示长度,即其后的 65478字节为数据内容长度,PES_header_data_length的位置是PES 包长度跳过两个字节后的位置。它的值为 07,也就是其后字节的长度,通过这个可以分割PES头部内容和数据段,且PES 是可以存在多个的。