IP cameras are of varying quality, some behaving erratically in my experience. Dealing with their RTSP streams requires a dose of fault-tolerance.
This appears to be a byproduct of the low-end of the CCTV industry playing fast and loose with standards, RTSP and ONVIF being the two most frequently abused.
Fortunately, you can usually work around these problems. Unless your IP cameras and controller are all designed to play nicely together, only use ONVIF for once-only discovery and settings management.
FFMPEG not very tolerant in RTSP setup
After struggling I started comparing the RTSP/SETUP messages between openRTSP
and ffmpeg
. openRTSP
by default already outputs a lot of verbose diagnostic.
openRTSP
openRTSP
sends the commands OPTIONS
, DESCRIBE
and then SETUP
. The SETUP messages were:
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
response by camera:
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
For FFMPEG
you have to use -v 9 and -loglevel 99
params to see RTSP messages. It only sent a DESCRIBE
request is:
DESCRIBE rtsp://192.168.0.103:554/onvif1 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.67.100
response by camera:
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=0-1
Session: 37287775;timeout=60
RTSP abused and FFMPEG hacking-Solution
Comparing the messages it's clear the camera can connect using RTSP/AVP/TCP interleaved TCP. But we can see by the camera answer that in the 'Transport:' line it doesn't include 'TCP' after 'RTP/AVP' as it was requested. Like:
Transport: RTP/AVP/('TCP' missing here);....
I analysed the code on and ffmpeg/libavformat/rtsp.c
and found the intuitive following calling sequence: ff_rtsp_connect
, ff_rtsp_make_setup_request
, ff_rtsp_send_cmd
, ff_rtsp_read_reply
and ff_rtsp_parse_line
. Inside this last one I found rtsp_parse_transport
and the following code:
if (!av_strcasecmp(lower_transport, "TCP"))
th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
lower_transport
is the text parsed after 'RTP/AVP;'
in my case being ""
empty char string since the camera server did not include it.
I insertd || !av_strcasecmp(lower_transport, "")
in the code. Making it assume that the transport is RTSP_LOWER_TRANSPORT_TCP
when lower_transport
is ommited. Like bellow:
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;
This tiny patch (git) for ffmpeg is available here. Apply using git am < RTSP_lower_transport_TCP.patch
on ffmpeg git repo.
After recompiling: FFMPEG is working perfectly!
I hacked FFMPEG making it tolerant with the RTSP abuse the camera server was doing. Since my version of FFMPEG will only run on my unused android tv (as a cctv/nvr camera server) this won't create any other problems.
A better solution would be the FFMPEG (Ticket) consider also the case of a missing lower transport on a rtsp server answer. Then compare with the client-sent request to define whether the lower transport was ommitted. And try to connect with it.
Advice
Probably if you reached here your ip camera might be suffering from some RTSP abuse. I recommend you to try using openRTSP
first to see if it manages to connect. If so, then try to debug its RTSP/setup messages. It's possible that some custom or hacking solution exists if you modify (at your own risk) the ffmpeg/libavformat/rtsp.c
code. Or you might/should use live555 library, VLC or mplayer.