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>
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 /*****************************************************************************
27 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_picture_pool.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 struct picture_release_sys_t
{
42 void (*release
)(picture_t
*);
43 picture_release_sys_t
*release_sys
;
46 int (*lock
)(picture_t
*);
47 void (*unlock
)(picture_t
*);
53 struct picture_pool_t
{
55 picture_pool_t
*master
;
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
));
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
) {
80 free(pool
->picture_reserved
);
87 picture_pool_t
*picture_pool_NewExtended(const picture_pool_configuration_t
*cfg
)
89 picture_pool_t
*pool
= Create(NULL
, cfg
->picture_count
);
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
));
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;
110 picture
->i_refcount
= 0;
111 picture
->pf_release
= Release
;
112 picture
->p_release_sys
= release_sys
;
115 pool
->picture
[i
] = picture
;
116 pool
->picture_reserved
[i
] = false;
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
);
142 picture_pool_t
*pool
= picture_pool_New(picture_count
, picture
);
149 for (int i
= 0; i
< picture_count
; i
++) {
152 picture_Release(picture
[i
]);
157 picture_pool_t
*picture_pool_Reserve(picture_pool_t
*master
, int count
)
159 picture_pool_t
*pool
= Create(master
, count
);
164 for (int i
= 0; i
< master
->picture_count
&& found
< count
; i
++) {
165 if (master
->picture_reserved
[i
])
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;
176 picture_pool_Delete(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
];
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;
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
);
207 free(pool
->picture_reserved
);
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
])
218 picture_t
*picture
= pool
->picture
[i
];
219 if (picture
->i_refcount
> 0)
226 picture
->p_release_sys
->tick
= pool
->tick
++;
227 picture_Hold(picture
);
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
])
241 picture_t
*picture
= pool
->picture
[i
];
243 if (picture
->i_refcount
> 0)
245 picture
->i_refcount
= 0;
246 } else if (picture
->i_refcount
== 0) {
248 } else if (!old
|| picture
->p_release_sys
->tick
< old
->p_release_sys
->tick
) {
253 if (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)
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
);
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
);