diff options
author | wm4 <nfxjfg@googlemail.com> | 2017-03-02 16:01:01 +0100 |
---|---|---|
committer | wm4 <nfxjfg@googlemail.com> | 2017-03-03 08:45:43 +0100 |
commit | 7dd44cde2abb156710f26a08b6cd6c8dd9a9793d (patch) | |
tree | d9339c09ab2b06216cd14127ee82d63cfe5014d5 | |
parent | 736f4af4fea44d15c5d08558d3fe6f1a0fc98173 (diff) | |
download | ffmpeg-7dd44cde2abb156710f26a08b6cd6c8dd9a9793d.tar.gz |
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.
-rw-r--r-- | ffmpeg.c | 31 | ||||
-rw-r--r-- | ffmpeg.h | 3 | ||||
-rw-r--r-- | ffmpeg_filter.c | 13 |
3 files changed, 44 insertions, 3 deletions
@@ -226,7 +226,7 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts) AV_BUFFERSRC_FLAG_PUSH); } -static void sub2video_update(InputStream *ist, AVSubtitle *sub) +void sub2video_update(InputStream *ist, AVSubtitle *sub) { AVFrame *frame = ist->sub2video.frame; int8_t *dst; @@ -480,6 +480,15 @@ static void ffmpeg_cleanup(int ret) av_frame_free(&frame); } av_fifo_free(fg->inputs[j]->frame_queue); + if (fg->inputs[j]->ist->sub2video.sub_queue) { + while (av_fifo_size(fg->inputs[j]->ist->sub2video.sub_queue)) { + AVSubtitle sub; + av_fifo_generic_read(fg->inputs[j]->ist->sub2video.sub_queue, + &sub, sizeof(sub), NULL); + avsubtitle_free(&sub); + } + av_fifo_free(fg->inputs[j]->ist->sub2video.sub_queue); + } av_buffer_unref(&fg->inputs[j]->hw_frames_ctx); av_freep(&fg->inputs[j]->name); av_freep(&fg->inputs[j]); @@ -2468,6 +2477,7 @@ fail: static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) { AVSubtitle subtitle; + int free_sub = 1; int i, ret = avcodec_decode_subtitle2(ist->dec_ctx, &subtitle, got_output, pkt); @@ -2502,7 +2512,21 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) if (!*got_output) return ret; - sub2video_update(ist, &subtitle); + if (ist->sub2video.frame) { + sub2video_update(ist, &subtitle); + } else if (ist->nb_filters) { + if (!ist->sub2video.sub_queue) + ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle)); + if (!ist->sub2video.sub_queue) + exit_program(1); + if (!av_fifo_space(ist->sub2video.sub_queue)) { + ret = av_fifo_realloc2(ist->sub2video.sub_queue, 2 * av_fifo_size(ist->sub2video.sub_queue)); + if (ret < 0) + exit_program(1); + } + av_fifo_generic_write(ist->sub2video.sub_queue, &subtitle, sizeof(subtitle), NULL); + free_sub = 0; + } if (!subtitle.num_rects) goto out; @@ -2520,7 +2544,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) } out: - avsubtitle_free(&subtitle); + if (free_sub) + avsubtitle_free(&subtitle); return ret; } @@ -337,6 +337,7 @@ typedef struct InputStream { struct sub2video { int64_t last_pts; int64_t end_pts; + AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init AVFrame *frame; int w, h; } sub2video; @@ -636,6 +637,8 @@ int filtergraph_is_simple(FilterGraph *fg); int init_simple_filtergraph(InputStream *ist, OutputStream *ost); int init_complex_filtergraph(FilterGraph *fg); +void sub2video_update(InputStream *ist, AVSubtitle *sub); + int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ffmpeg_parse_options(int argc, char **argv); diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c index 816c906c7e..da2a46d3b7 100644 --- a/ffmpeg_filter.c +++ b/ffmpeg_filter.c @@ -1137,6 +1137,19 @@ int configure_filtergraph(FilterGraph *fg) } } + /* process queued up subtitle packets */ + for (i = 0; i < fg->nb_inputs; i++) { + InputStream *ist = fg->inputs[i]->ist; + if (ist->sub2video.sub_queue && ist->sub2video.frame) { + while (av_fifo_size(ist->sub2video.sub_queue)) { + AVSubtitle tmp; + av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL); + sub2video_update(ist, &tmp); + avsubtitle_free(&tmp); + } + } + } + return 0; } |