libs: use glib >= 2.32 semantics for mutexes.
[vaapi:gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidisplaycache.c
1 /*
2  *  gstvaapidisplaycache.c - VA display cache
3  *
4  *  Copyright (C) 2012 Intel Corporation
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public License
8  *  as published by the Free Software Foundation; either version 2.1
9  *  of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301 USA
20  */
21
22 #include "sysdeps.h"
23 #include <glib.h>
24 #include <string.h>
25 #include "gstvaapidisplaycache.h"
26
27 #define DEBUG 1
28 #include "gstvaapidebug.h"
29
30 typedef struct _CacheEntry CacheEntry;
31 struct _CacheEntry {
32     GstVaapiDisplayInfo info;
33 };
34
35 struct _GstVaapiDisplayCache {
36     GMutex              mutex;
37     GList              *list;
38 };
39
40 static void
41 cache_entry_free(CacheEntry *entry)
42 {
43     GstVaapiDisplayInfo *info;
44
45     if (!entry)
46         return;
47
48     info = &entry->info;
49
50     if (info->display_name) {
51         g_free(info->display_name);
52         info->display_name = NULL;
53     }
54     g_slice_free(CacheEntry, entry);
55 }
56
57 static CacheEntry *
58 cache_entry_new(const GstVaapiDisplayInfo *di)
59 {
60     GstVaapiDisplayInfo *info;
61     CacheEntry *entry;
62
63     entry = g_slice_new(CacheEntry);
64     if (!entry)
65         return NULL;
66
67     info                 = &entry->info;
68     info->display        = di->display;
69     info->va_display     = di->va_display;
70     info->native_display = di->native_display;
71     info->display_type   = di->display_type;
72     info->display_name   = NULL;
73
74     if (di->display_name) {
75         info->display_name = g_strdup(di->display_name);
76         if (!info->display_name)
77             goto error;
78     }
79     return entry;
80
81 error:
82     cache_entry_free(entry);
83     return NULL;
84 }
85
86 #define CACHE_LOOKUP(cache, res, prop, comp_func, comp_data, user_data) do { \
87         GList *l;                                                       \
88                                                                         \
89         g_mutex_lock(&(cache)->mutex);                                  \
90         for (l = (cache)->list; l != NULL; l = l->next) {               \
91             GstVaapiDisplayInfo * const info =                          \
92                 &((CacheEntry *)l->data)->info;                         \
93             if (comp_func(info->prop, comp_data, user_data))            \
94                 break;                                                  \
95         }                                                               \
96         g_mutex_unlock(&(cache)->mutex);                                \
97         res = l;                                                        \
98     } while (0)
99
100 #define compare_equal(a, b, user_data) \
101     ((a) == (b))
102
103 #define compare_string(a, b, user_data) \
104     ((a) == (b) || ((a) && (b) && strcmp(a, b) == 0))
105
106 static GList *
107 cache_lookup_display(GstVaapiDisplayCache *cache, GstVaapiDisplay *display)
108 {
109     GList *m;
110
111     CACHE_LOOKUP(cache, m, display, compare_equal, display, NULL);
112     return m;
113 }
114
115 static GList *
116 cache_lookup_va_display(GstVaapiDisplayCache *cache, VADisplay va_display)
117 {
118     GList *m;
119
120     CACHE_LOOKUP(cache, m, va_display, compare_equal, va_display, NULL);
121     return m;
122 }
123
124 static GList *
125 cache_lookup_native_display(GstVaapiDisplayCache *cache, gpointer native_display)
126 {
127     GList *m;
128
129     CACHE_LOOKUP(cache, m, native_display, compare_equal, native_display, NULL);
130     return m;
131 }
132
133 /**
134  * gst_vaapi_display_cache_new:
135  *
136  * Creates a new VA display cache.
137  *
138  * Return value: the newly created #GstVaapiDisplayCache object
139  */
140 GstVaapiDisplayCache *
141 gst_vaapi_display_cache_new(void)
142 {
143     GstVaapiDisplayCache *cache;
144
145     cache = g_slice_new0(GstVaapiDisplayCache);
146     if (!cache)
147         return NULL;
148
149     g_mutex_init(&cache->mutex);
150     return cache;
151 }
152
153 /**
154  * gst_vaapi_display_cache_new:
155  * @cache: the #GstVaapiDisplayCache to destroy
156  *
157  * Destroys a VA display cache.
158  */
159 void
160 gst_vaapi_display_cache_free(GstVaapiDisplayCache *cache)
161 {
162     GList *l;
163
164     if (!cache)
165         return;
166
167     if (cache->list) {
168         for (l = cache->list; l != NULL; l = l->next)
169             cache_entry_free(l->data);
170         g_list_free(cache->list);
171         cache->list = NULL;
172     }
173     g_mutex_clear(&cache->mutex);
174     g_slice_free(GstVaapiDisplayCache, cache);
175 }
176
177 /**
178  * gst_vaapi_display_cache_get_size:
179  * @cache: the #GstVaapiDisplayCache
180  *
181  * Gets the size of the display cache @cache.
182  *
183  * Return value: the size of the display cache
184  */
185 guint
186 gst_vaapi_display_cache_get_size(GstVaapiDisplayCache *cache)
187 {
188     guint size;
189
190     g_return_val_if_fail(cache != NULL, 0);
191
192     g_mutex_lock(&cache->mutex);
193     size = g_list_length(cache->list);
194     g_mutex_unlock(&cache->mutex);
195     return size;
196 }
197
198 /**
199  * gst_vaapi_display_cache_add:
200  * @cache: the #GstVaapiDisplayCache
201  * @info: the display cache info to add
202  *
203  * Adds a new entry with data from @info. The display @info data is
204  * copied into the newly created cache entry.
205  *
206  * Return value: %TRUE on success
207  */
208 gboolean
209 gst_vaapi_display_cache_add(
210     GstVaapiDisplayCache       *cache,
211     GstVaapiDisplayInfo        *info
212 )
213 {
214     CacheEntry *entry;
215
216     g_return_val_if_fail(cache != NULL, FALSE);
217     g_return_val_if_fail(info != NULL, FALSE);
218
219     entry = cache_entry_new(info);
220     if (!entry)
221         return FALSE;
222
223     g_mutex_lock(&cache->mutex);
224     cache->list = g_list_prepend(cache->list, entry);
225     g_mutex_unlock(&cache->mutex);
226     return TRUE;
227 }
228
229 /**
230  * gst_vaapi_display_cache_remove:
231  * @cache: the #GstVaapiDisplayCache
232  * @display: the display to remove from cache
233  *
234  * Removes any cache entry that matches the specified #GstVaapiDisplay.
235  */
236 void
237 gst_vaapi_display_cache_remove(
238     GstVaapiDisplayCache       *cache,
239     GstVaapiDisplay            *display
240 )
241 {
242     GList *m;
243
244     m = cache_lookup_display(cache, display);
245     if (!m)
246         return;
247
248     cache_entry_free(m->data);
249     g_mutex_lock(&cache->mutex);
250     cache->list = g_list_delete_link(cache->list, m);
251     g_mutex_unlock(&cache->mutex);
252 }
253
254 /**
255  * gst_vaapi_display_cache_lookup:
256  * @cache: the #GstVaapiDisplayCache
257  * @display: the display to find
258  *
259  * Looks up the display cache for the specified #GstVaapiDisplay.
260  *
261  * Return value: a #GstVaapiDisplayInfo matching @display, or %NULL if
262  *   none was found
263  */
264 const GstVaapiDisplayInfo *
265 gst_vaapi_display_cache_lookup(
266     GstVaapiDisplayCache       *cache,
267     GstVaapiDisplay            *display
268 )
269 {
270     CacheEntry *entry;
271     GList *m;
272
273     g_return_val_if_fail(cache != NULL, NULL);
274     g_return_val_if_fail(display != NULL, NULL);
275
276     m = cache_lookup_display(cache, display);
277     if (!m)
278         return NULL;
279
280     entry = m->data;
281     return &entry->info;
282 }
283
284 /**
285  * gst_vaapi_display_cache_lookup_by_va_display:
286  * @cache: the #GstVaapiDisplayCache
287  * @va_display: the VA display to find
288  *
289  * Looks up the display cache for the specified VA display.
290  *
291  * Return value: a #GstVaapiDisplayInfo matching @va_display, or %NULL
292  *   if none was found
293  */
294 const GstVaapiDisplayInfo *
295 gst_vaapi_display_cache_lookup_by_va_display(
296     GstVaapiDisplayCache       *cache,
297     VADisplay                   va_display
298 )
299 {
300     CacheEntry *entry;
301     GList *m;
302
303     g_return_val_if_fail(cache != NULL, NULL);
304     g_return_val_if_fail(va_display != NULL, NULL);
305
306     m = cache_lookup_va_display(cache, va_display);
307     if (!m)
308         return NULL;
309
310     entry = m->data;
311     return &entry->info;
312 }
313
314 /**
315  * gst_vaapi_display_cache_lookup_by_native_display:
316  * @cache: the #GstVaapiDisplayCache
317  * @native_display: the native display to find
318  *
319  * Looks up the display cache for the specified native display.
320  *
321  * Return value: a #GstVaapiDisplayInfo matching @native_display, or
322  *   %NULL if none was found
323  */
324 const GstVaapiDisplayInfo *
325 gst_vaapi_display_cache_lookup_by_native_display(
326     GstVaapiDisplayCache       *cache,
327     gpointer                    native_display
328 )
329 {
330     CacheEntry *entry;
331     GList *m;
332
333     g_return_val_if_fail(cache != NULL, NULL);
334     g_return_val_if_fail(native_display != NULL, NULL);
335
336     m = cache_lookup_native_display(cache, native_display);
337     if (!m)
338         return NULL;
339
340     entry = m->data;
341     return &entry->info;
342 }
343
344 /**
345  * gst_vaapi_display_cache_lookup_by_name:
346  * @cache: the #GstVaapiDisplayCache
347  * @display_name: the display name to match
348  * @compare_func: an optional string comparison function
349  * @user_data: any relevant data pointer to the comparison function
350  *
351  * Looks up the display cache for the specified display name. A
352  * specific comparison function can be provided to avoid a plain
353  * strcmp().
354  *
355  * Return value: a #GstVaapiDisplayInfo matching @display_name, or
356  *   %NULL if none was found
357  */
358 const GstVaapiDisplayInfo *
359 gst_vaapi_display_cache_lookup_by_name(
360     GstVaapiDisplayCache       *cache,
361     const gchar                *display_name,
362     GCompareDataFunc            compare_func,
363     gpointer                    user_data
364 )
365 {
366     CacheEntry *entry;
367     GList *m;
368
369     g_return_val_if_fail(cache != NULL, NULL);
370
371     if (compare_func)
372         CACHE_LOOKUP(cache, m, display_name, compare_func, display_name, user_data);
373     else
374         CACHE_LOOKUP(cache, m, display_name, compare_string, display_name, NULL);
375     if (!m)
376         return NULL;
377
378     entry = m->data;
379     return &entry->info;
380 }