mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 21:51:09 +00:00
71ab07d9c6
Make it possible to add extra an extra filter to most of display cache lookup functions so that the GstVaapiDisplay instance can really match a compatible and existing display by type, instead of relying on extra string tags (e.g. "X11:" prefix, etc.).
407 lines
10 KiB
C
407 lines
10 KiB
C
/*
|
|
* gstvaapidisplaycache.c - VA display cache
|
|
*
|
|
* Copyright (C) 2012 Intel Corporation
|
|
*
|
|
* 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 "sysdeps.h"
|
|
#include <glib.h>
|
|
#include <string.h>
|
|
#include "gstvaapidisplaycache.h"
|
|
|
|
#define DEBUG 1
|
|
#include "gstvaapidebug.h"
|
|
|
|
typedef struct _CacheEntry CacheEntry;
|
|
struct _CacheEntry {
|
|
GstVaapiDisplayInfo info;
|
|
};
|
|
|
|
struct _GstVaapiDisplayCache {
|
|
GMutex mutex;
|
|
GList *list;
|
|
};
|
|
|
|
static void
|
|
cache_entry_free(CacheEntry *entry)
|
|
{
|
|
GstVaapiDisplayInfo *info;
|
|
|
|
if (!entry)
|
|
return;
|
|
|
|
info = &entry->info;
|
|
|
|
if (info->display_name) {
|
|
g_free(info->display_name);
|
|
info->display_name = NULL;
|
|
}
|
|
g_slice_free(CacheEntry, entry);
|
|
}
|
|
|
|
static CacheEntry *
|
|
cache_entry_new(const GstVaapiDisplayInfo *di)
|
|
{
|
|
GstVaapiDisplayInfo *info;
|
|
CacheEntry *entry;
|
|
|
|
entry = g_slice_new(CacheEntry);
|
|
if (!entry)
|
|
return NULL;
|
|
|
|
info = &entry->info;
|
|
info->display = di->display;
|
|
info->va_display = di->va_display;
|
|
info->native_display = di->native_display;
|
|
info->display_type = di->display_type;
|
|
info->display_name = NULL;
|
|
|
|
if (di->display_name) {
|
|
info->display_name = g_strdup(di->display_name);
|
|
if (!info->display_name)
|
|
goto error;
|
|
}
|
|
return entry;
|
|
|
|
error:
|
|
cache_entry_free(entry);
|
|
return NULL;
|
|
}
|
|
|
|
static inline gboolean
|
|
is_compatible_display_type(const GstVaapiDisplayType display_type,
|
|
guint display_types)
|
|
{
|
|
if (display_type == GST_VAAPI_DISPLAY_TYPE_ANY)
|
|
return TRUE;
|
|
if (display_types == GST_VAAPI_DISPLAY_TYPE_ANY)
|
|
return TRUE;
|
|
return ((1U << display_type) & display_types) != 0;
|
|
}
|
|
|
|
static GList *
|
|
cache_lookup_1(GstVaapiDisplayCache *cache, GCompareFunc func,
|
|
gconstpointer data, guint display_types)
|
|
{
|
|
GList *l;
|
|
|
|
g_mutex_lock(&cache->mutex);
|
|
for (l = cache->list; l != NULL; l = l->next) {
|
|
GstVaapiDisplayInfo * const info = &((CacheEntry *)l->data)->info;
|
|
if (!is_compatible_display_type(info->display_type, display_types))
|
|
continue;
|
|
if (func(info, data))
|
|
break;
|
|
}
|
|
g_mutex_unlock(&cache->mutex);
|
|
return l;
|
|
}
|
|
|
|
static inline const GstVaapiDisplayInfo *
|
|
cache_lookup(GstVaapiDisplayCache *cache, GCompareFunc func,
|
|
gconstpointer data, guint display_types)
|
|
{
|
|
GList * const m = cache_lookup_1(cache, func, data, display_types);
|
|
|
|
return m ? &((CacheEntry *)m->data)->info : NULL;
|
|
}
|
|
|
|
static gint
|
|
compare_display(gconstpointer a, gconstpointer display)
|
|
{
|
|
const GstVaapiDisplayInfo * const info = a;
|
|
|
|
return info->display == display;
|
|
}
|
|
|
|
static gint
|
|
compare_va_display(gconstpointer a, gconstpointer va_display)
|
|
{
|
|
const GstVaapiDisplayInfo * const info = a;
|
|
|
|
return info->va_display == va_display;
|
|
}
|
|
|
|
static gint
|
|
compare_native_display(gconstpointer a, gconstpointer native_display)
|
|
{
|
|
const GstVaapiDisplayInfo * const info = a;
|
|
|
|
return info->native_display == native_display;
|
|
}
|
|
|
|
static gint
|
|
compare_display_name(gconstpointer a, gconstpointer b)
|
|
{
|
|
const GstVaapiDisplayInfo * const info = a;
|
|
const gchar * const display_name = b;
|
|
|
|
if (info->display_name == NULL && display_name == NULL)
|
|
return TRUE;
|
|
if (!info->display_name || !display_name)
|
|
return FALSE;
|
|
return strcmp(info->display_name, display_name) == 0;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_new:
|
|
*
|
|
* Creates a new VA display cache.
|
|
*
|
|
* Return value: the newly created #GstVaapiDisplayCache object
|
|
*/
|
|
GstVaapiDisplayCache *
|
|
gst_vaapi_display_cache_new(void)
|
|
{
|
|
GstVaapiDisplayCache *cache;
|
|
|
|
cache = g_slice_new0(GstVaapiDisplayCache);
|
|
if (!cache)
|
|
return NULL;
|
|
|
|
g_mutex_init(&cache->mutex);
|
|
return cache;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_new:
|
|
* @cache: the #GstVaapiDisplayCache to destroy
|
|
*
|
|
* Destroys a VA display cache.
|
|
*/
|
|
void
|
|
gst_vaapi_display_cache_free(GstVaapiDisplayCache *cache)
|
|
{
|
|
GList *l;
|
|
|
|
if (!cache)
|
|
return;
|
|
|
|
if (cache->list) {
|
|
for (l = cache->list; l != NULL; l = l->next)
|
|
cache_entry_free(l->data);
|
|
g_list_free(cache->list);
|
|
cache->list = NULL;
|
|
}
|
|
g_mutex_clear(&cache->mutex);
|
|
g_slice_free(GstVaapiDisplayCache, cache);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_get_size:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
*
|
|
* Gets the size of the display cache @cache.
|
|
*
|
|
* Return value: the size of the display cache
|
|
*/
|
|
guint
|
|
gst_vaapi_display_cache_get_size(GstVaapiDisplayCache *cache)
|
|
{
|
|
guint size;
|
|
|
|
g_return_val_if_fail(cache != NULL, 0);
|
|
|
|
g_mutex_lock(&cache->mutex);
|
|
size = g_list_length(cache->list);
|
|
g_mutex_unlock(&cache->mutex);
|
|
return size;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_add:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @info: the display cache info to add
|
|
*
|
|
* Adds a new entry with data from @info. The display @info data is
|
|
* copied into the newly created cache entry.
|
|
*
|
|
* Return value: %TRUE on success
|
|
*/
|
|
gboolean
|
|
gst_vaapi_display_cache_add(
|
|
GstVaapiDisplayCache *cache,
|
|
GstVaapiDisplayInfo *info
|
|
)
|
|
{
|
|
CacheEntry *entry;
|
|
|
|
g_return_val_if_fail(cache != NULL, FALSE);
|
|
g_return_val_if_fail(info != NULL, FALSE);
|
|
|
|
entry = cache_entry_new(info);
|
|
if (!entry)
|
|
return FALSE;
|
|
|
|
g_mutex_lock(&cache->mutex);
|
|
cache->list = g_list_prepend(cache->list, entry);
|
|
g_mutex_unlock(&cache->mutex);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_remove:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @display: the display to remove from cache
|
|
*
|
|
* Removes any cache entry that matches the specified #GstVaapiDisplay.
|
|
*/
|
|
void
|
|
gst_vaapi_display_cache_remove(
|
|
GstVaapiDisplayCache *cache,
|
|
GstVaapiDisplay *display
|
|
)
|
|
{
|
|
GList *m;
|
|
|
|
m = cache_lookup_1(cache, compare_display, display,
|
|
GST_VAAPI_DISPLAY_TYPE_ANY);
|
|
if (!m)
|
|
return;
|
|
|
|
cache_entry_free(m->data);
|
|
g_mutex_lock(&cache->mutex);
|
|
cache->list = g_list_delete_link(cache->list, m);
|
|
g_mutex_unlock(&cache->mutex);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_lookup:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @display: the display to find
|
|
*
|
|
* Looks up the display cache for the specified #GstVaapiDisplay.
|
|
*
|
|
* Return value: a #GstVaapiDisplayInfo matching @display, or %NULL if
|
|
* none was found
|
|
*/
|
|
const GstVaapiDisplayInfo *
|
|
gst_vaapi_display_cache_lookup(
|
|
GstVaapiDisplayCache *cache,
|
|
GstVaapiDisplay *display
|
|
)
|
|
{
|
|
g_return_val_if_fail(cache != NULL, NULL);
|
|
g_return_val_if_fail(display != NULL, NULL);
|
|
|
|
return cache_lookup(cache, compare_display, display,
|
|
GST_VAAPI_DISPLAY_TYPE_ANY);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_lookup_custom:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @func: an comparison function
|
|
* @data: user data passed to the function
|
|
*
|
|
* Looks up an element in the display @cache using the supplied
|
|
* function @func to find the desired element. It iterates over all
|
|
* elements in cache, calling the given function which should return
|
|
* %TRUE when the desired element is found.
|
|
*
|
|
* The comparison function takes two gconstpointer arguments, a
|
|
* #GstVaapiDisplayInfo as the first argument, and that is used to
|
|
* compare against the given user @data argument as the second
|
|
* argument.
|
|
*
|
|
* Return value: a #GstVaapiDisplayInfo causing @func to succeed
|
|
* (i.e. returning %TRUE), or %NULL if none was found
|
|
*/
|
|
const GstVaapiDisplayInfo *
|
|
gst_vaapi_display_cache_lookup_custom(
|
|
GstVaapiDisplayCache *cache,
|
|
GCompareFunc func,
|
|
gconstpointer data,
|
|
guint display_types
|
|
)
|
|
{
|
|
g_return_val_if_fail(cache != NULL, NULL);
|
|
g_return_val_if_fail(func != NULL, NULL);
|
|
|
|
return cache_lookup(cache, func, data, display_types);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_lookup_by_va_display:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @va_display: the VA display to find
|
|
*
|
|
* Looks up the display cache for the specified VA display.
|
|
*
|
|
* Return value: a #GstVaapiDisplayInfo matching @va_display, or %NULL
|
|
* if none was found
|
|
*/
|
|
const GstVaapiDisplayInfo *
|
|
gst_vaapi_display_cache_lookup_by_va_display(
|
|
GstVaapiDisplayCache *cache,
|
|
VADisplay va_display
|
|
)
|
|
{
|
|
g_return_val_if_fail(cache != NULL, NULL);
|
|
g_return_val_if_fail(va_display != NULL, NULL);
|
|
|
|
return cache_lookup(cache, compare_va_display, va_display,
|
|
GST_VAAPI_DISPLAY_TYPE_ANY);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_lookup_by_native_display:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @native_display: the native display to find
|
|
*
|
|
* Looks up the display cache for the specified native display.
|
|
*
|
|
* Return value: a #GstVaapiDisplayInfo matching @native_display, or
|
|
* %NULL if none was found
|
|
*/
|
|
const GstVaapiDisplayInfo *
|
|
gst_vaapi_display_cache_lookup_by_native_display(
|
|
GstVaapiDisplayCache *cache,
|
|
gpointer native_display,
|
|
guint display_types
|
|
)
|
|
{
|
|
g_return_val_if_fail(cache != NULL, NULL);
|
|
g_return_val_if_fail(native_display != NULL, NULL);
|
|
|
|
return cache_lookup(cache, compare_native_display, native_display,
|
|
display_types);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_display_cache_lookup_by_name:
|
|
* @cache: the #GstVaapiDisplayCache
|
|
* @display_name: the display name to match
|
|
*
|
|
* Looks up the display cache for the specified display name.
|
|
*
|
|
* Return value: a #GstVaapiDisplayInfo matching @display_name, or
|
|
* %NULL if none was found
|
|
*/
|
|
const GstVaapiDisplayInfo *
|
|
gst_vaapi_display_cache_lookup_by_name(
|
|
GstVaapiDisplayCache *cache,
|
|
const gchar *display_name,
|
|
guint display_types
|
|
)
|
|
{
|
|
g_return_val_if_fail(cache != NULL, NULL);
|
|
|
|
return cache_lookup(cache, compare_display_name, display_name,
|
|
display_types);
|
|
}
|