Opened 5 years ago

Last modified 6 months ago

#6471 new defect

RTMPS stream does not work

Reported by: Ruben Sanchez Castellano Owned by:
Priority: normal Component: avformat
Version: git-master Keywords: rtmps
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no


Using FFmpeg v3.3.1 and trying to open a stream to an RTMPS URL (Facebook with SSL actually) results in a few RTMP packets written to the output stream but then libavformat tries to read something in return. The thing is Facebook does not returns anything resulting in a connection hanged after 5-6 packets.
I solved this issue with this:

rtmpproto.c:3220 from:

    ret = ffurl_read(rt->stream, &c, 1);


    //ret = ffurl_read(rt->stream, &c, 1);
    ret = AVERROR(EAGAIN));

This modification will force to not read anything from the server so the connection does not hang. With this fix I can see the RTMPS stream on Facebook Live preview and does not affect other RTMP streams.

Change History (5)

comment:1 by Adion, 3 years ago

I encountered the same problem, it appears to still exist in FFmpeg v4.1.3 and I think I found the underlying reason for this failure.

The full code is:

    /* set stream into nonblocking mode */
    rt->stream->flags |= AVIO_FLAG_NONBLOCK;

    /* try to read one byte from the stream */
    ret = ffurl_read(rt->stream, &c, 1);

    /* switch the stream back into blocking mode */
    rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;

The problem is that the non-blocking stream flag is not passed down to underlying protocols.
In the case of rtmp, this is not a problem since the protocol is tcp directly.
In the case of rtmps, the protocol is one of the tls implementations, and (at least for securetransport on mac and schannel on windows) they both use a secondary URLProtocol to make the call to tcp.
On this secondary URLProtocol, the flag is not updated however.
Instead of commenting out the lines, I've fixed it in tls_read instead, but to fix it anywhere might require deeper changes (a function to update URLProtocol flags so that protocols know they have to change the flags in the protocols they use perhaps?)

Anyway, here are the changes I've made to temporarily fix this:
In tls_schannel.c tls_read function, change the ffurl_read function to:

int set_flag_nonblock = 0;
if (h->flags&AVIO_FLAG_NONBLOCK && !(s->tcp->flags&AVIO_FLAG_NONBLOCK)) {
  s->tcp->flags |= AVIO_FLAG_NONBLOCK;
  set_flag_nonblock = 1;
ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset,
                 c->enc_buf_size - c->enc_buf_offset);
if (set_flag_nonblock)
  s->tcp->flags &= ~AVIO_FLAG_NONBLOCK;

In tls_securetransport.c I did something similar for tls_read_cb.

I don't use openssl, but at first sight it seems to use a similar way so probably is affected as well.

Last edited 3 years ago by Adion (previous) (diff)

comment:2 by Carl Eugen Hoyos, 3 years ago

Keywords: facebook removed
Priority: importantnormal

Please send your patch - made with git format-patch - to the FFmpeg development mailing list.

comment:3 by Adion, 3 years ago

Cc: added

Is it actually useful to send the patch in the way I did it?
The fix I did and tried is limited to schannel, and a similar one for securetransport.
There seem to be 4 other ssl implementations that are likely affected, and possibly more multi-layered protocols that might be affected too that I'm not aware of.

comment:4 by lebossejames, 2 years ago

Is it works now with ffmpeg?

comment:5 by Gyan, 6 months ago

Adion's workaround does the trick with SecureTransport backend.

If testers are available, I can submit that and similar patches for other TLS libs.

Note: See TracTickets for help on using tickets.