static gboolean ensure_vpp (GstVaapiDecodeBin * vaapidecbin) { GstVaapiDisplay *display; if (vaapidecbin->has_vpp != HAS_VPP_UNKNOWN) return TRUE; display = GST_VAAPI_PLUGIN_BASE_DISPLAY (vaapidecbin->decoder); if (display) { GST_INFO_OBJECT (vaapidecbin, "Got display from vaapidecode"); gst_vaapi_display_ref (display); } else { GST_INFO_OBJECT (vaapidecbin, "Creating a dummy display to test for vpp"); display = gst_vaapi_create_test_display (); } if (!display) return FALSE; vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ? HAS_VPP_YES : HAS_VPP_NO; gst_vaapi_display_unref (display); return TRUE; }
gboolean gst_vaapi_ensure_display (GstElement * element, GstVaapiDisplayType type) { GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element); GstVaapiDisplay *display; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); if (gst_vaapi_video_context_prepare (element, &plugin->display)) { /* Neighbour found and it updated the display */ if (gst_vaapi_plugin_base_has_display_type (plugin, type)) return TRUE; } /* If no neighboor, or application not interested, use system default */ if (plugin->gl_context) display = gst_vaapi_create_display_from_gl_context (plugin->gl_context); else display = gst_vaapi_create_display (type, plugin->display_name); if (!display) return FALSE; gst_vaapi_video_context_propagate (element, display); gst_vaapi_display_unref (display); return TRUE; }
gboolean gst_vaapi_ensure_display (gpointer element, GstVaapiDisplayType type) { GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element); GstVaapiDisplay *display; GstVideoContext *context; 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); /* Neighbour found and it updated the display */ if (gst_vaapi_plugin_base_has_display_type (plugin, type)) return TRUE; /* If no neighboor, or application not interested, use system default */ if (plugin->gl_context) display = gst_vaapi_create_display_from_gl_context (plugin->gl_context); else display = gst_vaapi_create_display (type, plugin->display_name); 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; }
GstVaapiDisplay * video_output_create_display (const gchar * display_name) { const VideoOutputInfo *o = g_video_output; GstVaapiDisplay *egl_display, *display = NULL; if (!o) { if (g_output_name) o = video_output_lookup (g_output_name); else { for (o = g_video_outputs; o->name != NULL; o++) { display = o->create_display (display_name); if (display) { if (gst_vaapi_display_get_display (display)) break; gst_vaapi_display_unref (display); display = NULL; } } } if (!o || !o->name) return NULL; g_print ("Using %s video output\n", o->name); g_video_output = o; } if (!display) display = o->create_display (display_name); if (g_egl_mode) { #if USE_EGL egl_display = gst_vaapi_display_egl_new (display, g_gles_version); #else egl_display = NULL; g_print ("error: unsupported EGL renderering mode\n"); #endif gst_vaapi_display_unref (display); if (!egl_display) return NULL; display = egl_display; } return display; }
static gboolean gst_vaapiencode_open (GstVideoEncoder * venc) { GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc); GstVaapiDisplay *const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY (encode); gboolean success; if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (encode))) return FALSE; GST_VAAPI_PLUGIN_BASE_DISPLAY (encode) = NULL; success = ensure_display (encode); if (old_display) gst_vaapi_display_unref (old_display); return success; }
static void gst_vaapi_decode_bin_handle_message (GstBin * bin, GstMessage * message) { GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (bin); GstMessageType type; GstContext *context = NULL; const gchar *context_type; GstVaapiDisplay *display = NULL; type = GST_MESSAGE_TYPE (message); if (type != GST_MESSAGE_HAVE_CONTEXT) goto bail; gst_message_parse_have_context (message, &context); if (!context) goto bail; context_type = gst_context_get_context_type (context); if (g_strcmp0 (context_type, GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME) != 0) goto bail; if (!gst_vaapi_video_context_get_display (context, &display)) goto bail; vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ? HAS_VPP_YES : HAS_VPP_NO; /* the underlying VA driver implementation doesn't support video * post-processing, hence we have to disable it */ if (vaapidecbin->has_vpp != HAS_VPP_YES) { GST_WARNING_OBJECT (vaapidecbin, "VA driver doesn't support VPP"); if (!vaapidecbin->disable_vpp) { vaapidecbin->disable_vpp = TRUE; g_object_notify_by_pspec (G_OBJECT (vaapidecbin), properties[PROP_DISABLE_VPP]); } } bail: if (display) gst_vaapi_display_unref (display); if (context) gst_context_unref (context); GST_BIN_CLASS (gst_vaapi_decode_bin_parent_class)->handle_message (bin, message); }
/* GstVideoContext interface */ static void plugin_set_display (GstVaapiPluginBase * plugin, GstVaapiDisplay * display) { const gchar *const display_name = gst_vaapi_display_get_display_name (display); if (plugin->display_name && g_strcmp0 (plugin->display_name, display_name)) { GST_DEBUG_OBJECT (plugin, "incompatible display name '%s', requested '%s'", display_name, plugin->display_name); gst_vaapi_display_replace (&plugin->display, NULL); } else { GST_INFO_OBJECT (plugin, "set display %p", display); gst_vaapi_display_replace (&plugin->display, display); plugin->display_type = gst_vaapi_display_get_display_type (display); gst_vaapi_plugin_base_set_display_name (plugin, display_name); } gst_vaapi_display_unref (display); }
static gboolean gst_vaapidecode_start (GstVideoDecoder * vdec) { GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); GstVaapiDisplay *const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode); gboolean success; /* Let GstVideoContext ask for a proper display to its neighbours */ /* Note: steal old display that may be allocated from get_caps() so that to retain a reference to it, thus avoiding extra initialization steps if we turn out to simply re-use the existing (cached) VA display */ GST_VAAPI_PLUGIN_BASE_DISPLAY (decode) = NULL; success = gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (decode)); if (old_display) gst_vaapi_display_unref (old_display); return success; }
static void app_free (App * app) { g_return_if_fail (app); if (app->parser) y4m_reader_close (app->parser); if (app->encoder) { gst_vaapi_encoder_flush (app->encoder); gst_vaapi_encoder_unref (app->encoder); } if (app->display) gst_vaapi_display_unref (app->display); if (app->output_file) fclose (app->output_file); g_slice_free (App, app); }
int main (int argc, char *argv[]) { GstVaapiDisplay *display; GstVaapiSurface *surface; GstVaapiID surface_id; GstVaapiSurface *surfaces[MAX_SURFACES]; GstVaapiVideoPool *pool; gint i; static const GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420; static const guint width = 320; static const guint height = 240; if (!video_output_init (&argc, argv, NULL)) g_error ("failed to initialize video output subsystem"); display = video_output_create_display (NULL); if (!display) g_error ("could not create Gst/VA display"); surface = gst_vaapi_surface_new (display, chroma_type, width, height); if (!surface) g_error ("could not create Gst/VA surface"); surface_id = gst_vaapi_surface_get_id (surface); g_print ("created surface %" GST_VAAPI_ID_FORMAT "\n", GST_VAAPI_ID_ARGS (surface_id)); gst_vaapi_object_unref (surface); pool = gst_vaapi_surface_pool_new (display, GST_VIDEO_FORMAT_ENCODED, width, height); if (!pool) g_error ("could not create Gst/VA surface pool"); for (i = 0; i < MAX_SURFACES; i++) { surface = gst_vaapi_video_pool_get_object (pool); if (!surface) g_error ("could not allocate Gst/VA surface from pool"); g_print ("created surface %" GST_VAAPI_ID_FORMAT " from pool\n", GST_VAAPI_ID_ARGS (gst_vaapi_surface_get_id (surface))); surfaces[i] = surface; } /* Check the pool doesn't return the last free'd surface */ surface = gst_vaapi_object_ref (surfaces[1]); for (i = 0; i < 2; i++) gst_vaapi_video_pool_put_object (pool, surfaces[i]); for (i = 0; i < 2; i++) { surfaces[i] = gst_vaapi_video_pool_get_object (pool); if (!surfaces[i]) g_error ("could not re-allocate Gst/VA surface%d from pool", i); g_print ("created surface %" GST_VAAPI_ID_FORMAT " from pool (realloc)\n", GST_VAAPI_ID_ARGS (gst_vaapi_surface_get_id (surfaces[i]))); } if (surface == surfaces[0]) g_error ("Gst/VA pool doesn't queue free surfaces"); for (i = MAX_SURFACES - 1; i >= 0; i--) { if (!surfaces[i]) continue; gst_vaapi_video_pool_put_object (pool, surfaces[i]); surfaces[i] = NULL; } /* Unref in random order to check objects are correctly refcounted */ gst_vaapi_display_unref (display); gst_vaapi_video_pool_unref (pool); gst_vaapi_object_unref (surface); video_output_exit (); return 0; }
static gboolean ensure_allowed_raw_caps (GstVaapiPluginBase * plugin) { GArray *formats, *out_formats; GstVaapiSurface *surface; GstVaapiDisplay *display; guint i; GstCaps *out_caps; gboolean ret = FALSE; if (plugin->allowed_raw_caps) return TRUE; out_formats = formats = NULL; surface = NULL; display = gst_vaapi_display_ref (plugin->display); formats = gst_vaapi_display_get_image_formats (display); if (!formats) goto bail; out_formats = g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat), formats->len); if (!out_formats) goto bail; surface = gst_vaapi_surface_new (display, GST_VAAPI_CHROMA_TYPE_YUV420, 64, 64); if (!surface) goto bail; for (i = 0; i < formats->len; i++) { const GstVideoFormat format = g_array_index (formats, GstVideoFormat, i); GstVaapiImage *image; if (format == GST_VIDEO_FORMAT_UNKNOWN) continue; image = gst_vaapi_image_new (display, format, 64, 64); if (!image) continue; if (gst_vaapi_surface_put_image (surface, image)) g_array_append_val (out_formats, format); gst_vaapi_object_unref (image); } out_caps = gst_vaapi_video_format_new_template_caps_from_list (out_formats); if (!out_caps) goto bail; gst_caps_replace (&plugin->allowed_raw_caps, out_caps); gst_caps_unref (out_caps); ret = TRUE; bail: if (formats) g_array_unref (formats); if (out_formats) g_array_unref (out_formats); if (surface) gst_vaapi_object_unref (surface); gst_vaapi_display_unref (display); return ret; }
static GstVaapiDisplay * gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object) { #if USE_GST_GL_HELPERS GstGLContext *const gl_context = GST_GL_CONTEXT (gl_context_object); GstGLDisplay *const gl_display = gst_gl_context_get_display (gl_context); gpointer native_display = GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display)); GstVaapiDisplay *display, *out_display; GstVaapiDisplayType display_type; switch (gst_gl_display_get_handle_type (gl_display)) { #if USE_X11 case GST_GL_DISPLAY_TYPE_X11: display_type = GST_VAAPI_DISPLAY_TYPE_X11; break; #endif #if USE_WAYLAND case GST_GL_DISPLAY_TYPE_WAYLAND: display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; break; #endif case GST_GL_DISPLAY_TYPE_ANY:{ /* Derive from the active window */ GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context); const gchar *const gl_window_type = g_getenv ("GST_GL_WINDOW"); display_type = GST_VAAPI_DISPLAY_TYPE_ANY; if (!gl_window) break; native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window)); if (gl_window_type) { #if USE_X11 if (!display_type && g_strcmp0 (gl_window_type, "x11") == 0) display_type = GST_VAAPI_DISPLAY_TYPE_X11; #endif #if USE_WAYLAND if (!display_type && g_strcmp0 (gl_window_type, "wayland") == 0) display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; #endif } else { #if USE_X11 if (!display_type && GST_GL_HAVE_WINDOW_X11) display_type = GST_VAAPI_DISPLAY_TYPE_X11; #endif #if USE_WAYLAND if (!display_type && GST_GL_HAVE_WINDOW_WAYLAND) display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; #endif } break; } default: display_type = GST_VAAPI_DISPLAY_TYPE_ANY; break; } if (!display_type) return NULL; display = gst_vaapi_create_display_from_handle (display_type, native_display); if (!display) return NULL; switch (gst_gl_context_get_gl_platform (gl_context)) { #if USE_EGL case GST_GL_PLATFORM_EGL:{ guint gles_version; switch (gst_gl_context_get_gl_api (gl_context)) { case GST_GL_API_GLES1: gles_version = 1; goto create_egl_display; case GST_GL_API_GLES2: gles_version = 2; goto create_egl_display; case GST_GL_API_OPENGL: case GST_GL_API_OPENGL3: gles_version = 0; create_egl_display: out_display = gst_vaapi_display_egl_new (display, gles_version); break; default: out_display = NULL; break; } if (!out_display) return NULL; gst_vaapi_display_egl_set_gl_context (GST_VAAPI_DISPLAY_EGL (out_display), GSIZE_TO_POINTER (gst_gl_context_get_gl_context (gl_context))); break; } #endif default: out_display = gst_vaapi_display_ref (display); break; } gst_vaapi_display_unref (display); return out_display; #endif GST_ERROR ("unsupported GStreamer version %s", GST_API_VERSION_S); return NULL; }
int main(int argc, char *argv[]) { GstVaapiDisplay *display, *display2; guint width, height, par_n, par_d; gst_init(&argc, &argv); #if USE_DRM g_print("#\n"); g_print("# Create display with gst_vaapi_display_drm_new()\n"); g_print("#\n"); { display = gst_vaapi_display_drm_new(NULL); if (!display) g_error("could not create Gst/VA display"); dump_info(display); gst_vaapi_display_unref(display); } g_print("\n"); g_print("#\n"); g_print("# Create display with gst_vaapi_display_drm_new_with_device()\n"); g_print("#\n"); { int drm_device; drm_device = open(DRM_DEVICE_PATH, O_RDWR|O_CLOEXEC); if (drm_device < 0) g_error("could not open DRM device"); display = gst_vaapi_display_drm_new_with_device(drm_device); if (!display) g_error("could not create Gst/VA display"); dump_info(display); gst_vaapi_display_unref(display); close(drm_device); } g_print("\n"); g_print("#\n"); g_print("# Create display with gst_vaapi_display_new_with_display() [vaGetDisplayDRM()]\n"); g_print("#\n"); { int drm_device; VADisplay va_display; drm_device = open(DRM_DEVICE_PATH, O_RDWR|O_CLOEXEC); if (drm_device < 0) g_error("could not open DRM device"); va_display = vaGetDisplayDRM(drm_device); if (!va_display) g_error("could not create VA display"); display = gst_vaapi_display_new_with_display(va_display); if (!display) g_error("could not create Gst/VA display"); dump_info(display); gst_vaapi_display_unref(display); close(drm_device); } g_print("\n"); #endif #if USE_X11 g_print("#\n"); g_print("# Create display with gst_vaapi_display_x11_new()\n"); g_print("#\n"); { display = gst_vaapi_display_x11_new(NULL); if (!display) g_error("could not create Gst/VA display"); if (CHECK_DISPLAY_CACHE) { display2 = gst_vaapi_display_x11_new(NULL); /* Check for the same X11 display */ g_assert(gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display)) == gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display2))); /* Check for the same VA display */ g_assert(gst_vaapi_display_get_display(display) == gst_vaapi_display_get_display(display2)); gst_vaapi_display_unref(display2); #if USE_GLX display2 = gst_vaapi_display_glx_new(NULL); /* Check for the different X11 display */ /* XXX: it is also desired to cache underlying X11 displays */ g_assert(gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display)) != gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display2))); /* Check for different VA display */ g_assert(gst_vaapi_display_get_display(display) != gst_vaapi_display_get_display(display2)); gst_vaapi_display_unref(display2); #endif } gst_vaapi_display_get_size(display, &width, &height); g_print("Display size: %ux%u\n", width, height); gst_vaapi_display_get_pixel_aspect_ratio(display, &par_n, &par_d); g_print("Pixel aspect ratio: %u/%u\n", par_n, par_d); dump_info(display); gst_vaapi_display_unref(display); } g_print("\n"); g_print("#\n"); g_print("# Create display with gst_vaapi_display_x11_new_with_display()\n"); g_print("#\n"); { Display *x11_display; x11_display = XOpenDisplay(NULL); if (!x11_display) g_error("could not create X11 display"); display = gst_vaapi_display_x11_new_with_display(x11_display); if (!display) g_error("could not create Gst/VA display"); if (CHECK_DISPLAY_CACHE) { display2 = gst_vaapi_display_x11_new_with_display(x11_display); /* Check for the same VA display */ g_assert(gst_vaapi_display_get_display(display) == gst_vaapi_display_get_display(display2)); gst_vaapi_display_unref(display2); } dump_info(display); gst_vaapi_display_unref(display); XCloseDisplay(x11_display); } g_print("\n"); g_print("#\n"); g_print("# Create display with gst_vaapi_display_new_with_display() [vaGetDisplay()]\n"); g_print("#\n"); { Display *x11_display; VADisplay va_display; x11_display = XOpenDisplay(NULL); if (!x11_display) g_error("could not create X11 display"); va_display = vaGetDisplay(x11_display); if (!va_display) g_error("could not create VA display"); display = gst_vaapi_display_new_with_display(va_display); if (!display) g_error("could not create Gst/VA display"); dump_info(display); gst_vaapi_display_unref(display); XCloseDisplay(x11_display); } g_print("\n"); #endif #if USE_GLX g_print("#\n"); g_print("# Create display with gst_vaapi_display_glx_new()\n"); g_print("#\n"); { display = gst_vaapi_display_glx_new(NULL); if (!display) g_error("could not create Gst/VA display"); if (CHECK_DISPLAY_CACHE) { display2 = gst_vaapi_display_glx_new(NULL); /* Check for the same X11 display */ g_assert(gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display)) == gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display2))); /* Check for the same VA display */ g_assert(gst_vaapi_display_get_display(display) == gst_vaapi_display_get_display(display2)); gst_vaapi_display_unref(display2); display2 = gst_vaapi_display_x11_new(NULL); /* Check for the same X11 display */ g_assert(gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display)) == gst_vaapi_display_x11_get_display( GST_VAAPI_DISPLAY_X11(display2))); /* Check for the same VA display */ g_assert(gst_vaapi_display_get_display(display) == gst_vaapi_display_get_display(display2)); gst_vaapi_display_unref(display2); } gst_vaapi_display_get_size(display, &width, &height); g_print("Display size: %ux%u\n", width, height); gst_vaapi_display_get_pixel_aspect_ratio(display, &par_n, &par_d); g_print("Pixel aspect ratio: %u/%u\n", par_n, par_d); dump_info(display); gst_vaapi_display_unref(display); } g_print("\n"); g_print("#\n"); g_print("# Create display with gst_vaapi_display_glx_new_with_display()\n"); g_print("#\n"); { Display *x11_display; x11_display = XOpenDisplay(NULL); if (!x11_display) g_error("could not create X11 display"); display = gst_vaapi_display_glx_new_with_display(x11_display); if (!display) g_error("could not create Gst/VA display"); dump_info(display); gst_vaapi_display_unref(display); XCloseDisplay(x11_display); } g_print("\n"); #ifdef HAVE_VA_VA_GLX_H g_print("#\n"); g_print("# Create display with gst_vaapi_display_new_with_display() [vaGetDisplayGLX()]\n"); g_print("#\n"); { Display *x11_display; VADisplay va_display; x11_display = XOpenDisplay(NULL); if (!x11_display) g_error("could not create X11 display"); va_display = vaGetDisplayGLX(x11_display); if (!va_display) g_error("could not create VA display"); display = gst_vaapi_display_new_with_display(va_display); if (!display) g_error("could not create Gst/VA display"); dump_info(display); gst_vaapi_display_unref(display); XCloseDisplay(x11_display); } g_print("\n"); #endif #endif #if USE_WAYLAND g_print("#\n"); g_print("# Create display with gst_vaapi_display_wayland_new()\n"); g_print("#\n"); { display = gst_vaapi_display_wayland_new(NULL); if (!display) g_error("could not create Gst/VA display"); gst_vaapi_display_get_size(display, &width, &height); g_print("Display size: %ux%u\n", width, height); gst_vaapi_display_get_pixel_aspect_ratio(display, &par_n, &par_d); g_print("Pixel aspect ratio: %u/%u\n", par_n, par_d); dump_info(display); gst_vaapi_display_unref(display); } g_print("\n"); #endif gst_deinit(); return 0; }