From: Vivia Nikolaidou Date: Fri, 26 Jun 2020 09:22:08 +0000 (+0300) Subject: video-converter: Make fast path work for equivalent transfer functions X-Git-Tag: 1.19.3~511^2~535 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ad55d3ce9d80e5c254d97ae21c340bb249b7f7c3;p=platform%2Fupstream%2Fgstreamer.git video-converter: Make fast path work for equivalent transfer functions For example, BT709, BT601, and BT2020_10 all have theoretically different transfer functions, but the same function in practice. In these cases, we should use the fast path for negotiating. Also, BT2020_12 is essentially the same as the other three, just with one more decimal point, so it gives the same result for fewer bits. This is now also aliased to the former three. Also make videoconvert do passthrough if the caps have equivalent transfer functions but are otherwise matching. As of the previous commit, we write the correct transfer function for BT601, instead of the (functionally identical but different ISO code) transfer function for BT709. Files created using GStreamer prior to that commit write the wrong transfer function for BT601 and are, strictly speaking, 2:4:5:4 instead. However, this commit takes care of negotiation, so that conversions from/to the same transfer function are done using the fast path. Fixes #783 Part-of: --- diff --git a/gst-libs/gst/video/video-color.c b/gst-libs/gst/video/video-color.c index 1ed47f1..c37dd5f 100644 --- a/gst-libs/gst/video/video-color.c +++ b/gst-libs/gst/video/video-color.c @@ -897,3 +897,51 @@ gst_video_color_primaries_from_iso (guint value) return GST_VIDEO_COLOR_PRIMARIES_UNKNOWN; } } + +static GstVideoTransferFunction +map_equivalent_transfer (GstVideoTransferFunction func, guint bpp) +{ + switch (func) { + case GST_VIDEO_TRANSFER_BT2020_12: + if (bpp >= 12) + break; + /* fallthrough */ + case GST_VIDEO_TRANSFER_BT709: + case GST_VIDEO_TRANSFER_BT601: + case GST_VIDEO_TRANSFER_BT2020_10: + return GST_VIDEO_TRANSFER_BT709; + default: + break; + } + + return func; +} + +/** + * gst_video_color_transfer_is_equivalent: + * @from_func: #GstVideoTransferFunction to convert from + * @from_bpp: bits per pixel to convert from + * @to_func: #GstVideoTransferFunction to convert into + * @to_bpp: bits per pixel to convert into + * + * Returns whether @from_func and @to_func are equivalent. There are cases + * (e.g. BT601, BT709, and BT2020_10) where several functions are functionally + * identical. In these cases, when doing conversion, we should consider them + * as equivalent. Also, BT2020_12 is the same as the aforementioned three for + * less than 12 bits per pixel. + * + * Returns: TRUE if @from_func and @to_func can be considered equivalent. + * + * Since: 1.18 + */ +gboolean +gst_video_color_transfer_is_equivalent (GstVideoTransferFunction from_func, + guint from_bpp, GstVideoTransferFunction to_func, guint to_bpp) +{ + from_func = map_equivalent_transfer (from_func, from_bpp); + to_func = map_equivalent_transfer (to_func, to_bpp); + if (from_func == GST_VIDEO_TRANSFER_BT2020_12 && to_bpp < 12 && + to_func == GST_VIDEO_TRANSFER_BT709) + return TRUE; + return from_func == to_func; +} diff --git a/gst-libs/gst/video/video-color.h b/gst-libs/gst/video/video-color.h index d0830df..b304d4a 100644 --- a/gst-libs/gst/video/video-color.h +++ b/gst-libs/gst/video/video-color.h @@ -287,6 +287,12 @@ GstVideoTransferFunction gst_video_color_transfer_from_iso (guint value); GST_VIDEO_API GstVideoColorPrimaries gst_video_color_primaries_from_iso (guint value); +GST_VIDEO_API +gboolean gst_video_color_transfer_is_equivalent (GstVideoTransferFunction from_func, + guint from_bpp, + GstVideoTransferFunction to_func, + guint to_bpp); + G_END_DECLS #endif /* __GST_VIDEO_COLOR_H__ */ diff --git a/gst-libs/gst/video/video-converter.c b/gst-libs/gst/video/video-converter.c index c89932a..21b212a 100644 --- a/gst-libs/gst/video/video-converter.c +++ b/gst-libs/gst/video/video-converter.c @@ -6741,6 +6741,7 @@ video_converter_lookup_fastpath (GstVideoConverter * convert) gboolean interlaced, same_matrix, same_primaries, same_size, crop, border; gboolean need_copy, need_set, need_mult; gint width, height; + guint in_bpp, out_bpp; width = GST_VIDEO_INFO_WIDTH (&convert->in_info); height = GST_VIDEO_INFO_HEIGHT (&convert->in_info); @@ -6748,6 +6749,9 @@ video_converter_lookup_fastpath (GstVideoConverter * convert) if (GET_OPT_DITHER_QUANTIZATION (convert) != 1) return FALSE; + in_bpp = convert->in_info.finfo->bits; + out_bpp = convert->out_info.finfo->bits; + /* we don't do gamma conversion in fastpath */ in_transf = convert->in_info.colorimetry.transfer; out_transf = convert->out_info.colorimetry.transfer; @@ -6755,7 +6759,9 @@ video_converter_lookup_fastpath (GstVideoConverter * convert) same_size = (width == convert->out_width && height == convert->out_height); /* fastpaths don't do gamma */ - if (CHECK_GAMMA_REMAP (convert) && (!same_size || in_transf != out_transf)) + if (CHECK_GAMMA_REMAP (convert) && (!same_size + || !gst_video_color_transfer_is_equivalent (in_transf, in_bpp, + out_transf, out_bpp))) return FALSE; need_copy = (convert->alpha_mode & ALPHA_MODE_COPY) == ALPHA_MODE_COPY; diff --git a/gst/videoconvert/gstvideoconvert.c b/gst/videoconvert/gstvideoconvert.c index 66783c5..b190c34 100644 --- a/gst/videoconvert/gstvideoconvert.c +++ b/gst/videoconvert/gstvideoconvert.c @@ -430,6 +430,9 @@ gst_video_convert_set_info (GstVideoFilter * filter, GstVideoInfo * out_info) { GstVideoConvert *space; + GstBaseTransformClass *gstbasetransform_class = + GST_BASE_TRANSFORM_GET_CLASS (filter); + GstVideoInfo tmp_info; space = GST_VIDEO_CONVERT_CAST (filter); @@ -451,6 +454,21 @@ gst_video_convert_set_info (GstVideoFilter * filter, if (in_info->interlace_mode != out_info->interlace_mode) goto format_mismatch; + /* if the only thing different in the caps is the transfer function, and + * we're converting between equivalent transfer functions, do passthrough */ + tmp_info = *in_info; + tmp_info.colorimetry.transfer = out_info->colorimetry.transfer; + if (gst_video_info_is_equal (&tmp_info, out_info)) { + if (gst_video_color_transfer_is_equivalent (in_info->colorimetry.transfer, + in_info->finfo->bits, out_info->colorimetry.transfer, + out_info->finfo->bits)) { + gstbasetransform_class->passthrough_on_same_caps = FALSE; + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE); + return TRUE; + } + } + gstbasetransform_class->passthrough_on_same_caps = TRUE; + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), FALSE); space->convert = gst_video_converter_new (in_info, out_info, gst_structure_new ("GstVideoConvertConfig",