]> git.sesse.net Git - vlc/blob - src/misc/picture_pool.c
Win32: use ShellExecuteW instead of ShellExecuteA in the update code
[vlc] / src / misc / picture_pool.c
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$
7  *
8  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32 #include <assert.h>
33
34 #include <vlc_common.h>
35 #include <vlc_picture_pool.h>
36
37 /*****************************************************************************
38  *
39  *****************************************************************************/
40 struct picture_release_sys_t {
41     /* Saved release */
42     void (*release)(picture_t *);
43     picture_release_sys_t *release_sys;
44
45     /* */
46     int  (*lock)(picture_t *);
47     void (*unlock)(picture_t *);
48
49     /* */
50     int64_t tick;
51 };
52
53 struct picture_pool_t {
54     /* */
55     int64_t   tick;
56     /* */
57     int       picture_count;
58     picture_t **picture;
59 };
60
61 static void Release(picture_t *);
62 static int  Lock(picture_t *);
63 static void Unlock(picture_t *);
64
65 picture_pool_t *picture_pool_NewExtended(const picture_pool_configuration_t *cfg)
66 {
67     picture_pool_t *pool = calloc(1, sizeof(*pool));
68     if (!pool)
69         return NULL;
70
71     pool->tick = 1;
72     pool->picture_count = cfg->picture_count;
73     pool->picture = calloc(pool->picture_count, sizeof(*pool->picture));
74     if (!pool->picture) {
75         free(pool);
76         return NULL;
77     }
78
79     for (int i = 0; i < cfg->picture_count; i++) {
80         picture_t *picture = cfg->picture[i];
81
82         /* The pool must be the only owner of the picture */
83         assert(picture->i_refcount == 1);
84
85         /* Install the new release callback */
86         picture_release_sys_t *release_sys = malloc(sizeof(*release_sys));
87         if (!release_sys)
88             abort();
89         release_sys->release     = picture->pf_release;
90         release_sys->release_sys = picture->p_release_sys;
91         release_sys->lock        = cfg->lock;
92         release_sys->unlock      = cfg->unlock;
93         release_sys->tick        = 0;
94
95         /* */
96         picture->i_refcount    = 0;
97         picture->pf_release    = Release;
98         picture->p_release_sys = release_sys;
99
100         /* */
101         pool->picture[i] = picture;
102     }
103     return pool;
104
105 }
106
107 picture_pool_t *picture_pool_New(int picture_count, picture_t *picture[])
108 {
109     picture_pool_configuration_t cfg;
110
111     memset(&cfg, 0, sizeof(cfg));
112     cfg.picture_count = picture_count;
113     cfg.picture       = picture;
114
115     return picture_pool_NewExtended(&cfg);
116 }
117
118 picture_pool_t *picture_pool_NewFromFormat(const video_format_t *fmt, int picture_count)
119 {
120     picture_t *picture[picture_count];
121
122     for (int i = 0; i < picture_count; i++) {
123         picture[i] = picture_NewFromFormat(fmt);
124         if (!picture[i])
125             goto error;
126     }
127     picture_pool_t *pool = picture_pool_New(picture_count, picture);
128     if (!pool)
129         goto error;
130
131     return pool;
132
133 error:
134     for (int i = 0; i < picture_count; i++) {
135         if (!picture[i])
136             break;
137         picture_Release(picture[i]);
138     }
139     return NULL;
140 }
141
142 void picture_pool_Delete(picture_pool_t *pool)
143 {
144     for (int i = 0; i < pool->picture_count; i++) {
145         picture_t *picture = pool->picture[i];
146         picture_release_sys_t *release_sys = picture->p_release_sys;
147
148         assert(picture->i_refcount == 0);
149
150         /* Restore old release callback */
151         picture->i_refcount    = 1;
152         picture->pf_release    = release_sys->release;
153         picture->p_release_sys = release_sys->release_sys;
154
155         picture_Release(picture);
156
157         free(release_sys);
158     }
159     free(pool->picture);
160     free(pool);
161 }
162
163 picture_t *picture_pool_Get(picture_pool_t *pool)
164 {
165     for (int i = 0; i < pool->picture_count; i++) {
166         picture_t *picture = pool->picture[i];
167         if (picture->i_refcount > 0)
168             continue;
169
170         if (Lock(picture))
171             continue;
172
173         /* */
174         picture->p_release_sys->tick = pool->tick++;
175         picture_Hold(picture);
176         return picture;
177     }
178     return NULL;
179 }
180
181 void picture_pool_NonEmpty(picture_pool_t *pool, bool reset)
182 {
183     picture_t *old = NULL;
184
185     for (int i = 0; i < pool->picture_count; i++) {
186         picture_t *picture = pool->picture[i];
187
188         if (reset) {
189             if (picture->i_refcount > 0)
190                 Unlock(picture);
191             picture->i_refcount = 0;
192         } else if (picture->i_refcount == 0) {
193             return;
194         } else if (!old || picture->p_release_sys->tick < old->p_release_sys->tick) {
195             old = picture;
196         }
197     }
198     if (!reset && old) {
199         if (old->i_refcount > 0)
200             Unlock(old);
201         old->i_refcount = 0;
202     }
203 }
204
205 static void Release(picture_t *picture)
206 {
207     assert(picture->i_refcount > 0);
208
209     if (--picture->i_refcount > 0)
210         return;
211     Unlock(picture);
212 }
213
214 static int Lock(picture_t *picture)
215 {
216     picture_release_sys_t *release_sys = picture->p_release_sys;
217     if (release_sys->lock)
218         return release_sys->lock(picture);
219     return VLC_SUCCESS;
220 }
221 static void Unlock(picture_t *picture)
222 {
223     picture_release_sys_t *release_sys = picture->p_release_sys;
224     if (release_sys->unlock)
225         release_sys->unlock(picture);
226 }
227