summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <[email protected]>2025-08-12 12:17:41 +0200
committerNiklas Haas <[email protected]>2025-09-02 09:55:31 +0000
commit68c083c43ff7a87619e15f13205ad45767b9fb53 (patch)
treee4c81eb14fe082b9960e419580bd2cefebaf70dd
parentfc5a6a3b390d2b2a0dbc6d1f1efa83a1f17a5d35 (diff)
avfilter/vf_libplacebo: refactor status handling
Instead of having a single s->status field to track the most recently EOF'd stream, track the number of active streams directly and only query the most recent status at the end. The reason this worked before is because we implicitly relied on the assumption that `ok` would always be true until all streams are EOF, but because it's possible to have gaps in the timeline when mixing multiple streams, this is not always the case in principle. In practice, this fixes a bug where the filter would early-exit (EOF) too soon, when any input reached EOF and there is a gap in the timeline.
-rw-r--r--libavfilter/vf_libplacebo.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 70aa746e80..e3761bead8 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -170,8 +170,7 @@ typedef struct LibplaceboContext {
/* input state */
LibplaceboInput *inputs;
int nb_inputs;
- int64_t status_pts; ///< tracks status of most recently used input
- int status;
+ int nb_active;
/* settings */
char *out_format_string;
@@ -768,6 +767,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct
return AVERROR(ENOMEM);
for (int i = 0; i < s->nb_inputs; i++)
RET(input_init(avctx, &s->inputs[i], i));
+ s->nb_active = s->nb_inputs;
s->linear_rr = pl_renderer_create(s->log, s->gpu);
/* fall through */
@@ -1166,11 +1166,7 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
pl_queue_push(input->queue, NULL); /* Signal EOF to pl_queue */
input->status = status;
input->status_pts = pts;
- if (!s->status || pts >= s->status_pts) {
- /* Also propagate to output unless overwritten by later status change */
- s->status = status;
- s->status_pts = pts;
- }
+ s->nb_active--;
}
return 0;
@@ -1254,8 +1250,18 @@ static int libplacebo_activate(AVFilterContext *ctx)
for (int i = 0; i < s->nb_inputs; i++)
drain_input_pts(&s->inputs[i], out_pts);
return output_frame(ctx, out_pts);
- } else if (s->status) {
- ff_outlink_set_status(outlink, s->status, s->status_pts);
+ } else if (s->nb_active == 0) {
+ /* Forward most recent status */
+ int status = s->inputs[0].status;
+ int64_t status_pts = s->inputs[0].status_pts;
+ for (int i = 1; i < s->nb_inputs; i++) {
+ const LibplaceboInput *in = &s->inputs[i];
+ if (in->status_pts > status_pts) {
+ status = s->inputs[i].status;
+ status_pts = s->inputs[i].status_pts;
+ }
+ }
+ ff_outlink_set_status(outlink, status, status_pts);
return 0;
}