Commit 00043979b0 for ffmpeg
commit 00043979b02430429b95bf758f12cb72ca9ec300
Author: Kacper Michajłow <kasper93@gmail.com>
Date: Wed Sep 30 03:05:35 2026 +0200
avfilter/vf_libplacebo: negotiate the chroma location
The output link takes the chroma_location value, or any location when it
is not set, and the output frames are rendered to the negotiated one, or
keep the location of the input when none was negotiated, the same way as
for the color space, color range and alpha mode. The inputs accept any
location, and input without one is assumed to be sited like the output.
The option can no longer be changed with commands, since it only takes
effect when the formats are negotiated.
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
diff --git a/doc/filters.texi b/doc/filters.texi
index f22d354691..bc33c79848 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -17262,9 +17262,12 @@ fail negotiation otherwise. Disabled by default.
@item color_trc
@item range
@item chroma_location
-Configure the colorspace that output frames will be delivered in. The default
-value of @code{auto} outputs frames in the same format as the input frames,
-leading to no change. For any other value, conversion will be performed.
+Configure the colorspace that output frames will be delivered in. For any value
+other than the default @code{auto}, conversion will be performed. With
+@code{auto}, @option{color_primaries} and @option{color_trc} keep the values of
+the input frames, while @option{colorspace}, @option{range} and
+@option{chroma_location} use the values negotiated with the filtergraph, which
+are those of the input unless a following filter requires others.
See the @ref{setparams} filter for a list of possible values.
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 5d3807e36d..b7097c2740 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -968,6 +968,8 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
out->colorspace = outlink->colorspace;
out->color_range = outlink->color_range;
out->alpha_mode = outlink->alpha_mode;
+ if (outlink->chroma_location != AVCHROMA_LOC_UNSPECIFIED)
+ out->chroma_location = outlink->chroma_location;
if (s->deinterlace)
out->flags &= ~(AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST);
@@ -983,8 +985,6 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
out->color_trc = s->color_trc;
if (s->color_primaries >= 0)
out->color_primaries = s->color_primaries;
- if (s->chroma_location >= 0)
- out->chroma_location = s->chroma_location;
/* Strip side data if no longer relevant */
if (out->width != ref->width || out->height != ref->height)
@@ -1146,6 +1146,10 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
.discard = discard_frame,
};
+ /* Input without a chroma location is assumed to be sited like the output. */
+ if (in->chroma_location == AVCHROMA_LOC_UNSPECIFIED)
+ in->chroma_location = outlink->chroma_location;
+
in->opaque = s;
pl_queue_push(input->queue, &src);
@@ -1351,6 +1355,7 @@ done:
RET(ff_formats_ref(ff_all_color_spaces(), &cfg_in[i]->color_spaces));
RET(ff_formats_ref(ff_all_color_ranges(), &cfg_in[i]->color_ranges));
RET(ff_formats_ref(ff_all_alpha_modes(), &cfg_in[i]->alpha_modes));
+ RET(ff_formats_ref(ff_all_chroma_locations(), &cfg_in[i]->chroma_locations));
}
RET(ff_formats_ref(outfmts, &cfg_out[0]->formats));
@@ -1366,6 +1371,10 @@ done:
outfmts = s->alpha_mode > 0 ? ff_make_formats_list_singleton(s->alpha_mode)
: ff_all_alpha_modes();
RET(ff_formats_ref(outfmts, &cfg_out[0]->alpha_modes));
+
+ outfmts = s->chroma_location > 0 ? ff_make_formats_list_singleton(s->chroma_location)
+ : ff_all_chroma_locations();
+ RET(ff_formats_ref(outfmts, &cfg_out[0]->chroma_locations));
return 0;
fail:
@@ -1669,8 +1678,8 @@ static const AVOption libplacebo_options[] = {
{"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
{"vlog", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_V_LOG}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
- {"chroma_location", "select chroma location", OFFSET(chroma_location), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCHROMA_LOC_NB-1, DYNAMIC, .unit = "chroma_location"},
- {"auto", "keep the same chroma location", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, STATIC, .unit = "chroma_location"},
+ {"chroma_location", "select chroma location", OFFSET(chroma_location), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCHROMA_LOC_NB-1, STATIC, .unit = "chroma_location"},
+ {"auto", "use the negotiated chroma location", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, STATIC, .unit = "chroma_location"},
{"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, STATIC, .unit = "chroma_location"},
{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, STATIC, .unit = "chroma_location"},
{"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_LEFT}, 0, 0, STATIC, .unit = "chroma_location"},