mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-27 09:38:17 +00:00
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 <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
2df43791d4
commit
99c5d18f41
10 changed files with 348 additions and 224 deletions
15
configure.ac
15
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]
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/videocontext.h>
|
||||
#include <gst/vaapi/gstvaapivideosink.h>
|
||||
#include <gst/vaapi/gstvaapivideobuffer.h>
|
||||
#include <gst/vaapi/gstvaapiutils_gst.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -29,12 +29,15 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gstvaapidecode.h"
|
||||
#include <gst/vaapi/gstvaapidisplay_x11.h>
|
||||
|
||||
#include <gst/vaapi/gstvaapidisplay.h>
|
||||
#include <gst/vaapi/gstvaapivideosink.h>
|
||||
#include <gst/vaapi/gstvaapivideobuffer.h>
|
||||
#include <gst/vaapi/gstvaapidecoder_ffmpeg.h>
|
||||
#include <gst/vaapi/gstvaapiutils_gst.h>
|
||||
#include <gst/video/videocontext.h>
|
||||
|
||||
#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)
|
||||
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);
|
||||
}
|
||||
|
|
162
gst/vaapi/gstvaapipluginutil.c
Normal file
162
gst/vaapi/gstvaapipluginutil.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* gstvaapipluginutil.h - VA-API plugin helpers
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corporation
|
||||
* Copyright (C) 2011 Collabora
|
||||
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "gstvaapipluginutil.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_VAAPI_GLX
|
||||
#include <gst/vaapi/gstvaapidisplay_glx.h>
|
||||
#else
|
||||
#include <gst/vaapi/gstvaapidisplay_x11.h>
|
||||
#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;
|
||||
}
|
|
@ -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 <nicolas.dufresne@collabora.co.uk>
|
||||
*
|
||||
* 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 <gst/gst.h>
|
||||
#include <gst/video/videocontext.h>
|
||||
#include <gst/vaapi/gstvaapidisplay.h>
|
||||
|
||||
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);
|
|
@ -31,8 +31,9 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/gstutils_version.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/videocontext.h>
|
||||
#include <gst/vaapi/gstvaapivideobuffer.h>
|
||||
#include <gst/vaapi/gstvaapivideosink.h>
|
||||
#include <gst/vaapi/gstvaapidisplay_x11.h>
|
||||
|
@ -41,11 +42,13 @@
|
|||
#include <gst/vaapi/gstvaapidisplay_glx.h>
|
||||
#include <gst/vaapi/gstvaapiwindow_glx.h>
|
||||
#endif
|
||||
#include "gstvaapisink.h"
|
||||
|
||||
/* Supported interfaces */
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,6 @@ struct _GstVaapiSink {
|
|||
/*< private >*/
|
||||
GstVideoSink parent_instance;
|
||||
|
||||
gchar *display_name;
|
||||
GstVaapiDisplay *display;
|
||||
GstVaapiWindow *window;
|
||||
guint window_width;
|
||||
|
|
Loading…
Reference in a new issue