From bbf6cb754cc832a9663e3a3137f97edc85785d1d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 20 Jul 2013 22:11:50 +0200 Subject: [PATCH] avfilter/vf_scale: Add in/out yuv color matrix option Signed-off-by: Michael Niedermayer --- doc/filters.texi | 27 +++++++++++++++++ libavfilter/vf_scale.c | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index 1217f7e8e1..c8d8578e86 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6252,6 +6252,33 @@ applies a bilinear scaling algorithm. @item size, s Set the video size, the value must be a valid abbreviation or in the form @var{width}x@var{height}. + +@item in_color_matrix +@item out_color_matrix +Set in/output YCbCr colorspace type. +This allows the autodetected value to be overridden as well as allows forcing +a specific value used for the output and encoder. +If not specified, the colorspace type depends on the pixel format. +@table @samp +@item auto +Choose automatically + +@item bt709 +ITU Rec BT709 + +@item fcc +United States Federal Communications Commission Title 47 Code of +Federal Regulations (2003) 73.682 (a) + +@item bt601 +ITU Rec BT601 +ITU-R Rec. BT.470-6 System B, G +Society of Motion Picture and Television Engineers 170M (2004) + +@item smpte240m +Society of Motion Picture and Television Engineers 240M +@end table + @end table The values of the @var{w} and @var{h} options are expressions diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index c91bbaa7dd..999d299f20 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -90,6 +90,9 @@ typedef struct { char *w_expr; ///< width expression string char *h_expr; ///< height expression string char *flags_str; + + char *in_color_matrix; + char *out_color_matrix; } ScaleContext; static av_cold int init(AVFilterContext *ctx) @@ -181,6 +184,38 @@ static int query_formats(AVFilterContext *ctx) return 0; } +static const int *parse_yuv_type(const char *s, enum AVColorSpace colorspace) +{ + const static int32_t yuv2rgb_coeffs[8][4] = { + {}, + { 117504, 138453, 13954, 34903 }, /* ITU-R Rec. 709 (1990) */ + { 104597, 132201, 25675, 53279 }, /* unspecified */ + { 104597, 132201, 25675, 53279 }, /* reserved */ + { 104448, 132798, 24759, 53109 }, /* FCC */ + { 104597, 132201, 25675, 53279 }, /* ITU-R Rec. 624-4 System B, G */ + { 104597, 132201, 25675, 53279 }, /* SMPTE 170M */ + { 117579, 136230, 16907, 35559 } /* SMPTE 240M (1987) */ + }; + if (!s) + s = "bt601"; + + if (s && strstr(s, "bt709")) { + colorspace = AVCOL_SPC_BT709; + } else if (s && strstr(s, "fcc")) { + colorspace = AVCOL_SPC_FCC; + } else if (s && strstr(s, "smpte240m")) { + colorspace = AVCOL_SPC_SMPTE240M; + } else if (s && (strstr(s, "bt601") || strstr(s, "bt470") || strstr(s, "smpte170m"))) { + colorspace = AVCOL_SPC_BT470BG; + } + + if (colorspace < 1 || colorspace > 7) { + colorspace = AVCOL_SPC_BT470BG; + } + + return yuv2rgb_coeffs[colorspace]; +} + static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -381,6 +416,35 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) if(scale->output_is_pal) avpriv_set_systematic_pal2((uint32_t*)out->data[1], outlink->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : outlink->format); + if ( scale->in_color_matrix + || scale->out_color_matrix + || scale-> in_range != AVCOL_RANGE_UNSPECIFIED + || scale->out_range != AVCOL_RANGE_UNSPECIFIED) { + int in_full, out_full, brightness, contrast, saturation; + const int *inv_table, *table; + + sws_getColorspaceDetails(scale->sws, (int **)&inv_table, &in_full, + (int **)&table, &out_full, + &brightness, &contrast, &saturation); + + if (scale->in_color_matrix) + inv_table = parse_yuv_type(scale->in_color_matrix, av_frame_get_colorspace(in)); + if (scale->out_color_matrix) + table = parse_yuv_type(scale->out_color_matrix, AVCOL_SPC_UNSPECIFIED); + + sws_setColorspaceDetails(scale->sws, inv_table, in_full, + table, out_full, + brightness, contrast, saturation); + if (scale->isws[0]) + sws_setColorspaceDetails(scale->isws[0], inv_table, in_full, + table, out_full, + brightness, contrast, saturation); + if (scale->isws[1]) + sws_setColorspaceDetails(scale->isws[1], inv_table, in_full, + table, out_full, + brightness, contrast, saturation); + } + av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, @@ -409,6 +473,8 @@ static const AVOption scale_options[] = { { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_INT, {.i64 = 0 }, -1, 1, FLAGS }, { "size", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, { "s", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, + { "in_color_matrix", "set input YCbCr type", OFFSET(in_color_matrix), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "out_color_matrix", "set output YCbCr type", OFFSET(out_color_matrix), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, { NULL }, };