1 /*****************************************************************************
2 * picture_pool.c : picture pool functions
3 *****************************************************************************
4 * Copyright (C) 2009 VLC authors and VideoLAN
5 * Copyright (C) 2009 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_picture_pool.h>
36 #include <vlc_atomic.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 struct picture_gc_sys_t
{
43 void (*destroy
)(picture_t
*);
47 int (*lock
)(picture_t
*);
48 void (*unlock
)(picture_t
*);
54 struct picture_pool_t
{
56 picture_pool_t
*master
;
61 bool *picture_reserved
;
64 static void Destroy(picture_t
*);
65 static int Lock(picture_t
*);
66 static void Unlock(picture_t
*);
68 static picture_pool_t
*Create(picture_pool_t
*master
, int picture_count
)
70 picture_pool_t
*pool
= calloc(1, sizeof(*pool
));
74 pool
->master
= master
;
75 pool
->tick
= master
? master
->tick
: 1;
76 pool
->picture_count
= picture_count
;
77 pool
->picture
= calloc(pool
->picture_count
, sizeof(*pool
->picture
));
78 pool
->picture_reserved
= calloc(pool
->picture_count
, sizeof(*pool
->picture_reserved
));
79 if (!pool
->picture
|| !pool
->picture_reserved
) {
81 free(pool
->picture_reserved
);
88 picture_pool_t
*picture_pool_NewExtended(const picture_pool_configuration_t
*cfg
)
90 picture_pool_t
*pool
= Create(NULL
, cfg
->picture_count
);
94 for (int i
= 0; i
< cfg
->picture_count
; i
++) {
95 picture_t
*picture
= cfg
->picture
[i
];
97 /* The pool must be the only owner of the picture */
98 assert(!picture_IsReferenced(picture
));
100 /* Install the new release callback */
101 picture_gc_sys_t
*gc_sys
= malloc(sizeof(*gc_sys
));
104 gc_sys
->destroy
= picture
->gc
.pf_destroy
;
105 gc_sys
->destroy_sys
= picture
->gc
.p_sys
;
106 gc_sys
->lock
= cfg
->lock
;
107 gc_sys
->unlock
= cfg
->unlock
;
111 vlc_atomic_set(&picture
->gc
.refcount
, 0);
112 picture
->gc
.pf_destroy
= Destroy
;
113 picture
->gc
.p_sys
= gc_sys
;
116 pool
->picture
[i
] = picture
;
117 pool
->picture_reserved
[i
] = false;
123 picture_pool_t
*picture_pool_New(int picture_count
, picture_t
*picture
[])
125 picture_pool_configuration_t cfg
;
127 memset(&cfg
, 0, sizeof(cfg
));
128 cfg
.picture_count
= picture_count
;
129 cfg
.picture
= picture
;
131 return picture_pool_NewExtended(&cfg
);
134 picture_pool_t
*picture_pool_NewFromFormat(const video_format_t
*fmt
, int picture_count
)
136 picture_t
*picture
[picture_count
];
138 for (int i
= 0; i
< picture_count
; i
++) {
139 picture
[i
] = picture_NewFromFormat(fmt
);
143 picture_pool_t
*pool
= picture_pool_New(picture_count
, picture
);
150 for (int i
= 0; i
< picture_count
; i
++) {
153 picture_Release(picture
[i
]);
158 picture_pool_t
*picture_pool_Reserve(picture_pool_t
*master
, int count
)
160 picture_pool_t
*pool
= Create(master
, count
);
165 for (int i
= 0; i
< master
->picture_count
&& found
< count
; i
++) {
166 if (master
->picture_reserved
[i
])
169 assert(vlc_atomic_get(&master
->picture
[i
]->gc
.refcount
) == 0);
170 master
->picture_reserved
[i
] = true;
172 pool
->picture
[found
] = master
->picture
[i
];
173 pool
->picture_reserved
[found
] = false;
177 picture_pool_Delete(pool
);
183 void picture_pool_Delete(picture_pool_t
*pool
)
185 for (int i
= 0; i
< pool
->picture_count
; i
++) {
186 picture_t
*picture
= pool
->picture
[i
];
188 for (int j
= 0; j
< pool
->master
->picture_count
; j
++) {
189 if (pool
->master
->picture
[j
] == picture
)
190 pool
->master
->picture_reserved
[j
] = false;
193 picture_gc_sys_t
*gc_sys
= picture
->gc
.p_sys
;
195 assert(vlc_atomic_get(&picture
->gc
.refcount
) == 0);
196 assert(!pool
->picture_reserved
[i
]);
198 /* Restore old release callback */
199 vlc_atomic_set(&picture
->gc
.refcount
, 1);
200 picture
->gc
.pf_destroy
= gc_sys
->destroy
;
201 picture
->gc
.p_sys
= gc_sys
->destroy_sys
;
203 picture_Release(picture
);
208 free(pool
->picture_reserved
);
213 picture_t
*picture_pool_Get(picture_pool_t
*pool
)
215 for (int i
= 0; i
< pool
->picture_count
; i
++) {
216 if (pool
->picture_reserved
[i
])
219 picture_t
*picture
= pool
->picture
[i
];
220 if (vlc_atomic_get(&picture
->gc
.refcount
) > 0)
227 picture
->p_next
= NULL
;
228 picture
->gc
.p_sys
->tick
= pool
->tick
++;
229 picture_Hold(picture
);
235 void picture_pool_NonEmpty(picture_pool_t
*pool
, bool reset
)
237 picture_t
*old
= NULL
;
239 for (int i
= 0; i
< pool
->picture_count
; i
++) {
240 if (pool
->picture_reserved
[i
])
243 picture_t
*picture
= pool
->picture
[i
];
245 if (vlc_atomic_get(&picture
->gc
.refcount
) > 0)
247 vlc_atomic_set(&picture
->gc
.refcount
, 0);
248 } else if (vlc_atomic_get(&picture
->gc
.refcount
) == 0) {
250 } else if (!old
|| picture
->gc
.p_sys
->tick
< old
->gc
.p_sys
->tick
) {
255 if (vlc_atomic_get(&old
->gc
.refcount
) > 0)
257 vlc_atomic_set(&old
->gc
.refcount
, 0);
260 int picture_pool_GetSize(picture_pool_t
*pool
)
262 return pool
->picture_count
;
265 static void Destroy(picture_t
*picture
)
270 static int Lock(picture_t
*picture
)
272 picture_gc_sys_t
*gc_sys
= picture
->gc
.p_sys
;
274 return gc_sys
->lock(picture
);
277 static void Unlock(picture_t
*picture
)
279 picture_gc_sys_t
*gc_sys
= picture
->gc
.p_sys
;
281 gc_sys
->unlock(picture
);