vapostproc: Process HDR caps
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Mon, 25 Oct 2021 11:41:49 +0000 (13:41 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 9 Feb 2022 10:26:02 +0000 (10:26 +0000)
This patch adds a new parameter: hdr-tone-mapping (same as
vaapipostproc), if the HDR capabilites are availabe in driver, and
it's disabled by default.

If hdr-tone-mapping is enabled then HDR fields in sink caps are
processed in frames from HDR to SDR, removing those hdr fields in
source pad caps too.

hdr-tone-mapping is not enabled if a color conversion is also
requested, since it fails to process in the iHD driver, so far.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1258>

subprojects/gst-plugins-bad/sys/va/gstvafilter.c
subprojects/gst-plugins-bad/sys/va/gstvafilter.h
subprojects/gst-plugins-bad/sys/va/gstvavpp.c

index cb41c2a..4e7764a 100644 (file)
@@ -676,6 +676,15 @@ gst_va_filter_install_properties (GstVaFilter * self, GObjectClass * klass)
 
         break;
       }
+      case VAProcFilterHighDynamicRangeToneMapping:{
+        const VAProcFilterCapHighDynamicRange *caps = &filter->caps.hdr;
+        if (caps->metadata_type == VAProcHighDynamicRangeMetadataHDR10
+            && (caps->caps_flag & VA_TONE_MAPPING_HDR_TO_SDR)) {
+          g_object_class_install_property (klass, GST_VA_FILTER_PROP_HDR,
+              g_param_spec_boolean ("hdr-tone-mapping", "HDR tone mapping",
+                  "Enable HDR to SDR tone mapping", FALSE, common_flags));
+        }
+      }
       default:
         break;
     }
@@ -1608,6 +1617,8 @@ _create_pipeline_buffer (GstVaFilter * self, GstVaSample * src,
     .output_surface_flag = dst->flags,
     .input_color_properties = self->input_color_properties,
     .output_color_properties = self->output_color_properties,
+    /* output to SDR */
+    .output_hdr_metadata = NULL,
   };
   /* *INDENT-ON* */
 
index a9e6680..4de1f64 100644 (file)
@@ -53,6 +53,7 @@ enum {
   GST_VA_FILTER_PROP_DISABLE_PASSTHROUGH,
   GST_VA_FILTER_PROP_DEINTERLACE_METHOD,
   GST_VA_FILTER_PROP_ADD_BORDERS,
+  GST_VA_FILTER_PROP_HDR,
   GST_VA_FILTER_PROP_LAST
 };
 
index f69734f..d85bfa7 100644 (file)
  *
  */
 
-/* ToDo:
- *
- * + HDR tone mapping
- */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -121,6 +116,10 @@ struct _GstVaVpp
   gint borders_h;
   gint borders_w;
 
+  gboolean hdr_mapping;
+  gboolean has_hdr_meta;
+  VAHdrMetaDataHDR10 hdr_meta;
+
   GList *channels;
 };
 
