• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2021 Igalia, S.L.
3  *     Author: Víctor Jáquez <vjaquez@igalia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "vasurfaceimage.h"
22 
23 #include "gstvavideoformat.h"
24 #include <va/va.h>
25 
26 gboolean
va_destroy_surfaces(GstVaDisplay * display,VASurfaceID * surfaces,gint num_surfaces)27 va_destroy_surfaces (GstVaDisplay * display, VASurfaceID * surfaces,
28     gint num_surfaces)
29 {
30   VADisplay dpy = gst_va_display_get_va_dpy (display);
31   VAStatus status;
32 
33   g_return_val_if_fail (num_surfaces > 0, FALSE);
34 
35   gst_va_display_lock (display);
36   status = vaDestroySurfaces (dpy, surfaces, num_surfaces);
37   gst_va_display_unlock (display);
38   if (status != VA_STATUS_SUCCESS) {
39     GST_ERROR ("vaDestroySurfaces: %s", vaErrorStr (status));
40     return FALSE;
41   }
42 
43   return TRUE;
44 
45 }
46 
47 gboolean
va_create_surfaces(GstVaDisplay * display,guint rt_format,guint fourcc,guint width,guint height,gint usage_hint,VASurfaceAttribExternalBuffers * ext_buf,VASurfaceID * surfaces,guint num_surfaces)48 va_create_surfaces (GstVaDisplay * display, guint rt_format, guint fourcc,
49     guint width, guint height, gint usage_hint,
50     VASurfaceAttribExternalBuffers * ext_buf, VASurfaceID * surfaces,
51     guint num_surfaces)
52 {
53   VADisplay dpy = gst_va_display_get_va_dpy (display);
54   /* *INDENT-OFF* */
55   VASurfaceAttrib attrs[5] = {
56     {
57       .type = VASurfaceAttribUsageHint,
58       .flags = VA_SURFACE_ATTRIB_SETTABLE,
59       .value.type = VAGenericValueTypeInteger,
60       .value.value.i = usage_hint,
61     },
62     {
63       .type = VASurfaceAttribMemoryType,
64       .flags = VA_SURFACE_ATTRIB_SETTABLE,
65       .value.type = VAGenericValueTypeInteger,
66       .value.value.i = (ext_buf && ext_buf->num_buffers > 0)
67                                ? VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
68                                : VA_SURFACE_ATTRIB_MEM_TYPE_VA,
69     },
70   };
71   /* *INDENT-ON* */
72   VAStatus status;
73   guint num_attrs = 2;
74 
75   g_return_val_if_fail (num_surfaces > 0, FALSE);
76 
77   if (fourcc > 0) {
78     /* *INDENT-OFF* */
79     attrs[num_attrs++] = (VASurfaceAttrib) {
80       .type = VASurfaceAttribPixelFormat,
81       .flags = VA_SURFACE_ATTRIB_SETTABLE,
82       .value.type = VAGenericValueTypeInteger,
83       .value.value.i = fourcc,
84     };
85     /* *INDENT-ON* */
86   }
87 
88   if (ext_buf) {
89     /* *INDENT-OFF* */
90     attrs[num_attrs++] = (VASurfaceAttrib) {
91       .type = VASurfaceAttribExternalBufferDescriptor,
92       .flags = VA_SURFACE_ATTRIB_SETTABLE,
93       .value.type = VAGenericValueTypePointer,
94       .value.value.p = ext_buf,
95     };
96     /* *INDENT-ON* */
97   }
98 
99   gst_va_display_lock (display);
100   status = vaCreateSurfaces (dpy, rt_format, width, height, surfaces,
101       num_surfaces, attrs, num_attrs);
102   gst_va_display_unlock (display);
103   if (status != VA_STATUS_SUCCESS) {
104     GST_ERROR ("vaCreateSurfaces: %s", vaErrorStr (status));
105     return FALSE;
106   }
107 
108   return TRUE;
109 }
110 
111 gboolean
va_export_surface_to_dmabuf(GstVaDisplay * display,VASurfaceID surface,guint32 flags,VADRMPRIMESurfaceDescriptor * desc)112 va_export_surface_to_dmabuf (GstVaDisplay * display, VASurfaceID surface,
113     guint32 flags, VADRMPRIMESurfaceDescriptor * desc)
114 {
115   VADisplay dpy = gst_va_display_get_va_dpy (display);
116   VAStatus status;
117 
118   gst_va_display_lock (display);
119   status = vaExportSurfaceHandle (dpy, surface,
120       VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, flags, desc);
121   gst_va_display_unlock (display);
122   if (status != VA_STATUS_SUCCESS) {
123     GST_ERROR ("vaExportSurfaceHandle: %s", vaErrorStr (status));
124     return FALSE;
125   }
126 
127   return TRUE;
128 }
129 
130 gboolean
va_destroy_image(GstVaDisplay * display,VAImageID image_id)131 va_destroy_image (GstVaDisplay * display, VAImageID image_id)
132 {
133   VADisplay dpy = gst_va_display_get_va_dpy (display);
134   VAStatus status;
135 
136   gst_va_display_lock (display);
137   status = vaDestroyImage (dpy, image_id);
138   gst_va_display_unlock (display);
139   if (status != VA_STATUS_SUCCESS) {
140     GST_ERROR ("vaDestroyImage: %s", vaErrorStr (status));
141     return FALSE;
142   }
143   return TRUE;
144 }
145 
146 gboolean
va_get_derive_image(GstVaDisplay * display,VASurfaceID surface,VAImage * image)147 va_get_derive_image (GstVaDisplay * display, VASurfaceID surface,
148     VAImage * image)
149 {
150   VADisplay dpy = gst_va_display_get_va_dpy (display);
151   VAStatus status;
152 
153   gst_va_display_lock (display);
154   status = vaDeriveImage (dpy, surface, image);
155   gst_va_display_unlock (display);
156   if (status != VA_STATUS_SUCCESS) {
157     GST_WARNING ("vaDeriveImage: %s", vaErrorStr (status));
158     return FALSE;
159   }
160 
161   return TRUE;
162 }
163 
164 gboolean
va_create_image(GstVaDisplay * display,GstVideoFormat format,gint width,gint height,VAImage * image)165 va_create_image (GstVaDisplay * display, GstVideoFormat format, gint width,
166     gint height, VAImage * image)
167 {
168   VADisplay dpy = gst_va_display_get_va_dpy (display);
169   const VAImageFormat *va_format;
170   VAStatus status;
171 
172   va_format = gst_va_image_format_from_video_format (format);
173   if (!va_format)
174     return FALSE;
175 
176   gst_va_display_lock (display);
177   status =
178       vaCreateImage (dpy, (VAImageFormat *) va_format, width, height, image);
179   gst_va_display_unlock (display);
180   if (status != VA_STATUS_SUCCESS) {
181     GST_ERROR ("vaCreateImage: %s", vaErrorStr (status));
182     return FALSE;
183   }
184   return TRUE;
185 }
186 
187 gboolean
va_get_image(GstVaDisplay * display,VASurfaceID surface,VAImage * image)188 va_get_image (GstVaDisplay * display, VASurfaceID surface, VAImage * image)
189 {
190   VADisplay dpy = gst_va_display_get_va_dpy (display);
191   VAStatus status;
192 
193   gst_va_display_lock (display);
194   status = vaGetImage (dpy, surface, 0, 0, image->width, image->height,
195       image->image_id);
196   gst_va_display_unlock (display);
197   if (status != VA_STATUS_SUCCESS) {
198     GST_ERROR ("vaGetImage: %s", vaErrorStr (status));
199     return FALSE;
200   }
201 
202   return TRUE;
203 }
204 
205 gboolean
va_sync_surface(GstVaDisplay * display,VASurfaceID surface)206 va_sync_surface (GstVaDisplay * display, VASurfaceID surface)
207 {
208   VADisplay dpy = gst_va_display_get_va_dpy (display);
209   VAStatus status;
210 
211   gst_va_display_lock (display);
212   status = vaSyncSurface (dpy, surface);
213   gst_va_display_unlock (display);
214   if (status != VA_STATUS_SUCCESS) {
215     GST_WARNING ("vaSyncSurface: %s", vaErrorStr (status));
216     return FALSE;
217   }
218   return TRUE;
219 }
220 
221 gboolean
va_map_buffer(GstVaDisplay * display,VABufferID buffer,gpointer * data)222 va_map_buffer (GstVaDisplay * display, VABufferID buffer, gpointer * data)
223 {
224   VADisplay dpy = gst_va_display_get_va_dpy (display);
225   VAStatus status;
226 
227   gst_va_display_lock (display);
228   status = vaMapBuffer (dpy, buffer, data);
229   gst_va_display_unlock (display);
230   if (status != VA_STATUS_SUCCESS) {
231     GST_WARNING ("vaMapBuffer: %s", vaErrorStr (status));
232     return FALSE;
233   }
234   return TRUE;
235 }
236 
237 gboolean
va_unmap_buffer(GstVaDisplay * display,VABufferID buffer)238 va_unmap_buffer (GstVaDisplay * display, VABufferID buffer)
239 {
240   VADisplay dpy = gst_va_display_get_va_dpy (display);
241   VAStatus status;
242 
243   gst_va_display_lock (display);
244   status = vaUnmapBuffer (dpy, buffer);
245   gst_va_display_unlock (display);
246   if (status != VA_STATUS_SUCCESS) {
247     GST_WARNING ("vaUnmapBuffer: %s", vaErrorStr (status));
248     return FALSE;
249   }
250   return TRUE;
251 }
252 
253 gboolean
va_put_image(GstVaDisplay * display,VASurfaceID surface,VAImage * image)254 va_put_image (GstVaDisplay * display, VASurfaceID surface, VAImage * image)
255 {
256   VADisplay dpy = gst_va_display_get_va_dpy (display);
257   VAStatus status;
258 
259   if (!va_sync_surface (display, surface))
260     return FALSE;
261 
262   gst_va_display_lock (display);
263   status = vaPutImage (dpy, surface, image->image_id, 0, 0, image->width,
264       image->height, 0, 0, image->width, image->height);
265   gst_va_display_unlock (display);
266   if (status != VA_STATUS_SUCCESS) {
267     GST_ERROR ("vaPutImage: %s", vaErrorStr (status));
268     return FALSE;
269   }
270   return TRUE;
271 }
272 
273 gboolean
va_ensure_image(GstVaDisplay * display,VASurfaceID surface,GstVideoInfo * info,VAImage * image,gboolean derived)274 va_ensure_image (GstVaDisplay * display, VASurfaceID surface,
275     GstVideoInfo * info, VAImage * image, gboolean derived)
276 {
277   gboolean ret = TRUE;
278 
279   if (image->image_id != VA_INVALID_ID)
280     return TRUE;
281 
282   if (!va_sync_surface (display, surface))
283     return FALSE;
284 
285   if (derived) {
286     ret = va_get_derive_image (display, surface, image);
287   } else {
288     ret = va_create_image (display, GST_VIDEO_INFO_FORMAT (info),
289         GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), image);
290   }
291 
292   return ret;
293 }
294 
295 gboolean
va_check_surface(GstVaDisplay * display,VASurfaceID surface)296 va_check_surface (GstVaDisplay * display, VASurfaceID surface)
297 {
298   VADisplay dpy = gst_va_display_get_va_dpy (display);
299   VAStatus status;
300   VASurfaceStatus state;
301 
302   gst_va_display_lock (display);
303   status = vaQuerySurfaceStatus (dpy, surface, &state);
304   gst_va_display_unlock (display);
305 
306   if (status != VA_STATUS_SUCCESS)
307     GST_ERROR ("vaQuerySurfaceStatus: %s", vaErrorStr (status));
308 
309   GST_LOG ("surface %#x status %d", surface, state);
310 
311   return (status == VA_STATUS_SUCCESS);
312 }
313 
314 gboolean
va_copy_surface(GstVaDisplay * display,VASurfaceID dst,VASurfaceID src)315 va_copy_surface (GstVaDisplay * display, VASurfaceID dst, VASurfaceID src)
316 {
317 #if VA_CHECK_VERSION (1, 12, 0)
318   VADisplay dpy = gst_va_display_get_va_dpy (display);
319   /* *INDENT-OFF* */
320   VACopyObject obj_src = {
321     .obj_type = VACopyObjectSurface,
322     .object = {
323       .surface_id = src,
324     },
325   };
326   VACopyObject obj_dst = {
327     .obj_type = VACopyObjectSurface,
328     .object = {
329       .surface_id = dst,
330     },
331   };
332   VACopyOption option = {
333     .bits = {
334       .va_copy_sync = VA_EXEC_SYNC,
335       .va_copy_mode = VA_EXEC_MODE_DEFAULT,
336     },
337   };
338   /* *INDENT-ON* */
339   VAStatus status;
340 
341   gst_va_display_lock (display);
342   status = vaCopy (dpy, &obj_dst, &obj_src, option);
343   gst_va_display_unlock (display);
344   if (status != VA_STATUS_SUCCESS) {
345     GST_INFO ("vaCopy: %s", vaErrorStr (status));
346     return FALSE;
347   }
348   return TRUE;
349 #else
350   return FALSE;
351 #endif
352 }
353