Can't play RTSP livestream with UDP transport behind a NAT
See original GitHub issuePlease help me to configure ExoPlayer in such a way that it would be able to play RTSP with UDP even behind a NAT =) Maybe you have some advice on how we should configure a NAT or our IP cameras.
Currently, I’m able to connect to the camera only over TCP transport (after RtspClient::retryWithRtpTcp gets called).
I wonder why it doesn’t work with UDP?! We use the IJK player in our application to play RTSP live-streaming over UDP. But we want to replace it completely with ExoPlayer.
ExoPlayer has less latency (for about 150ms) even using TCP transport. I hope with UDP it would be even faster. But I can’t force it to work with UDP behind NAT.
I have checked requests both from IJK and ExoPlayer - final PLAY requests for UDP are the same:
----> SETUP rtsp://99.83.253.210:1988/trackID=0 RTSP/1.0
cseq: 3
user-agent: ExoPlayerLib/2.14.1
authorization: Digest username="admin", realm="Login to AMC000E00283B932F2", nonce="3e9f37bceaa57de21e7a0f4e8447ac8d", uri="rtsp://99.83.253.210:1988/trackID=0", response="6e5e2d8cd0874f05f4159a946c957134"
transport: RTP/AVP;unicast;client_port=44772-44773
<---- RTSP/1.0 200 OK
CSeq: 3
Session: 46575065826722;timeout=60
Transport: RTP/AVP/UDP;unicast;client_port=44772-44773;server_port=30232-30233;ssrc=3C6F439F
x-Dynamic-Rate: 1
----> PLAY rtsp://99.83.253.210:1988 RTSP/1.0
cseq: 4
user-agent: ExoPlayerLib/2.14.1
session: 46575065826722
authorization: Digest username="admin", realm="Login to AMC000E00283B932F2", nonce="3e9f37bceaa57de21e7a0f4e8447ac8d", uri="rtsp://99.83.253.210:1988", response="d812d55ed6fd1251c6a7b40e6413f7b3"
range: npt=0.000-
<---- RTSP/1.0 200 OK
CSeq: 4
Session: 46575065826722
Range: npt=0.000000-
RTP-Info: url=trackID=0;seq=59654;rtptime=4151165751
IJK Player:
----> SETUP rtsp://99.83.253.210:1134/trackID=0 RTSP/1.0
Transport: RTP/AVP/UDP;unicast;client_port=6270-6271
x-Dynamic-Rate: 0
CSeq: 4
User-Agent: Lavf57.71.100
Authorization: Digest username="admin", realm="Login to AMC000A7FE389979C2", nonce="975d6b191017a8aaa246c31e7202be24", uri="rtsp://99.83.253.210:1134/trackID=0", response="0d6bc7640e2b708ad325cf64bf61d0bb"
<---- RTSP/1.0 200 OK
CSeq: 4
Session: 610760585462;timeout=60
Transport: RTP/AVP/UDP;unicast;client_port=6270-6271;server_port=38122-38123;ssrc=029DB495
x-Dynamic-Rate: 1
----> UDP 886 15:22:17.666169 192.168.86.37 99.83.253.210 UDP 54 54552 → 38122 Len=12
----> RTCP 887 15:22:17.666602 192.168.86.37 99.83.253.210 RTCP 50 Receiver Report
----> PLAY rtsp://99.83.253.210:1134/ RTSP/1.0
Range: npt=0.000-
CSeq: 5
User-Agent: Lavf57.71.100
Session: 610760585462
Authorization: Digest username="admin", realm="Login to AMC000A7FE389979C2", nonce="975d6b191017a8aaa246c31e7202be24", uri="rtsp://99.83.253.210:1134/", response="e313ab753802c188545746644b3cb297"
<---- RTSP/1.0
200 OK
CSeq: 5
Session: 610760585462
Range: npt=0.000000-
RTP-Info: url=trackID=0;seq=32256;rtptime=4067785369
<---- RTCP 891 15:22:17.774673 99.83.253.210 192.168.86.37 RTCP 90 Sender Report Source description
----> TCP 892 15:22:17.815697 192.168.86.37 99.83.253.210 TCP 54 62790 → 1134 [ACK] Seq=1357 Ack=1214 Win=130048 Len=0
<---- UDP
<---- UDP
<---- UDP
The only difference is Transport: RTP/AVP/UDP
header. But adding /UDP to DEFAULT_UDP_TRANSPORT_FORMAT
doesn’t help.
Another thing that I have noticed - is that IJK Player sends two extra packets between SETUP and PLAY requests.
This one is interesting because it targets the server port described in the SETUP response:
UDP 886 15:22:17.666169 192.168.86.37 99.83.253.210 UDP 54 54552 → 38122 Len=12
Issue Analytics
- State:
- Created 2 years ago
- Comments:7 (3 by maintainers)
Top GitHub Comments
Glad that it worked!
IMO your current solution looks good given that you normally have only 4 sockets open for a playback.There will be multiple layers of plumbing to do if you want to do it “rigorously”: from
RtspClient
toRtspMediaPeriod
toRtpDataChannel
, and toUdpDataSourceRtpDataChannel
and eventuallyUdpDataSource
. And it won’t be as elegant even if you do the plumbing.If we have a better option for how to access sockets from
UdpDataSource
, please write it here!