I bought a cheap chinese ip camera (GWIPC-26xxx/Yoosee). I want to record its stream with ffmpeg.
On FFMPEG I manage to make it work only using the RTSP/UDP transport protocol, like bellow. It also plays flawlessly on VLC.
ffmpeg -rtsp_transport udp -i rtsp://admin:[email protected]:554/onvif1 streamfile.mkv
pass is a password defined on the android camera app client.
But I highly prefer the RTSP/TCP transport because using UDP the images are frequently corrupted. Images that appear smeared and teared. So I tested almost anything and even compiled FFMPEG from source using the latest repository. But nothing makes ffmpeg work, android or windows. If use -rtsp_transport tcp I allways end-up receiving:
[rtsp @ 0xxxxxxx] Nonmatching transport in server reply
Finally discovered openRTSP that uses the same library that VLC uses. With it I managed to make it connect using RTSP/TCP (after compiling from source).
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
More details on openRTSP params here.
The weirdest part is the comparison of the RTSP setup messages (FFMPEG vs openRTSP). It seams clear that the ip camera server supports RTP/AVP/TCP. RTP interleaved into the existing TCP connection.
And looking the source code of ffmpeg/libavformat/rtsp.c it seams ffmpeg is having some problem indentifying it?
...
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
FFMPEG not very tolerant in RTSP setup
After struggling I started comparing the RTSP/SETUP messages between
openRTSPandffmpeg.openRTSPby default already outputs a lot of verbose diagnostic.openRTSP
openRTSPsends the commandsOPTIONS,DESCRIBEand thenSETUP. The SETUP messages were:response by camera:
FFMPEG
For
FFMPEGyou have to use-v 9 and -loglevel 99params to see RTSP messages. It only sent aDESCRIBErequest is:response by camera:
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:
I analysed the code on and
ffmpeg/libavformat/rtsp.cand found the intuitive calling sequence:ff_rtsp_connect,ff_rtsp_make_setup_request,ff_rtsp_send_cmd,ff_rtsp_read_replyandff_rtsp_parse_line. Inside this last one I foundrtsp_parse_transportand the following code:lower_transportis 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 isRTSP_LOWER_TRANSPORT_TCPwhenlower_transportis ommited. Like bellow:This tiny patch (git) for ffmpeg is available here. Apply using
git am < RTSP_lower_transport_TCP.patchon 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
openRTSPfirst 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) theffmpeg/libavformat/rtsp.ccode. Or you might/should use live555 library, VLC or mplayer.