zeerd's blog     Article     Search     About     Tags     Pebble     Feed

闲来生雅趣,无事乐逍遥。对窗相望雪,一盏茶香飘。

负载H.264的RTP数据流解析

#H.264 #RTP


使用Gstreamer推送和接收负载H.264的RTP流,并解析其数据包。

Gstreamer播放

推送:

gst-launch-1.0 filesrc location=xxx.mp4  \
  ! qtdemux ! h264parse ! rtph264pay ! udpsink host=127.0.0.1 port=1234

接收:

gst-launch-1.0 udpsrc uri=udp://127.0.0.1:1234 caps = 'application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, packetization-mode=(string)1, profile-level-id=(string)42c00d, sprop-parameter-sets=(string)"Z0LADasgKDPz4CIAAAMAAgAAAwBhHihUkA\=\=\,aM48gA\=\=", payload=(int)96, ssrc=(uint)4189219711, timestamp-offset=(uint)2420114382, seqnum-offset=(uint)5370, a-framerate=(string)24' \
  ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink

“接收”命令中,udpsrc的caps中的超长字符串可以通过“推送”命令来获取。 只要在“推送”命令后面添加一个-v参数就可以了。注意,查找其中“udpsink”对应的caps字符串。

Wireshark

默认的Wireshark可能无法解析RTP的数据包。这个时候可以尝试激活一些额外的选项。

打开菜单,Analyze -> Enable Prorocols,向下找到RTP。 可以看到,这下面的几个子项目默认是不勾选的。可以尝试一下勾选,看看能否解决问题。

包结构

可以参照 RTP Header Usage

下面是一段随机截取的数据:

0000   00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   ........ ......E.
0010   05 94 91 d5 40 00 40 11  a5 81 7f 00 00 01 7f 00   ....@.@. ........
0020   00 01 ec bc 04 D2 05 80  03 94 80 60 f2 8e 2e f3   ....@... ...`....
0030   1d 42 7e 10 8c 76 5c 81  9a 63 2c 09 ad 65 d6 bd   .B~..v\. .c,..e..
0040   c2 b4 86 19 76 53 d5 b3  ef fe c4 64 bd 97 0f f4   ....vS.. ...d....
0050   09 6a ba ae 91 7b 3d be  99 37 e6 2b 92 d9 7e 84   .j...{=. .7.+..~.
0060   a5 ff 9a ee fe db 04 fa  aa aa aa f1 f8 57 21 1a   ........ .....W!.
0070   7f ff b1 3e 27 f8 21 08  de fb bb ba fe 08 01 0c   ...>'.!. ........
                           ......

从第0x2A个字节开始是 RTP 的数据包。 分析数据,可以看到,CC(即CSRC count)为0,也就是说没有 CSRC 。

从第0x36个字节开始的“5c 81 …”,表示这是一个FU-A类型的H.264数据包。 0x5c表示它的低5位(即Type)是111002=2810,即FU-A。 0x81的高3位为1002,表示其S位为1,即这是一个起始帧; 低5位为000012,表示其是一个“非IDR”帧。