[FFmpeg-devel] [PATCH] ffmpeg: do not mark outputs as finished unless AVERROR_EOF

Mort Yao soi at mort.ninja
Sun Nov 22 03:38:25 CET 2015


For now, the concat demuxer summarily drops the whole output streams in case of
an error (e.g. EINVAL), which might not be the ideal behavior if the rest of
input has yet to be processed and concatenated.

To reproduce,

$ ffmpeg -y -f concat -i filelist.txt -c copy output.mp4

On example input:

https://www.dropbox.com/s/pwd7eqlyg0mvg3c/filelist.txt
https://www.dropbox.com/s/qf688bqjbvrjdzd/part-05.mp4 (this file contains some
corrupted frames)
https://www.dropbox.com/s/ac4fm79a4xbvtgj/part-06.mp4
https://www.dropbox.com/s/dwoe8do0qy2o68t/part-07.mp4

Something like "filelist.txt: Invalid argument" immediately stops the concat
demuxer before processing the second file, which is a premature finish since
all 3 files actually can (and ought to) be further concatenated.

Solution:

Whenever an error occurred in get_input_packet(), process_input() used to
attempt to mark all outputs that didn't go through lavfi as finished. However,
for a concat demuxer, doing so might drop the rest of input streams (in case of
an error such like EINVAL returned by av_read_frame()) and produce incomplete
outputs unexpectedly. This patch shall allow for only finishing outputs when
end-of-file encountered, by checking whether the return code is AVERROR_EOF.
---
 ffmpeg.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index bf5e983..246229c 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -3751,23 +3751,23 @@ static int process_input(int file_index)
             print_error(is->filename, ret);
             if (exit_on_error)
                 exit_program(1);
-        }
-
-        for (i = 0; i < ifile->nb_streams; i++) {
-            ist = input_streams[ifile->ist_index + i];
-            if (ist->decoding_needed) {
-                ret = process_input_packet(ist, NULL, 0);
-                if (ret>0)
-                    return 0;
-            }
+        } else {
+            for (i = 0; i < ifile->nb_streams; i++) {
+                ist = input_streams[ifile->ist_index + i];
+                if (ist->decoding_needed) {
+                    ret = process_input_packet(ist, NULL, 0);
+                    if (ret>0)
+                        return 0;
+                }

-            /* mark all outputs that don't go through lavfi as finished */
-            for (j = 0; j < nb_output_streams; j++) {
-                OutputStream *ost = output_streams[j];
+                /* mark all outputs that don't go through lavfi as finished */
+                for (j = 0; j < nb_output_streams; j++) {
+                    OutputStream *ost = output_streams[j];

-                if (ost->source_index == ifile->ist_index + i &&
-                    (ost->stream_copy || ost->enc->type == AVMEDIA_TYPE_SUBTITLE))
-                    finish_output_stream(ost);
+                    if (ost->source_index == ifile->ist_index + i &&
+                        (ost->stream_copy || ost->enc->type == AVMEDIA_TYPE_SUBTITLE))
+                        finish_output_stream(ost);
+                }
             }
         }

--
2.6.2


More information about the ffmpeg-devel mailing list