/*
* gstvaapipluginutil.h - VA-API plugin helpers
*
- * Copyright (C) 2011-2012 Intel Corporation
+ * Copyright (C) 2011-2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
* Copyright (C) 2011 Collabora
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
*
*/
#include "gst/vaapi/sysdeps.h"
-#include <gst/video/videocontext.h>
+#include "gstvaapivideocontext.h"
#if USE_DRM
# include <gst/vaapi/gstvaapidisplay_drm.h>
#endif
# include <gst/vaapi/gstvaapidisplay_wayland.h>
#endif
#include "gstvaapipluginutil.h"
+#include "gstvaapipluginbase.h"
/* Preferred first */
static const char *display_types[] = {
- "gst-vaapi-display",
- "vaapi-display",
+ "gst-vaapi-display",
+ "vaapi-display",
#if USE_WAYLAND
- "wl-display",
- "wl-display-name",
+ "wl-display",
+ "wl-display-name",
#endif
#if USE_X11
- "x11-display",
- "x11-display-name",
+ "x11-display",
+ "x11-display-name",
#endif
#if USE_DRM
- "drm-device",
- "drm-device-path",
+ "drm-device",
+ "drm-device-path",
#endif
- NULL
+ NULL
};
-typedef struct {
- const gchar *type_str;
- GstVaapiDisplayType type;
- GstVaapiDisplay * (*create_display)(const gchar *);
+typedef struct
+{
+ const gchar *type_str;
+ GstVaapiDisplayType type;
+ GstVaapiDisplay *(*create_display) (const gchar *);
} DisplayMap;
static const DisplayMap g_display_map[] = {
#if USE_WAYLAND
- { "wayland",
- GST_VAAPI_DISPLAY_TYPE_WAYLAND,
- gst_vaapi_display_wayland_new },
-#endif
-#if USE_X11
- { "x11",
- GST_VAAPI_DISPLAY_TYPE_X11,
- gst_vaapi_display_x11_new },
+ {"wayland",
+ GST_VAAPI_DISPLAY_TYPE_WAYLAND,
+ gst_vaapi_display_wayland_new},
#endif
#if USE_GLX
- { "glx",
- GST_VAAPI_DISPLAY_TYPE_GLX,
- gst_vaapi_display_glx_new },
+ {"glx",
+ GST_VAAPI_DISPLAY_TYPE_GLX,
+ gst_vaapi_display_glx_new},
+#endif
+#if USE_X11
+ {"x11",
+ GST_VAAPI_DISPLAY_TYPE_X11,
+ gst_vaapi_display_x11_new},
#endif
#if USE_DRM
- { "drm",
- GST_VAAPI_DISPLAY_TYPE_DRM,
- gst_vaapi_display_drm_new },
+ {"drm",
+ GST_VAAPI_DISPLAY_TYPE_DRM,
+ gst_vaapi_display_drm_new},
#endif
- { NULL, }
+ {NULL,}
};
+static GstVaapiDisplay *
+gst_vaapi_create_display (GstVaapiDisplayType display_type)
+{
+ GstVaapiDisplay *display = NULL;
+ const DisplayMap *m;
+
+ for (m = g_display_map; m->type_str != NULL; m++) {
+ if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY && display_type != m->type)
+ continue;
+
+ display = m->create_display (NULL);
+ if (display || display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
+ break;
+ }
+ return display;
+}
+
gboolean
-gst_vaapi_ensure_display(
- gpointer element,
- GstVaapiDisplayType display_type,
- GstVaapiDisplay **display_ptr
-)
+gst_vaapi_ensure_display (gpointer element, GstVaapiDisplayType type)
{
- GstVaapiDisplay *display;
- GstVideoContext *context;
- const DisplayMap *m;
-
- g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
- g_return_val_if_fail(display_ptr != NULL, FALSE);
-
- /* Already exist ? */
- display = *display_ptr;
- if (display)
- return TRUE;
-
- context = GST_VIDEO_CONTEXT(element);
- g_return_val_if_fail(context != NULL, FALSE);
-
- gst_video_context_prepare(context, display_types);
-
- /* Neighbour found and it updated the display */
- if (*display_ptr)
- return TRUE;
-
- /* If no neighboor, or application not interested, use system default */
- for (m = g_display_map; m->type_str != NULL; m++) {
- if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY &&
- display_type != m->type)
- continue;
-
- display = m->create_display(NULL);
- if (display) {
- /* FIXME: allocator should return NULL if an error occurred */
- if (gst_vaapi_display_get_display(display)) {
- display_type = m->type;
- break;
- }
- g_object_unref(display);
- display = NULL;
- }
+ GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element);
+ GstVaapiDisplay *display;
+ GstVideoContext *context;
- if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
- break;
- }
+ g_return_val_if_fail (GST_IS_VIDEO_CONTEXT (element), FALSE);
+
+ context = GST_VIDEO_CONTEXT (element);
+ g_return_val_if_fail (context != NULL, FALSE);
+
+ gst_vaapi_video_context_prepare (context, display_types);
- if (display_ptr)
- *display_ptr = display;
- return display != NULL;
+ /* Neighbour found and it updated the display */
+ if (plugin->display
+ && gst_vaapi_display_type_is_compatible (plugin->display_type, type))
+ return TRUE;
+
+ /* If no neighboor, or application not interested, use system default */
+ display = gst_vaapi_create_display (type);
+ if (!display)
+ return FALSE;
+
+ gst_vaapi_video_context_propagate (context, display);
+ GST_VAAPI_PLUGIN_BASE_DISPLAY_REPLACE (plugin, display);
+ gst_vaapi_display_unref (display);
+ return TRUE;
}
void
-gst_vaapi_set_display(
- const gchar *type,
- const GValue *value,
- GstVaapiDisplay **display
-)
+gst_vaapi_set_display (const gchar * type,
+ const GValue * value, GstVaapiDisplay ** display_ptr)
{
- GstVaapiDisplay *dpy = NULL;
+ GstVaapiDisplay *display = NULL;
- if (!strcmp(type, "vaapi-display")) {
- g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
- dpy = gst_vaapi_display_new_with_display(g_value_get_pointer(value));
- }
- else if (!strcmp(type, "gst-vaapi-display")) {
- g_return_if_fail(G_VALUE_HOLDS_OBJECT(value));
- dpy = g_value_dup_object(value);
- }
+ if (!strcmp (type, "vaapi-display")) {
+ g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
+ display = gst_vaapi_display_new_with_display (g_value_get_pointer (value));
+ } else if (!strcmp (type, "gst-vaapi-display")) {
+ g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
+ display = gst_vaapi_display_ref (g_value_get_pointer (value));
+ }
#if USE_DRM
- else if (!strcmp(type, "drm-device")) {
- gint device;
- g_return_if_fail(G_VALUE_HOLDS_INT(value));
- device = g_value_get_int(value);
- dpy = gst_vaapi_display_drm_new_with_device(device);
- }
- else if (!strcmp(type, "drm-device-path")) {
- const gchar *device_path;
- g_return_if_fail(G_VALUE_HOLDS_STRING(value));
- device_path = g_value_get_string(value);
- dpy = gst_vaapi_display_drm_new(device_path);
- }
+ else if (!strcmp (type, "drm-device")) {
+ gint device;
+ g_return_if_fail (G_VALUE_HOLDS_INT (value));
+ device = g_value_get_int (value);
+ display = gst_vaapi_display_drm_new_with_device (device);
+ } else if (!strcmp (type, "drm-device-path")) {
+ const gchar *device_path;
+ g_return_if_fail (G_VALUE_HOLDS_STRING (value));
+ device_path = g_value_get_string (value);
+ display = gst_vaapi_display_drm_new (device_path);
+ }
#endif
#if USE_X11
- else if (!strcmp(type, "x11-display-name")) {
- g_return_if_fail(G_VALUE_HOLDS_STRING(value));
+ else if (!strcmp (type, "x11-display-name")) {
+ g_return_if_fail (G_VALUE_HOLDS_STRING (value));
#if USE_GLX
- dpy = gst_vaapi_display_glx_new(g_value_get_string(value));
+ display = gst_vaapi_display_glx_new (g_value_get_string (value));
#endif
- if (!dpy)
- dpy = gst_vaapi_display_x11_new(g_value_get_string(value));
- }
- else if (!strcmp(type, "x11-display")) {
- g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
+ if (!display)
+ display = gst_vaapi_display_x11_new (g_value_get_string (value));
+ } else if (!strcmp (type, "x11-display")) {
+ g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
#if USE_GLX
- dpy = gst_vaapi_display_glx_new_with_display(g_value_get_pointer(value));
+ display =
+ gst_vaapi_display_glx_new_with_display (g_value_get_pointer (value));
#endif
- if (!dpy)
- dpy = gst_vaapi_display_x11_new_with_display(g_value_get_pointer(value));
- }
+ if (!display)
+ display =
+ gst_vaapi_display_x11_new_with_display (g_value_get_pointer (value));
+ }
#endif
#if USE_WAYLAND
- else if (!strcmp(type, "wl-display")) {
- struct wl_display *wl_display;
- g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
- wl_display = g_value_get_pointer(value);
- dpy = gst_vaapi_display_wayland_new_with_display(wl_display);
- }
- else if (!strcmp(type, "wl-display-name")) {
- const gchar *display_name;
- g_return_if_fail(G_VALUE_HOLDS_STRING(value));
- display_name = g_value_get_string(value);
- dpy = gst_vaapi_display_wayland_new(display_name);
- }
+ else if (!strcmp (type, "wl-display")) {
+ struct wl_display *wl_display;
+ g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
+ wl_display = g_value_get_pointer (value);
+ display = gst_vaapi_display_wayland_new_with_display (wl_display);
+ } else if (!strcmp (type, "wl-display-name")) {
+ const gchar *display_name;
+ g_return_if_fail (G_VALUE_HOLDS_STRING (value));
+ display_name = g_value_get_string (value);
+ display = gst_vaapi_display_wayland_new (display_name);
+ }
#endif
- if (dpy) {
- if (*display)
- g_object_unref(*display);
- *display = dpy;
- }
+ if (display) {
+ gst_vaapi_display_replace (display_ptr, display);
+ gst_vaapi_display_unref (display);
+ }
}
gboolean
-gst_vaapi_reply_to_query(GstQuery *query, GstVaapiDisplay *display)
+gst_vaapi_reply_to_query (GstQuery * query, GstVaapiDisplay * display)
{
- GstVaapiDisplayType display_type;
- const gchar **types;
- const gchar *type;
- gint i;
- gboolean res = FALSE;
+#if GST_CHECK_VERSION(1,1,0)
+ const gchar *type = NULL;
+ GstContext *context;
- if (!display)
- return FALSE;
+ if (GST_QUERY_TYPE (query) != GST_QUERY_CONTEXT)
+ return FALSE;
- types = gst_video_context_query_get_supported_types(query);
+ if (!display)
+ return FALSE;
- if (!types)
- return FALSE;
+ if (!gst_query_parse_context_type (query, &type))
+ return FALSE;
- display_type = gst_vaapi_display_get_display_type(display);
- for (i = 0; types[i] && !res; i++) {
- type = types[i];
+ if (g_strcmp0 (type, GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME))
+ return FALSE;
- res = TRUE;
- if (!strcmp(type, "gst-vaapi-display")) {
- gst_video_context_query_set_object(query, type, G_OBJECT(display));
- }
- else if (!strcmp(type, "vaapi-display")) {
- VADisplay vadpy = gst_vaapi_display_get_display(display);
- gst_video_context_query_set_pointer(query, type, vadpy);
- }
- else {
- switch (display_type) {
+ context = gst_vaapi_video_context_new_with_display (display, FALSE);
+ gst_query_set_context (query, context);
+ gst_context_unref (context);
+
+ return TRUE;
+#else
+ GstVaapiDisplayType display_type;
+ const gchar **types;
+ const gchar *type;
+ gint i;
+ gboolean res = FALSE;
+
+ if (GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM)
+ return FALSE;
+
+ if (!display)
+ return FALSE;
+
+ types = gst_video_context_query_get_supported_types (query);
+
+ if (!types)
+ return FALSE;
+
+ display_type = gst_vaapi_display_get_display_type (display);
+ for (i = 0; types[i] && !res; i++) {
+ type = types[i];
+
+ res = TRUE;
+ if (!strcmp (type, "gst-vaapi-display")) {
+ gst_video_context_query_set_pointer (query, type, display);
+ } else if (!strcmp (type, "vaapi-display")) {
+ VADisplay vadpy = gst_vaapi_display_get_display (display);
+ gst_video_context_query_set_pointer (query, type, vadpy);
+ } else {
+ switch (display_type) {
#if USE_DRM
- case GST_VAAPI_DISPLAY_TYPE_DRM: {
- GstVaapiDisplayDRM * const drm_dpy =
- GST_VAAPI_DISPLAY_DRM(display);
- if (!strcmp(type, "drm-device-path"))
- gst_video_context_query_set_string(query, type,
- gst_vaapi_display_drm_get_device_path(drm_dpy));
+ case GST_VAAPI_DISPLAY_TYPE_DRM:{
+ GstVaapiDisplayDRM *const drm_dpy = GST_VAAPI_DISPLAY_DRM (display);
+ if (!strcmp (type, "drm-device-path"))
+ gst_video_context_query_set_string (query, type,
+ gst_vaapi_display_drm_get_device_path (drm_dpy));
#if 0
- /* XXX: gst_video_context_query_set_int() does not exist yet */
- else if (!strcmp(type, "drm-device"))
- gst_video_context_query_set_int(query, type,
- gst_vaapi_display_drm_get_device(drm_dpy));
+ /* XXX: gst_video_context_query_set_int() does not exist yet */
+ else if (!strcmp (type, "drm-device"))
+ gst_video_context_query_set_int (query, type,
+ gst_vaapi_display_drm_get_device (drm_dpy));
#endif
- else
- res = FALSE;
- break;
- }
+ else
+ res = FALSE;
+ break;
+ }
#endif
#if USE_X11
#if USE_GLX
- case GST_VAAPI_DISPLAY_TYPE_GLX:
+ case GST_VAAPI_DISPLAY_TYPE_GLX:
#endif
- case GST_VAAPI_DISPLAY_TYPE_X11: {
- GstVaapiDisplayX11 * const xvadpy =
- GST_VAAPI_DISPLAY_X11(display);
- Display * const x11dpy =
- gst_vaapi_display_x11_get_display(xvadpy);
- if (!strcmp(type, "x11-display"))
- gst_video_context_query_set_pointer(query, type, x11dpy);
- else if (!strcmp(type, "x11-display-name"))
- gst_video_context_query_set_string(query, type,
- DisplayString(x11dpy));
- else
- res = FALSE;
- break;
- }
+ case GST_VAAPI_DISPLAY_TYPE_X11:{
+ GstVaapiDisplayX11 *const xvadpy = GST_VAAPI_DISPLAY_X11 (display);
+ Display *const x11dpy = gst_vaapi_display_x11_get_display (xvadpy);
+ if (!strcmp (type, "x11-display"))
+ gst_video_context_query_set_pointer (query, type, x11dpy);
+ else if (!strcmp (type, "x11-display-name"))
+ gst_video_context_query_set_string (query, type,
+ DisplayString (x11dpy));
+ else
+ res = FALSE;
+ break;
+ }
#endif
#if USE_WAYLAND
- case GST_VAAPI_DISPLAY_TYPE_WAYLAND: {
- GstVaapiDisplayWayland * const wlvadpy =
- GST_VAAPI_DISPLAY_WAYLAND(display);
- struct wl_display * const wldpy =
- gst_vaapi_display_wayland_get_display(wlvadpy);
- if (!strcmp(type, "wl-display"))
- gst_video_context_query_set_pointer(query, type, wldpy);
- else
- res = FALSE;
- break;
- }
-#endif
- default:
- res = FALSE;
- break;
- }
+ case GST_VAAPI_DISPLAY_TYPE_WAYLAND:{
+ GstVaapiDisplayWayland *const wlvadpy =
+ GST_VAAPI_DISPLAY_WAYLAND (display);
+ struct wl_display *const wldpy =
+ gst_vaapi_display_wayland_get_display (wlvadpy);
+ if (!strcmp (type, "wl-display"))
+ gst_video_context_query_set_pointer (query, type, wldpy);
+ else
+ res = FALSE;
+ break;
}
+#endif
+ default:
+ res = FALSE;
+ break;
+ }
}
- return res;
+ }
+ return res;
+#endif /* !GST_CHECK_VERSION(1,1,0) */
}
gboolean
-gst_vaapi_append_surface_caps(GstCaps *out_caps, GstCaps *in_caps)
+gst_vaapi_append_surface_caps (GstCaps * out_caps, GstCaps * in_caps)
{
- GstStructure *structure;
- const GValue *v_width, *v_height, *v_framerate, *v_par;
- guint i, n_structures;
-
- structure = gst_caps_get_structure(in_caps, 0);
- v_width = gst_structure_get_value(structure, "width");
- v_height = gst_structure_get_value(structure, "height");
- v_framerate = gst_structure_get_value(structure, "framerate");
- v_par = gst_structure_get_value(structure, "pixel-aspect-ratio");
- if (!v_width || !v_height)
- return FALSE;
-
- n_structures = gst_caps_get_size(out_caps);
- for (i = 0; i < n_structures; i++) {
- structure = gst_caps_get_structure(out_caps, i);
- gst_structure_set_value(structure, "width", v_width);
- gst_structure_set_value(structure, "height", v_height);
- if (v_framerate)
- gst_structure_set_value(structure, "framerate", v_framerate);
- if (v_par)
- gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
- }
+ GstStructure *structure;
+ const GValue *v_width, *v_height, *v_framerate, *v_par;
+ guint i, n_structures;
+
+ structure = gst_caps_get_structure (in_caps, 0);
+ v_width = gst_structure_get_value (structure, "width");
+ v_height = gst_structure_get_value (structure, "height");
+ v_framerate = gst_structure_get_value (structure, "framerate");
+ v_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+ if (!v_width || !v_height)
+ return FALSE;
+
+ n_structures = gst_caps_get_size (out_caps);
+ for (i = 0; i < n_structures; i++) {
+ structure = gst_caps_get_structure (out_caps, i);
+ gst_structure_set_value (structure, "width", v_width);
+ gst_structure_set_value (structure, "height", v_height);
+ if (v_framerate)
+ gst_structure_set_value (structure, "framerate", v_framerate);
+ if (v_par)
+ gst_structure_set_value (structure, "pixel-aspect-ratio", v_par);
+ }
+ return TRUE;
+}
+
+gboolean
+gst_vaapi_apply_composition (GstVaapiSurface * surface, GstBuffer * buffer)
+{
+#if GST_CHECK_VERSION(1,0,0)
+ GstVideoOverlayCompositionMeta *const cmeta =
+ gst_buffer_get_video_overlay_composition_meta (buffer);
+ GstVideoOverlayComposition *composition;
+
+ if (!cmeta)
+ return TRUE;
+ composition = cmeta->overlay;
+#else
+ GstVideoOverlayComposition *const composition =
+ gst_video_buffer_get_overlay_composition (buffer);
+#endif
+ if (!composition)
return TRUE;
+ return gst_vaapi_surface_set_subpictures_from_composition (surface,
+ composition, TRUE);
+}
+
+gboolean
+gst_vaapi_value_set_format (GValue * value, GstVideoFormat format)
+{
+#if GST_CHECK_VERSION(1,0,0)
+ const gchar *str;
+
+ str = gst_video_format_to_string (format);
+ if (!str)
+ return FALSE;
+
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, str);
+#else
+ guint32 fourcc;
+
+ fourcc = gst_video_format_to_fourcc (format);
+ if (!fourcc)
+ return FALSE;
+
+ g_value_init (value, GST_TYPE_FOURCC);
+ gst_value_set_fourcc (value, fourcc);
+#endif
+ return TRUE;
}
gboolean
-gst_vaapi_apply_composition(GstVaapiSurface *surface, GstBuffer *buffer)
+gst_vaapi_value_set_format_list (GValue * value, GArray * formats)
+{
+ GValue v_format = G_VALUE_INIT;
+ guint i;
+
+ g_value_init (value, GST_TYPE_LIST);
+ for (i = 0; i < formats->len; i++) {
+ GstVideoFormat const format = g_array_index (formats, GstVideoFormat, i);
+
+ if (!gst_vaapi_value_set_format (&v_format, format))
+ continue;
+ gst_value_list_append_value (value, &v_format);
+ g_value_unset (&v_format);
+ }
+ return TRUE;
+}
+
+void
+set_video_template_caps (GstCaps * caps)
+{
+ GstStructure *const structure = gst_caps_get_structure (caps, 0);
+
+ gst_structure_set (structure,
+ "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+ "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+}
+
+GstCaps *
+gst_vaapi_video_format_new_template_caps (GstVideoFormat format)
+{
+#if GST_CHECK_VERSION(1,0,0)
+ GstCaps *caps;
+
+ g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
+
+ caps = gst_caps_new_empty_simple ("video/x-raw");
+ if (!caps)
+ return NULL;
+
+ gst_caps_set_simple (caps,
+ "format", G_TYPE_STRING, gst_video_format_to_string (format), NULL);
+ set_video_template_caps (caps);
+ return caps;
+#else
+ return gst_video_format_new_template_caps (format);
+#endif
+}
+
+GstCaps *
+gst_vaapi_video_format_new_template_caps_from_list (GArray * formats)
{
- GstVideoOverlayComposition * const composition =
- gst_video_buffer_get_overlay_composition(buffer);
+#if GST_CHECK_VERSION(1,0,0)
+ GValue v_formats = G_VALUE_INIT;
+ GstCaps *caps;
+
+ caps = gst_caps_new_empty_simple ("video/x-raw");
+ if (!caps)
+ return NULL;
+
+ if (!gst_vaapi_value_set_format_list (&v_formats, formats)) {
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ gst_caps_set_value (caps, "format", &v_formats);
+ set_video_template_caps (caps);
+#else
+ GstCaps *caps, *tmp_caps;
+ guint i;
+
+ g_return_val_if_fail (formats != NULL, NULL);
+
+ caps = gst_caps_new_empty ();
+ if (!caps)
+ return NULL;
- if (!composition)
- return FALSE;
- return gst_vaapi_surface_set_subpictures_from_composition(surface,
- composition, TRUE);
+ for (i = 0; i < formats->len; i++) {
+ const GstVideoFormat format = g_array_index (formats, GstVideoFormat, i);
+ tmp_caps = gst_vaapi_video_format_new_template_caps (format);
+ if (tmp_caps)
+ gst_caps_append (caps, tmp_caps);
+ }
+#endif
+ return caps;
+}
+
+GstCaps *
+gst_vaapi_video_format_new_template_caps_with_features (GstVideoFormat format,
+ const gchar * features_string)
+{
+ GstCaps *caps;
+
+ caps = gst_vaapi_video_format_new_template_caps (format);
+ if (!caps)
+ return NULL;
+
+#if GST_CHECK_VERSION(1,1,0)
+ GstCapsFeatures *const features =
+ gst_caps_features_new (features_string, NULL);
+ if (!features) {
+ gst_caps_unref (caps);
+ return NULL;
+ }
+ gst_caps_set_features (caps, 0, features);
+#endif
+ return caps;
+}
+
+GstVaapiCapsFeature
+gst_vaapi_find_preferred_caps_feature (GstPad * pad, GstVideoFormat format)
+{
+ GstVaapiCapsFeature feature = GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY;
+#if GST_CHECK_VERSION(1,1,0)
+ guint i, num_structures;
+ GstCaps *caps = NULL;
+ GstCaps *gl_texture_upload_caps = NULL;
+ GstCaps *sysmem_caps = NULL;
+ GstCaps *vaapi_caps = NULL;
+ GstCaps *out_caps;
+
+ out_caps = gst_pad_peer_query_caps (pad, NULL);
+ if (!out_caps)
+ goto cleanup;
+
+ gl_texture_upload_caps =
+ gst_vaapi_video_format_new_template_caps_with_features
+ (GST_VIDEO_FORMAT_RGBA,
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META);
+ if (!gl_texture_upload_caps)
+ goto cleanup;
+
+ if (format == GST_VIDEO_FORMAT_ENCODED)
+ format = GST_VIDEO_FORMAT_I420;
+
+ vaapi_caps =
+ gst_vaapi_video_format_new_template_caps_with_features (format,
+ GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE);
+ if (!vaapi_caps)
+ goto cleanup;
+
+ sysmem_caps =
+ gst_vaapi_video_format_new_template_caps_with_features (format,
+ GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+ if (!sysmem_caps)
+ goto cleanup;
+
+ num_structures = gst_caps_get_size (out_caps);
+ for (i = 0; i < num_structures; i++) {
+ GstCapsFeatures *const features = gst_caps_get_features (out_caps, i);
+ GstStructure *const structure = gst_caps_get_structure (out_caps, i);
+
+ caps = gst_caps_new_full (gst_structure_copy (structure), NULL);
+ if (!caps)
+ continue;
+ gst_caps_set_features (caps, 0, gst_caps_features_copy (features));
+
+ if (gst_caps_can_intersect (caps, vaapi_caps) &&
+ feature < GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE)
+ feature = GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE;
+ else if (gst_caps_can_intersect (caps, gl_texture_upload_caps) &&
+ feature < GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META)
+ feature = GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META;
+ else if (gst_caps_can_intersect (caps, sysmem_caps) &&
+ feature < GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY)
+ feature = GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY;
+ gst_caps_replace (&caps, NULL);
+ }
+
+cleanup:
+ gst_caps_replace (&gl_texture_upload_caps, NULL);
+ gst_caps_replace (&sysmem_caps, NULL);
+ gst_caps_replace (&vaapi_caps, NULL);
+ gst_caps_replace (&caps, NULL);
+ gst_caps_replace (&out_caps, NULL);
+#endif
+ return feature;
+}
+
+gboolean
+gst_caps_set_interlaced (GstCaps * caps, GstVideoInfo * vip)
+{
+#if GST_CHECK_VERSION(1,0,0)
+ GstVideoInterlaceMode mode;
+ const gchar *mode_str;
+
+ mode = vip ? GST_VIDEO_INFO_INTERLACE_MODE (vip) :
+ GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+ switch (mode) {
+ case GST_VIDEO_INTERLACE_MODE_PROGRESSIVE:
+ mode_str = "progressive";
+ break;
+ case GST_VIDEO_INTERLACE_MODE_INTERLEAVED:
+ mode_str = "interleaved";
+ break;
+ case GST_VIDEO_INTERLACE_MODE_MIXED:
+ mode_str = "mixed";
+ break;
+ default:
+ GST_ERROR ("unsupported `interlace-mode' %d", mode);
+ return FALSE;
+ }
+
+ gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING, mode_str, NULL);
+#else
+ gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN,
+ vip ? GST_VIDEO_INFO_IS_INTERLACED (vip) : FALSE, NULL);
+#endif
+ return TRUE;
}