python - 如何使用 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 上播放它。
我不想做的事
- 我不想使用 VLC 转储流
- 我不想使用 FFMPEG 转储流
我尝试过的事情
所以我已经设法解析了RTSP
和RTP
标头,并了解了 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_a
是5 3
,1 3
被重建为整个 NAL 单元0x61
和0x65
.
我的问题
- 我知道在 RTSP 会话开始时,会发送一些数据以更好地了解如何解析 RTSP 会话(也称为 SDP),但我很确定所有数据也应该存在于 H264 有效负载中并且应该是即使没有告诉它如何解析数据也可以播放,或者我总是可以假设数据是如何编码的,如果我确定我正在与哪个 IP-Camera 供应商通信。那是对的吗?
- 我上面的python代码片段是否正确?(解析认为)
- 为什么在我的数据流上我只收到视频数据包(
fragment_type = 0x1C
),而我没有看到其他任何东西。 - 当简单地使用 VLC 连接到 IP-Camera 并单击
Tools-->Codec Information
时,呈现的编解码器是:Codec: H264 - MPEG-4 AVC (part 10) (h264)
,我认为它应该被解析为 H264,我也尝试将其解析为 MPEG 但失败了,我将其解析为 H264 是否正确?
解决方案
推荐阅读
- java - 从具有多个 SSN 的文件中仅使用部分掩码屏蔽所有 SSN
- javascript - 在“updated_cart_totals”jQuery 事件中获取 WooCommerce 刷新的购物车总数
- python - 如何从我的谷歌地图自动提取数据(KMZ?JSON?)
- reverse-proxy - 应该如何配置 Tinyproxy 以正确地将流量路由回客户端?
- python - 图像在 Keras 中没有标准化
- r - 堆叠的 geom_bar():在可变宽度的条之间保持相等的间隙
- javascript - 使用状态和模板文字进行重定向反应
- android - 詹金斯:':app:processDevManifest'任务步骤中的NullPointerException
- apache-kafka - 我如何询问 kafka 哪些主题具有非凡的覆盖?
- php - 无法将 where 子句添加到 eloquent 模型