*/
#include "config.h"
+#include <string.h>
#include "gstvaapiutils.h"
#include "gstvaapidisplay.h"
#include "gstvaapidisplay_priv.h"
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)
}
if (priv->display) {
- vaTerminate(priv->display);
+ if (!priv->parent)
+ vaTerminate(priv->display);
priv->display = NULL;
}
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;
unsigned int *flags = NULL;
gint i, j, n, num_entrypoints, major_version, minor_version;
VAStatus status;
+ GstVaapiDisplayInfo info;
+ const GstVaapiDisplayInfo *cached_info = NULL;
+
+ memset(&info, 0, sizeof(info));
+ info.display = display;
- if (!priv->display && priv->create_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)
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));
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);
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
GstVaapiDisplayPrivate *priv = GST_VAAPI_DISPLAY_GET_PRIVATE(display);
display->priv = priv;
+ priv->parent = NULL;
priv->display = NULL;
priv->width = 0;
priv->height = 0;
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);
* @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
*
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,
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
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
#define GST_VAAPI_DISPLAY_PRIV_H
#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapidisplaycache.h>
G_BEGIN_DECLS
* Base class for VA displays.
*/
struct _GstVaapiDisplayPrivate {
+ GstVaapiDisplay *parent;
GStaticRecMutex mutex;
VADisplay display;
guint width;
guint create_display : 1;
};
+GstVaapiDisplayCache *
+gst_vaapi_display_get_cache(void);
+
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_PRIV_H */
*/
#include "config.h"
+#include <string.h>
#include "gstvaapiutils.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapidisplay_x11.h"
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)
{
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)
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)
}
}
-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
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;