2 * gstvaapipluginutil.h - VA-API plugin helpers
4 * Copyright (C) 2011-2014 Intel Corporation
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
6 * Copyright (C) 2011 Collabora
7 * Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
25 #include "gst/vaapi/sysdeps.h"
26 #include "gstvaapivideocontext.h"
28 # include <gst/vaapi/gstvaapidisplay_drm.h>
31 # include <gst/vaapi/gstvaapidisplay_x11.h>
34 # include <gst/vaapi/gstvaapidisplay_glx.h>
37 # include <gst/vaapi/gstvaapidisplay_wayland.h>
39 #include "gstvaapipluginutil.h"
40 #include "gstvaapipluginbase.h"
43 static const char *display_types[] = {
63 const gchar *type_str;
64 GstVaapiDisplayType type;
65 GstVaapiDisplay *(*create_display) (const gchar *);
68 static const DisplayMap g_display_map[] = {
71 GST_VAAPI_DISPLAY_TYPE_WAYLAND,
72 gst_vaapi_display_wayland_new},
76 GST_VAAPI_DISPLAY_TYPE_GLX,
77 gst_vaapi_display_glx_new},
81 GST_VAAPI_DISPLAY_TYPE_X11,
82 gst_vaapi_display_x11_new},
86 GST_VAAPI_DISPLAY_TYPE_DRM,
87 gst_vaapi_display_drm_new},
92 static GstVaapiDisplay *
93 gst_vaapi_create_display (GstVaapiDisplayType display_type,
94 const gchar * display_name)
96 GstVaapiDisplay *display = NULL;
99 for (m = g_display_map; m->type_str != NULL; m++) {
100 if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY && display_type != m->type)
103 display = m->create_display (display_name);
104 if (display || display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
111 gst_vaapi_ensure_display (gpointer element, GstVaapiDisplayType type)
113 GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element);
114 GstVaapiDisplay *display;
115 GstVideoContext *context;
117 g_return_val_if_fail (GST_IS_VIDEO_CONTEXT (element), FALSE);
119 context = GST_VIDEO_CONTEXT (element);
120 g_return_val_if_fail (context != NULL, FALSE);
122 gst_vaapi_video_context_prepare (context, display_types);
124 /* Neighbour found and it updated the display */
126 && gst_vaapi_display_type_is_compatible (plugin->display_type, type))
129 /* If no neighboor, or application not interested, use system default */
130 display = gst_vaapi_create_display (type, plugin->display_name);
134 gst_vaapi_video_context_propagate (context, display);
135 GST_VAAPI_PLUGIN_BASE_DISPLAY_REPLACE (plugin, display);
136 gst_vaapi_display_unref (display);
141 gst_vaapi_set_display (const gchar * type,
142 const GValue * value, GstVaapiDisplay ** display_ptr)
144 GstVaapiDisplay *display = NULL;
146 if (!strcmp (type, "vaapi-display")) {
147 g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
148 display = gst_vaapi_display_new_with_display (g_value_get_pointer (value));
149 } else if (!strcmp (type, "gst-vaapi-display")) {
150 g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
151 display = gst_vaapi_display_ref (g_value_get_pointer (value));
154 else if (!strcmp (type, "drm-device")) {
156 g_return_if_fail (G_VALUE_HOLDS_INT (value));
157 device = g_value_get_int (value);
158 display = gst_vaapi_display_drm_new_with_device (device);
159 } else if (!strcmp (type, "drm-device-path")) {
160 const gchar *device_path;
161 g_return_if_fail (G_VALUE_HOLDS_STRING (value));
162 device_path = g_value_get_string (value);
163 display = gst_vaapi_display_drm_new (device_path);
167 else if (!strcmp (type, "x11-display-name")) {
168 g_return_if_fail (G_VALUE_HOLDS_STRING (value));
170 display = gst_vaapi_display_glx_new (g_value_get_string (value));
173 display = gst_vaapi_display_x11_new (g_value_get_string (value));
174 } else if (!strcmp (type, "x11-display")) {
175 g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
178 gst_vaapi_display_glx_new_with_display (g_value_get_pointer (value));
182 gst_vaapi_display_x11_new_with_display (g_value_get_pointer (value));
186 else if (!strcmp (type, "wl-display")) {
187 struct wl_display *wl_display;
188 g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
189 wl_display = g_value_get_pointer (value);
190 display = gst_vaapi_display_wayland_new_with_display (wl_display);
191 } else if (!strcmp (type, "wl-display-name")) {
192 const gchar *display_name;
193 g_return_if_fail (G_VALUE_HOLDS_STRING (value));
194 display_name = g_value_get_string (value);
195 display = gst_vaapi_display_wayland_new (display_name);
200 gst_vaapi_display_replace (display_ptr, display);
201 gst_vaapi_display_unref (display);
206 gst_vaapi_reply_to_query (GstQuery * query, GstVaapiDisplay * display)
208 #if GST_CHECK_VERSION(1,1,0)
209 const gchar *type = NULL;
212 if (GST_QUERY_TYPE (query) != GST_QUERY_CONTEXT)
218 if (!gst_query_parse_context_type (query, &type))
221 if (g_strcmp0 (type, GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME))
224 context = gst_vaapi_video_context_new_with_display (display, FALSE);
225 gst_query_set_context (query, context);
226 gst_context_unref (context);
230 GstVaapiDisplayType display_type;
234 gboolean res = FALSE;
236 if (GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM)
242 types = gst_video_context_query_get_supported_types (query);
247 display_type = gst_vaapi_display_get_display_type (display);
248 for (i = 0; types[i] && !res; i++) {
252 if (!strcmp (type, "gst-vaapi-display")) {
253 gst_video_context_query_set_pointer (query, type, display);
254 } else if (!strcmp (type, "vaapi-display")) {
255 VADisplay vadpy = gst_vaapi_display_get_display (display);
256 gst_video_context_query_set_pointer (query, type, vadpy);
258 switch (display_type) {
260 case GST_VAAPI_DISPLAY_TYPE_DRM:{
261 GstVaapiDisplayDRM *const drm_dpy = GST_VAAPI_DISPLAY_DRM (display);
262 if (!strcmp (type, "drm-device-path"))
263 gst_video_context_query_set_string (query, type,
264 gst_vaapi_display_drm_get_device_path (drm_dpy));
266 /* XXX: gst_video_context_query_set_int() does not exist yet */
267 else if (!strcmp (type, "drm-device"))
268 gst_video_context_query_set_int (query, type,
269 gst_vaapi_display_drm_get_device (drm_dpy));
278 case GST_VAAPI_DISPLAY_TYPE_GLX:
280 case GST_VAAPI_DISPLAY_TYPE_X11:{
281 GstVaapiDisplayX11 *const xvadpy = GST_VAAPI_DISPLAY_X11 (display);
282 Display *const x11dpy = gst_vaapi_display_x11_get_display (xvadpy);
283 if (!strcmp (type, "x11-display"))
284 gst_video_context_query_set_pointer (query, type, x11dpy);
285 else if (!strcmp (type, "x11-display-name"))
286 gst_video_context_query_set_string (query, type,
287 DisplayString (x11dpy));
294 case GST_VAAPI_DISPLAY_TYPE_WAYLAND:{
295 GstVaapiDisplayWayland *const wlvadpy =
296 GST_VAAPI_DISPLAY_WAYLAND (display);
297 struct wl_display *const wldpy =
298 gst_vaapi_display_wayland_get_display (wlvadpy);
299 if (!strcmp (type, "wl-display"))
300 gst_video_context_query_set_pointer (query, type, wldpy);
313 #endif /* !GST_CHECK_VERSION(1,1,0) */
317 gst_vaapi_append_surface_caps (GstCaps * out_caps, GstCaps * in_caps)
319 GstStructure *structure;
320 const GValue *v_width, *v_height, *v_framerate, *v_par;
321 guint i, n_structures;
323 structure = gst_caps_get_structure (in_caps, 0);
324 v_width = gst_structure_get_value (structure, "width");
325 v_height = gst_structure_get_value (structure, "height");
326 v_framerate = gst_structure_get_value (structure, "framerate");
327 v_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
328 if (!v_width || !v_height)
331 n_structures = gst_caps_get_size (out_caps);
332 for (i = 0; i < n_structures; i++) {
333 structure = gst_caps_get_structure (out_caps, i);
334 gst_structure_set_value (structure, "width", v_width);
335 gst_structure_set_value (structure, "height", v_height);
337 gst_structure_set_value (structure, "framerate", v_framerate);
339 gst_structure_set_value (structure, "pixel-aspect-ratio", v_par);
345 gst_vaapi_apply_composition (GstVaapiSurface * surface, GstBuffer * buffer)
347 #if GST_CHECK_VERSION(1,0,0)
348 GstVideoOverlayCompositionMeta *const cmeta =
349 gst_buffer_get_video_overlay_composition_meta (buffer);
350 GstVideoOverlayComposition *composition;
354 composition = cmeta->overlay;
356 GstVideoOverlayComposition *const composition =
357 gst_video_buffer_get_overlay_composition (buffer);
361 return gst_vaapi_surface_set_subpictures_from_composition (surface,
366 gst_vaapi_value_set_format (GValue * value, GstVideoFormat format)
368 #if GST_CHECK_VERSION(1,0,0)
371 str = gst_video_format_to_string (format);
375 g_value_init (value, G_TYPE_STRING);
376 g_value_set_string (value, str);
380 fourcc = gst_video_format_to_fourcc (format);
384 g_value_init (value, GST_TYPE_FOURCC);
385 gst_value_set_fourcc (value, fourcc);
391 gst_vaapi_value_set_format_list (GValue * value, GArray * formats)
393 GValue v_format = G_VALUE_INIT;
396 g_value_init (value, GST_TYPE_LIST);
397 for (i = 0; i < formats->len; i++) {
398 GstVideoFormat const format = g_array_index (formats, GstVideoFormat, i);
400 if (!gst_vaapi_value_set_format (&v_format, format))
402 gst_value_list_append_value (value, &v_format);
403 g_value_unset (&v_format);
409 set_video_template_caps (GstCaps * caps)
411 GstStructure *const structure = gst_caps_get_structure (caps, 0);
413 gst_structure_set (structure,
414 "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
415 "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
416 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
417 "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
421 gst_vaapi_video_format_new_template_caps (GstVideoFormat format)
423 #if GST_CHECK_VERSION(1,0,0)
426 g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
428 caps = gst_caps_new_empty_simple ("video/x-raw");
432 gst_caps_set_simple (caps,
433 "format", G_TYPE_STRING, gst_video_format_to_string (format), NULL);
434 set_video_template_caps (caps);
437 return gst_video_format_new_template_caps (format);
442 gst_vaapi_video_format_new_template_caps_from_list (GArray * formats)
444 #if GST_CHECK_VERSION(1,0,0)
445 GValue v_formats = G_VALUE_INIT;
448 caps = gst_caps_new_empty_simple ("video/x-raw");
452 if (!gst_vaapi_value_set_format_list (&v_formats, formats)) {
453 gst_caps_unref (caps);
457 gst_caps_set_value (caps, "format", &v_formats);
458 set_video_template_caps (caps);
460 GstCaps *caps, *tmp_caps;
463 g_return_val_if_fail (formats != NULL, NULL);
465 caps = gst_caps_new_empty ();
469 for (i = 0; i < formats->len; i++) {
470 const GstVideoFormat format = g_array_index (formats, GstVideoFormat, i);
471 tmp_caps = gst_vaapi_video_format_new_template_caps (format);
473 gst_caps_append (caps, tmp_caps);
480 gst_vaapi_video_format_new_template_caps_with_features (GstVideoFormat format,
481 const gchar * features_string)
485 caps = gst_vaapi_video_format_new_template_caps (format);
489 #if GST_CHECK_VERSION(1,1,0)
490 GstCapsFeatures *const features =
491 gst_caps_features_new (features_string, NULL);
493 gst_caps_unref (caps);
496 gst_caps_set_features (caps, 0, features);
502 gst_vaapi_find_preferred_caps_feature (GstPad * pad, GstVideoFormat format)
504 GstVaapiCapsFeature feature = GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY;
505 #if GST_CHECK_VERSION(1,1,0)
506 guint i, num_structures;
507 GstCaps *caps = NULL;
508 GstCaps *gl_texture_upload_caps = NULL;
509 GstCaps *sysmem_caps = NULL;
510 GstCaps *vaapi_caps = NULL;
513 out_caps = gst_pad_peer_query_caps (pad, NULL);
517 gl_texture_upload_caps =
518 gst_vaapi_video_format_new_template_caps_with_features
519 (GST_VIDEO_FORMAT_RGBA,
520 GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META);
521 if (!gl_texture_upload_caps)
524 if (format == GST_VIDEO_FORMAT_ENCODED)
525 format = GST_VIDEO_FORMAT_I420;
528 gst_vaapi_video_format_new_template_caps_with_features (format,
529 GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE);
534 gst_vaapi_video_format_new_template_caps_with_features (format,
535 GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
539 num_structures = gst_caps_get_size (out_caps);
540 for (i = 0; i < num_structures; i++) {
541 GstCapsFeatures *const features = gst_caps_get_features (out_caps, i);
542 GstStructure *const structure = gst_caps_get_structure (out_caps, i);
544 caps = gst_caps_new_full (gst_structure_copy (structure), NULL);
547 gst_caps_set_features (caps, 0, gst_caps_features_copy (features));
549 if (gst_caps_can_intersect (caps, vaapi_caps) &&
550 feature < GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE)
551 feature = GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE;
552 else if (gst_caps_can_intersect (caps, gl_texture_upload_caps) &&
553 feature < GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META)
554 feature = GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META;
555 else if (gst_caps_can_intersect (caps, sysmem_caps) &&
556 feature < GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY)
557 feature = GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY;
558 gst_caps_replace (&caps, NULL);
562 gst_caps_replace (&gl_texture_upload_caps, NULL);
563 gst_caps_replace (&sysmem_caps, NULL);
564 gst_caps_replace (&vaapi_caps, NULL);
565 gst_caps_replace (&caps, NULL);
566 gst_caps_replace (&out_caps, NULL);
572 gst_caps_set_interlaced (GstCaps * caps, GstVideoInfo * vip)
574 #if GST_CHECK_VERSION(1,0,0)
575 GstVideoInterlaceMode mode;
576 const gchar *mode_str;
578 mode = vip ? GST_VIDEO_INFO_INTERLACE_MODE (vip) :
579 GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
581 case GST_VIDEO_INTERLACE_MODE_PROGRESSIVE:
582 mode_str = "progressive";
584 case GST_VIDEO_INTERLACE_MODE_INTERLEAVED:
585 mode_str = "interleaved";
587 case GST_VIDEO_INTERLACE_MODE_MIXED:
591 GST_ERROR ("unsupported `interlace-mode' %d", mode);
595 gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING, mode_str, NULL);
597 gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN,
598 vip ? GST_VIDEO_INFO_IS_INTERLACED (vip) : FALSE, NULL);