Opened 7 years ago
Last modified 8 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: | adionc@gmail.com | Blocked By: | |
Blocking: | Reproduced by developer: | yes | |
Analyzed by developer: | no |
Description
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); to: //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 (7)
comment:2 by , 5 years ago
Keywords: | facebook removed |
---|---|
Priority: | important → normal |
Please send your patch - made with git format-patch
- to the FFmpeg development mailing list.
comment:3 by , 5 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:5 by , 3 years 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.
comment:6 by , 2 years ago
Reproduced by developer: | set |
---|
I have had to use the fix described above for one of my projects, and can confirm both the existence of the problem, and the solution to be a working solution. Although I made my own patch in vcpkg. I will describe the process encase others find it of value.
I use vcpkg ffmpeg:x64-windows build in Visual Studio 2022. To make a vcpkg patch, you must first create a patch file <vcpkg_install_dir>/ports/ffmpeg/nonblock-tls.patch
with the following diff contents:
diff --git a/libavformat/tls_schannel.c b/libavformat/tls_schannel.c index d4959f7..4c10dad 100644 --- a/libavformat/tls_schannel.c +++ b/libavformat/tls_schannel.c @@ -415,8 +415,16 @@ static int tls_read(URLContext *h, uint8_t *buf, int len) } } - ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset, - c->enc_buf_size - c->enc_buf_offset); + 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; + if (ret == AVERROR_EOF) { c->connection_closed = 1; ret = 0; diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c index f6a1a5e..518100c 100644 --- a/libavformat/tls_securetransport.c +++ b/libavformat/tls_securetransport.c @@ -198,7 +198,16 @@ static OSStatus tls_read_cb(SSLConnectionRef connection, void *data, size_t *dat URLContext *h = (URLContext*)connection; TLSContext *c = h->priv_data; size_t requested = *dataLength; + + int set_flag_nonblock = 0; + if (h->flags&AVIO_FLAG_NONBLOCK && !(c->tls_shared.tcp->flags&AVIO_FLAG_NONBLOCK)) { + c->tls_shared.tcp->flags |= AVIO_FLAG_NONBLOCK; + set_flag_nonblock = 1; + } int read = ffurl_read(c->tls_shared.tcp, data, requested); + if (set_flag_nonblock) + c->tls_shared.tcp->flags &= ~AVIO_FLAG_NONBLOCK; + if (read <= 0) { *dataLength = 0; switch(AVUNERROR(read)) {
Then you must update the portfile.cmake
file in the same directory <vcpkg_install_dir>/ports/ffmpeg/portfile.cmake
There will be a list of .patch
files under a PATCHES
directive, add the nonblock-tls.patch
file to that list for example:
if(VCPKG_TARGET_IS_WINDOWS) set(PATCHES 0017-Patch-for-ticket-9019-CUDA-Compile-Broken-Using-MSVC.patch) # https://trac.ffmpeg.org/ticket/9019 endif() vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO ffmpeg/ffmpeg REF n4.4.1 SHA512 a53e617937f9892c5cfddb00896be9ad8a3e398dc7cf3b6c893b52ff38aff6ff0cbc61a44cd5f93d9a28f775e71ae82996a5e2b699a769c1de8f882aab34c797 HEAD_REF master PATCHES 0001-create-lib-libraries.patch 0003-fix-windowsinclude.patch 0004-fix-debug-build.patch 0006-fix-StaticFeatures.patch 0007-fix-lib-naming.patch 0009-Fix-fdk-detection.patch 0010-Fix-x264-detection.patch 0011-Fix-x265-detection.patch 0012-Fix-ssl-110-detection.patch 0013-define-WINVER.patch 0014-avfilter-dependency-fix.patch # https://ffmpeg.org/pipermail/ffmpeg-devel/2021-February/275819.html 0015-Fix-xml2-detection.patch 0016-configure-dnn-needs-avformat.patch # https://ffmpeg.org/pipermail/ffmpeg-devel/2021-May/279926.html ${PATCHES} 0018-libaom-Dont-use-aom_codec_av1_dx_algo.patch 0019-libx264-Do-not-explicitly-set-X264_API_IMPORTS.patch 0020-fix-aarch64-libswscale.patch 0021-fix-sdl2-version-check.patch nonblock-tls.patch )
Now you must remove and then reinstall ffmpeg using vcpkg.
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:
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:
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.