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
openRTSP
andffmpeg
.openRTSP
by default already outputs a lot of verbose diagnostic.openRTSP
openRTSP
sends the commandsOPTIONS
,DESCRIBE
and thenSETUP
. The SETUP messages were:response by camera:
FFMPEG
For
FFMPEG
you have to use-v 9 and -loglevel 99
params to see RTSP messages. It only sent aDESCRIBE
request 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.c
and found the intuitive calling sequence:ff_rtsp_connect
,ff_rtsp_make_setup_request
,ff_rtsp_send_cmd
,ff_rtsp_read_reply
andff_rtsp_parse_line
. Inside this last one I foundrtsp_parse_transport
and the following code: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 isRTSP_LOWER_TRANSPORT_TCP
whenlower_transport
is ommited. Like bellow: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) theffmpeg/libavformat/rtsp.c
code. Or you might/should use live555 library, VLC or mplayer.