Hello everyone,
we use ffmpeg libraries to ingest our video streams using the RTMP protocol . 
So far we use the librtmp backend instead of the built-in implementation  since 
we  require  Flash url Autentication parameters  (needed for many CDN's ), 
Until now, we were using ffmpeg 2.7.0 successfully to do this  but as we 
upgraded to newer master builds (i.e, 387464b) we found that many times 
av_interleaved_write calls would be stuck when writing small audio or video 
packets .

Since we could not find a definitive cause for this , we built ffmpeg & librmtp 
libraries in debug mode to review the call stack. We have discovered that when 
our program hangs the retry_transfer_wrapper (avio.c) loop never breaks:

https://github.com/FFmpeg/FFmpeg/blob/4ac88ba5487e026bf81da565f97cfcf8f920657d/libavformat/avio.c#L376

while (len < size_min) { 
[...]
ret = transfer_func(h, buf + len, size - len);
[...]

 else if (ret == AVERROR_EOF)
            return (len > 0) ? len : AVERROR_EOF;
        else if (ret < 0)
            return ret;
 [...]
len += ret; //loop counter
}
Further debugging showed us that transfer_func actually calls RTMP_Write  from 
Librtmp (rtmp.c. 
https://git.ffmpeg.org/gitweb/rtmpdump.git/blob_plain/HEAD:/librtmp/rtmp.c)
 This callback returns 0 when packet size is less than 11 bytes (size-len) 
[...]
    if (size < 11) {
      /* FLV pkt too small */
      return 0;
    }
[...]

So, if transfer_func = 0, there is no way to break the loop since this special 
case is not handled (ret ==0).

We reviewed history for avio.c and we found that in commit 
858db4b01fa2b55ee55056c033054ca54ac9b0fd  , the error handling mechanism was 
changed so that  0 was no longer threated as an EOF:
https://github.com/FFmpeg/FFmpeg/commit/858db4b01fa2b55ee55056c033054ca54ac9b0fd

 According to commit message, "...In case of returning >= 0, url_read/url_write 
is retried until error is returned.". Ever since then, the code in master does 
not seem to handle "LIBRTMP: FLV special case for  packet too small (code =0)". 
Previously, in  ffmpeg 2.7.0,)  an error code 0 would return len (0) and break 
the loop:
https://github.com/FFmpeg/FFmpeg/blob/6e94e77632df457da03b5c27fff8a1b976f6994d/libavformat/avio.c#L324


We where thinking about adding a custom handler for ret =0 in avio.c to handle 
this case.
[.]
} else if (ret == AVERROR_EOF)
            return (len > 0) ? len : AVERROR_EOF;
        else if (ret < 0)
            return ret;
        else if (ret == 0) ///handle "LIBRTMP FLV packet too small code" here
            return len;
        if (ret) {
            fast_retries = FFMAX(fast_retries, 2);
            wait_since = 0;
        }

However, we don't want to formally submit  this patch right now, since  we 
don't know how this could impact other protocols and parts of ffmpeg. Moreover, 
commit 858db4b also modified aviobuf.c cache.c  , so we would prefer to discuss 
with the ffmpeg community  if this is a valid approach.


Regards,
Albert Andaluz
Research Engineer


MEDIAPRO
Av. Diagonal 177, Planta 14
08018 Barcelona - Spain
Landline: +34 93 476 1551 (ext. 2327)
aandaluz (at) mediapro.tv
www.automatic.tv



_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to