MMFMWK-8195 waylandsink: add internal dmabuf pool to support SW decode

add internal dmabuf pool to support SW decode. Propose to upstream if
ion available.

upstreams status: imx specific
diff --git a/configure.ac b/configure.ac
index 943412c..04427b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -535,6 +535,13 @@
   AC_SUBST(WINSOCK2_LIBS)
 fi
 
+dnl ion allocator
+old_CFLAGS=$CFLAGS
+PKG_CHECK_MODULES(GST, gstreamer-$GST_MAJORMINOR >= 1.14, CFLAGS="$CFLAGS `$PKG_CONFIG --cflags gstreamer-allocators-1.0`")
+AC_CHECK_HEADERS([linux/ion.h gst/allocators/gstionmemory.h], HAVE_ION="yes", HAVE_ION="no")
+AM_CONDITIONAL(USE_ION, test "x$HAVE_ION" = "xyes")
+CFLAGS=$old_CFLAGS
+
 dnl Vulkan
 PKG_CHECK_MODULES(XCB, xcb >= 1.10, GST_VULKAN_HAVE_WINDOW_XCB=1, GST_VULKAN_HAVE_WINDOW_XCB=0)
 AM_CONDITIONAL(USE_XCB, test "x$GST_VULKAN_HAVE_WINDOW_XCB" = "x1")
diff --git a/ext/wayland/Makefile.am b/ext/wayland/Makefile.am
index 30925a1..d1f66e2 100644
--- a/ext/wayland/Makefile.am
+++ b/ext/wayland/Makefile.am
@@ -39,6 +39,10 @@
 	$(WAYLAND_LIBS)
 libgstwaylandsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
+if USE_ION
+libgstwaylandsink_la_CFLAGS += -DHAVE_ION_ALLOCATOR
+endif
+
 noinst_HEADERS = \
 	gstwaylandsink.h \
 	wlshmallocator.h \
diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c
index 2c4a714..f4b32cf 100644
--- a/ext/wayland/gstwaylandsink.c
+++ b/ext/wayland/gstwaylandsink.c
@@ -53,6 +53,10 @@
 #include <gst/video/videooverlay.h>
 #include <gst/video/gstvideohdr10meta.h>
 
+#ifdef HAVE_ION_ALLOCATOR
+#include <gst/allocators/gstionmemory.h>
+#endif
+
 #include <drm_fourcc.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
@@ -566,20 +570,44 @@
   return caps;
 }
 
