From b7a233335719f5ec9792af38bfb66da2d10308e8 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Thu, 28 Nov 2024 13:51:06 +0100 Subject: [PATCH] avfilter/vf_scale: add colorspace and transfer property options In the long run, it would be ideal if we could add these to the avfilter negotiation as well, but for now, this is a good start. --- doc/filters.texi | 56 ++++++++++++++++++++++++++++++++ libavfilter/vf_scale.c | 73 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 9068a8a4e7..b926b865ae 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -21189,6 +21189,62 @@ is used by default. Possible values: @item bottom @end table +@item in_primaries +@item out_primaries +Set in/output RGB primaries. + +This allows the autodetected value to be overridden as well as allows forcing +a specific value used for the output and encoder. Possible values: + +@table @samp +@item auto +Choose automatically. This is the default. + +@item bt709 +@item bt470m +@item bt470bg +@item smpte170m +@item smpte240m +@item film +@item bt2020 +@item smpte428 +@item smpte431 +@item smpte432 +@item jedec-p22 +@item ebu3213 +@end table + +@item in_transfer +@item out_transfer +Set in/output transfer response curve (TRC). + +This allows the autodetected value to be overridden as well as allows forcing +a specific value used for the output and encoder. Possible values: + +@table @samp +@item auto +Choose automatically. This is the default. + +@item bt709 +@item bt470m +@item gamma22 +@item bt470bg +@item gamma28 +@item smpte170m +@item smpte240m +@item linear +@item iec61966-2-1 +@item srgb +@item iec61966-2-4 +@item xvycc +@item bt1361e +@item bt2020-10 +@item bt2020-12 +@item smpte2084 +@item smpte428 +@item arib-std-b67 +@end table + @item force_original_aspect_ratio Enable decreasing or increasing output video width or height if necessary to keep the original aspect ratio. Possible values: diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index d86e50f79b..d4236f4b6c 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -160,7 +160,10 @@ typedef struct ScaleContext { int in_color_matrix; int out_color_matrix; - + int in_primaries; + int out_primaries; + int in_transfer; + int out_transfer; int in_range; int out_range; @@ -387,6 +390,30 @@ static av_cold int init(AVFilterContext *ctx) if (ret < 0) return ret; + if (scale->in_primaries != -1 && !sws_test_primaries(scale->in_primaries, 0)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported input primaries '%s'\n", + av_color_primaries_name(scale->in_primaries)); + return AVERROR(EINVAL); + } + + if (scale->out_primaries != -1 && !sws_test_primaries(scale->out_primaries, 1)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported output primaries '%s'\n", + av_color_primaries_name(scale->out_primaries)); + return AVERROR(EINVAL); + } + + if (scale->in_transfer != -1 && !sws_test_transfer(scale->in_transfer, 0)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported input transfer '%s'\n", + av_color_transfer_name(scale->in_transfer)); + return AVERROR(EINVAL); + } + + if (scale->out_transfer != -1 && !sws_test_transfer(scale->out_transfer, 1)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported output transfer '%s'\n", + av_color_transfer_name(scale->out_transfer)); + return AVERROR(EINVAL); + } + if (scale->in_color_matrix != -1 && !sws_test_colorspace(scale->in_color_matrix, 0)) { av_log(ctx, AV_LOG_ERROR, "Unsupported input color matrix '%s'\n", av_color_space_name(scale->in_color_matrix)); @@ -815,6 +842,10 @@ scale: if (scale->in_color_matrix != -1) in->colorspace = scale->in_color_matrix; + if (scale->in_primaries != -1) + in->color_primaries = scale->in_primaries; + if (scale->in_transfer != -1) + in->color_trc = scale->in_transfer; if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) in->color_range = scale->in_range; in->chroma_location = scale->in_chroma_loc; @@ -832,6 +863,10 @@ scale: out->colorspace = outlink->colorspace; if (scale->out_chroma_loc != AVCHROMA_LOC_UNSPECIFIED) out->chroma_location = scale->out_chroma_loc; + if (scale->out_primaries != -1) + out->color_primaries = scale->out_primaries; + if (scale->out_transfer != -1) + out->color_trc = scale->out_transfer; av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, @@ -1084,6 +1119,42 @@ static const AVOption scale_options[] = { {"top", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOP}, 0, 0, FLAGS, .unit = "chroma_loc"}, {"bottomleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOMLEFT}, 0, 0, FLAGS, .unit = "chroma_loc"}, {"bottom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOM}, 0, 0, FLAGS, .unit = "chroma_loc"}, + { "in_primaries", "set input primaries", OFFSET(in_primaries), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_PRI_NB-1, .flags = FLAGS, .unit = "primaries" }, + { "out_primaries", "set output primaries", OFFSET(out_primaries), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_PRI_NB-1, .flags = FLAGS, .unit = "primaries"}, + {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "primaries"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, 0, 0, FLAGS, .unit = "primaries"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470M}, 0, 0, FLAGS, .unit = "primaries"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, 0, 0, FLAGS, .unit = "primaries"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, 0, 0, FLAGS, .unit = "primaries"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE240M}, 0, 0, FLAGS, .unit = "primaries"}, + {"film", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_FILM}, 0, 0, FLAGS, .unit = "primaries"}, + {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, 0, 0, FLAGS, .unit = "primaries"}, + {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE428}, 0, 0, FLAGS, .unit = "primaries"}, + {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, 0, 0, FLAGS, .unit = "primaries"}, + {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, 0, 0, FLAGS, .unit = "primaries"}, + {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, 0, 0, FLAGS, .unit = "primaries"}, + {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, 0, 0, FLAGS, .unit = "primaries"}, + { "in_transfer", "set output color transfer", OFFSET(in_transfer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_TRC_NB-1, .flags = FLAGS, .unit = "transfer"}, + {"out_transfer", "set output color transfer", OFFSET(out_transfer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AVCOL_TRC_NB-1, .flags = FLAGS, .unit = "transfer"}, + {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "transfer"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, 0, 0, FLAGS, .unit = "transfer"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, 0, 0, FLAGS, .unit = "transfer"}, + {"gamma22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, 0, 0, FLAGS, .unit = "transfer"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, 0, 0, FLAGS, .unit = "transfer"}, + {"gamma28", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, 0, 0, FLAGS, .unit = "transfer"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE170M}, 0, 0, FLAGS, .unit = "transfer"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE240M}, 0, 0, FLAGS, .unit = "transfer"}, + {"linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_LINEAR}, 0, 0, FLAGS, .unit = "transfer"}, + {"iec61966-2-1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, 0, 0, FLAGS, .unit = "transfer"}, + {"srgb", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, 0, 0, FLAGS, .unit = "transfer"}, + {"iec61966-2-4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, 0, 0, FLAGS, .unit = "transfer"}, + {"xvycc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, 0, 0, FLAGS, .unit = "transfer"}, + {"bt1361e", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT1361_ECG}, 0, 0, FLAGS, .unit = "transfer"}, + {"bt2020-10", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_10}, 0, 0, FLAGS, .unit = "transfer"}, + {"bt2020-12", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12}, 0, 0, FLAGS, .unit = "transfer"}, + {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, 0, 0, FLAGS, .unit = "transfer"}, + {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE428}, 0, 0, FLAGS, .unit = "transfer"}, + {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, 0, 0, FLAGS, .unit = "transfer"}, { "in_v_chr_pos", "input vertical chroma position in luma grid/256" , OFFSET(in_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, { "in_h_chr_pos", "input horizontal chroma position in luma grid/256", OFFSET(in_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, { "out_v_chr_pos", "output vertical chroma position in luma grid/256" , OFFSET(out_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS },