首页 > 解决方案 > 如何使用 VLC 播放已经流式传输的 H264 RTSP 数据 - 使用 Wireshark 转储到文件

问题描述

背景故事

我的局域网上有一个 IP 摄像头,我已经使用 VLC 连接到它(CTRL + N添加rtsp://192.168.1.10<- IP 摄像头配置的 IP 地址),在 VLC 连接后,我开始使用 Wireshark 嗅探流量。大约 30 秒后,在 Wireshark 上,我单击“Follow TCP stream”,然后将来自摄像头的流量转储到我的计算机上。

我的目标

我希望能够从 Wireshark(或其他网络嗅探替代方案)获取转储的 RTSP 流,提取 H264 数据,然后能够在 VLC 上播放它。

我不想做的事

  1. 我不想使用 VLC 转储流
  2. 我不想使用 FFMPEG 转储流

我尝试过的事情

所以我已经设法解析了RTSPRTP标头,并了解了 H264 有效负载的开始位置,例如:

00000000     24 00 05 A0 80 60 35 85 14 0C 1F DE 43 13 B7 58
00000010     7C 81 9A 26 26 64 33 FF 7C 11 99 87 4B 15 FA 06 
00000020     06 47 12 C5 6E 39 56 56 82 0D E0 1F 8D 1B 8A A7

从 offset 开始0x00000000,有RTSP 标头 24 00 05 A0。使用 python 解压:

magic, channel, length = struct.unpack(">BBH", data)

之后,在偏移量之间0x00000004 to 0x00000010,我有RTP 标头,解析为

bits_header_a, bits_header_b, sequence_number, timestamp, ssrc_identifier = struct.unpack(">BBHII", data)

并且从偏移量中0x00000010我得到了实际的有效载荷。

我查看了 RFC ,以及在此问题上给出的很好的答案,但还没有完全理解接下来我在从 RTSP 实际有效负载中重建 H264 数据时做错了什么。这是我在之前解析的每个有效负载(帧)数据(python)上执行的一段较大代码的一部分,以创建数据帧:

first_byte = "{0:>08s}".format(bin(ord(frame[0]))[2:])
second_byte = "{0:>08s}".format(bin(ord(frame[1]))[2:])
rest_of_data = frame[2:]


# First byte
nal_unit_a = int(first_byte[:3], 2)
fragment_type = int(first_byte[3:], 2)

# Second byte
start_bit = int(second_byte[0], 2)
end_bit = int(second_byte[1], 2)
nal_unit_b = int(second_byte[3:], 2)


# Video data
if 0x1C == fragment_type:
    
    # Middle frame, just add
    if 0 == start_bit and 0 == end_bit:
        total_data += rest_of_data
        continue
        
    # First frame in sequence
    elif 1 == start_bit:
        print " [*] Found start frame"
        nal_unit = chr((nal_unit_a << 5) | nal_unit_b)
        if ord(nal_unit) != ( (ord(frame[0]) & 0xe0)  |  (ord(frame[1]) & 0x1F)):
            print "Unexpected"
        total_data += "\x00\x00\x00\x01"
        total_data += nal_unit
        total_data += rest_of_data
        continue
    
    # End
    elif 0 == start_bit and 1 == end_bit:
        print " [*] Found end frame"
        total_data += rest_of_data

我正在按照我认为应该的方式重建 NALU。我正在为每个有效负载执行此代码。但是输出无法在 VLC 上播放(即使在设置 VLC Demux 模块以强制 H264 解析之后)。我很确定我遗漏了一些东西,因为我没有修复与时间戳和 H264 相关的任何内容,因此可能存在问题。我得到的nal_unit_b, 和的唯一值nal_unit_a5 3,1 3被重建为整个 NAL 单元0x610x65.

我的问题

  1. 我知道在 RTSP 会话开始时,会发送一些数据以更好地了解如何解析 RTSP 会话(也称为 SDP),但我很确定所有数据也应该存在于 H264 有效负载中并且应该是即使没有告诉它如何解析数据也可以播放,或者我总是可以假设数据是如何编码的,如果我确定我正在与哪个 IP-Camera 供应商通信。那是对的吗?
  2. 我上面的python代码片段是否正确?(解析认为)
  3. 为什么在我的数据流上我只收到视频数据包(fragment_type = 0x1C),而我没有看到其他任何东西。
  4. 当简单地使用 VLC 连接到 IP-Camera 并单击Tools-->Codec Information时,呈现的编解码器是:Codec: H264 - MPEG-4 AVC (part 10) (h264),我认为它应该被解析为 H264,我也尝试将其解析为 MPEG 但失败了,我将其解析为 H264 是否正确?

标签: pythonwiresharkh.264rtspip-camera

解决方案


推荐阅读