PR #25823 opened by Zhao Zhili (quink)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25823
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25823.patch

FFmpeg has no limited range RGB. swscale expands limited range YUV to
full range RGB, but this filter inherited the input range, so YUV input
produced studio range RGB that other filters read as full range.

# Summary of changes

Briefly describe what this PR does and why.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



>From 124fb14408d69d572611c25e7ae744661b33bff8 Mon Sep 17 00:00:00 2001
From: Zhao Zhili <[email protected]>
Date: Thu, 5 Nov 2026 22:23:14 +0800
Subject: [PATCH] avfilter/vf_scale_d3d12: always output full range RGB

FFmpeg has no limited range RGB. swscale expands limited range YUV to
full range RGB, but this filter inherited the input range, so YUV input
produced studio range RGB that other filters read as full range.
---
 doc/filters.texi             | 16 ++++------------
 libavfilter/vf_scale_d3d12.c | 29 +++++++++++++++++------------
 2 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index ec23628067a..6a3ecc8dd60 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -22458,11 +22458,10 @@ Limited range.
 Full range.
 @end table
 
-If not specified, it defaults to the input range, except that a
-@option{out_color_transfer} of @code{linear} (explicit or defaulted,
-see below) always selects @code{full} range. If the range is still
-unspecified at that point, it defaults to @code{limited} for YUV
-output and @code{full} for RGB output.
+This option only applies to YUV output; RGB output is always full range
+and @code{limited} is rejected for it.
+If not specified, YUV output uses the input range, or @code{limited} if
+the input range is unspecified.
 
 @item out_color_primaries
 Set the output color primaries. It accepts the same values as the
@@ -22528,13 +22527,6 @@ its HDR color properties:
 @example
 scale_d3d12=format=x2bgr10
 @end example
-
-@item
-Scale and convert to full-range BGRA, for example before @code{hwdownload}
-feeds a renderer that expects full-range RGB:
-@example
-scale_d3d12=format=bgra:out_range=full
-@end example
 @end itemize
 
 @section scharr
diff --git a/libavfilter/vf_scale_d3d12.c b/libavfilter/vf_scale_d3d12.c
index cadd48e5a02..a726ba2fd1f 100644
--- a/libavfilter/vf_scale_d3d12.c
+++ b/libavfilter/vf_scale_d3d12.c
@@ -626,8 +626,8 @@ static int d3d12_scale_get_colorspace(AVFilterContext *ctx, 
int is_rgb, int is_o
                 if (is_output)
                     av_log(ctx, AV_LOG_ERROR,
                            "Studio range linear RGB has no DXGI color "
-                           "space; use out_range=full, or a non-linear "
-                           "out_color_transfer (e.g. bt709)\n");
+                           "space; use a non-linear out_color_transfer "
+                           "(e.g. bt709)\n");
                 else
                     av_log(ctx, AV_LOG_ERROR,
                            "Studio range linear RGB has no DXGI color "
@@ -1230,7 +1230,7 @@ static int scale_d3d12_filter_frame(AVFilterLink *inlink, 
AVFrame *in)
             input_601_hint = in_primaries;
 
         /* Output color properties: options override, otherwise inherit
-         * from the input. RGB output defaults to full range. */
+         * from the input. RGB output is always full range. */
         out_map = d3d12_scale_map_from_dxgi(s->output_format);
         s->output_is_rgb = out_map ? out_map->is_rgb : 0;
         const AVPixFmtDescriptor *out_desc = out_map ? 
av_pix_fmt_desc_get(out_map->pix_fmt) : NULL;
@@ -1250,17 +1250,15 @@ static int scale_d3d12_filter_frame(AVFilterLink 
*inlink, AVFrame *in)
         if (!s->output_is_rgb && out_spc == AVCOL_SPC_RGB)
             out_spc = AVCOL_SPC_UNSPECIFIED;
 
-        if (s->color_range != AVCOL_RANGE_UNSPECIFIED)
-            out_range = s->color_range;
-        else if (out_trc == AVCOL_TRC_LINEAR)
-            /* Linear RGB has no studio-range DXGI color space either  default
-             * to full range and let the processor do the limited->full 
expansion
-             * instead. */
+        /* There is no limited range RGB in FFmpeg. */
+        if (s->output_is_rgb)
             out_range = AVCOL_RANGE_JPEG;
+        else if (s->color_range != AVCOL_RANGE_UNSPECIFIED)
+            out_range = s->color_range;
         else if (in->color_range != AVCOL_RANGE_UNSPECIFIED)
             out_range = in->color_range;
         else
-            out_range = s->output_is_rgb ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
+            out_range = AVCOL_RANGE_MPEG;
 
         ret = d3d12_scale_get_colorspace(ctx, s->output_is_rgb, 1, &out_spc, 
&out_range,
                                          &out_primaries, &out_trc, 
in->chroma_location,
@@ -1756,12 +1754,19 @@ static int scale_d3d12_config_props(AVFilterLink 
*outlink)
     const D3D12ScaleFormatMap *in_map = 
d3d12_scale_map_from_pixfmt(in_frames_ctx->sw_format);
     int input_is_rgb = in_map ? in_map->is_rgb : 0;
 
+    if (s->output_is_rgb && s->color_range == AVCOL_RANGE_MPEG) {
+        av_log(ctx, AV_LOG_ERROR, "out_range=limited does not apply to RGB 
output; "
+               "remove the option or choose a YUV output format\n");
+        av_buffer_unref(&s->hw_frames_ctx_out);
+
+        return AVERROR(EINVAL);
+    }
+
     if (s->color_primaries != AVCOL_PRI_UNSPECIFIED ||
         s->color_transfer  != AVCOL_TRC_UNSPECIFIED ||
         s->color_matrix    != AVCOL_SPC_UNSPECIFIED ||
         input_is_rgb       != s->output_is_rgb ||
-        frames_ctx->sw_format == AV_PIX_FMT_RGBAF16 ||
-        (input_is_rgb && s->color_range != AVCOL_RANGE_UNSPECIFIED))
+        frames_ctx->sw_format == AV_PIX_FMT_RGBAF16)
         av_frame_side_data_remove_by_props(&outlink->side_data, 
&outlink->nb_side_data,
                                            AV_SIDE_DATA_PROP_COLOR_DEPENDENT);
 
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to