+#define ISALIGNED(a, b) (!(a & (b-1)))
+
 static GstBufferPool *
 gst_wayland_create_pool (GstWaylandSink * sink, GstCaps * caps)
 {
   GstBufferPool *pool = NULL;
   GstStructure *structure;
   gsize size = sink->video_info.size;
-  GstAllocator *alloc;
+  GstAllocator *alloc = NULL;
 
   pool = g_object_new (gst_wayland_pool_get_type (), NULL);
 
+#ifdef HAVE_ION_ALLOCATOR
+  alloc = gst_ion_allocator_obtain ();
+#endif
+
   structure = gst_buffer_pool_get_config (pool);
   gst_buffer_pool_config_set_params (structure, caps, size, 2, 0);
+  if (!alloc)
+    alloc = gst_wl_shm_allocator_get ();
+  else {
+    gint w = GST_VIDEO_INFO_WIDTH (&sink->video_info);
+    gint h = GST_VIDEO_INFO_HEIGHT (&sink->video_info);
+    if (!ISALIGNED (w, 16) || !ISALIGNED (h, 16)) {
+      GstVideoAlignment alignment;
 
-  alloc = gst_wl_shm_allocator_get ();
+      memset (&alignment, 0, sizeof (GstVideoAlignment));
+      alignment.padding_right = GST_ROUND_UP_N (w, 16) - w;
+      alignment.padding_bottom = GST_ROUND_UP_N (h, 16) - h;
+
+      GST_DEBUG ("align buffer pool, w(%d) h(%d), padding_right (%d), padding_bottom (%d)",
+          w, h, alignment.padding_right, alignment.padding_bottom);
+
+      gst_buffer_pool_config_add_option (structure, GST_BUFFER_POOL_OPTION_VIDEO_META);
+      gst_buffer_pool_config_add_option (structure, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
+      gst_buffer_pool_config_set_video_alignment (structure, &alignment);
+    }
+  }
   gst_buffer_pool_config_set_allocator (structure, alloc, NULL);
   if (!gst_buffer_pool_set_config (pool, structure)) {
     g_object_unref (pool);
@@ -649,7 +677,7 @@
   GstCaps *caps;
   GstBufferPool *pool = NULL;
   gboolean need_pool;
-  GstAllocator *alloc;
+  GstAllocator *alloc = NULL;
   guint64 drm_modifier;
 
   gst_query_parse_allocation (query, &caps, &need_pool);
@@ -660,11 +688,19 @@
   if (need_pool)
     pool = gst_wayland_create_pool (sink, caps);
 
+  if (pool) {
+    GstStructure *config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_get_allocator (config, &alloc, NULL);
+    g_object_ref (alloc);
+    gst_structure_free (config);
+  }
+
   gst_query_add_allocation_pool (query, pool, sink->video_info.size, 2, 0);
   if (pool)
     g_object_unref (pool);
 
-  alloc = gst_wl_shm_allocator_get ();
+  if (!alloc)
+    alloc = gst_wl_shm_allocator_get ();
   gst_query_add_allocation_param (query, alloc, NULL);
   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
   gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
@@ -866,76 +902,102 @@
     if (gst_buffer_n_memory (buffer) == 1 && gst_is_fd_memory (mem))
       wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
           &sink->video_info);
+  }
 
-    /* If nothing worked, copy into our internal pool */
-    if (!wbuf) {
-      GstVideoFrame src, dst;
-      GstVideoInfo src_info = sink->video_info;
+  /* If nothing worked, copy into our internal pool */
+  if (!wbuf) {
+    GstVideoFrame src, dst;
+    GstVideoInfo src_info = sink->video_info;
 
-      /* rollback video info changes */
-      sink->video_info = old_vinfo;
+    /* rollback video info changes */
+    sink->video_info = old_vinfo;
 
-      /* we don't know how to create a wl_buffer directly from the provided
-       * memory, so we have to copy the data to shm memory that we know how
-       * to handle... */
+    GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
+        "copying to internal memory", buffer);
 
-      GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
-          "copying to wl_shm memory", buffer);
+    /* sink->pool always exists (created in set_caps), but it may not
+     * be active if upstream is not using it */
+    if (!gst_buffer_pool_is_active (sink->pool)) {
+      GstStructure *config;
+      GstCaps *caps;
 
-      /* sink->pool always exists (created in set_caps), but it may not
-       * be active if upstream is not using it */
-      if (!gst_buffer_pool_is_active (sink->pool)) {
-        GstStructure *config;
-        GstCaps *caps;
+      config = gst_buffer_pool_get_config (sink->pool);
+      gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL);
 
-        config = gst_buffer_pool_get_config (sink->pool);
-        gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL);
+      /* revert back to default strides and offsets */
+      gst_video_info_from_caps (&sink->video_info, caps);
+      gst_buffer_pool_config_set_params (config, caps, sink->video_info.size,
+          2, 0);
 
-        /* revert back to default strides and offsets */
-        gst_video_info_from_caps (&sink->video_info, caps);
-        gst_buffer_pool_config_set_params (config, caps, sink->video_info.size,
-            2, 0);
+      /* This is a video pool, it should not fail with basic setings */
+      if (!gst_buffer_pool_set_config (sink->pool, config) ||
+          !gst_buffer_pool_set_active (sink->pool, TRUE))
+        goto activate_failed;
+    }
 
