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;
+}
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__ */
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);
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;
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;
GstVideoInfo * out_info)
{
GstVideoConvert *space;
+ GstBaseTransformClass *gstbasetransform_class =
+ GST_BASE_TRANSFORM_GET_CLASS (filter);
+ GstVideoInfo tmp_info;
space = GST_VIDEO_CONVERT_CAST (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",