diff --git a/configure b/configure
index 64538b17e2..8392c26015 100755
--- a/configure
+++ b/configure
@@ -6588,7 +6588,7 @@ enabled libopus           && {
         require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create
     }
 }
-enabled libplacebo        && require_pkg_config libplacebo "libplacebo >= 4.184.0" libplacebo/vulkan.h pl_vulkan_create
+enabled libplacebo        && require_pkg_config libplacebo "libplacebo >= 4.192.0" libplacebo/vulkan.h pl_vulkan_create
 enabled libpulse          && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new
 enabled librabbitmq       && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection
 enabled librav1e          && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 5b1e7b5285..1386aaeb3a 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -47,6 +47,7 @@ typedef struct LibplaceboContext {
     int force_divisible_by;
     int normalize_sar;
     int apply_filmgrain;
+    int apply_dovi;
     int colorspace;
     int color_range;
     int color_primaries;
@@ -281,8 +282,16 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in)
     LibplaceboContext *s = avctx->priv;
     struct pl_render_params params;
     struct pl_frame image, target;
-    ok = pl_map_avframe(s->gpu, &image, NULL, in);
-    ok &= pl_map_avframe(s->gpu, &target, NULL, out);
+    ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params(
+        .frame    = in,
+        .map_dovi = s->apply_dovi,
+    ));
+
+    ok &= pl_map_avframe_ex(s->gpu, &target, pl_avframe_params(
+        .frame    = out,
+        .map_dovi = false,
+    ));
+
     if (!ok) {
         err = AVERROR_EXTERNAL;
         goto fail;
@@ -381,7 +390,7 @@ fail:
 
 static int filter_frame(AVFilterLink *link, AVFrame *in)
 {
-    int err;
+    int err, changed;
     AVFilterContext *ctx = link->dst;
     LibplaceboContext *s = ctx->priv;
     AVFilterLink *outlink = ctx->outputs[0];
@@ -400,6 +409,14 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
     out->width = outlink->w;
     out->height = outlink->h;
 
+    if (s->apply_dovi && av_frame_get_side_data(in, AV_FRAME_DATA_DOVI_METADATA)) {
+        /* Output of dovi reshaping is always BT.2020+PQ, so infer the correct
+         * output colorspace defaults */
+        out->colorspace = AVCOL_SPC_BT2020_NCL;
+        out->color_primaries = AVCOL_PRI_BT2020;
+        out->color_trc = AVCOL_TRC_SMPTE2084;
+    }
+
     if (s->colorspace >= 0)
         out->colorspace = s->colorspace;
     if (s->color_range >= 0)
@@ -411,6 +428,17 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
 
     RET(process_frames(ctx, out, in));
 
+    int changed_csp = s->colorspace      != out->colorspace     ||
+                      s->color_range     != out->color_range    ||
+                      s->color_trc       != out->color_trc      ||
+                      s->color_primaries != out->color_primaries;
+
+    if (s->apply_dovi || changed_csp) {
+        /* Strip side data if no longer relevant */
+        av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_RPU_BUFFER);
+        av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_METADATA);
+    }
+
     if (s->apply_filmgrain)
         av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
 
@@ -559,6 +587,7 @@ static const AVOption libplacebo_options[] = {
     { "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC },
     { "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
     { "apply_filmgrain", "Apply film grain metadata", OFFSET(apply_filmgrain), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
+    { "apply_dolbyvision", "Apply Dolby Vision metadata", OFFSET(apply_dovi), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
 
     { "deband", "Enable debanding", OFFSET(deband), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
     { "deband_iterations", "Deband iterations", OFFSET(deband_iterations), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 16, DYNAMIC },
