waylandsink: support HDR10 video playback

upstream status: imx specific

Signed-off-by: Haihua Hu <jared.hu@nxp.com>
diff --git a/ext/wayland/Makefile.am b/ext/wayland/Makefile.am
index ecdb957..9730443 100644
--- a/ext/wayland/Makefile.am
+++ b/ext/wayland/Makefile.am
@@ -6,7 +6,9 @@
 	linux-dmabuf-unstable-v1-protocol.c \
 	linux-dmabuf-unstable-v1-client-protocol.h \
 	alpha-compositing-unstable-v1-protocol.c \
-	alpha-compositing-unstable-v1-client-protocol.h
+	alpha-compositing-unstable-v1-client-protocol.h	\
+	hdr10-metadata-unstable-v1-protocol.c \
+	hdr10-metadata-unstable-v1-client-protocol.h
 
 libgstwaylandsink_la_SOURCES =  \
 	gstwaylandsink.c \
@@ -20,7 +22,8 @@
 nodist_libgstwaylandsink_la_SOURCES = \
 	viewporter-protocol.c \
 	linux-dmabuf-unstable-v1-protocol.c \
-	alpha-compositing-unstable-v1-protocol.c
+	alpha-compositing-unstable-v1-protocol.c \
+	hdr10-metadata-unstable-v1-protocol.c
 
 libgstwaylandsink_la_CFLAGS = \
 	$(GST_PLUGINS_BAD_CFLAGS) \
diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c
index e9be60e..90758aa 100644
--- a/ext/wayland/gstwaylandsink.c
+++ b/ext/wayland/gstwaylandsink.c
@@ -51,6 +51,7 @@
 
 #include <gst/wayland/wayland.h>
 #include <gst/video/videooverlay.h>
+#include <gst/video/gstvideohdr10meta.h>
 
 #include <drm_fourcc.h>
 #include <xf86drm.h>
@@ -105,6 +106,7 @@
 gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query);
 static gboolean gst_wayland_sink_show_frame (GstVideoSink * bsink,
     GstBuffer * buffer);
