This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit f3d2f99263e1f19b497f5d3b6280d3588c704495 Author: Kacper Michajłow <[email protected]> AuthorDate: Wed Sep 9 07:13:03 2026 +0200 Commit: Kacper Michajłow <[email protected]> CommitDate: Thu Oct 1 14:31:15 2026 +0000 avfilter/buffersrc: add chroma_location parameter Lets the caller state the chroma siting of the frames it feeds in, which is what the rest of the graph negotiates against. A tagged source constrains the link to its own value, an untagged one places no constraint at all, there being nothing to convert from. Signed-off-by: Kacper Michajłow <[email protected]> --- doc/APIchanges | 4 ++-- doc/filters.texi | 7 ++++++ libavfilter/buffersrc.c | 57 +++++++++++++++++++++++++++++++++++++++++++------ libavfilter/buffersrc.h | 5 +++++ libavfilter/version.h | 2 +- 5 files changed, 65 insertions(+), 10 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 103817062c..80683f77e2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,8 +2,8 @@ The last version increases of all libraries were on 2026-06-23. API changes, most recent first: -2026-09-xx - xxxxxxxxxx - lavfi 12.4.101 - avfilter.h - Add AVFilterLink.chroma_location. +2026-09-xx - xxxxxxxxxx - lavfi 12.4.102 - avfilter.h buffersrc.h + Add AVFilterLink.chroma_location and AVBufferSrcParameters.chroma_location. 2026-09-xx - xxxxxxxxxx - lavc 63.16.100 - avcodec.h Add AV_CODEC_CONFIG_CHROMA_LOCATION. diff --git a/doc/filters.texi b/doc/filters.texi index aa3b37490b..7de2855c78 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -30110,6 +30110,13 @@ A string representing the alpha mode of the buffered video frames. It may be a number corresponding to an alpha mode, or an alpha mode name. +@item chroma_location +A string representing the chroma sample location of the buffered video +frames. It may be a number corresponding to a chroma sample location, or a +chroma sample location name. When it is not set, the filtergraph chooses the +chroma sample location of the output. Frames without a chroma sample location +are tagged with the one negotiated for the output. + @item pixel_aspect, sar The sample (pixel) aspect ratio of the input video. diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 16efa6e6c8..8e6097df08 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -54,6 +54,7 @@ typedef struct BufferSourceContext { enum AVColorSpace color_space, prev_color_space; enum AVColorRange color_range, prev_color_range; enum AVAlphaMode alpha_mode, prev_alpha_mode; + enum AVChromaLocation chroma_location, prev_chroma_location; AVRational pixel_aspect; AVBufferRef *hw_frames_ctx; @@ -69,19 +70,25 @@ typedef struct BufferSourceContext { int eof; int64_t last_pts; int link_delta, prev_delta; + + int chroma_loc_warned; } BufferSourceContext; -#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, csp, range, alpha, pts)\ +#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, csp, range, alpha, chromaloc, pts)\ c->link_delta = c->w != width || c->h != height || c->pix_fmt != format ||\ - c->color_space != csp || c->color_range != range || c->alpha_mode != alpha;\ + c->color_space != csp || c->color_range != range || c->alpha_mode != alpha ||\ + c->chroma_location != chromaloc;\ c->prev_delta = c->prev_w != width || c->prev_h != height || c->prev_pix_fmt != format ||\ - c->prev_color_space != csp || c->prev_color_range != range || c->prev_alpha_mode != alpha;\ + c->prev_color_space != csp || c->prev_color_range != range || c->prev_alpha_mode != alpha ||\ + c->prev_chroma_location != chromaloc;\ if (c->link_delta) {\ int loglevel = c->prev_delta ? AV_LOG_WARNING : AV_LOG_DEBUG;\ av_log(s, loglevel, "Changing video frame properties on the fly is not supported by all filters.\n");\ - av_log(s, loglevel, "filter context - w: %d h: %d fmt: %d csp: %s range: %s alpha: %s, incoming frame - w: %d h: %d fmt: %d csp: %s range: %s alpha: %s pts_time: %s\n",\ + av_log(s, loglevel, "filter context - w: %d h: %d fmt: %d csp: %s range: %s alpha: %s chroma_loc: %s, incoming frame - w: %d h: %d fmt: %d csp: %s range: %s alpha: %s chroma_loc: %s pts_time: %s\n",\ c->w, c->h, c->pix_fmt, av_color_space_name(c->color_space), av_color_range_name(c->color_range), av_alpha_mode_name(c->alpha_mode),\ + av_chroma_location_name(c->chroma_location),\ width, height, format, av_color_space_name(csp), av_color_range_name(range), av_alpha_mode_name(alpha),\ + av_chroma_location_name(chromaloc),\ av_ts2timestr(pts, &s->outputs[0]->time_base));\ }\ if (c->prev_delta) {\ @@ -93,6 +100,7 @@ typedef struct BufferSourceContext { c->prev_color_space = csp;\ c->prev_color_range = range;\ c->prev_alpha_mode = alpha;\ + c->prev_chroma_location = chromaloc;\ } #define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, layout, format, pts)\ @@ -115,6 +123,7 @@ AVBufferSrcParameters *av_buffersrc_parameters_alloc(void) par->color_range = AVCOL_RANGE_UNSPECIFIED; par->color_space = AVCOL_SPC_UNSPECIFIED; par->alpha_mode = AVALPHA_MODE_UNSPECIFIED; + par->chroma_location = AVCHROMA_LOC_UNSPECIFIED; return par; } @@ -151,6 +160,8 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par s->color_range = s->prev_color_range = param->color_range; if (param->alpha_mode != AVALPHA_MODE_UNSPECIFIED) s->alpha_mode = s->prev_alpha_mode = param->alpha_mode; + if (param->chroma_location != AVCHROMA_LOC_UNSPECIFIED) + s->chroma_location = s->prev_chroma_location = param->chroma_location; break; case AVMEDIA_TYPE_AUDIO: if (param->format != AV_SAMPLE_FMT_NONE) { @@ -230,7 +241,8 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra case AVMEDIA_TYPE_VIDEO: CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height, frame->format, frame->colorspace, - frame->color_range, frame->alpha_mode, frame->pts); + frame->color_range, frame->alpha_mode, + frame->chroma_location, frame->pts); break; case AVMEDIA_TYPE_AUDIO: /* For layouts unknown on input but known on link after negotiation. */ @@ -264,6 +276,15 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra copy->color_range = ctx->outputs[0]->color_range; if (copy->alpha_mode == AVALPHA_MODE_UNSPECIFIED) copy->alpha_mode = ctx->outputs[0]->alpha_mode; + if (copy->chroma_location == AVCHROMA_LOC_UNSPECIFIED) { + copy->chroma_location = ctx->outputs[0]->chroma_location; + /* The input never said where its chroma sits, so it is assumed to be + * compatible with whatever the rest of the graph settled on. */ + if (copy->chroma_location != AVCHROMA_LOC_UNSPECIFIED) + av_log_once(ctx, AV_LOG_WARNING, AV_LOG_VERBOSE, &s->chroma_loc_warned, + "Input has no chroma sample location, assuming %s\n", + av_chroma_location_name(copy->chroma_location)); + } ret = ff_filter_frame(ctx->outputs[0], copy); if (ret < 0) @@ -339,12 +360,12 @@ static av_cold int init_video(AVFilterContext *ctx) return AVERROR(EINVAL); } - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d csp:%s range:%s alpha:%s\n", + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d csp:%s range:%s alpha:%s chroma_loc:%s\n", c->w, c->h, av_get_pix_fmt_name(c->pix_fmt), c->time_base.num, c->time_base.den, c->frame_rate.num, c->frame_rate.den, c->pixel_aspect.num, c->pixel_aspect.den, av_color_space_name(c->color_space), av_color_range_name(c->color_range), - av_alpha_mode_name(c->alpha_mode)); + av_alpha_mode_name(c->alpha_mode), av_chroma_location_name(c->chroma_location)); return common_init(ctx); } @@ -399,6 +420,15 @@ static const AVOption buffer_options[] = { { "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, V, .unit = "alpha"}, { "straight", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_STRAIGHT}, 0, 0, V, .unit = "alpha"}, { "premultiplied", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_PREMULTIPLIED}, 0, 0, V, .unit = "alpha"}, + { "chroma_location", "select chroma sample location", OFFSET(chroma_location), AV_OPT_TYPE_INT, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, AVCHROMA_LOC_NB-1, V, .unit = "chroma_loc"}, + { "unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, V, .unit = "chroma_loc"}, + { "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, V, .unit = "chroma_loc"}, + { "left", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_LEFT}, 0, 0, V, .unit = "chroma_loc"}, + { "center", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_CENTER}, 0, 0, V, .unit = "chroma_loc"}, + { "topleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOPLEFT}, 0, 0, V, .unit = "chroma_loc"}, + { "top", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOP}, 0, 0, V, .unit = "chroma_loc"}, + { "bottomleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOMLEFT}, 0, 0, V, .unit = "chroma_loc"}, + { "bottom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOM}, 0, 0, V, .unit = "chroma_loc"}, { NULL }, }; @@ -484,6 +514,7 @@ static int query_formats(const AVFilterContext *ctx, AVFilterFormats *color_spaces = NULL; AVFilterFormats *color_ranges = NULL; AVFilterFormats *alpha_modes = NULL; + AVFilterFormats *chroma_locations = NULL; int ret; switch (ctx->outputs[0]->type) { @@ -525,6 +556,18 @@ static int query_formats(const AVFilterContext *ctx, if ((ret = ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, alpha_modes)) < 0) return ret; } + if (av_pix_fmt_desc_get(swfmt)->log2_chroma_w || + av_pix_fmt_desc_get(swfmt)->log2_chroma_h) { + if (c->chroma_location != AVCHROMA_LOC_UNSPECIFIED) { + if ((ret = ff_add_format(&chroma_locations, c->chroma_location)) < 0) + return ret; + if ((ret = ff_set_common_chroma_locations2(ctx, cfg_in, cfg_out, + chroma_locations)) < 0) + return ret; + } + /* Untagged input places no constraint, there is nothing to convert + * from, so whatever the rest of the graph wants is used as is. */ + } break; } case AVMEDIA_TYPE_AUDIO: diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index 75824d964d..fb6dfa3487 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -128,6 +128,11 @@ typedef struct AVBufferSrcParameters { * Video only, the alpha mode. */ enum AVAlphaMode alpha_mode; + + /** + * Video only, the chroma sample location. + */ + enum AVChromaLocation chroma_location; } AVBufferSrcParameters; /** diff --git a/libavfilter/version.h b/libavfilter/version.h index cd37ff7921..19a7c929cc 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -32,7 +32,7 @@ #include "version_major.h" #define LIBAVFILTER_VERSION_MINOR 4 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
