diff mbox

[FFmpeg-devel] ffmpeg: Properly handle EOF return when flushing encoder

Message ID 20191023121141.26997-1-andriy.gelman@gmail.com
State New
Headers show

Commit Message

Andriy Gelman Oct. 23, 2019, 12:11 p.m. UTC
From: Andriy Gelman <andriy.gelman@gmail.com>

When flushing an encoder we send a NULL frame to avcodec_send_frame()
and then deque all compressed packets in avcodec_recieve_packet() until
AVERROR(EAGAIN) is returned (indicating that all compressed packets have
been removed). The second time that avcodec_send_frame() is called with a
NULL frame it returns AVERROR_EOF.

At the moment, avcoded_send_frame() treats all errors as fatal errors,
even when AVERROR_EOF is returned, meaning that an encoder is not
properly shutdown.
Since all other returns are handled after the while loop, it suffices to
break when AVERROR_EOF is encountered to fix this problem.
---
 fftools/ffmpeg.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

Comments

James Almer Oct. 23, 2019, 5:25 p.m. UTC | #1
On 10/23/2019 9:11 AM, Andriy Gelman wrote:
> From: Andriy Gelman <andriy.gelman@gmail.com>
> 
> When flushing an encoder we send a NULL frame to avcodec_send_frame()
> and then deque all compressed packets in avcodec_recieve_packet() until
> AVERROR(EAGAIN) is returned (indicating that all compressed packets have
> been removed). The second time that avcodec_send_frame() is called with a
> NULL frame it returns AVERROR_EOF.
> 
> At the moment, avcoded_send_frame() treats all errors as fatal errors,
> even when AVERROR_EOF is returned, meaning that an encoder is not
> properly shutdown.
> Since all other returns are handled after the while loop, it suffices to
> break when AVERROR_EOF is encountered to fix this problem.
> ---
>  fftools/ffmpeg.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> index 8e408c808a..9e9fc7a714 100644
> --- a/fftools/ffmpeg.c
> +++ b/fftools/ffmpeg.c
> @@ -1933,12 +1933,8 @@ static void flush_encoders(void)
>  
>              while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) {
>                  ret = avcodec_send_frame(enc, NULL);
> -                if (ret < 0) {
> -                    av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
> -                           desc,
> -                           av_err2str(ret));
> -                    exit_program(1);
> -                }
> +                if (ret == AVERROR_EOF)
> +                    break;

avcodec_receive_packet() is not meant to return EAGAIN when in flushing
mode. If it's not instead returning AVERROR_EOF when there's nothing to
output, then it's a bug in the encoder that's propagating the wrong
error code, and it should be fixed there.

>              }
>  
>              update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index);
>
diff mbox

Patch

diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 8e408c808a..9e9fc7a714 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1933,12 +1933,8 @@  static void flush_encoders(void)
 
             while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) {
                 ret = avcodec_send_frame(enc, NULL);
-                if (ret < 0) {
-                    av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
-                           desc,
-                           av_err2str(ret));
-                    exit_program(1);
-                }
+                if (ret == AVERROR_EOF)
+                    break;
             }
 
             update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index);