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.
... | ... |
@@ -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 |
|