本文链接:从RTSP协议传输的H264视频流中取出每一帧的类型(I、P、B帧)
RTSP是一个控制协议,其中的数据是用RTP传输的。
RTP使用了UDP,每个UDP包的内容区(没有UDP头)都包含以下的几个部分:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | RTP_FIXED_HEADER 0                   1                   2                   3  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |V=2|P|X|  CC   |M|     PT      |       sequence number         |  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |                           timestamp                           |  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  |           synchronization source (SSRC) identifier            |  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+  |            contributing source (CSRC) identifiers             |  |                             ....                              |  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 
V: 版本
P: 填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头。
CC: CSRC的个数
M: 对于H264视频帧,表示这是最后一个分片
PT: 载荷类型,H264是96(0x60)
SSRC: 会话标识
CSRC: 忘记了
紧随其后的是NALU_HEADER
| 1 2 3 4 5 6 | NALU_HEADER  +---------------+  |0|1|2|3|4|5|6|7|  +-+-+-+-+-+-+-+-+  |F|NRI|  Type   |  +---------------+ | 
F: 始终为0
NRI: 重要性
Type: 类型
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Type    Packet      Type name                        ---------------------------------------------------- 0       undefined                                  1                   不分区,非IDR图像的片(I, P, B帧) 2                   片分区A 3                   片分区B 4                   片分区C 5                   IDR图像中的片(I帧) 6                   补充增强信息单元(SEI) 7                   序列参数集(SPS) 8                   图像参数集(PPS) 9                   分界符 10                  序列结束 11                  码流结束 12                  填充 13-23   reserved 24      STAP-A      Single-time aggregation packet     25      STAP-B      Single-time aggregation packet     26      MTAP16      Multi-time aggregation packet      27      MTAP24      Multi-time aggregation packet      28      FU-A        Fragmentation unit                 29      FU-B        Fragmentation unit                  30-31   undefined | 
如果H264的Slice过大,无法装入一个UDP包中,一般来说这里就要分包。分包时,NALU_HEADER中Type字段为FU-A(28),下一字节为FU_HEADER。
| 1 2 3 4 5 6 | FU_HEADER +---------------+ |0|1|2|3|4|5|6|7| +-+-+-+-+-+-+-+-+ |S|E|R|  Type   | +---------------+ | 
S: 开始的片
E: 结束的片
R: 始终为0
Type: 类型,和NALU_HEADER的类型一致
后面的部分就是H264的内容了。H264是按照Slice传输的,每个Slice有一个Slice头,据说Slide头使用了指数哥伦布编码(k=0),需要先进行解码。
指数哥伦布编码(k=0):
| 1 2 3 4 5 6 7 8 9 10 | 数据  数据+1        写作二进制(n位)   前加n-1个0(编码结果) 0       1           1                   1 1       2           10                  010 2       3           11                  011 3       4           100                 00100 4       5           101                 00101 5       6           110                 00110 6       7           111                 00111 7       8           1000                0001000 ...     ...         ...                 ... | 
解码就反过来,先数0的个数,然后再取相应位数的数据出来。
011110100001101 -> 011 1 1 010 0001101 -> 11 1 1 10 1101 -> 3 1 1 2 13 -> 2 0 0 1 12
Slide头的第二个参数为slice_type,也就是解出来的第二个数,表示IPB帧:
| 1 2 3 4 5 6 7 8 9 10 11 | slice_type  Name of slice_type 0           P (P slice) 1           B (B slice) 2           I (I slice) 3           SP (SP slice) 4           SI (SI slice) 5           P (P slice) 6           B (B slice) 7           I (I slice) 8           SP (SP slice) 9           SI (SI slice) | 
参考:
[1] http://blog.csdn.net/jefry_xdz/article/details/8461343
[2] http://www.cnweblog.com/fly2700/archive/2012/02/23/319718.html
[3] http://blog.csdn.net/wangjiannuaa/article/details/6966505
[4] http://blog.sina.com.cn/s/blog_4171e65d0100o4pt.html
[5] http://baike.baidu.com/view/1268656.htm?fromtitle=RTP&fromid=8974125&type=syn