summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubosz Sarnecki <lubosz.sarnecki@collabora.co.uk>2015-11-13 17:40:08 +0100
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2015-12-18 15:56:34 -0500
commit1cd97865982da5cecf1f9ca7df9ea2714aab7f2b (patch)
tree1a6a7ab09c6f5abf8adbb081795f5b0a0db4db44
parent41738ca83b63c911e6b90f1dbce748830282031b (diff)
downloadgstreamer-plugins-bad-1cd97865982da5cecf1f9ca7df9ea2714aab7f2b.tar.gz
eglimagememory: Methods to create GstGLMemory from dmabufs
Maps GstVideoFormats to suitable DRM fourccs which work with glcolorconvert, using gst_gl_memory_alloc(). We require mostly only 4 formats to be supported by the driver. We require DRM equivalent to RGB16, RGBA, R8 and RG88. This way it's compatible with DesktopGL, since GL_TEXTURE_2D is used and limit driver requirements. With this we can virtually support all formats the glcolorconvert supports. https://bugzilla.gnome.org/show_bug.cgi?id=743345
-rw-r--r--gst-libs/gst/gl/egl/gsteglimagememory.c132
-rw-r--r--gst-libs/gst/gl/egl/gsteglimagememory.h5
2 files changed, 137 insertions, 0 deletions
diff --git a/gst-libs/gst/gl/egl/gsteglimagememory.c b/gst-libs/gst/gl/egl/gsteglimagememory.c
index 6e13a9fe0..cba98f8bb 100644
--- a/gst-libs/gst/gl/egl/gsteglimagememory.c
+++ b/gst-libs/gst/gl/egl/gsteglimagememory.c
@@ -27,6 +27,23 @@
#include "gsteglimagememory.h"
#include <string.h>
+#if GST_GL_HAVE_DMABUF
+#include <gst/allocators/gstdmabuf.h>
+#include <libdrm/drm_fourcc.h>
+
+#ifndef DRM_FORMAT_R8
+#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ')
+#endif
+
+#ifndef DRM_FORMAT_RG88
+#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8')
+#endif
+
+#ifndef DRM_FORMAT_GR88
+#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8')
+#endif
+#endif
+
GST_DEBUG_CATEGORY_STATIC (GST_CAT_EGL_IMAGE_MEMORY);
#define GST_CAT_DEFAULT GST_CAT_EGL_IMAGE_MEMORY
@@ -311,9 +328,124 @@ gst_eglimage_to_gl_texture_upload_meta (GstVideoGLTextureUploadMeta *
gst_gl_buffer_pool_replace_last_buffer (GST_GL_BUFFER_POOL (meta->
buffer->pool), meta->buffer);
+
return TRUE;
}
+#if GST_GL_HAVE_DMABUF
+/*
+ * GStreamer format descriptions differ from DRM formats as the representation
+ * is relative to a register, hence in native endianness. To reduce the driver
+ * requirement, we only import with a subset of texture formats and use
+ * shaders to convert. This way we avoid having to use external texture
+ * target.
+ */
+static int
+_drm_fourcc_from_info (GstVideoInfo * info, int plane)
+{
+ GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ const gint rgba_fourcc = DRM_FORMAT_ABGR8888;
+ const gint rg_fourcc = DRM_FORMAT_GR88;
+#else
+ const gint rgba_fourcc = DRM_FORMAT_RGBA8888;
+ const gint rg_fourcc = DRM_FORMAT_RG88;
+#endif
+
+ GST_DEBUG ("Getting DRM fourcc for %s plane %i",
+ gst_video_format_to_string (format), plane);
+
+ switch (format) {
+ case GST_VIDEO_FORMAT_RGB16:
+ return DRM_FORMAT_RGB565;
+
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_RGBx:
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_BGRx:
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_xRGB:
+ return rgba_fourcc;
+
+ case GST_VIDEO_FORMAT_GRAY8:
+ return DRM_FORMAT_R8;
+
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_UYVY:
+ return rg_fourcc;
+
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV21:
+ return plane == 0 ? DRM_FORMAT_R8 : rg_fourcc;
+
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_Y41B:
+ case GST_VIDEO_FORMAT_Y42B:
+ case GST_VIDEO_FORMAT_YV12:
+ return DRM_FORMAT_R8;
+
+ default:
+ GST_ERROR ("Unsupported format for DMABuf.");
+ return -1;
+ }
+}
+
+GstMemory *
+gst_egl_image_memory_from_dmabuf (GstGLContext * context,
+ gint dmabuf, GstVideoInfo * in_info, gint plane, gsize offset)
+{
+ GstGLContextEGL *ctx_egl = GST_GL_CONTEXT_EGL (context);
+ GstEGLImageAllocator *allocator;
+ gint fourcc;
+ gint atti = 0;
+ EGLint attribs[13];
+ EGLImageKHR img = EGL_NO_IMAGE_KHR;
+
+ allocator = gst_egl_image_allocator_obtain ();
+ fourcc = _drm_fourcc_from_info (in_info, plane);
+
+ GST_DEBUG ("fourcc %.4s (%d) plane %d (%dx%d)",
+ (char *) &fourcc, fourcc, plane,
+ GST_VIDEO_INFO_COMP_WIDTH (in_info, plane),
+ GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane));
+
+ attribs[atti++] = EGL_WIDTH;
+ attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, plane);
+ attribs[atti++] = EGL_HEIGHT;
+ attribs[atti++] = GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane);
+
+ attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
+ attribs[atti++] = fourcc;
+
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
+ attribs[atti++] = dmabuf;
+
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
+ attribs[atti++] = offset;
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
+ attribs[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, plane);
+
+ attribs[atti] = EGL_NONE;
+
+ for (int i = 0; i < atti; i++)
+ GST_LOG ("attr %i: %08X", i, attribs[i]);
+
+ g_assert (atti == 12);
+
+ img = ctx_egl->eglCreateImage (ctx_egl->egl_display, EGL_NO_CONTEXT,
+ EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
+
+ if (!img) {
+ GST_WARNING_OBJECT (allocator, "eglCreateImage failed: %s",
+ gst_gl_context_egl_get_error_string ());
+ return NULL;
+ }
+
+ return gst_egl_image_allocator_wrap (allocator, ctx_egl, img, 0, 0,
+ in_info->size, NULL, NULL);
+}
+#endif /* GST_GL_HAVE_DMABUF */
+
gboolean
gst_egl_image_memory_setup_buffer (GstGLContext * ctx, GstVideoInfo * info,
GstBuffer * buffer)
diff --git a/gst-libs/gst/gl/egl/gsteglimagememory.h b/gst-libs/gst/gl/egl/gsteglimagememory.h
index ce1fd4493..aced24706 100644
--- a/gst-libs/gst/gl/egl/gsteglimagememory.h
+++ b/gst-libs/gst/gl/egl/gsteglimagememory.h
@@ -64,6 +64,11 @@ GstVideoGLTextureOrientation gst_egl_image_memory_get_orientation (GstMemory * m
void gst_egl_image_memory_set_orientation (GstMemory * mem,
GstVideoGLTextureOrientation orientation);
+#if GST_GL_HAVE_DMABUF
+GstMemory * gst_egl_image_memory_from_dmabuf (GstGLContext * context,
+ gint dmabuf, GstVideoInfo * in_info, gint plane, gsize offset);
+#endif
+
G_END_DECLS
#endif /* _GST_GL_MEMORY_H_ */