Fix various typos
[vlc/asuraparaju-public.git] / src / misc / picture_pool.c
blob39ae0f8304b05b631c228b083b4490c10470ccbd
1 /*****************************************************************************
2 * picture_pool.c : picture pool functions
3 *****************************************************************************
4 * Copyright (C) 2009 the VideoLAN team
5 * Copyright (C) 2009 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
6 * $Id$
8 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32 #include <assert.h>
34 #include <vlc_common.h>
35 #include <vlc_picture_pool.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 struct picture_release_sys_t {
41 /* Saved release */
42 void (*release)(picture_t *);
43 picture_release_sys_t *release_sys;
45 /* */
46 int (*lock)(picture_t *);
47 void (*unlock)(picture_t *);
49 /* */
50 int64_t tick;
53 struct picture_pool_t {
54 /* */
55 picture_pool_t *master;
56 int64_t tick;
57 /* */
58 int picture_count;
59 picture_t **picture;
60 bool *picture_reserved;
63 static void Release(picture_t *);
64 static int Lock(picture_t *);
65 static void Unlock(picture_t *);
67 static picture_pool_t *Create(picture_pool_t *master, int picture_count)
69 picture_pool_t *pool = calloc(1, sizeof(*pool));
70 if (!pool)
71 return NULL;
73 pool->master = master;
74 pool->tick = master ? master->tick : 1;
75 pool->picture_count = picture_count;
76 pool->picture = calloc(pool->picture_count, sizeof(*pool->picture));
77 pool->picture_reserved = calloc(pool->picture_count, sizeof(*pool->picture_reserved));
78 if (!pool->picture || !pool->picture_reserved) {
79 free(pool->picture);
80 free(pool->picture_reserved);
81 free(pool);
82 return NULL;
84 return pool;
87 picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg)
89 picture_pool_t *pool = Create(NULL, cfg->picture_count);
90 if (!pool)
91 return NULL;
93 for (int i = 0; i < cfg->picture_count; i++) {
94 picture_t *picture = cfg->picture[i];
96 /* The pool must be the only owner of the picture */
97 assert(picture->i_refcount == 1);
99 /* Install the new release callback */
100 picture_release_sys_t *release_sys = malloc(sizeof(*release_sys));
101 if (!release_sys)
102 abort();
103 release_sys->release = picture->pf_release;
104 release_sys->release_sys = picture->p_release_sys;
105 release_sys->lock = cfg->lock;
106 release_sys->unlock = cfg->unlock;
107 release_sys->tick = 0;
109 /* */
110 picture->i_refcount = 0;
111 picture->pf_release = Release;
112 picture->p_release_sys = release_sys;
114 /* */
115 pool->picture[i] = picture;
116 pool->picture_reserved[i] = false;
118 return pool;
122 picture_pool_t *picture_pool_New(int picture_count, picture_t *picture[])
124 picture_pool_configuration_t cfg;
126 memset(&cfg, 0, sizeof(cfg));
127 cfg.picture_count = picture_count;
128 cfg.picture = picture;
130 return picture_pool_NewExtended(&cfg);
133 picture_pool_t *picture_pool_NewFromFormat(const video_format_t *fmt, int picture_count)
135 picture_t *picture[picture_count];
137 for (int i = 0; i < picture_count; i++) {
138 picture[i] = picture_NewFromFormat(fmt);
139 if (!picture[i])
140 goto error;
142 picture_pool_t *pool = picture_pool_New(picture_count, picture);
143 if (!pool)
144 goto error;
146 return pool;
148 error:
149 for (int i = 0; i < picture_count; i++) {
150 if (!picture[i])
151 break;
152 picture_Release(picture[i]);
154 return NULL;
157 picture_pool_t *picture_pool_Reserve(picture_pool_t *master, int count)
159 picture_pool_t *pool = Create(master, count);
160 if (!pool)
161 return NULL;
163 int found = 0;
164 for (int i = 0; i < master->picture_count && found < count; i++) {
165 if (master->picture_reserved[i])
166 continue;
168 assert(master->picture[i]->i_refcount == 0);
169 master->picture_reserved[i] = true;
171 pool->picture[found] = master->picture[i];
172 pool->picture_reserved[found] = false;
173 found++;
175 if (found < count) {
176 picture_pool_Delete(pool);
177 return NULL;
179 return pool;
182 void picture_pool_Delete(picture_pool_t *pool)
184 for (int i = 0; i < pool->picture_count; i++) {
185 picture_t *picture = pool->picture[i];
186 if (pool->master) {
187 for (int j = 0; j < pool->master->picture_count; j++) {
188 if (pool->master->picture[j] == picture)
189 pool->master->picture_reserved[j] = false;
191 } else {
192 picture_release_sys_t *release_sys = picture->p_release_sys;
194 assert(picture->i_refcount == 0);
195 assert(!pool->picture_reserved[i]);
197 /* Restore old release callback */
198 picture->i_refcount = 1;
199 picture->pf_release = release_sys->release;
200 picture->p_release_sys = release_sys->release_sys;
202 picture_Release(picture);
204 free(release_sys);
207 free(pool->picture_reserved);
208 free(pool->picture);
209 free(pool);
212 picture_t *picture_pool_Get(picture_pool_t *pool)
214 for (int i = 0; i < pool->picture_count; i++) {
215 if (pool->picture_reserved[i])
216 continue;
218 picture_t *picture = pool->picture[i];
219 if (picture->i_refcount > 0)
220 continue;
222 if (Lock(picture))
223 continue;
225 /* */
226 picture->p_release_sys->tick = pool->tick++;
227 picture_Hold(picture);
228 return picture;
230 return NULL;
233 void picture_pool_NonEmpty(picture_pool_t *pool, bool reset)
235 picture_t *old = NULL;
237 for (int i = 0; i < pool->picture_count; i++) {
238 if (pool->picture_reserved[i])
239 continue;
241 picture_t *picture = pool->picture[i];
242 if (reset) {
243 if (picture->i_refcount > 0)
244 Unlock(picture);
245 picture->i_refcount = 0;
246 } else if (picture->i_refcount == 0) {
247 return;
248 } else if (!old || picture->p_release_sys->tick < old->p_release_sys->tick) {
249 old = picture;
252 if (!reset && old) {
253 if (old->i_refcount > 0)
254 Unlock(old);
255 old->i_refcount = 0;
258 int picture_pool_GetSize(picture_pool_t *pool)
260 return pool->picture_count;
263 static void Release(picture_t *picture)
265 assert(picture->i_refcount > 0);
267 if (--picture->i_refcount > 0)
268 return;
269 Unlock(picture);
272 static int Lock(picture_t *picture)
274 picture_release_sys_t *release_sys = picture->p_release_sys;
275 if (release_sys->lock)
276 return release_sys->lock(picture);
277 return VLC_SUCCESS;
279 static void Unlock(picture_t *picture)
281 picture_release_sys_t *release_sys = picture->p_release_sys;
282 if (release_sys->unlock)
283 release_sys->unlock(picture);