-        /* This is a video pool, it should not fail with basic setings */
-        if (!gst_buffer_pool_set_config (sink->pool, config) ||
-            !gst_buffer_pool_set_active (sink->pool, TRUE))
-          goto activate_failed;
+    ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
+    if (ret != GST_FLOW_OK)
+      goto no_buffer;
+
+    wlbuffer = gst_buffer_get_wl_buffer (to_render);
+
+    /* attach a wl_buffer if there isn't one yet */
+    if (G_UNLIKELY (!wlbuffer)) {
+      mem = gst_buffer_peek_memory (to_render, 0);
+      if (gst_wl_display_check_format_for_dmabuf (sink->display, format)
+          && gst_is_dmabuf_memory (mem)) {
+        GstVideoInfo info = sink->video_info;
+
+        if (sink->pool && gst_buffer_pool_is_active (sink->pool)) {
+          GstStructure *config;
+          GstVideoAlignment video_align;
+          memset (&video_align, 0, sizeof(GstVideoAlignment));
+          config = gst_buffer_pool_get_config (sink->pool);
+
+          if (gst_buffer_pool_config_has_option (config,
+                    GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) {
+            gst_buffer_pool_config_get_video_alignment (config, &video_align);
+
+            GST_DEBUG_OBJECT (sink, "pool has alignment (%d, %d) , (%d, %d)",
+              video_align.padding_left, video_align.padding_top,
+              video_align.padding_right, video_align.padding_bottom);
+
+            gst_video_info_align (&info, &video_align);
+          }
+          gst_structure_free (config);
+        }
+
+        wbuf = gst_wl_linux_dmabuf_construct_wl_buffer (to_render, sink->display,
+            &info);
       }
 
-      ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
-      if (ret != GST_FLOW_OK)
-        goto no_buffer;
-
-      wlbuffer = gst_buffer_get_wl_buffer (to_render);
-
-      /* attach a wl_buffer if there isn't one yet */
-      if (G_UNLIKELY (!wlbuffer)) {
-        mem = gst_buffer_peek_memory (to_render, 0);
+      if (!wbuf) {
+        GST_DEBUG_OBJECT (sink, "no dmabuf available, try shm");
         wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
             &sink->video_info);
-
-        if (G_UNLIKELY (!wbuf))
-          goto no_wl_buffer_shm;
-
-        gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
       }
 
-      if (!gst_video_frame_map (&dst, &sink->video_info, to_render,
-              GST_MAP_WRITE))
-        goto dst_map_failed;
+      if (G_UNLIKELY (!wbuf))
+        goto no_wl_buffer_shm;
 
-      if (!gst_video_frame_map (&src, &src_info, buffer, GST_MAP_READ)) {
-        gst_video_frame_unmap (&dst);
-        goto src_map_failed;
-      }
-
-      gst_video_frame_copy (&dst, &src);
-
-      gst_video_frame_unmap (&src);
-      gst_video_frame_unmap (&dst);
-
-      goto render;
+      gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
     }
+
+    if (!gst_video_frame_map (&dst, &sink->video_info, to_render,
+            GST_MAP_WRITE))
+      goto dst_map_failed;
+
+    if (!gst_video_frame_map (&src, &src_info, buffer, GST_MAP_READ)) {
+      gst_video_frame_unmap (&dst);
+      goto src_map_failed;
+    }
+
+    gst_video_frame_copy (&dst, &src);
+
+    gst_video_frame_unmap (&src);
+    gst_video_frame_unmap (&dst);
+
+    goto render;
   }
 
   if (!wbuf)
diff --git a/ext/wayland/wlvideoformat.c b/ext/wayland/wlvideoformat.c
index d2138ad..82738e6 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_YUV420, GST_VIDEO_FORMAT_I420},
   {DRM_FORMAT_P010, GST_VIDEO_FORMAT_NV12_10LE},
 };