]> code.ossystems Code Review - meta-freescale.git/blob
50631faca15766750e23f69c39a9a1ddefdd651a
[meta-freescale.git] /
1 From 56c58831b61cdb79f61f2f68c32854646241326b Mon Sep 17 00:00:00 2001
2 From: Carlos Rafael Giani <dv@pseudoterminal.org>
3 Date: Wed, 28 Mar 2018 00:47:33 +0200
4 Subject: [PATCH 2/2] gl/egl: Add gst_egl_image_from_dmabuf_direct() function
5
6 This also renames the existing gst_egl_image_from_dmabuf() to clarify the
7 difference between the two
8
9 https://bugzilla.gnome.org/show_bug.cgi?id=783521
10 ---
11  docs/libs/gst-plugins-base-libs-sections.txt |   3 +-
12  gst-libs/gst/gl/egl/gsteglimage.c            | 238 ++++++++++++++++++++++++++-
13  gst-libs/gst/gl/egl/gsteglimage.h            |   8 +-
14  3 files changed, 239 insertions(+), 10 deletions(-)
15
16 diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt
17 index c2c528a76..3c4dfdf61 100644
18 --- a/docs/libs/gst-plugins-base-libs-sections.txt
19 +++ b/docs/libs/gst-plugins-base-libs-sections.txt
20 @@ -3853,7 +3853,8 @@ GstGLBaseFilterPrivate
21  <SECTION>
22  <FILE>gsteglimage</FILE>
23  <TITLE>GstEGLImage</TITLE>
24 -gst_egl_image_from_dmabuf
25 +gst_egl_image_from_dmabuf_as_rgba_plane
26 +gst_egl_image_from_dmabuf_direct
27  gst_egl_image_from_texture
28  gst_egl_image_get_image
29  gst_egl_image_new_wrapped
30 diff --git a/gst-libs/gst/gl/egl/gsteglimage.c b/gst-libs/gst/gl/egl/gsteglimage.c
31 index fdd603807..9f4a018fc 100644
32 --- a/gst-libs/gst/gl/egl/gsteglimage.c
33 +++ b/gst-libs/gst/gl/egl/gsteglimage.c
34 @@ -29,9 +29,9 @@
35   *
36   * #GstEGLImage represents and holds an #EGLImage handle.
37   *
38 - * A #GstEGLImage can be created from a dmabuf with gst_egl_image_from_dmabuf()
39 - * or #GstGLMemoryEGL provides a #GstAllocator to allocate #EGLImage's bound to
40 - * and OpenGL texture.
41 + * A #GstEGLImage can be created from a dmabuf with gst_egl_image_from_dmabuf_direct()
42 + * or gst_egl_image_from_dmabuf_as_rgba_plane(), or #GstGLMemoryEGL provides a
43 + * #GstAllocator to allocate #EGLImage's bound to and OpenGL texture.
44   */
45  
46  #ifdef HAVE_CONFIG_H
47 @@ -344,12 +344,12 @@ gst_egl_image_from_texture (GstGLContext * context, GstGLMemory * gl_mem,
48  /*
49   * GStreamer format descriptions differ from DRM formats as the representation
50   * is relative to a register, hence in native endianness. To reduce the driver
51 - * requirement, we only import with a subset of texture formats and use
52 + * requirement, we only import with a subset of RGBA texture formats and use
53   * shaders to convert. This way we avoid having to use external texture
54   * target.
55   */
56  static int
57 -_drm_fourcc_from_info (GstVideoInfo * info, int plane)
58 +_drm_rgba_fourcc_from_info (GstVideoInfo * info, int plane)
59  {
60    GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
61  #if G_BYTE_ORDER == G_LITTLE_ENDIAN
62 @@ -410,19 +410,113 @@ _drm_fourcc_from_info (GstVideoInfo * info, int plane)
63        return -1;
64    }
65  }
66
67 +/*
68 + * Variant of _drm_rgba_fourcc_from_info() that is used in case the GPU can
69 + * handle YUV formats directly (by using internal shaders, or hardwired
70 + * YUV->RGB conversion matrices etc.)
71 + */
72 +static int
73 +_drm_direct_fourcc_from_info (GstVideoInfo * info)
74 +{
75 +  GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
76 +
77 +  GST_DEBUG ("Getting DRM fourcc for %s", gst_video_format_to_string (format));
78 +
79 +  switch (format) {
80 +    case GST_VIDEO_FORMAT_YUY2:
81 +      return DRM_FORMAT_YUYV;
82 +
83 +    case GST_VIDEO_FORMAT_YVYU:
84 +      return DRM_FORMAT_YVYU;
85 +
86 +    case GST_VIDEO_FORMAT_UYVY:
87 +      return DRM_FORMAT_UYVY;
88 +
89 +    case GST_VIDEO_FORMAT_VYUY:
90 +      return DRM_FORMAT_VYUY;
91 +
92 +    case GST_VIDEO_FORMAT_AYUV:
93 +      return DRM_FORMAT_AYUV;
94 +
95 +    case GST_VIDEO_FORMAT_NV12:
96 +      return DRM_FORMAT_NV12;
97 +
98 +    case GST_VIDEO_FORMAT_NV21:
99 +      return DRM_FORMAT_NV21;
100 +
101 +    case GST_VIDEO_FORMAT_NV16:
102 +      return DRM_FORMAT_NV16;
103 +
104 +    case GST_VIDEO_FORMAT_NV61:
105 +      return DRM_FORMAT_NV61;
106 +
107 +    case GST_VIDEO_FORMAT_NV24:
108 +      return DRM_FORMAT_NV24;
109 +
110 +    case GST_VIDEO_FORMAT_YUV9:
111 +      return DRM_FORMAT_YUV410;
112 +
113 +    case GST_VIDEO_FORMAT_YVU9:
114 +      return DRM_FORMAT_YVU410;
115 +
116 +    case GST_VIDEO_FORMAT_Y41B:
117 +      return DRM_FORMAT_YUV411;
118 +
119 +    case GST_VIDEO_FORMAT_I420:
120 +      return DRM_FORMAT_YUV420;
121 +
122 +    case GST_VIDEO_FORMAT_YV12:
123 +      return DRM_FORMAT_YVU420;
124 +
125 +    case GST_VIDEO_FORMAT_Y42B:
126 +      return DRM_FORMAT_YUV422;
127 +
128 +    case GST_VIDEO_FORMAT_Y444:
129 +      return DRM_FORMAT_YUV444;
130 +
131 +    case GST_VIDEO_FORMAT_RGB16:
132 +    case GST_VIDEO_FORMAT_BGR16:
133 +    case GST_VIDEO_FORMAT_RGB:
134 +    case GST_VIDEO_FORMAT_BGR:
135 +    case GST_VIDEO_FORMAT_RGBA:
136 +    case GST_VIDEO_FORMAT_RGBx:
137 +    case GST_VIDEO_FORMAT_BGRA:
138 +    case GST_VIDEO_FORMAT_BGRx:
139 +    case GST_VIDEO_FORMAT_ARGB:
140 +    case GST_VIDEO_FORMAT_xRGB:
141 +    case GST_VIDEO_FORMAT_ABGR:
142 +    case GST_VIDEO_FORMAT_xBGR:
143 +    case GST_VIDEO_FORMAT_GRAY8:
144 +      /* Use _drm_rgba_fourcc_from_info() as fallback for RGB formats */
145 +      return _drm_rgba_fourcc_from_info (info, 0);
146 +
147 +    default:
148 +      GST_ERROR ("Unsupported format for DMABuf.");
149 +      return -1;
150 +  }
151 +}
152  
153  /**
154 - * gst_egl_image_from_dmabuf:
155 + * gst_egl_image_from_dmabuf_as_rgba_plane:
156   * @context: a #GstGLContext (must be an EGL context)
157   * @dmabuf: the DMA-Buf file descriptor
158   * @in_info: the #GstVideoInfo in @dmabuf
159   * @plane: the plane in @in_info to create and #GstEGLImage for
160   * @offset: the byte-offset in the data
161   *
162 + * Creates an EGL image that imports the dmabuf FD. The dmabuf data
163 + * is passed as RGBA data. Shaders later take this "RGBA" data and
164 + * convert it from its true format (described by in_info) to actual
165 + * RGBA output. For example, with I420, three EGL images are created,
166 + * one for each plane, each EGL image with a single-channel R format.
167 + * With NV12, two EGL images are created, one with R format, one
168 + * with RG format etc.
169 + *
170   * Returns: a #GstEGLImage wrapping @dmabuf or %NULL on failure
171   */
172  GstEGLImage *
173 -gst_egl_image_from_dmabuf (GstGLContext * context,
174 +gst_egl_image_from_dmabuf_as_rgba_plane (GstGLContext * context,
175      gint dmabuf, GstVideoInfo * in_info, gint plane, gsize offset)
176  {
177    GstGLFormat format;
178 @@ -432,7 +526,7 @@ gst_egl_image_from_dmabuf (GstGLContext * context,
179    gint fourcc;
180    gint i;
181  
182 -  fourcc = _drm_fourcc_from_info (in_info, plane);
183 +  fourcc = _drm_rgba_fourcc_from_info (in_info, plane);
184    format = gst_gl_format_from_video_info (context, in_info, plane);
185  
186    GST_DEBUG ("fourcc %.4s (%d) plane %d (%dx%d)",
187 @@ -470,6 +564,134 @@ gst_egl_image_from_dmabuf (GstGLContext * context,
188        (GstEGLImageDestroyNotify) _destroy_egl_image);
189  }
190  
191 +/**
192 + * gst_egl_image_from_dmabuf_direct:
193 + * @context: a #GstGLContext (must be an EGL context)
194 + * @buffer: the #GstBuffer containing DMA-Buf memory
195 + * @in_info: the #GstVideoInfo in @dmabuf
196 + *
197 + * Creates an EGL image that imports the dmabuf FD. The dmabuf data
198 + * is passed directly as the format described in in_info. This is
199 + * useful if the hardware is capable of performing color space conversions
200 + * internally. The appropriate DRM format is picked, and the EGL image
201 + * is created with this DRM format.
202 + *
203 + * Another notable difference to gst_egl_image_from_dmabuf_as_rgba_plane()
204 + * is that this function creates one EGL image for all planes, not just one.
205 + *
206 + * Returns: a #GstEGLImage wrapping @dmabuf or %NULL on failure
207 + */
208 +GstEGLImage *
209 +gst_egl_image_from_dmabuf_direct (GstGLContext * context,
210 +    GstBuffer * buffer, GstVideoInfo * in_info)
211 +{
212 +#define MAX_NUM_DMA_BUF_PLANES (3)
213 +
214 +  guint mems_idx[MAX_NUM_DMA_BUF_PLANES];
215 +  gsize mems_skip[MAX_NUM_DMA_BUF_PLANES];
216 +  GstMemory *mems[MAX_NUM_DMA_BUF_PLANES];
217 +  EGLImageKHR img;
218 +  guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info);
219 +  gint fourcc = _drm_direct_fourcc_from_info (in_info);
220 +  gint i;
221 +
222 +  /* Explanation of array length:
223 +   * - 6 plane independent values are at the start (width, height, format FourCC)
224 +   * - 6 values per plane, and there are up to MAX_NUM_DMA_BUF_PLANES planes
225 +   * - 1 extra value for the EGL_NONE sentinel
226 +   */
227 +  guintptr attribs[6 + 6 * (MAX_NUM_DMA_BUF_PLANES) + 1] = {
228 +    EGL_WIDTH, GST_VIDEO_INFO_WIDTH (in_info),
229 +    EGL_HEIGHT, GST_VIDEO_INFO_HEIGHT (in_info),
230 +    EGL_LINUX_DRM_FOURCC_EXT, fourcc
231 +  };
232 +
233 +  static const EGLint egl_dmabuf_plane_fd_attr[MAX_NUM_DMA_BUF_PLANES] = {
234 +    EGL_DMA_BUF_PLANE0_FD_EXT,
235 +    EGL_DMA_BUF_PLANE1_FD_EXT,
236 +    EGL_DMA_BUF_PLANE2_FD_EXT,
237 +  };
238 +  static const EGLint egl_dmabuf_plane_offset_attr[MAX_NUM_DMA_BUF_PLANES] = {
239 +    EGL_DMA_BUF_PLANE0_OFFSET_EXT,
240 +    EGL_DMA_BUF_PLANE1_OFFSET_EXT,
241 +    EGL_DMA_BUF_PLANE2_OFFSET_EXT,
242 +  };
243 +  static const EGLint egl_dmabuf_plane_pitch_attr[MAX_NUM_DMA_BUF_PLANES] = {
244 +    EGL_DMA_BUF_PLANE0_PITCH_EXT,
245 +    EGL_DMA_BUF_PLANE1_PITCH_EXT,
246 +    EGL_DMA_BUF_PLANE2_PITCH_EXT,
247 +  };
248 +
249 +  /* Make sure we never set up more than MAX_NUM_DMA_BUF_PLANES planes */
250 +  if (G_UNLIKELY (n_planes > MAX_NUM_DMA_BUF_PLANES))
251 +    n_planes = MAX_NUM_DMA_BUF_PLANES;
252 +
253 +  GST_DEBUG ("Setting up EGL image attributes for %u plane(s)", n_planes);
254 +
255 +  for (i = 0; i < n_planes; i++) {
256 +    guint plane_size;
257 +    guint length;
258 +    gsize offset, stride;
259 +    gint fd;
260 +
261 +    plane_size = gst_gl_get_plane_data_size (in_info, NULL, i);
262 +
263 +    /* In the buffer, find the memory block that corresponds to the current plane,
264 +     * and note down the offset (which is needed for the EGLImage) and the index
265 +     * of the memory block */
266 +    if (!gst_buffer_find_memory (buffer, in_info->offset[i], plane_size,
267 +            &mems_idx[i], &length, &mems_skip[i])) {
268 +      GST_DEBUG ("Couldn't find memory for plane %d", i);
269 +      return NULL;
270 +    }
271 +
272 +    /* We can't have more then one dmabuf per plane */
273 +    if (length != 1) {
274 +      GST_DEBUG
275 +          ("There are multiple dmabufs for plane %d, which is unsupported", i);
276 +      return NULL;
277 +    }
278 +
279 +    /* Get a pointer to the memory block we found earlier */
280 +    mems[i] = gst_buffer_peek_memory (buffer, mems_idx[i]);
281 +
282 +    /* And all memory found must be dmabuf */
283 +    if (!gst_is_dmabuf_memory (mems[i])) {
284 +      GST_DEBUG ("Plane %d memory isn't dmabuf", i);
285 +      return NULL;
286 +    }
287 +
288 +    fd = gst_dmabuf_memory_get_fd (mems[i]);
289 +    offset = mems[i]->offset + mems_skip[i];
290 +    stride = GST_VIDEO_INFO_PLANE_STRIDE (in_info, i);
291 +
292 +    /* Set up configuration for the i-th plane */
293 +    attribs[6 + 6 * i + 0] = egl_dmabuf_plane_fd_attr[i];
294 +    attribs[6 + 6 * i + 1] = fd;
295 +    attribs[6 + 6 * i + 2] = egl_dmabuf_plane_offset_attr[i];
296 +    attribs[6 + 6 * i + 3] = offset;
297 +    attribs[6 + 6 * i + 4] = egl_dmabuf_plane_pitch_attr[i];
298 +    attribs[6 + 6 * i + 5] = stride;
299 +
300 +    GST_DEBUG ("Plane %d has FD %d offset %" G_GSIZE_FORMAT " stride %"
301 +        G_GSIZE_FORMAT, i, fd, offset, stride);
302 +  }
303 +
304 +  /* Add the EGL_NONE sentinel */
305 +  attribs[6 + 6 * n_planes] = EGL_NONE;
306 +
307 +  img = _gst_egl_image_create (context, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
308 +  if (!img) {
309 +    GST_WARNING ("eglCreateImage failed: %s",
310 +        gst_egl_get_error_string (eglGetError ()));
311 +    return NULL;
312 +  }
313 +
314 +  /* TODO: RGBA or RGB? */
315 +  return gst_egl_image_new_wrapped (context, img, GST_GL_RGB, NULL,
316 +      (GstEGLImageDestroyNotify) _destroy_egl_image);
317 +}
318 +
319  gboolean
320  gst_egl_image_export_dmabuf (GstEGLImage * image, int *fd, gint * stride,
321      gsize * offset)
322 diff --git a/gst-libs/gst/gl/egl/gsteglimage.h b/gst-libs/gst/gl/egl/gsteglimage.h
323 index aaebceccf..5a75bc4f9 100644
324 --- a/gst-libs/gst/gl/egl/gsteglimage.h
325 +++ b/gst-libs/gst/gl/egl/gsteglimage.h
326 @@ -83,11 +83,17 @@ GstEGLImage *           gst_egl_image_from_texture              (GstGLContext *
327                                                                   guintptr * attribs);
328  #if GST_GL_HAVE_DMABUF
329  GST_GL_API
330 -GstEGLImage *           gst_egl_image_from_dmabuf               (GstGLContext * context,
331 +GstEGLImage *           gst_egl_image_from_dmabuf_as_rgba_plane (GstGLContext * context,
332                                                                   gint dmabuf,
333                                                                   GstVideoInfo * in_info,
334                                                                   gint plane,
335                                                                   gsize offset);
336 +
337 +GST_GL_API
338 +GstEGLImage *           gst_egl_image_from_dmabuf_direct        (GstGLContext * context,
339 +                                                                 GstBuffer * buffer,
340 +                                                                 GstVideoInfo * in_info);
341 +
342  GST_GL_API
343  gboolean                gst_egl_image_export_dmabuf             (GstEGLImage *image, int *fd, gint *stride, gsize *offset);
344  #endif
345 -- 
346 2.14.1
347