diff mbox

[FFmpeg-devel,04/11] avformat/muxers: Add non-blocking mode support for av_write_trailer

Message ID 1470144262-13167-5-git-send-email-sebechlebskyjan@gmail.com
State Superseded
Headers show

Commit Message

sebechlebskyjan@gmail.com Aug. 2, 2016, 1:24 p.m. UTC
From: Jan Sebechlebsky <sebechlebskyjan@gmail.com>

This makes av_write_trailer not to free the resources if write_trailer
call returns AVERROR(EAGAIN) allowing repeated calls of write_trailer of
non-blocking muxer.

Signed-off-by: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
---
 libavformat/avformat.h | 6 +++++-
 libavformat/mux.c      | 3 +++
 2 files changed, 8 insertions(+), 1 deletion(-)

Comments

Michael Niedermayer Aug. 10, 2016, 5:04 p.m. UTC | #1
On Tue, Aug 02, 2016 at 03:24:15PM +0200, sebechlebskyjan@gmail.com wrote:
> From: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
> 
> This makes av_write_trailer not to free the resources if write_trailer
> call returns AVERROR(EAGAIN) allowing repeated calls of write_trailer of
> non-blocking muxer.
> 
> Signed-off-by: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
> ---
>  libavformat/avformat.h | 6 +++++-
>  libavformat/mux.c      | 3 +++
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 818184e..9191c69 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -2508,8 +2508,12 @@ int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
>   *
>   * May only be called after a successful call to avformat_write_header.
>   *
> + * If AVFMT_FLAG_NONBLOCK is set, this call may return AVERROR(EAGAIN)
> + * meaning the operation is pending and the call should be repeated.
> + *
>   * @param s media file handle
> - * @return 0 if OK, AVERROR_xxx on error
> + * @return 0 if OK, AVERROR(EAGAIN) in case call should be repeated,
> + *         other AVERROR on error
>   */
>  int av_write_trailer(AVFormatContext *s);
>  
> diff --git a/libavformat/mux.c b/libavformat/mux.c
> index e9973ed..b58e4c1 100644
> --- a/libavformat/mux.c
> +++ b/libavformat/mux.c
> @@ -1238,6 +1238,9 @@ fail:
>          }
>      }
>  
> +    if (ret == AVERROR(EAGAIN))
> +        return ret;

IIUC the non blocking code works only if packet interleaving is not
used (which is implied by AVFMT_FLAG_NONBLOCK being set)

is there an assert ensuring that EAGAIN only occurs in such case
somewhere ?

if it would occur with the interleave code then
ret could be set before or maybe even set to EAGAIN and then

    if (s->internal->header_written && s->oformat->write_trailer) {
        if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
            avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
        if (ret >= 0) {
        ret = s->oformat->write_trailer(s);
        } else {
            s->oformat->write_trailer(s);
        }
    }

would do all kinds of unexpected things like ignoring the write_trailer
return  or returning to the user EAGAIN even when trailer didnt return
that, ...

[...]
sebechlebskyjan@gmail.com Aug. 11, 2016, 9:32 a.m. UTC | #2
On 08/10/2016 07:04 PM, Michael Niedermayer wrote:

> On Tue, Aug 02, 2016 at 03:24:15PM +0200, sebechlebskyjan@gmail.com wrote:
>> From: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
>>
>> This makes av_write_trailer not to free the resources if write_trailer
>> call returns AVERROR(EAGAIN) allowing repeated calls of write_trailer of
>> non-blocking muxer.
>>
>> Signed-off-by: Jan Sebechlebsky <sebechlebskyjan@gmail.com>
>> ---
>>   libavformat/avformat.h | 6 +++++-
>>   libavformat/mux.c      | 3 +++
>>   2 files changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
>> index 818184e..9191c69 100644
>> --- a/libavformat/avformat.h
>> +++ b/libavformat/avformat.h
>> @@ -2508,8 +2508,12 @@ int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
>>    *
>>    * May only be called after a successful call to avformat_write_header.
>>    *
>> + * If AVFMT_FLAG_NONBLOCK is set, this call may return AVERROR(EAGAIN)
>> + * meaning the operation is pending and the call should be repeated.
>> + *
>>    * @param s media file handle
>> - * @return 0 if OK, AVERROR_xxx on error
>> + * @return 0 if OK, AVERROR(EAGAIN) in case call should be repeated,
>> + *         other AVERROR on error
>>    */
>>   int av_write_trailer(AVFormatContext *s);
>>   
>> diff --git a/libavformat/mux.c b/libavformat/mux.c
>> index e9973ed..b58e4c1 100644
>> --- a/libavformat/mux.c
>> +++ b/libavformat/mux.c
>> @@ -1238,6 +1238,9 @@ fail:
>>           }
>>       }
>>   
>> +    if (ret == AVERROR(EAGAIN))
>> +        return ret;
> IIUC the non blocking code works only if packet interleaving is not
> used (which is implied by AVFMT_FLAG_NONBLOCK being set)
>
> is there an assert ensuring that EAGAIN only occurs in such case
> somewhere ?
I've just added comment to av_interleaved_write_frame that it cannot be 
used with muxer
operating in non-blocking mode, but it is certainly good idea to add 
assert as well.
I'll modify and resend the patch with the comment change to add assert too.

> if it would occur with the interleave code then
> ret could be set before or maybe even set to EAGAIN and then
>
>      if (s->internal->header_written && s->oformat->write_trailer) {
>          if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
>              avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
>          if (ret >= 0) {
>          ret = s->oformat->write_trailer(s);
>          } else {
>              s->oformat->write_trailer(s);
>          }
>      }
>
> would do all kinds of unexpected things like ignoring the write_trailer
> return  or returning to the user EAGAIN even when trailer didnt return
> that, ...
>
> [...]
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Regards,
Jan
diff mbox

Patch

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 818184e..9191c69 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -2508,8 +2508,12 @@  int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index);
  *
  * May only be called after a successful call to avformat_write_header.
  *
+ * If AVFMT_FLAG_NONBLOCK is set, this call may return AVERROR(EAGAIN)
+ * meaning the operation is pending and the call should be repeated.
+ *
  * @param s media file handle
- * @return 0 if OK, AVERROR_xxx on error
+ * @return 0 if OK, AVERROR(EAGAIN) in case call should be repeated,
+ *         other AVERROR on error
  */
 int av_write_trailer(AVFormatContext *s);
 
diff --git a/libavformat/mux.c b/libavformat/mux.c
index e9973ed..b58e4c1 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -1238,6 +1238,9 @@  fail:
         }
     }
 
+    if (ret == AVERROR(EAGAIN))
+        return ret;
+
     if (s->oformat->deinit)
         s->oformat->deinit(s);