Browse code

ffmpeg: delay processing of subtitles before filters are initialized

If a subtitle packet came before the first video frame could be fully
decoded, the subtitle packet would get discarded. This puts the subtitle
into a queue instead, and processes it once the attached filter graph is
initialized.

wm4 authored on 2017/03/03 00:01:01
Showing 3 changed files
... ...
@@ -226,7 +226,7 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts)
226 226
                                      AV_BUFFERSRC_FLAG_PUSH);
227 227
 }
228 228
 
229
-static void sub2video_update(InputStream *ist, AVSubtitle *sub)
229
+void sub2video_update(InputStream *ist, AVSubtitle *sub)
230 230
 {
231 231
     AVFrame *frame = ist->sub2video.frame;
232 232
     int8_t *dst;
... ...
@@ -480,6 +480,15 @@ static void ffmpeg_cleanup(int ret)
480 480
                 av_frame_free(&frame);
481 481
             }
482 482
             av_fifo_free(fg->inputs[j]->frame_queue);
483
+            if (fg->inputs[j]->ist->sub2video.sub_queue) {
484
+                while (av_fifo_size(fg->inputs[j]->ist->sub2video.sub_queue)) {
485
+                    AVSubtitle sub;
486
+                    av_fifo_generic_read(fg->inputs[j]->ist->sub2video.sub_queue,
487
+                                         &sub, sizeof(sub), NULL);
488
+                    avsubtitle_free(&sub);
489
+                }
490
+                av_fifo_free(fg->inputs[j]->ist->sub2video.sub_queue);
491
+            }
483 492
             av_buffer_unref(&fg->inputs[j]->hw_frames_ctx);
484 493
             av_freep(&fg->inputs[j]->name);
485 494
             av_freep(&fg->inputs[j]);
... ...
@@ -2468,6 +2477,7 @@ fail:
2468 2468
 static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
2469 2469
 {
2470 2470
     AVSubtitle subtitle;
2471
+    int free_sub = 1;
2471 2472
     int i, ret = avcodec_decode_subtitle2(ist->dec_ctx,
2472 2473
                                           &subtitle, got_output, pkt);
2473 2474
 
... ...
@@ -2502,7 +2512,21 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
2502 2502
     if (!*got_output)
2503 2503
         return ret;
2504 2504
 
2505
-    sub2video_update(ist, &subtitle);
2505
+    if (ist->sub2video.frame) {
2506
+        sub2video_update(ist, &subtitle);
2507
+    } else if (ist->nb_filters) {
2508
+        if (!ist->sub2video.sub_queue)
2509
+            ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle));
2510
+        if (!ist->sub2video.sub_queue)
2511
+            exit_program(1);
2512
+        if (!av_fifo_space(ist->sub2video.sub_queue)) {
2513
+            ret = av_fifo_realloc2(ist->sub2video.sub_queue, 2 * av_fifo_size(ist->sub2video.sub_queue));
2514
+            if (ret < 0)
2515
+                exit_program(1);
2516
+        }
2517
+        av_fifo_generic_write(ist->sub2video.sub_queue, &subtitle, sizeof(subtitle), NULL);
2518
+        free_sub = 0;
2519
+    }
2506 2520
 
2507 2521
     if (!subtitle.num_rects)
2508 2522
         goto out;
... ...
@@ -2520,7 +2544,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
2520 2520
     }
2521 2521
 
2522 2522
 out:
2523
-    avsubtitle_free(&subtitle);
2523
+    if (free_sub)
2524
+        avsubtitle_free(&subtitle);
2524 2525
     return ret;
2525 2526
 }
2526 2527
 
... ...
@@ -337,6 +337,7 @@ typedef struct InputStream {
337 337
     struct sub2video {
338 338
         int64_t last_pts;
339 339
         int64_t end_pts;
340
+        AVFifoBuffer *sub_queue;    ///< queue of AVSubtitle* before filter init
340 341
         AVFrame *frame;
341 342
         int w, h;
342 343
     } sub2video;
... ...
@@ -636,6 +637,8 @@ int filtergraph_is_simple(FilterGraph *fg);
636 636
 int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
637 637
 int init_complex_filtergraph(FilterGraph *fg);
638 638
 
639
+void sub2video_update(InputStream *ist, AVSubtitle *sub);
640
+
639 641
 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
640 642
 
641 643
 int ffmpeg_parse_options(int argc, char **argv);
... ...
@@ -1137,6 +1137,19 @@ int configure_filtergraph(FilterGraph *fg)
1137 1137
         }
1138 1138
     }
1139 1139
 
1140
+    /* process queued up subtitle packets */
1141
+    for (i = 0; i < fg->nb_inputs; i++) {
1142
+        InputStream *ist = fg->inputs[i]->ist;
1143
+        if (ist->sub2video.sub_queue && ist->sub2video.frame) {
1144
+            while (av_fifo_size(ist->sub2video.sub_queue)) {
1145
+                AVSubtitle tmp;
1146
+                av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL);
1147
+                sub2video_update(ist, &tmp);
1148
+                avsubtitle_free(&tmp);
1149
+            }
1150
+        }
1151
+    }
1152
+
1140 1153
     return 0;
1141 1154
 }
1142 1155