diff options
author | Niklas Haas <git@haasn.dev> | 2023-06-15 16:01:55 +0200 |
---|---|---|
committer | Niklas Haas <git@haasn.dev> | 2023-06-20 17:09:58 +0200 |
commit | 502b699a506b7854d382a58e4910f5f13f4846e4 (patch) | |
tree | a99bcaf0e09bb8b0f2921ff8e052301e469370f1 /libavfilter | |
parent | 0eb37c2419ad8728fbc5df8dc85791fc8fdf26e2 (diff) | |
download | ffmpeg-502b699a506b7854d382a58e4910f5f13f4846e4.tar.gz |
lavfi/vf_libplacebo: determine PTS of next frame from any input
When combining multiple inputs with different PTS and durations, in
input-timed mode, we emit one output frame for every input frame PTS,
from *any* input. So when combining a low FPS stream with a high FPS
stream, the output framerate would match the higher FPS, independent of
which order they are specified in.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/vf_libplacebo.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index a56ebbf54e..47f019fa19 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -973,11 +973,11 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input) static int libplacebo_activate(AVFilterContext *ctx) { - int ret; + int ret, retry = 0; LibplaceboContext *s = ctx->priv; LibplaceboInput *in = &s->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; - int64_t pts; + int64_t pts, out_pts; FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); pl_log_level_update(s->log, get_log_level()); @@ -989,24 +989,31 @@ static int libplacebo_activate(AVFilterContext *ctx) if (ff_outlink_frame_wanted(outlink)) { if (s->fps.num) { - pts = outlink->frame_count_out; - } else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) { - /* No frames queued */ - if (in->status) { - pts = in->status_pts; - } else { - ff_inlink_request_frame(in->link); - return 0; + out_pts = outlink->frame_count_out; + } else { + /* Determine the PTS of the next frame from any active input */ + out_pts = INT64_MAX; + for (int i = 0; i < s->nb_inputs; i++) { + LibplaceboInput *in = &s->inputs[i]; + if (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0) { + out_pts = FFMIN(out_pts, pts); + } else if (!in->status) { + ff_inlink_request_frame(in->link); + retry = true; + } } + + if (retry) /* some inputs are incomplete */ + return 0; } - if (s->status && pts >= s->status_pts) { + if (s->status && out_pts >= s->status_pts) { ff_outlink_set_status(outlink, s->status, s->status_pts); return 0; } in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params( - .pts = pts * av_q2d(outlink->time_base), + .pts = out_pts * av_q2d(outlink->time_base), .radius = pl_frame_mix_radius(&s->params), .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)), )); @@ -1018,7 +1025,7 @@ static int libplacebo_activate(AVFilterContext *ctx) case PL_QUEUE_OK: if (!s->fps.num) av_fifo_drain2(in->out_pts, 1); - return output_frame(ctx, pts); + return output_frame(ctx, out_pts); case PL_QUEUE_ERR: return AVERROR_EXTERNAL; } |