diff mbox series

[FFmpeg-devel,v2,11/22] lavfi/vf_libplacebo: support blending multiple inputs

Message ID 20230618111955.40994-13-ffmpeg@haasn.xyz
State New
Headers show
Series [FFmpeg-devel,v2,01/22] lavfi/vf_libplacebo: drop redundant case | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Niklas Haas June 18, 2023, 11:17 a.m. UTC
From: Niklas Haas <git@haasn.dev>

Subsequent inputs require frame blending to be enabled, in order to not
overwrite the existing frame contents.

For output metadata, we implicitly copy the metadata of the *first*
available stream (falling back to the second stream if the first has
already reached EOF, and so on). This is done to resolve any conflicts
between inputs with differing metadata. So when e.g. input 1 is HDR and
output 2 is SDR, the output will be HDR, and vice versa. This logic
could probablly be improved by dynamically determining some "superior"
set of metadata, but I don't want to handle that complexity in this
series.
---
 libavfilter/vf_libplacebo.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 5b45d4f8fb5..5ea6fcd7920 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -786,12 +786,18 @@  static int output_frame(AVFilterContext *ctx, int64_t pts)
 {
     int err = 0, ok, changed_csp;
     LibplaceboContext *s = ctx->priv;
-    LibplaceboInput *in = &s->inputs[0];
     AVFilterLink *outlink = ctx->outputs[0];
     const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
-    const AVFrame *ref = ref_frame(&in->mix);
     struct pl_frame target;
+    const AVFrame *ref = NULL;
     AVFrame *out;
+
+    /* Use the first active input as metadata reference */
+    for (int i = 0; i < s->nb_inputs; i++) {
+        const LibplaceboInput *in = &s->inputs[i];
+        if (in->qstatus == PL_QUEUE_OK && (ref = ref_frame(&in->mix)))
+            break;
+    }
     if (!ref)
         return 0;
 
@@ -862,8 +868,18 @@  static int output_frame(AVFilterContext *ctx, int64_t pts)
         goto fail;
     }
 
-    update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));
-    pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
+    /* Draw first frame opaque, others with blending */
+    s->params.skip_target_clearing = false;
+    s->params.blend_params = NULL;
+    for (int i = 0; i < s->nb_inputs; i++) {
+        LibplaceboInput *in = &s->inputs[i];
+        if (in->qstatus != PL_QUEUE_OK)
+            continue;
+        update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));
+        pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
+        s->params.skip_target_clearing = true;
+        s->params.blend_params = &pl_alpha_overlay;
+    }
 
     if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
         pl_unmap_avframe(s->gpu, &target);