@@ -304,6 +303,10 @@ gst_va_vpp_set_property (GObject * object, guint prop_id,
     case GST_VA_FILTER_PROP_ADD_BORDERS:
       self->add_borders = g_value_get_boolean (value);
       break;
+    case GST_VA_FILTER_PROP_HDR:
+      self->hdr_mapping = g_value_get_boolean (value);
+      g_atomic_int_set (&self->rebuild_filters, TRUE);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -365,6 +368,9 @@ gst_va_vpp_get_property (GObject * object, guint prop_id, GValue * value,
     case GST_VA_FILTER_PROP_ADD_BORDERS:
       g_value_set_boolean (value, self->add_borders);
       break;
+    case GST_VA_FILTER_PROP_HDR:
+      g_value_set_boolean (value, self->hdr_mapping);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -393,6 +399,47 @@ gst_va_vpp_update_properties (GstVaBaseTransform * btrans)
   _update_properties_unlocked (self);
 }
 
+static void
+_set_hdr_metadata (GstVaVpp * self, GstCaps * caps)
+{
+  GstVideoMasteringDisplayInfo mdinfo;
+  GstVideoContentLightLevel llevel;
+
+  self->has_hdr_meta = FALSE;
+
+  if (gst_video_mastering_display_info_from_caps (&mdinfo, caps)) {
+    self->hdr_meta.display_primaries_x[0] = mdinfo.display_primaries[1].x;
+    self->hdr_meta.display_primaries_x[1] = mdinfo.display_primaries[2].x;
+    self->hdr_meta.display_primaries_x[2] = mdinfo.display_primaries[0].x;
+
+    self->hdr_meta.display_primaries_y[0] = mdinfo.display_primaries[1].y;
+    self->hdr_meta.display_primaries_y[1] = mdinfo.display_primaries[2].y;
+    self->hdr_meta.display_primaries_y[2] = mdinfo.display_primaries[0].y;
+
+    self->hdr_meta.white_point_x = mdinfo.white_point.x;
+    self->hdr_meta.white_point_y = mdinfo.white_point.y;
+
+    self->hdr_meta.max_display_mastering_luminance =
+        mdinfo.max_display_mastering_luminance;
+    self->hdr_meta.min_display_mastering_luminance =
+        mdinfo.min_display_mastering_luminance;
+
+    self->has_hdr_meta = TRUE;
+  }
+
+
+  if (gst_video_content_light_level_from_caps (&llevel, caps)) {
+    self->hdr_meta.max_content_light_level = llevel.max_content_light_level;
+    self->hdr_meta.max_pic_average_light_level =
+        llevel.max_frame_average_light_level;
+
+    self->has_hdr_meta = TRUE;
+  };
+
+  /* rebuild filters only if hdr mapping is enabled */
+  g_atomic_int_set (&self->rebuild_filters, self->hdr_mapping);
+}
+
 static gboolean
 gst_va_vpp_set_info (GstVaBaseTransform * btrans, GstCaps * incaps,
     GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
@@ -484,6 +531,7 @@ gst_va_vpp_set_info (GstVaBaseTransform * btrans, GstCaps * incaps,
     self->op_flags &= ~VPP_CONVERT_FEATURE;
 
   if (gst_va_filter_set_video_info (btrans->filter, in_info, out_info)) {
+    _set_hdr_metadata (self, incaps);
     gst_va_vpp_update_passthrough (self, FALSE);
     return TRUE;
   }
@@ -611,13 +659,50 @@ _add_filter_cb_buffer (GstVaVpp * self,
   return FALSE;
 }
 
+static inline gboolean
+_add_filter_hdr_buffer (GstVaVpp * self,
+    const VAProcFilterCapHighDynamicRange * caps)
+{
+  GstVaBaseTransform *btrans = GST_VA_BASE_TRANSFORM (self);
+  /* *INDENT-OFF* */
+  VAProcFilterParameterBufferHDRToneMapping params = {
+    .type = VAProcFilterHighDynamicRangeToneMapping,
+    .data = {
+      .metadata_type = VAProcHighDynamicRangeMetadataHDR10,
+      .metadata = &self->hdr_meta,
+      .metadata_size = sizeof (self->hdr_meta),
+    },
+  };
+  /* *INDENT-ON* */
+
+  /* if not has hdr meta, it may try later again */
+  if (!(self->has_hdr_meta && self->hdr_mapping))
+    return FALSE;
+
+  if (!(caps && caps->metadata_type == VAProcHighDynamicRangeMetadataHDR10
+          && (caps->caps_flag & VA_TONE_MAPPING_HDR_TO_SDR)))
+    goto bail;
+
+  if (self->op_flags & VPP_CONVERT_FORMAT) {
+    GST_WARNING_OBJECT (self, "Cannot apply HDR with color conversion");
+    goto bail;
+  }
+
+  return gst_va_filter_add_filter_buffer (btrans->filter, &params,
+      sizeof (params), 1);
+
+bail:
+  self->hdr_mapping = FALSE;
+  return FALSE;
+}
+
 static void
 _build_filters (GstVaVpp * self)
 {
   GstVaBaseTransform *btrans = GST_VA_BASE_TRANSFORM (self);
   static const VAProcFilterType filter_types[] = { VAProcFilterNoiseReduction,
     VAProcFilterSharpening, VAProcFilterSkinToneEnhancement,
-    VAProcFilterColorBalance,
+    VAProcFilterColorBalance, VAProcFilterHighDynamicRangeToneMapping,
   };
   guint i, num_caps;
   gboolean apply = FALSE;
@@ -641,6 +726,8 @@ _build_filters (GstVaVpp * self)
       case VAProcFilterColorBalance:
         apply |= _add_filter_cb_buffer (self, caps, num_caps);
         break;
+      case VAProcFilterHighDynamicRangeToneMapping:
+        apply |= _add_filter_hdr_buffer (self, caps);
       default:
         break;
     }
@@ -1705,6 +1792,15 @@ copy_misc_fields_from_input (GstCaps * in_caps, GstCaps * out_caps)
   }
 }
 
+static inline void
+remove_hdr_fields (GstCaps * caps)
+{
+  GstStructure *s = gst_caps_get_structure (caps, 0);
+
+  gst_structure_remove_fields (s, "mastering-display-info",
+      "content-light-level", "hdr-format", NULL);
+}
+
 static GstCaps *
 gst_va_vpp_fixate_caps (GstBaseTransform * trans, GstPadDirection direction,
     GstCaps * caps, GstCaps * othercaps)
@@ -1737,6 +1833,8 @@ gst_va_vpp_fixate_caps (GstBaseTransform * trans, GstPadDirection direction,
     } else {
       /* Try and preserve input colorimetry / chroma information */
       transfer_colorimetry_from_input (self, caps, result);
+      if (self->hdr_mapping)
+        remove_hdr_fields (result);
     }
   }
 
@@ -2066,6 +2164,13 @@ gst_va_vpp_init (GTypeInstance * instance, gpointer g_class)
     _create_colorbalance_channel (self, "SATURATION");
   }
 
+  /* HDR tone mapping */
+  pspec = g_object_class_find_property (g_class, "hdr-tone-mapping");
+  if (pspec) {
+    self->hdr_mapping =
+        g_value_get_boolean (g_param_spec_get_default_value (pspec));
+  }
+
   /* enable QoS */
   gst_base_transform_set_qos_enabled (GST_BASE_TRANSFORM (instance), TRUE);
 }