From 99c5d18f412a6f42d6bbf9b931675b8597a1539f Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Fri, 4 Nov 2011 16:50:15 -0400 Subject: [PATCH] Port to GstVideoContext interface. This new interface allows for upstream and downstream display sharing that works in both static and dynamic pipelines. Signed-off-by: Gwenole Beauchesne --- configure.ac | 15 ++ gst-libs/gst/vaapi/Makefile.am | 2 - gst-libs/gst/vaapi/gstvaapiutils_gst.c | 108 ------------ gst/vaapi/Makefile.am | 5 + gst/vaapi/gstvaapiconvert.c | 70 +++++++- gst/vaapi/gstvaapidecode.c | 86 ++++++---- gst/vaapi/gstvaapipluginutil.c | 162 ++++++++++++++++++ .../vaapi/gstvaapipluginutil.h | 17 +- gst/vaapi/gstvaapisink.c | 106 +++++------- gst/vaapi/gstvaapisink.h | 1 - 10 files changed, 348 insertions(+), 224 deletions(-) delete mode 100644 gst-libs/gst/vaapi/gstvaapiutils_gst.c create mode 100644 gst/vaapi/gstvaapipluginutil.c rename gst-libs/gst/vaapi/gstvaapiutils_gst.h => gst/vaapi/gstvaapipluginutil.h (62%) diff --git a/configure.ac b/configure.ac index 9baa50c56d..4334d75395 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,13 @@ m4_define([gst_plugins_base_version], m4_define([va_api_x11_version], [0.31.0]) m4_define([va_api_glx_version], [0.32.0]) +# gst plugins-bad version number +m4_define([gst_plugins_bad_major_version], [0]) +m4_define([gst_plugins_bad_minor_version], [10]) +m4_define([gst_plugins_bad_micro_version], [22]) +m4_define([gst_plugins_bad_version], + [gst_plugins_bad_major_version.gst_plugins_bad_minor_version.gst_plugins_bad_micro_version]) + # libva package version number m4_define([libva_x11_package_version], [1.0.3]) m4_define([libva_glx_package_version], [1.0.9]) @@ -61,6 +68,7 @@ dnl Versions for GStreamer and plugins-base GST_MAJORMINOR=gst_major_minor_version GST_VERSION_REQUIRED=gst_version GST_PLUGINS_BASE_VERSION_REQUIRED=gst_plugins_base_version +GST_PLUGINS_BAD_VERSION_REQUIRED=gst_plugins_bad_version AC_SUBST(GST_MAJORMINOR) AC_SUBST(GST_VERSION_REQUIRED) AC_SUBST(GST_PLUGINS_BASE_VERSION_REQUIRED) @@ -168,6 +176,13 @@ PKG_CHECK_MODULES([GST_VIDEO], AC_SUBST(GST_VIDEO_CFLAGS) AC_SUBST(GST_VIDEO_LIBS) +dnl Check for GStreamer basevideo +PKG_CHECK_MODULES([GST_BASEVIDEO], + [gstreamer-basevideo-$GST_MAJORMINOR >= $GST_PLUGINS_BAD_VERSION_REQUIRED] +) +AC_SUBST(GST_BASEVIDEO_CFLAGS) +AC_SUBST(GST_BASEVIDEO_LIBS) + dnl Check for GStreamer interfaces PKG_CHECK_MODULES([GST_INTERFACES], [gstreamer-interfaces-$GST_MAJORMINOR >= $GST_PLUGINS_BASE_VERSION_REQUIRED] diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am index 1feca33835..17ead8b308 100644 --- a/gst-libs/gst/vaapi/Makefile.am +++ b/gst-libs/gst/vaapi/Makefile.am @@ -37,7 +37,6 @@ libgstvaapi_source_c = \ gstvaapisurfacepool.c \ gstvaapisurfaceproxy.c \ gstvaapiutils.c \ - gstvaapiutils_gst.c \ gstvaapivalue.c \ gstvaapivideobuffer.c \ gstvaapivideopool.c \ @@ -77,7 +76,6 @@ libgstvaapi_source_priv_h = \ gstvaapidisplay_priv.h \ gstvaapiobject_priv.h \ gstvaapiutils.h \ - gstvaapiutils_gst.h \ $(libgst_vaapi_ffmpeg_source_priv_h) \ $(NULL) diff --git a/gst-libs/gst/vaapi/gstvaapiutils_gst.c b/gst-libs/gst/vaapi/gstvaapiutils_gst.c deleted file mode 100644 index 7a0e7dae44..0000000000 --- a/gst-libs/gst/vaapi/gstvaapiutils_gst.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * gstvaapiutils_gst.c - GST utilties - * - * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "gstvaapiutils_gst.h" -#include "gstvaapivideosink.h" -#include "gstvaapivideobuffer.h" - -#define DEBUG 1 -#include "gstvaapidebug.h" - -static GstVaapiDisplay * -lookup_through_vaapisink_iface(GstElement *element) -{ - GstVaapiDisplay *display; - GstVaapiVideoSink *sink; - - GST_DEBUG("looking for a downstream vaapisink"); - - /* Look for a downstream vaapisink */ - sink = gst_vaapi_video_sink_lookup(element); - if (!sink) - return NULL; - - display = gst_vaapi_video_sink_get_display(sink); - GST_DEBUG(" found display %p", display); - return display; -} - -static GstVaapiDisplay * -lookup_through_peer_buffer(GstElement *element) -{ - GstVaapiDisplay *display; - GstPad *pad; - GstBuffer *buffer; - GstFlowReturn ret; - - GST_DEBUG("looking for a GstVaapiVideoBuffer from peer"); - - /* Look for a GstVaapiVideoBuffer from peer */ - pad = gst_element_get_static_pad(element, "src"); - if (!pad) - return NULL; - - buffer = NULL; - ret = gst_pad_alloc_buffer(pad, 0, 0, GST_PAD_CAPS(pad), &buffer); - g_object_unref(pad); - if (ret != GST_FLOW_OK || !buffer) - return NULL; - - display = GST_VAAPI_IS_VIDEO_BUFFER(buffer) ? - gst_vaapi_video_buffer_get_display(GST_VAAPI_VIDEO_BUFFER(buffer)) : - NULL; - gst_buffer_unref(buffer); - - GST_DEBUG(" found display %p", display); - return display; -} - -/** - * gst_vaapi_display_lookup_downstream: - * @element: a #GstElement - * - * Finds a suitable #GstVaapiDisplay downstream from @element. - * - * 1. Check whether a downstream element implements the - * #GstVaapiVideoSinkInterface interface. - * - * 2. Check whether the @element peer implements a custom - * buffer_alloc() function that allocates #GstVaapiVideoBuffer - * buffers. - * - * Return value: a downstream allocated #GstVaapiDisplay object, or - * %NULL if none was found - */ -GstVaapiDisplay * -gst_vaapi_display_lookup_downstream(GstElement *element) -{ - GstVaapiDisplay *display; - - display = lookup_through_vaapisink_iface(element); - if (display) - return display; - - display = lookup_through_peer_buffer(element); - if (display) - return display; - - return NULL; -} diff --git a/gst/vaapi/Makefile.am b/gst/vaapi/Makefile.am index 3e842dcb34..0b18d08f11 100644 --- a/gst/vaapi/Makefile.am +++ b/gst/vaapi/Makefile.am @@ -2,6 +2,7 @@ plugin_LTLIBRARIES = libgstvaapi.la libgstvaapi_CFLAGS = \ $(LIBVA_CFLAGS) \ + -DGST_USE_UNSTABLE_API \ -I$(top_srcdir)/gst-libs if USE_VAAPI_GLX @@ -16,12 +17,14 @@ libgstvaapi_la_SOURCES = \ gstvaapi.c \ gstvaapiconvert.c \ gstvaapidecode.c \ + gstvaapipluginutil.c \ gstvaapisink.c \ $(NULL) noinst_HEADERS = \ gstvaapiconvert.h \ gstvaapidecode.h \ + gstvaapipluginutil.h \ gstvaapisink.h \ $(NULL) @@ -31,6 +34,7 @@ libgstvaapi_la_CFLAGS = \ $(GST_BASE_CFLAGS) \ $(GST_VIDEO_CFLAGS) \ $(GST_INTERFACES_CFLAGS) \ + $(GST_BASEVIDEO_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) libgstvaapi_la_LIBADD = \ @@ -39,6 +43,7 @@ libgstvaapi_la_LIBADD = \ $(GST_BASE_LIBS) \ $(GST_VIDEO_LIBS) \ $(GST_INTERFACES_LIBS) \ + $(GST_BASEVIDEO_LIBS) \ $(GST_PLUGINS_BASE_LIBS) libgstvaapi_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/vaapi/gstvaapiconvert.c b/gst/vaapi/gstvaapiconvert.c index 8c2896c0d9..f8719403bc 100644 --- a/gst/vaapi/gstvaapiconvert.c +++ b/gst/vaapi/gstvaapiconvert.c @@ -29,11 +29,14 @@ */ #include "config.h" + #include #include +#include #include #include -#include + +#include "gstvaapipluginutil.h" #include "gstvaapiconvert.h" #define GST_PLUGIN_NAME "vaapiconvert" @@ -73,11 +76,15 @@ static GstStaticPadTemplate gst_vaapiconvert_src_factory = GST_PAD_ALWAYS, GST_STATIC_CAPS(gst_vaapiconvert_vaapi_caps_str)); -GST_BOILERPLATE( +#define GstVideoContextClass GstVideoContextInterface +GST_BOILERPLATE_WITH_INTERFACE( GstVaapiConvert, gst_vaapiconvert, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM); + GST_TYPE_BASE_TRANSFORM, + GstVideoContext, + GST_TYPE_VIDEO_CONTEXT, + gst_video_context); /* * Direct rendering levels (direct-rendering) @@ -145,6 +152,34 @@ gst_vaapiconvert_prepare_output_buffer( GstBuffer **poutbuf ); +static gboolean +gst_vaapiconvert_query( + GstPad *pad, + GstQuery *query +); + +/* GstVideoContext interface */ + +static void +gst_vaapiconvert_set_video_context(GstVideoContext *context, const gchar *type, + const GValue *value) +{ + GstVaapiConvert *convert = GST_VAAPICONVERT (context); + gst_vaapi_set_display (type, value, &convert->display); +} + +static gboolean +gst_video_context_supported (GstVaapiConvert *convert, GType iface_type) +{ + return (iface_type == GST_TYPE_VIDEO_CONTEXT); +} + +static void +gst_video_context_interface_init(GstVideoContextInterface *iface) +{ + iface->set_context = gst_vaapiconvert_set_video_context; +} + static void gst_vaapiconvert_destroy(GstVaapiConvert *convert) { @@ -289,7 +324,7 @@ gst_vaapiconvert_class_init(GstVaapiConvertClass *klass) static void gst_vaapiconvert_init(GstVaapiConvert *convert, GstVaapiConvertClass *klass) { - GstPad *sinkpad; + GstPad *sinkpad, *srcpad; convert->display = NULL; convert->images = NULL; @@ -310,20 +345,20 @@ gst_vaapiconvert_init(GstVaapiConvert *convert, GstVaapiConvertClass *klass) gst_vaapiconvert_sinkpad_buffer_alloc ); g_object_unref(sinkpad); + + /* Override query on src pad */ + srcpad = gst_element_get_static_pad(GST_ELEMENT(convert), "src"); + gst_pad_set_query_function(srcpad, gst_vaapiconvert_query); } static gboolean gst_vaapiconvert_start(GstBaseTransform *trans) { GstVaapiConvert * const convert = GST_VAAPICONVERT(trans); - GstVaapiDisplay *display; - /* Look for a downstream display */ - display = gst_vaapi_display_lookup_downstream(GST_ELEMENT(trans)); - if (!display) + if (!gst_vaapi_ensure_display(convert, &convert->display)) return FALSE; - convert->display = g_object_ref(display); return TRUE; } @@ -766,3 +801,20 @@ gst_vaapiconvert_prepare_output_buffer( *poutbuf = buffer; return GST_FLOW_OK; } + +static gboolean +gst_vaapiconvert_query(GstPad *pad, GstQuery *query) +{ + GstVaapiConvert *convert = GST_VAAPICONVERT (gst_pad_get_parent_element (pad)); + gboolean res; + + GST_DEBUG ("sharing display %p", convert->display); + + if (gst_vaapi_reply_to_query (query, convert->display)) + res = TRUE; + else + res = gst_pad_query_default (pad, query); + + g_object_unref (convert); + return res; +} diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 19f0e91780..716c3525a4 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -29,12 +29,15 @@ */ #include "config.h" -#include "gstvaapidecode.h" -#include + +#include #include #include #include -#include +#include + +#include "gstvaapidecode.h" +#include "gstvaapipluginutil.h" #define GST_PLUGIN_NAME "vaapidecode" #define GST_PLUGIN_DESC "A VA-API based video decoder" @@ -80,11 +83,15 @@ static GstStaticPadTemplate gst_vaapidecode_src_factory = GST_PAD_ALWAYS, GST_STATIC_CAPS(gst_vaapidecode_src_caps_str)); -GST_BOILERPLATE( +#define GstVideoContextClass GstVideoContextInterface +GST_BOILERPLATE_WITH_INTERFACE( GstVaapiDecode, gst_vaapidecode, GstElement, - GST_TYPE_ELEMENT); + GST_TYPE_ELEMENT, + GstVideoContext, + GST_TYPE_VIDEO_CONTEXT, + gst_video_context); enum { PROP_0, @@ -257,24 +264,10 @@ error_commit_buffer: } } -static inline gboolean -gst_vaapidecode_ensure_display(GstVaapiDecode *decode) -{ - GstVaapiDisplay *display; - - if (!decode->display) { - display = gst_vaapi_display_lookup_downstream(GST_ELEMENT(decode)); - if (!display) - return FALSE; - decode->display = g_object_ref(display); - } - return TRUE; -} - static gboolean gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps) { - if (!gst_vaapidecode_ensure_display(decode)) + if (!gst_vaapi_ensure_display(decode, &decode->display)) return FALSE; decode->decoder_mutex = g_mutex_new(); @@ -339,6 +332,28 @@ gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps) return gst_vaapidecode_create(decode, caps); } +/* GstVideoContext interface */ + +static void +gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type, + const GValue *value) +{ + GstVaapiDecode *decode = GST_VAAPIDECODE (context); + gst_vaapi_set_display (type, value, &decode->display); +} + +static gboolean +gst_video_context_supported (GstVaapiDecode *decode, GType iface_type) +{ + return (iface_type == GST_TYPE_VIDEO_CONTEXT); +} + +static void +gst_video_context_interface_init(GstVideoContextInterface *iface) +{ + iface->set_context = gst_vaapidecode_set_video_context; +} + static void gst_vaapidecode_base_init(gpointer klass) { @@ -494,15 +509,10 @@ gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode) if (decode->allowed_caps) return TRUE; - if (gst_vaapidecode_ensure_display(decode)) - display = g_object_ref(decode->display); - else { - display = gst_vaapi_display_x11_new(NULL); - if (!display) - goto error_no_display; - } + if (!gst_vaapi_ensure_display(decode, &decode->display)) + goto error_no_display; - decode_caps = gst_vaapi_display_get_decode_caps(display); + decode_caps = gst_vaapi_display_get_decode_caps(decode->display); if (!decode_caps) goto error_no_decode_caps; n_decode_caps = gst_caps_get_size(decode_caps); @@ -530,7 +540,6 @@ gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode) } gst_caps_unref(decode_caps); - g_object_unref(display); return TRUE; /* ERRORS */ @@ -542,14 +551,12 @@ error_no_display: error_no_decode_caps: { GST_DEBUG("failed to retrieve VA decode caps"); - g_object_unref(display); return FALSE; } error_no_memory: { GST_DEBUG("failed to allocate allowed-caps set"); gst_caps_unref(decode_caps); - g_object_unref(display); return FALSE; } } @@ -621,6 +628,22 @@ gst_vaapidecode_src_event(GstPad *pad, GstEvent *event) return gst_pad_push_event(decode->sinkpad, event); } +static gboolean +gst_vaapidecode_query (GstPad *pad, GstQuery *query) { + GstVaapiDecode *decode = GST_VAAPIDECODE (gst_pad_get_parent_element (pad)); + gboolean res; + + GST_DEBUG ("sharing display %p", decode->display); + + if (gst_vaapi_reply_to_query (query, decode->display)) + res = TRUE; + else + res = gst_pad_query_default (pad, query); + + g_object_unref (decode); + return res; +} + static void gst_vaapidecode_init(GstVaapiDecode *decode, GstVaapiDecodeClass *klass) { @@ -656,5 +679,6 @@ gst_vaapidecode_init(GstVaapiDecode *decode, GstVaapiDecodeClass *klass) gst_pad_use_fixed_caps(decode->srcpad); gst_pad_set_event_function(decode->srcpad, gst_vaapidecode_src_event); + gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query); gst_element_add_pad(GST_ELEMENT(decode), decode->srcpad); } diff --git a/gst/vaapi/gstvaapipluginutil.c b/gst/vaapi/gstvaapipluginutil.c new file mode 100644 index 0000000000..a95fb8c66b --- /dev/null +++ b/gst/vaapi/gstvaapipluginutil.c @@ -0,0 +1,162 @@ +/* + * gstvaapipluginutil.h - VA-API plugin helpers + * + * Copyright (C) 2011 Intel Corporation + * Copyright (C) 2011 Collabora + * Author: Nicolas Dufresne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstvaapipluginutil.h" + +#include + +#ifdef USE_VAAPI_GLX +#include +#else +#include +#endif + +/* Preferred first */ +static const char *display_types[] = { + "gst-vaapi-display", + "vaapi-display", + "x11-display", + "x11-display-name", + NULL +}; + +gboolean +gst_vaapi_ensure_display (gpointer element, GstVaapiDisplay **display) +{ + GstVideoContext *context; + + g_return_val_if_fail (GST_IS_VIDEO_CONTEXT (element), FALSE); + g_return_val_if_fail (display != NULL, FALSE); + + /* Already exist ? */ + if (*display) + return TRUE; + + context = GST_VIDEO_CONTEXT (element); + gst_video_context_prepare (context, display_types); + + /* If no neighboor, or application not interested, use system default */ + if (!*display) +#if USE_VAAPI_GLX + *display = gst_vaapi_display_glx_new (""); +#else + *display = gst_vaapi_display_x11_new (""); +#endif + + /* FIXME allocator should return NULL in case of failure */ + if (*display && !gst_vaapi_display_get_display(*display)) { + g_object_unref (*display); + *display = NULL; + } + + return (*display != NULL); +} + +void +gst_vaapi_set_display (const gchar *type, + const GValue *value, + GstVaapiDisplay **display) +{ + GstVaapiDisplay *dpy = NULL; + + if (!strcmp (type, "x11-display-name")) { + g_return_if_fail (G_VALUE_HOLDS_STRING (value)); +#if USE_VAAPI_GLX + dpy = gst_vaapi_display_glx_new (g_value_get_string (value)); +#else + dpy = gst_vaapi_display_x11_new (g_value_get_string (value)); +#endif + } else if (!strcmp (type, "x11-display")) { + g_return_if_fail (G_VALUE_HOLDS_POINTER (value)); +#if USE_VAAPI_GLX + dpy = gst_vaapi_display_glx_new_with_display (g_value_get_pointer (value)); +#else + dpy = gst_vaapi_display_x11_new_with_display (g_value_get_pointer (value)); +#endif + } else 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 (dpy) { + if (*display) + g_object_unref (*display); + *display = dpy; + } +} + +gboolean +gst_vaapi_reply_to_query (GstQuery *query, GstVaapiDisplay *display) +{ + const gchar **types; + const gchar *type; + gint i; + gboolean res = FALSE; + + if (!display) + return FALSE; + + types = gst_video_context_query_get_supported_types (query); + + if (!types) + return FALSE; + + for (i = 0; types[i]; i++) { + type = types[i]; + + 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 if (!strcmp (type, "x11-display") && + GST_VAAPI_IS_DISPLAY_X11(display)) { + GstVaapiDisplayX11 *xvadpy = GST_VAAPI_DISPLAY_X11 (display); + Display *x11dpy = gst_vaapi_display_x11_get_display (xvadpy); + gst_video_context_query_set_pointer (query, type, x11dpy); + + } else if (!strcmp (type, "x11-display-name") && + GST_VAAPI_IS_DISPLAY_X11(display)) { + GstVaapiDisplayX11 *xvadpy = GST_VAAPI_DISPLAY_X11 (display); + Display *x11dpy = gst_vaapi_display_x11_get_display (xvadpy); + gst_video_context_query_set_string (query, type, DisplayString(x11dpy)); + + } else { + continue; + } + + res = TRUE; + break; + } + + return res; +} diff --git a/gst-libs/gst/vaapi/gstvaapiutils_gst.h b/gst/vaapi/gstvaapipluginutil.h similarity index 62% rename from gst-libs/gst/vaapi/gstvaapiutils_gst.h rename to gst/vaapi/gstvaapipluginutil.h index 350f20a3e5..3d31938a5a 100644 --- a/gst-libs/gst/vaapi/gstvaapiutils_gst.h +++ b/gst/vaapi/gstvaapipluginutil.h @@ -1,7 +1,9 @@ /* - * gstvaapiutils_gst.h - GST utilties + * gstvaapipluginutil.h - VA-API plugins private helper * - * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems + * Copyright (C) 2011 Intel Corporation + * Copyright (C) 2011 Collabora + * Author: Nicolas Dufresne * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -19,13 +21,10 @@ * Boston, MA 02110-1301 USA */ -#ifndef GST_VAAPI_UTILS_GST_H -#define GST_VAAPI_UTILS_GST_H - #include +#include #include -GstVaapiDisplay * -gst_vaapi_display_lookup_downstream(GstElement *element); - -#endif /* GST_VAAPI_UTILS_GST_H */ +gboolean gst_vaapi_ensure_display (gpointer element, GstVaapiDisplay **display); +void gst_vaapi_set_display (const gchar *type, const GValue *value, GstVaapiDisplay **display); +gboolean gst_vaapi_reply_to_query (GstQuery *query, GstVaapiDisplay *display); diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c index 35c2af3cba..b2477c3e87 100644 --- a/gst/vaapi/gstvaapisink.c +++ b/gst/vaapi/gstvaapisink.c @@ -31,8 +31,9 @@ #include "config.h" #include -#include #include +#include +#include #include #include #include @@ -41,11 +42,13 @@ #include #include #endif -#include "gstvaapisink.h" /* Supported interfaces */ #include +#include "gstvaapisink.h" +#include "gstvaapipluginutil.h" + #define HAVE_GST_XOVERLAY_SET_WINDOW_HANDLE \ GST_PLUGINS_BASE_CHECK_VERSION(0,10,31) @@ -84,7 +87,6 @@ enum { PROP_0, PROP_USE_GLX, - PROP_DISPLAY, PROP_FULLSCREEN, PROP_SYNCHRONOUS, PROP_USE_REFLECTION @@ -98,7 +100,7 @@ gst_vaapisink_implements_interface_supported( GType type ) { - return (type == GST_VAAPI_TYPE_VIDEO_SINK || + return (type == GST_TYPE_VIDEO_CONTEXT || type == GST_TYPE_X_OVERLAY); } @@ -110,19 +112,18 @@ gst_vaapisink_implements_iface_init(GstImplementsInterfaceClass *iface) /* GstVaapiVideoSink interface */ -static GstVaapiDisplay * -gst_vaapisink_get_display(GstVaapiSink *sink); - -static GstVaapiDisplay * -gst_vaapi_video_sink_do_get_display(GstVaapiVideoSink *sink) +static void +gst_vaapisink_set_video_context(GstVideoContext *context, const gchar *type, + const GValue *value) { - return gst_vaapisink_get_display(GST_VAAPISINK(sink)); + GstVaapiSink *sink = GST_VAAPISINK (context); + gst_vaapi_set_display (type, value, &sink->display); } static void -gst_vaapi_video_sink_iface_init(GstVaapiVideoSinkInterface *iface) +gst_vaapisink_video_context_iface_init(GstVideoContextInterface *iface) { - iface->get_display = gst_vaapi_video_sink_do_get_display; + iface->set_context = gst_vaapisink_set_video_context; } /* GstXOverlay interface */ @@ -191,8 +192,8 @@ gst_vaapisink_iface_init(GType type) G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE, gst_vaapisink_implements_iface_init); - G_IMPLEMENT_INTERFACE(GST_VAAPI_TYPE_VIDEO_SINK, - gst_vaapi_video_sink_iface_init); + G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT, + gst_vaapisink_video_context_iface_init); G_IMPLEMENT_INTERFACE(GST_TYPE_X_OVERLAY, gst_vaapisink_xoverlay_iface_init); } @@ -204,11 +205,6 @@ gst_vaapisink_destroy(GstVaapiSink *sink) g_object_unref(sink->display); sink->display = NULL; } - - if (sink->display_name) { - g_free(sink->display_name); - sink->display_name = NULL; - } } /* Checks whether a ConfigureNotify event is in the queue */ @@ -262,23 +258,6 @@ configure_notify_event_pending( return args.match; } -static inline gboolean -gst_vaapisink_ensure_display(GstVaapiSink *sink) -{ - if (!sink->display) { -#if USE_VAAPISINK_GLX - if (sink->use_glx) - sink->display = gst_vaapi_display_glx_new(sink->display_name); - else -#endif - sink->display = gst_vaapi_display_x11_new(sink->display_name); - if (!sink->display || !gst_vaapi_display_get_display(sink->display)) - return FALSE; - g_object_set(sink, "synchronous", sink->synchronous, NULL); - } - return sink->display != NULL; -} - static gboolean gst_vaapisink_ensure_render_rect(GstVaapiSink *sink, guint width, guint height) { @@ -384,7 +363,7 @@ gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) int x, y; XID xid = window_id; - if (!gst_vaapisink_ensure_display(sink)) + if (!gst_vaapi_ensure_display(sink, &sink->display)) return FALSE; gst_vaapi_display_lock(sink->display); @@ -427,8 +406,6 @@ gst_vaapisink_start(GstBaseSink *base_sink) { GstVaapiSink * const sink = GST_VAAPISINK(base_sink); - if (!gst_vaapisink_ensure_display(sink)) - return FALSE; return TRUE; } @@ -471,6 +448,9 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps) sink->video_par_d = video_par_d; GST_DEBUG("video pixel-aspect-ratio %d/%d", video_par_n, video_par_d); + if (!gst_vaapi_ensure_display(sink, &sink->display)) + return FALSE; + gst_vaapi_display_get_size(sink->display, &display_width, &display_height); if (!gst_vaapisink_ensure_render_rect(sink, display_width, display_height)) return FALSE; @@ -515,6 +495,9 @@ gst_vaapisink_buffer_alloc( GstStructure *structure; GstBuffer *buffer; + if (!gst_vaapi_ensure_display(sink, &sink->display)) + goto error_ensure_display; + structure = gst_caps_get_structure(caps, 0); if (!gst_structure_has_name(structure, "video/x-vaapi-surface")) goto error_invalid_caps; @@ -528,6 +511,11 @@ gst_vaapisink_buffer_alloc( return GST_FLOW_OK; /* ERRORS */ +error_ensure_display: + { + GST_ERROR("failed to ensure display"); + return GST_FLOW_UNEXPECTED; + } error_invalid_caps: { GST_ERROR("failed to validate input caps"); @@ -719,6 +707,12 @@ gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer) guint flags; gboolean success; + if (sink->display != gst_vaapi_video_buffer_get_display (vbuffer)) { + if (sink->display) + g_object_unref (sink->display); + sink->display = g_object_ref (gst_vaapi_video_buffer_get_display (vbuffer)); + } + if (!sink->window) return GST_FLOW_UNEXPECTED; @@ -740,6 +734,14 @@ gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer) return success ? GST_FLOW_OK : GST_FLOW_UNEXPECTED; } +static gboolean +gst_vaapisink_query(GstBaseSink *base_sink, GstQuery *query) +{ + GstVaapiSink *sink = GST_VAAPISINK(base_sink); + GST_DEBUG ("sharing display %p", sink->display); + return gst_vaapi_reply_to_query (query, sink->display); +} + static void gst_vaapisink_finalize(GObject *object) { @@ -762,10 +764,6 @@ gst_vaapisink_set_property( case PROP_USE_GLX: sink->use_glx = g_value_get_boolean(value); break; - case PROP_DISPLAY: - g_free(sink->display_name); - sink->display_name = g_strdup(g_value_get_string(value)); - break; case PROP_FULLSCREEN: sink->fullscreen = g_value_get_boolean(value); break; @@ -795,9 +793,6 @@ gst_vaapisink_get_property( case PROP_USE_GLX: g_value_set_boolean(value, sink->use_glx); break; - case PROP_DISPLAY: - g_value_set_string(value, sink->display_name); - break; case PROP_FULLSCREEN: g_value_set_boolean(value, sink->fullscreen); break; @@ -845,6 +840,7 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) basesink_class->buffer_alloc = gst_vaapisink_buffer_alloc; basesink_class->preroll = gst_vaapisink_show_frame; basesink_class->render = gst_vaapisink_show_frame; + basesink_class->query = gst_vaapisink_query; #if USE_VAAPISINK_GLX g_object_class_install_property @@ -866,15 +862,6 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) G_PARAM_READWRITE)); #endif - g_object_class_install_property - (object_class, - PROP_DISPLAY, - g_param_spec_string("display", - "X11 display name", - "X11 display name", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, PROP_FULLSCREEN, @@ -903,7 +890,6 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) static void gst_vaapisink_init(GstVaapiSink *sink, GstVaapiSinkClass *klass) { - sink->display_name = NULL; sink->display = NULL; sink->window = NULL; sink->window_width = 0; @@ -919,11 +905,3 @@ gst_vaapisink_init(GstVaapiSink *sink, GstVaapiSinkClass *klass) sink->use_glx = USE_VAAPISINK_GLX; sink->use_reflection = FALSE; } - -GstVaapiDisplay * -gst_vaapisink_get_display(GstVaapiSink *sink) -{ - if (!gst_vaapisink_ensure_display(sink)) - return NULL; - return sink->display; -} diff --git a/gst/vaapi/gstvaapisink.h b/gst/vaapi/gstvaapisink.h index d30692d64d..221e452f77 100644 --- a/gst/vaapi/gstvaapisink.h +++ b/gst/vaapi/gstvaapisink.h @@ -67,7 +67,6 @@ struct _GstVaapiSink { /*< private >*/ GstVideoSink parent_instance; - gchar *display_name; GstVaapiDisplay *display; GstVaapiWindow *window; guint window_width;