mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
display: use VA display cache for X11 and GLX winsys.
This commit is contained in:
parent
773272475f
commit
9516f00f8e
5 changed files with 188 additions and 27 deletions
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include "gstvaapiutils.h"
|
||||
#include "gstvaapidisplay.h"
|
||||
#include "gstvaapidisplay_priv.h"
|
||||
|
@ -50,6 +51,22 @@ enum {
|
|||
PROP_HEIGHT
|
||||
};
|
||||
|
||||
static inline GstVaapiDisplayCache *
|
||||
get_display_cache(void)
|
||||
{
|
||||
static GstVaapiDisplayCache *g_display_cache = NULL;
|
||||
|
||||
if (!g_display_cache)
|
||||
g_display_cache = gst_vaapi_display_cache_new();
|
||||
return g_display_cache;
|
||||
}
|
||||
|
||||
GstVaapiDisplayCache *
|
||||
gst_vaapi_display_get_cache(void)
|
||||
{
|
||||
return get_display_cache();
|
||||
}
|
||||
|
||||
/* Append GstVaapiImageFormat to formats array */
|
||||
static inline void
|
||||
append_format(GArray *formats, GstVaapiImageFormat format)
|
||||
|
@ -281,7 +298,8 @@ gst_vaapi_display_destroy(GstVaapiDisplay *display)
|
|||
}
|
||||
|
||||
if (priv->display) {
|
||||
vaTerminate(priv->display);
|
||||
if (!priv->parent)
|
||||
vaTerminate(priv->display);
|
||||
priv->display = NULL;
|
||||
}
|
||||
|
||||
|
@ -290,12 +308,20 @@ gst_vaapi_display_destroy(GstVaapiDisplay *display)
|
|||
if (klass->close_display)
|
||||
klass->close_display(display);
|
||||
}
|
||||
|
||||
if (priv->parent) {
|
||||
g_object_unref(priv->parent);
|
||||
priv->parent = NULL;
|
||||
}
|
||||
|
||||
gst_vaapi_display_cache_remove(get_display_cache(), display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vaapi_display_create(GstVaapiDisplay *display)
|
||||
{
|
||||
GstVaapiDisplayPrivate * const priv = display->priv;
|
||||
GstVaapiDisplayCache *cache;
|
||||
gboolean has_errors = TRUE;
|
||||
VAProfile *profiles = NULL;
|
||||
VAEntrypoint *entrypoints = NULL;
|
||||
|
@ -303,16 +329,21 @@ gst_vaapi_display_create(GstVaapiDisplay *display)
|
|||
unsigned int *flags = NULL;
|
||||
gint i, j, n, num_entrypoints, major_version, minor_version;
|
||||
VAStatus status;
|
||||
GstVaapiDisplayInfo info;
|
||||
const GstVaapiDisplayInfo *cached_info = NULL;
|
||||
|
||||
if (!priv->display && priv->create_display) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.display = display;
|
||||
|
||||
if (priv->display)
|
||||
info.va_display = priv->display;
|
||||
else if (priv->create_display) {
|
||||
GstVaapiDisplayClass *klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
|
||||
if (klass->open_display && !klass->open_display(display))
|
||||
return FALSE;
|
||||
if (klass->get_display) {
|
||||
priv->display = klass->get_display(display);
|
||||
if (!priv->display)
|
||||
return FALSE;
|
||||
}
|
||||
if (!klass->get_display || !klass->get_display(display, &info))
|
||||
return FALSE;
|
||||
priv->display = info.va_display;
|
||||
if (klass->get_size)
|
||||
klass->get_size(display, &priv->width, &priv->height);
|
||||
if (klass->get_size_mm)
|
||||
|
@ -322,10 +353,25 @@ gst_vaapi_display_create(GstVaapiDisplay *display)
|
|||
if (!priv->display)
|
||||
return FALSE;
|
||||
|
||||
status = vaInitialize(priv->display, &major_version, &minor_version);
|
||||
if (!vaapi_check_status(status, "vaInitialize()"))
|
||||
goto end;
|
||||
GST_DEBUG("VA-API version %d.%d", major_version, minor_version);
|
||||
cache = get_display_cache();
|
||||
if (!cache)
|
||||
return FALSE;
|
||||
cached_info = gst_vaapi_display_cache_lookup_by_va_display(
|
||||
cache,
|
||||
info.va_display
|
||||
);
|
||||
if (cached_info) {
|
||||
if (priv->parent)
|
||||
g_object_unref(priv->parent);
|
||||
priv->parent = g_object_ref(cached_info->display);
|
||||
}
|
||||
|
||||
if (!priv->parent) {
|
||||
status = vaInitialize(priv->display, &major_version, &minor_version);
|
||||
if (!vaapi_check_status(status, "vaInitialize()"))
|
||||
goto end;
|
||||
GST_DEBUG("VA-API version %d.%d", major_version, minor_version);
|
||||
}
|
||||
|
||||
/* VA profiles */
|
||||
profiles = g_new(VAProfile, vaMaxNumProfiles(priv->display));
|
||||
|
@ -419,6 +465,11 @@ gst_vaapi_display_create(GstVaapiDisplay *display)
|
|||
append_formats(priv->subpicture_formats, formats, n);
|
||||
g_array_sort(priv->subpicture_formats, compare_rgb_formats);
|
||||
|
||||
if (!cached_info) {
|
||||
if (!gst_vaapi_display_cache_add(cache, &info))
|
||||
goto end;
|
||||
}
|
||||
|
||||
has_errors = FALSE;
|
||||
end:
|
||||
g_free(profiles);
|
||||
|
@ -431,13 +482,21 @@ end:
|
|||
static void
|
||||
gst_vaapi_display_lock_default(GstVaapiDisplay *display)
|
||||
{
|
||||
g_static_rec_mutex_lock(&display->priv->mutex);
|
||||
GstVaapiDisplayPrivate *priv = display->priv;
|
||||
|
||||
if (priv->parent)
|
||||
priv = priv->parent->priv;
|
||||
g_static_rec_mutex_lock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_display_unlock_default(GstVaapiDisplay *display)
|
||||
{
|
||||
g_static_rec_mutex_unlock(&display->priv->mutex);
|
||||
GstVaapiDisplayPrivate *priv = display->priv;
|
||||
|
||||
if (priv->parent)
|
||||
priv = priv->parent->priv;
|
||||
g_static_rec_mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -562,6 +621,7 @@ gst_vaapi_display_init(GstVaapiDisplay *display)
|
|||
GstVaapiDisplayPrivate *priv = GST_VAAPI_DISPLAY_GET_PRIVATE(display);
|
||||
|
||||
display->priv = priv;
|
||||
priv->parent = NULL;
|
||||
priv->display = NULL;
|
||||
priv->width = 0;
|
||||
priv->height = 0;
|
||||
|
@ -590,6 +650,16 @@ gst_vaapi_display_init(GstVaapiDisplay *display)
|
|||
GstVaapiDisplay *
|
||||
gst_vaapi_display_new_with_display(VADisplay va_display)
|
||||
{
|
||||
GstVaapiDisplayCache * const cache = get_display_cache();
|
||||
const GstVaapiDisplayInfo *info;
|
||||
|
||||
g_return_val_if_fail(va_display != NULL, NULL);
|
||||
g_return_val_if_fail(cache != NULL, NULL);
|
||||
|
||||
info = gst_vaapi_display_cache_lookup_by_va_display(cache, va_display);
|
||||
if (info)
|
||||
return g_object_ref(info->display);
|
||||
|
||||
return g_object_new(GST_VAAPI_TYPE_DISPLAY,
|
||||
"display", va_display,
|
||||
NULL);
|
||||
|
|
|
@ -95,7 +95,7 @@ struct _GstVaapiDisplay {
|
|||
* @unlock: (optional) virtual function to unlock a display
|
||||
* @sync: (optional) virtual function to sync a display
|
||||
* @flush: (optional) virtual function to flush pending requests of a display
|
||||
* @get_display: virtual function to retrieve the #VADisplay
|
||||
* @get_display: virtual function to retrieve the #GstVaapiDisplayInfo
|
||||
* @get_size: virtual function to retrieve the display dimensions, in pixels
|
||||
* @get_size_mm: virtual function to retrieve the display dimensions, in millimeters
|
||||
*
|
||||
|
@ -112,7 +112,8 @@ struct _GstVaapiDisplayClass {
|
|||
void (*unlock) (GstVaapiDisplay *display);
|
||||
void (*sync) (GstVaapiDisplay *display);
|
||||
void (*flush) (GstVaapiDisplay *display);
|
||||
VADisplay (*get_display) (GstVaapiDisplay *display);
|
||||
gboolean (*get_display) (GstVaapiDisplay *display,
|
||||
GstVaapiDisplayInfo *info);
|
||||
void (*get_size) (GstVaapiDisplay *display,
|
||||
guint *pwidth, guint *pheight);
|
||||
void (*get_size_mm) (GstVaapiDisplay *display,
|
||||
|
|
|
@ -46,10 +46,19 @@ gst_vaapi_display_glx_finalize(GObject *object)
|
|||
G_OBJECT_CLASS(gst_vaapi_display_glx_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static VADisplay
|
||||
gst_vaapi_display_glx_get_va_display(GstVaapiDisplay *display)
|
||||
static gboolean
|
||||
gst_vaapi_display_glx_get_display_info(
|
||||
GstVaapiDisplay *display,
|
||||
GstVaapiDisplayInfo *info
|
||||
)
|
||||
{
|
||||
return vaGetDisplayGLX(GST_VAAPI_DISPLAY_XDISPLAY(display));
|
||||
GstVaapiDisplayClass * const dpy_class =
|
||||
GST_VAAPI_DISPLAY_CLASS(gst_vaapi_display_glx_parent_class);
|
||||
|
||||
info->va_display = vaGetDisplayGLX(GST_VAAPI_DISPLAY_XDISPLAY(display));
|
||||
if (!info->va_display)
|
||||
return FALSE;
|
||||
return dpy_class->get_display(display, info);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -59,7 +68,7 @@ gst_vaapi_display_glx_class_init(GstVaapiDisplayGLXClass *klass)
|
|||
GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
|
||||
|
||||
object_class->finalize = gst_vaapi_display_glx_finalize;
|
||||
dpy_class->get_display = gst_vaapi_display_glx_get_va_display;
|
||||
dpy_class->get_display = gst_vaapi_display_glx_get_display_info;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define GST_VAAPI_DISPLAY_PRIV_H
|
||||
|
||||
#include <gst/vaapi/gstvaapidisplay.h>
|
||||
#include <gst/vaapi/gstvaapidisplaycache.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -70,6 +71,7 @@ G_BEGIN_DECLS
|
|||
* Base class for VA displays.
|
||||
*/
|
||||
struct _GstVaapiDisplayPrivate {
|
||||
GstVaapiDisplay *parent;
|
||||
GStaticRecMutex mutex;
|
||||
VADisplay display;
|
||||
guint width;
|
||||
|
@ -85,6 +87,9 @@ struct _GstVaapiDisplayPrivate {
|
|||
guint create_display : 1;
|
||||
};
|
||||
|
||||
GstVaapiDisplayCache *
|
||||
gst_vaapi_display_get_cache(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_VAAPI_DISPLAY_PRIV_H */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include "gstvaapiutils.h"
|
||||
#include "gstvaapidisplay_priv.h"
|
||||
#include "gstvaapidisplay_x11.h"
|
||||
|
@ -46,6 +47,40 @@ enum {
|
|||
PROP_X11_SCREEN
|
||||
};
|
||||
|
||||
static inline const gchar *
|
||||
get_default_display_name(void)
|
||||
{
|
||||
static const gchar *g_display_name;
|
||||
|
||||
if (!g_display_name)
|
||||
g_display_name = getenv("DISPLAY");
|
||||
return g_display_name;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
compare_display_name(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
const gchar *display_name;
|
||||
|
||||
/* XXX: handle screen number? */
|
||||
if (a && b)
|
||||
return strcmp(a, b) == 0;
|
||||
|
||||
/* Match "" or default display name */
|
||||
if (a)
|
||||
display_name = a;
|
||||
else if (b)
|
||||
display_name = b;
|
||||
else
|
||||
return TRUE;
|
||||
|
||||
if (*display_name == '\0')
|
||||
return TRUE;
|
||||
if (strcmp(display_name, get_default_display_name()) == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_display_x11_finalize(GObject *object)
|
||||
{
|
||||
|
@ -139,13 +174,29 @@ static void
|
|||
gst_vaapi_display_x11_constructed(GObject *object)
|
||||
{
|
||||
GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
|
||||
GstVaapiDisplayX11Private * const priv = display->priv;
|
||||
GstVaapiDisplayCache * const cache = gst_vaapi_display_get_cache();
|
||||
const GstVaapiDisplayInfo *info;
|
||||
GObjectClass *parent_class;
|
||||
|
||||
display->priv->create_display = display->priv->x11_display == NULL;
|
||||
priv->create_display = priv->x11_display == NULL;
|
||||
|
||||
/* Don't create X11 display if there is one in the cache already */
|
||||
if (priv->create_display) {
|
||||
info = gst_vaapi_display_cache_lookup_by_name(
|
||||
cache,
|
||||
priv->display_name,
|
||||
compare_display_name, NULL
|
||||
);
|
||||
if (info) {
|
||||
priv->x11_display = info->native_display;
|
||||
priv->create_display = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset display-name if the user provided his own X11 display */
|
||||
if (!display->priv->create_display)
|
||||
set_display_name(display, XDisplayString(display->priv->x11_display));
|
||||
if (!priv->create_display)
|
||||
set_display_name(display, XDisplayString(priv->x11_display));
|
||||
|
||||
parent_class = G_OBJECT_CLASS(gst_vaapi_display_x11_parent_class);
|
||||
if (parent_class->constructed)
|
||||
|
@ -158,7 +209,6 @@ gst_vaapi_display_x11_open_display(GstVaapiDisplay *display)
|
|||
GstVaapiDisplayX11Private * const priv =
|
||||
GST_VAAPI_DISPLAY_X11(display)->priv;
|
||||
|
||||
/* XXX: maintain an X11 display cache */
|
||||
if (priv->create_display) {
|
||||
priv->x11_display = XOpenDisplay(priv->display_name);
|
||||
if (!priv->x11_display)
|
||||
|
@ -217,10 +267,36 @@ gst_vaapi_display_x11_flush(GstVaapiDisplay *display)
|
|||
}
|
||||
}
|
||||
|
||||
static VADisplay
|
||||
gst_vaapi_display_x11_get_va_display(GstVaapiDisplay *display)
|
||||
static gboolean
|
||||
gst_vaapi_display_x11_get_display_info(
|
||||
GstVaapiDisplay *display,
|
||||
GstVaapiDisplayInfo *info
|
||||
)
|
||||
{
|
||||
return vaGetDisplay(GST_VAAPI_DISPLAY_XDISPLAY(display));
|
||||
GstVaapiDisplayX11Private * const priv =
|
||||
GST_VAAPI_DISPLAY_X11(display)->priv;
|
||||
GstVaapiDisplayCache *cache;
|
||||
const GstVaapiDisplayInfo *cached_info;
|
||||
|
||||
/* Return any cached info even if child has its own VA display */
|
||||
cache = gst_vaapi_display_get_cache();
|
||||
if (!cache)
|
||||
return FALSE;
|
||||
cached_info = gst_vaapi_display_cache_lookup_by_native_display(cache, priv->x11_display);
|
||||
if (cached_info) {
|
||||
*info = *cached_info;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Otherwise, create VA display if there is none already */
|
||||
info->native_display = priv->x11_display;
|
||||
info->display_name = priv->display_name;
|
||||
if (!info->va_display) {
|
||||
info->va_display = vaGetDisplay(priv->x11_display);
|
||||
if (!info->va_display)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -280,7 +356,7 @@ gst_vaapi_display_x11_class_init(GstVaapiDisplayX11Class *klass)
|
|||
dpy_class->close_display = gst_vaapi_display_x11_close_display;
|
||||
dpy_class->sync = gst_vaapi_display_x11_sync;
|
||||
dpy_class->flush = gst_vaapi_display_x11_flush;
|
||||
dpy_class->get_display = gst_vaapi_display_x11_get_va_display;
|
||||
dpy_class->get_display = gst_vaapi_display_x11_get_display_info;
|
||||
dpy_class->get_size = gst_vaapi_display_x11_get_size;
|
||||
dpy_class->get_size_mm = gst_vaapi_display_x11_get_size_mm;
|
||||
|
||||
|
|
Loading…
Reference in a new issue