FFMPEG:“服务器回复中的传输不匹配”但 openRTSP 有效 Quoting WisdomFFMPEG 在 RTSP 设置中不太宽容RTSP 被滥用和 FFMPEG hacking-解决方案重新编译后:FFMPEG完美运行!

问题描述

我买了一个便宜的中国网络摄像机 (GWIPC-26xxx/Yoosee)。我想用 ffmpeg 记录它的流。

FFMPEG上,我设法使用RTSP/UDP传输协议使其工作,如下所示。它还可以在 VLC 上完美播放。

ffmpeg -rtsp_transport udp -i rtsp://admin:pass@192.168.0.103:554/onvif1 streamfile.mkv

pass 是在 android 相机应用客户端上定义的密码。

但是我非常喜欢 RTSP/TCP 传输,因为使用 UDP 图像经常损坏。出现污点和撕裂的图像。所以我测试了几乎所有东西,甚至使用 latest repository 从源代码编译 FFMPEG。但没有什么能让 ffmpeg 工作,android 或 windows。如果使用 -rtsp_transport tcp 我总是最终收到:

[rtsp @ 0xxxxxxx] Nonmatching transport in server reply

终于发现 openRTSP 使用的库与 VLC 使用的库相同。有了它,我设法使用 RTSP/TCP 连接(从源代码编译后)。

openRTSP -n -D 1 -c -B 10000000 -b 10000000 -q -Q -F cam_file \ 
-d 60 -P 30 -t -u admin pass rtsp://192.168.0.103:554/onvif1

有关 openRTSP 参数 here 的更多详细信息。

最奇怪的部分是 RTSP 设置消息(FFMPEG 与 openRTSP)的比较。很明显,网络摄像机服务器支持 RTP/AVP/TCP。 RTP 交错到现有的 TCP 连接中。

查看 ffmpeg/libavformat/rtsp.c 的源代码,发现 ffmpeg 在识别它时遇到了一些问题?

...
if (reply->transports[0].lower_transport != lower_transport) {
    av_log(s,AV_LOG_ERROR,"Nonmatching transport in server reply\n");
    err = AVERROR_INVALIDDATA;
    goto fail;
}
...

解决方法

Quoting Wisdom

IP 摄像头的质量参差不齐,根据我的经验,有些摄像头表现不正常。处理他们的 RTSP 流需要一定的容错能力。
这似乎是 CCTV 行业低端玩弄标准的副产品,RTSP 和 ONVIF 最常被滥用的两个​​强>。 幸运的是,您通常可以解决这些问题。除非您的 IP 摄像机和控制器都设计为可以很好地协同工作,否则只能使用 ONVIF 进行一次性发现和设置管理。

FFMPEG 在 RTSP 设置中不太宽容

在挣扎之后,我开始比较 openRTSPffmpeg 之间的 RTSP/SETUP 消息。 openRTSP 默认已经输出了很多详细的诊断信息。

openRTSP

openRTSP 发送命令 OPTIONSDESCRIBESETUP。 SETUP 消息是:

Sending request: SETUP rtsp://192.168.0.103:554/onvif1/track2 RTSP/1.0
CSeq: 6
Authorization: Digest username="admin",realm="HIipCamera",nonce="ddd21dbd0620b6fb4b1f9bcbb06340a0",uri="rtsp://192.168.0.103:554/onvif1",response="91d9c611aa004eeb1390b3fbb9373648"
User-Agent: ./openRTSP (LIVE555 Streaming Media v2021.02.11)
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
Session: 3a4d2e6d

相机响应:

Received a complete SETUP response:
RTSP/1.0 200 OK
CSeq: 6
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=2-3
Session: 3a4d2e6d;timeout=60

FFMPEG

对于 FFMPEG,您必须使用 -v 9 and -loglevel 99 参数才能查看 RTSP 消息。它只发送了一个 DESCRIBE 请求是:

DESCRIBE rtsp://192.168.0.103:554/onvif1 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.67.100

相机响应:

Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=0-1
Session: 37287775;timeout=60

RTSP 被滥用和 FFMPEG hacking-解决方案

比较消息很明显,相机可以使用 RTSP/AVP/TCP 交错 TCP 进行连接。但是我们可以通过摄像头的回答看到,在'Transport:'行中,在'RTP/AVP'之后不包含'TCP' > 按照要求。喜欢:

Transport: RTP/AVP/('TCP' missing here);....

我分析了 ffmpeg/libavformat/rtsp.c 上的代码,发现了以下直观的调用序列:ff_rtsp_connectff_rtsp_make_setup_requestff_rtsp_send_cmdff_rtsp_read_reply 和 {{1} }.在最后一个中,我发现了 ff_rtsp_parse_line 和以下代码:

rtsp_parse_transport

if (!av_strcasecmp(lower_transport,"TCP")) th->lower_transport = RTSP_LOWER_TRANSPORT_TCP; else th->lower_transport = RTSP_LOWER_TRANSPORT_UDP; 是在 lower_transport 之后解析的文本,在我的例子中是 'RTP/AVP;' 空字符字符串,因为相机服务器没有包含它。

我在代码中插入了 ""。当省略 || !av_strcasecmp(lower_transport,"") 时,假设传输是 RTSP_LOWER_TRANSPORT_TCP。如下图:

lower_transport

重新编译后:FFMPEG完美运行!

破解了 FFMPEG 使其容忍 RTSP 滥用相机服务器正在做的事情。由于我的 FFMPEG 版本只能在我未使用的 android 电视上运行(作为 cctv/nvr 摄像机服务器),因此不会产生任何其他问题。

更好的解决方案是 FFMPEG (Ticket) 还考虑在 rtsp 服务器答案上缺少较低传输的情况。然后与客户端发送的请求进行比较以定义是否省略了较低的传输。并尝试与之建立联系。

建议

可能如果您到达这里,您的网络摄像头可能会遭受一些 RTSP 滥用。我建议您先尝试使用 if (!av_strcasecmp(lower_transport,"TCP") || !av_strcasecmp(lower_transport,"")) th->lower_transport = RTSP_LOWER_TRANSPORT_TCP; else th->lower_transport = RTSP_LOWER_TRANSPORT_UDP; ,看看它是否能够连接。如果是,则尝试调试其 RTSP/设置消息。如果您修改(风险自担)openRTSP 代码,则可能存在某些自定义或黑客解决方案。或者您可能/应该使用 live555 库、VLC 或 mplayer。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...