Commit 7dd44cde authored by wm4's avatar wm4

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.
parent 736f4af4
...@@ -226,7 +226,7 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts) ...@@ -226,7 +226,7 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts)
AV_BUFFERSRC_FLAG_PUSH); AV_BUFFERSRC_FLAG_PUSH);
} }
static void sub2video_update(InputStream *ist, AVSubtitle *sub) void sub2video_update(InputStream *ist, AVSubtitle *sub)
{ {
AVFrame *frame = ist->sub2video.frame; AVFrame *frame = ist->sub2video.frame;
int8_t *dst; int8_t *dst;
...@@ -480,6 +480,15 @@ static void ffmpeg_cleanup(int ret) ...@@ -480,6 +480,15 @@ static void ffmpeg_cleanup(int ret)
av_frame_free(&frame); av_frame_free(&frame);
} }
av_fifo_free(fg->inputs[j]->frame_queue); 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_buffer_unref(&fg->inputs[j]->hw_frames_ctx);
av_freep(&fg->inputs[j]->name); av_freep(&fg->inputs[j]->name);
av_freep(&fg->inputs[j]); av_freep(&fg->inputs[j]);
...@@ -2468,6 +2477,7 @@ fail: ...@@ -2468,6 +2477,7 @@ fail:
static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
{ {
AVSubtitle subtitle; AVSubtitle subtitle;
int free_sub = 1;
int i, ret = avcodec_decode_subtitle2(ist->dec_ctx, int i, ret = avcodec_decode_subtitle2(ist->dec_ctx,
&subtitle, got_output, pkt); &subtitle, got_output, pkt);
...@@ -2502,7 +2512,21 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) ...@@ -2502,7 +2512,21 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
if (!*got_output) if (!*got_output)
return ret; return ret;
if (ist->sub2video.frame) {
sub2video_update(ist, &subtitle); 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) if (!subtitle.num_rects)
goto out; goto out;
...@@ -2520,6 +2544,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) ...@@ -2520,6 +2544,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
} }
out: out:
if (free_sub)
avsubtitle_free(&subtitle); avsubtitle_free(&subtitle);
return ret; return ret;
} }
......
...@@ -337,6 +337,7 @@ typedef struct InputStream { ...@@ -337,6 +337,7 @@ typedef struct InputStream {
struct sub2video { struct sub2video {
int64_t last_pts; int64_t last_pts;
int64_t end_pts; int64_t end_pts;
AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init
AVFrame *frame; AVFrame *frame;
int w, h; int w, h;
} sub2video; } sub2video;
...@@ -636,6 +637,8 @@ int filtergraph_is_simple(FilterGraph *fg); ...@@ -636,6 +637,8 @@ int filtergraph_is_simple(FilterGraph *fg);
int init_simple_filtergraph(InputStream *ist, OutputStream *ost); int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
int init_complex_filtergraph(FilterGraph *fg); int init_complex_filtergraph(FilterGraph *fg);
void sub2video_update(InputStream *ist, AVSubtitle *sub);
int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
int ffmpeg_parse_options(int argc, char **argv); int ffmpeg_parse_options(int argc, char **argv);
......
...@@ -1137,6 +1137,19 @@ int configure_filtergraph(FilterGraph *fg) ...@@ -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; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment