Opened 9 months ago
Last modified 9 months ago
#10838 new defect
RTMP protocol, ffmpeg to ffmpeg, always ends with a connection reset (broken pipe)
Reported by: | Momtchil Momtchev | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | undetermined |
Version: | git-master | Keywords: | RTMP |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
When using ffmpeg as a server and ffmpeg as a client, RTMP streaming always ends with a connection reset.
The bug is present since at least 4.4.2 in Ubuntu 22.04 to the latest git of today.
The server sends its data, then once it is finished, it immediately closes its end. The TCP connection remains in a half-closed state. The client continues reading and at the end sends an RTMP_PT_BYTES_READ
(called an Acknowledgment, type 3, in the offical specs) message which causes the remote end to reply with a TCP RST
packet. This renders checking for errors difficult, as there is no nominal case - the error is always expected.
How to reproduce:
./ffmpeg -i input.mp4 -f flv -ar 44100 -flvflags no_duration_filesize \ -listen 1 rtmp://localhost:9099/video ./ffmpeg -y -i rtmp://localhost:9099/video output.mp4
I was not able to find anything on the connection teardown in the specifications:
https://rtmp.veriskope.com/docs/spec/#543acknowledgement-3
But given the wording of the acknowledgment section, I will be inclined to say that this is the server's fault - since it has to expect that the client will ack its last packet - which means that it should keep its end open until this ack is received.
Change History (5)
comment:1 by , 9 months ago
comment:2 by , 9 months ago
The parsing of the received acks happens in a muxer thread, while the closing of the connection is triggered by of_write_trailer
-> avio_closep
in the main thread. Can you please advise on the thread model, I am willing to fix this. Should I delay the closing of the connection in avio_closep
? This is something that most other protocols are likely already doing?
comment:3 by , 9 months ago
I found the reason and it is a design problem:
https://git.ffmpeg.org/gitweb/ffmpeg.git/blob/HEAD:/fftools/ffmpeg_mux.c#l407
In the main loop of muxer_thread()
, after sch_mux_receive()
has reported that the input stream is finished, the loop exits, ending the pipeline. This is simply how the pipeline works, fixing it here would require a major redesign.
A proper solution would be to implement ACK handling in the RTMP protocol and do not return from rtmp_write()
until the remote has actually acknowledged - taking into account the window. It should buffer the window, handle retransmits and block when the remote is lagging.
An easy fix would be to simply delay the closing in avio_closep()
/ rtmp_close()
with a timeout. I wonder if this would have any consequences?
comment:4 by , 9 months ago
Just tested VLC which behaves the same way as the ffmpeg client - it sends one last ack after receiving everything that is rejected by the ffmpeg server. However VLC does not report an error to the user, it simply hides it.
In fact, by going through the code, I have the feeling that at the moment the server simply does not care at all about acknowledgments received from the client - it parses them but doesn't do anything else.