+static void gst_wayland_sink_config_hdr10 (GstWaylandSink *sink, GstBuffer * buf);
 
 /* VideoOverlay interface */
 static void gst_wayland_sink_videooverlay_init (GstVideoOverlayInterface *
@@ -391,6 +393,7 @@
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       gst_buffer_replace (&sink->last_buffer, NULL);
+      gst_wayland_sink_config_hdr10 (sink, NULL);
       if (sink->window) {
         if (gst_wl_window_is_toplevel (sink->window)) {
           g_clear_object (&sink->window);
@@ -489,6 +492,14 @@
       g_value_set_static_string (&value, gst_wl_shm_format_to_string (fmt));
       gst_value_list_append_and_take_value (&shm_list, &value);
     }
+    /** FIXME:work around for 10bit format not in the none capsfeature list
+     * need vpu add memory:DMABuf capsfeature when output dmabuf
+    */
+    if (HAS_DCSS()) {
+      g_value_init (&value, G_TYPE_STRING);
+      g_value_set_static_string (&value,  gst_video_format_to_string(GST_VIDEO_FORMAT_NV12_10LE));
+      gst_value_list_append_and_take_value (&shm_list, &value);
+    }
 
     gst_structure_take_value (gst_caps_get_structure (caps, 0), "format",
         &shm_list);
@@ -671,6 +682,68 @@
   gst_wl_window_render (sink->window, wlbuffer, info);
 }
 
+static void
+gst_wayland_sink_config_hdr10 (GstWaylandSink *sink, GstBuffer * buf)
+{
+  GstVideoHdr10Meta *meta = NULL;
+  GstWlDisplay *display = sink->display;
+  guint32 eotf = 0;
+  guint32 type = 0;
+  guint32 display_primaries_red = 0;
+  guint32 display_primaries_green = 0;
+  guint32 display_primaries_blue = 0;
+  guint32 white_point = 0;
+  guint32 mastering_display_luminance = 0;
+  guint32 max_cll = 0;
+  guint32 max_fall = 0;
+
+  /* buf could be NULL when resize */
+  if (buf)
+    meta = gst_buffer_get_video_hdr10_meta (buf);
+
+  if (meta) {
+    GST_INFO_OBJECT (sink, "redPrimary x=%d y=%d", meta->hdr10meta.redPrimary[0], meta->hdr10meta.redPrimary[1]);
+    GST_INFO_OBJECT (sink, "greenPrimary x=%d y=%d", meta->hdr10meta.greenPrimary[0], meta->hdr10meta.greenPrimary[1]);
+    GST_INFO_OBJECT (sink, "bluePrimary x=%d y=%d", meta->hdr10meta.bluePrimary[0], meta->hdr10meta.bluePrimary[1]);
+    GST_INFO_OBJECT (sink, "whitePoint x=%d y=%d", meta->hdr10meta.whitePoint[0], meta->hdr10meta.whitePoint[1]);
+    GST_INFO_OBJECT (sink, "maxMasteringLuminance %d", meta->hdr10meta.maxMasteringLuminance);
+    GST_INFO_OBJECT (sink, "minMasteringLuminance %d", meta->hdr10meta.minMasteringLuminance);
+    GST_INFO_OBJECT (sink, "maxContentLightLevel %d", meta->hdr10meta.maxContentLightLevel);
+    GST_INFO_OBJECT (sink, "maxFrameAverageLightLevel %d", meta->hdr10meta.maxFrameAverageLightLevel);
+    GST_INFO_OBJECT (sink, "transferCharacteristics %d", meta->hdr10meta.transferCharacteristics);
+    GST_INFO_OBJECT (sink, "colourPrimaries %d", meta->hdr10meta.colourPrimaries);
+    GST_INFO_OBJECT (sink, "matrixCoeffs %d", meta->hdr10meta.matrixCoeffs);
+    GST_INFO_OBJECT (sink, "fullRange %d", meta->hdr10meta.fullRange);
+    GST_INFO_OBJECT (sink, "chromaSampleLocTypeTopField %d", meta->hdr10meta.chromaSampleLocTypeTopField);
+    GST_INFO_OBJECT (sink, "chromaSampleLocTypeBottomField %d", meta->hdr10meta.chromaSampleLocTypeBottomField);
+
+    eotf = SMPTE_ST2084;
+    type = 0;
+    display_primaries_red = (guint)(meta->hdr10meta.redPrimary[0] << 16 | meta->hdr10meta.redPrimary[1]);
+    display_primaries_green = (guint)(meta->hdr10meta.greenPrimary[0] << 16 | meta->hdr10meta.greenPrimary[1]);
+    display_primaries_blue = (guint)(meta->hdr10meta.bluePrimary[0] << 16 | meta->hdr10meta.bluePrimary[1]);
+    white_point = (guint)(meta->hdr10meta.whitePoint[0] << 16 | meta->hdr10meta.whitePoint[1]);
+    mastering_display_luminance = (guint)(((meta->hdr10meta.maxMasteringLuminance / 10000) & 0xffff) << 16
+                                          | (meta->hdr10meta.minMasteringLuminance & 0xffff));
+    max_cll = meta->hdr10meta.maxContentLightLevel;
+    max_fall = meta->hdr10meta.maxFrameAverageLightLevel;
+  }
+
+  if (display->hdr10_metadata) {
+    zwp_hdr10_metadata_v1_set_metadata (display->hdr10_metadata,
+        eotf,
+        type,
+        display_primaries_red,
+        display_primaries_green,
+        display_primaries_blue,
+        white_point,
+        mastering_display_luminance,
+        max_cll,
+        max_fall);
+    wl_display_roundtrip (display->display);
+  }
+}
+
 static GstFlowReturn
 gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
 {
@@ -713,6 +786,9 @@
   
   gst_wl_window_set_source_crop (sink->window, buffer);
 
+  if (sink->frame_showed == 0)
+    gst_wayland_sink_config_hdr10 (sink, buffer);
+
   wlbuffer = gst_buffer_get_wl_buffer (buffer);
 
   if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) {
diff --git a/ext/wayland/wldisplay.c b/ext/wayland/wldisplay.c
index 7ce632d..7a773f9 100644
--- a/ext/wayland/wldisplay.c
+++ b/ext/wayland/wldisplay.c
@@ -90,6 +90,9 @@
   if (self->alpha_compositing)
     zwp_alpha_compositing_v1_destroy(self->alpha_compositing);
 
+  if (self->hdr10_metadata)
+    zwp_hdr10_metadata_v1_destroy (self->hdr10_metadata);
+
   if (self->shell)
     wl_shell_destroy (self->shell);
 
diff --git a/ext/wayland/wldisplay.h b/ext/wayland/wldisplay.h
index 2a815a7..d34caed 100644
--- a/ext/wayland/wldisplay.h
+++ b/ext/wayland/wldisplay.h
@@ -27,6 +27,7 @@
 #include "viewporter-client-protocol.h"
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
 #include "alpha-compositing-unstable-v1-client-protocol.h"
+#include "hdr10-metadata-unstable-v1-client-protocol.h"
 
 G_BEGIN_DECLS
 
@@ -57,6 +58,7 @@
   struct wp_viewporter *viewporter;
   struct zwp_linux_dmabuf_v1 *dmabuf;
   struct zwp_alpha_compositing_v1 *alpha_compositing;
+  struct zwp_hdr10_metadata_v1 *hdr10_metadata;
   GArray *shm_formats;
   GArray *dmabuf_formats;
 
diff --git a/ext/wayland/wlvideoformat.c b/ext/wayland/wlvideoformat.c
index 77cfac8..d2138ad 100644
--- a/ext/wayland/wlvideoformat.c
+++ b/ext/wayland/wlvideoformat.c
@@ -110,6 +110,7 @@
   {DRM_FORMAT_RGB565, GST_VIDEO_FORMAT_RGB16},
   {DRM_FORMAT_YUYV, GST_VIDEO_FORMAT_YUY2},
   {DRM_FORMAT_NV12, GST_VIDEO_FORMAT_NV12},
+  {DRM_FORMAT_P010, GST_VIDEO_FORMAT_NV12_10LE},
 };
 
 enum wl_shm_format