gstreamer/gst-libs/gst/vaapi/gstvaapidisplaycache.c
Gwenole Beauchesne 71ab07d9c6 display: make it possible to lookup the display cache by type.
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.).
2013-05-27 16:07:15 +02:00

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);
}