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},
};