4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2011 Blender Foundation.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation,
27 * ***** END GPL LICENSE BLOCK *****
30 /** \file blender/blenkernel/intern/moviecache.c
34 #include "MEM_guardedalloc.h"
35 #include "MEM_CacheLimiterC-Api.h"
37 #include "BLI_utildefines.h"
38 #include "BLI_ghash.h"
39 #include "BLI_mempool.h"
41 #include "BKE_moviecache.h"
43 #include "IMB_imbuf_types.h"
44 #include "IMB_imbuf.h"
46 static MEM_CacheLimiterC *limitor= NULL;
48 typedef struct MovieCache {
52 MovieCacheGetKeyDataFP getdatafp;
54 struct BLI_mempool *keys_pool;
55 struct BLI_mempool *items_pool;
56 struct BLI_mempool *userkeys_pool;
59 unsigned long curtime;
61 int totseg, *points; /* for visual statistics optimization */
64 typedef struct MovieCacheKey {
65 MovieCache *cache_owner;
69 typedef struct MovieCacheItem {
70 MovieCache *cache_owner;
72 MEM_CacheLimiterHandleC * c_handle;
73 unsigned long last_access;
76 static unsigned int moviecache_hashhash(const void *keyv)
78 MovieCacheKey *key= (MovieCacheKey*)keyv;
80 return key->cache_owner->hashfp(key->userkey);
83 static int moviecache_hashcmp(const void *av, const void *bv)
85 const MovieCacheKey *a= (MovieCacheKey*)av;
86 const MovieCacheKey *b= (MovieCacheKey*)bv;
88 return a->cache_owner->cmpfp(a->userkey, b->userkey);
91 static void moviecache_keyfree(void *val)
93 MovieCacheKey *key= (MovieCacheKey*)val;
95 BLI_mempool_free(key->cache_owner->keys_pool, key);
98 static void moviecache_valfree(void *val)
100 MovieCacheItem *item= (MovieCacheItem*)val;
103 MEM_CacheLimiter_unmanage(item->c_handle);
104 IMB_freeImBuf(item->ibuf);
107 BLI_mempool_free(item->cache_owner->items_pool, item);
110 static void check_unused_keys(MovieCache *cache)
114 iter= BLI_ghashIterator_new(cache->hash);
115 while(!BLI_ghashIterator_isDone(iter)) {
116 MovieCacheKey *key= BLI_ghashIterator_getKey(iter);
117 MovieCacheItem *item= BLI_ghashIterator_getValue(iter);
119 BLI_ghashIterator_step(iter);
122 BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
125 BLI_ghashIterator_free(iter);
128 static int compare_int(const void *av, const void *bv)
130 const int *a= (int *)av;
131 const int *b= (int *)bv;
135 static void IMB_moviecache_destructor(void *p)
137 MovieCacheItem *item= (MovieCacheItem *) p;
139 if (item && item->ibuf) {
140 IMB_freeImBuf(item->ibuf);
143 item->c_handle= NULL;
147 /* approximate size of ImBuf in memory */
148 static intptr_t IMB_get_size_in_memory(ImBuf *ibuf)
151 intptr_t size= 0, channel_size= 0;
153 size+= sizeof(ImBuf);
156 channel_size+= sizeof(char);
159 channel_size= sizeof(float);
161 size+= channel_size*ibuf->x*ibuf->y*ibuf->channels;
164 for(a= 0; a<ibuf->miptot; a++) {
166 size+= IMB_get_size_in_memory(ibuf->mipmap[a]);
171 size+= sizeof(unsigned int)*ibuf->ytiles*ibuf->xtiles;
177 static intptr_t get_item_size (void *p)
179 intptr_t size= sizeof(MovieCacheItem);
180 MovieCacheItem *item= (MovieCacheItem *) p;
183 size+= IMB_get_size_in_memory(item->ibuf);
188 void BKE_moviecache_init(void)
190 limitor= new_MEM_CacheLimiter(IMB_moviecache_destructor, get_item_size);
193 void BKE_moviecache_destruct(void)
196 delete_MEM_CacheLimiter(limitor);
199 struct MovieCache *BKE_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp,
200 MovieCacheGetKeyDataFP getdatafp)
204 cache= MEM_callocN(sizeof(MovieCache), "MovieCache");
205 cache->keys_pool= BLI_mempool_create(sizeof(MovieCacheKey), 64, 64, 0);
206 cache->items_pool= BLI_mempool_create(sizeof(MovieCacheItem), 64, 64, 0);
207 cache->userkeys_pool= BLI_mempool_create(keysize, 64, 64, 0);
208 cache->hash= BLI_ghash_new(moviecache_hashhash, moviecache_hashcmp, "MovieClip ImBuf cache hash");
210 cache->keysize= keysize;
211 cache->hashfp= hashfp;
213 cache->getdatafp= getdatafp;
218 void BKE_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
221 MovieCacheItem *item;
224 BKE_moviecache_init();
228 key= BLI_mempool_alloc(cache->keys_pool);
229 key->cache_owner= cache;
230 key->userkey= BLI_mempool_alloc(cache->userkeys_pool);;
231 memcpy(key->userkey, userkey, cache->keysize);
233 item= BLI_mempool_alloc(cache->items_pool);
235 item->cache_owner= cache;
236 item->last_access= cache->curtime++;
237 item->c_handle= NULL;
239 BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
240 BLI_ghash_insert(cache->hash, key, item);
242 item->c_handle= MEM_CacheLimiter_insert(limitor, item);
244 MEM_CacheLimiter_ref(item->c_handle);
245 MEM_CacheLimiter_enforce_limits(limitor);
246 MEM_CacheLimiter_unref(item->c_handle);
248 /* cache limiter can't remove unused keys which points to destoryed values */
249 check_unused_keys(cache);
252 MEM_freeN(cache->points);
257 ImBuf* BKE_moviecache_get(MovieCache *cache, void *userkey)
260 MovieCacheItem *item;
262 key.cache_owner= cache;
263 key.userkey= userkey;
264 item= (MovieCacheItem*)BLI_ghash_lookup(cache->hash, &key);
267 item->last_access= cache->curtime++;
270 MEM_CacheLimiter_touch(item->c_handle);
271 IMB_refImBuf(item->ibuf);
280 void BKE_moviecache_free(MovieCache *cache)
282 BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree);
284 BLI_mempool_destroy(cache->keys_pool);
285 BLI_mempool_destroy(cache->items_pool);
286 BLI_mempool_destroy(cache->userkeys_pool);
289 MEM_freeN(cache->points);
294 /* get segments of cached frames. useful for debugging cache policies */
295 void BKE_moviecache_get_cache_segments(MovieCache *cache, int *totseg_r, int **points_r)
300 if(!cache->getdatafp)
304 *totseg_r= cache->totseg;
305 *points_r= cache->points;
307 int totframe= BLI_ghash_size(cache->hash);
308 int *frames= MEM_callocN(totframe*sizeof(int), "movieclip cache frames");
312 iter= BLI_ghashIterator_new(cache->hash);
314 while(!BLI_ghashIterator_isDone(iter)) {
315 MovieCacheKey *key= BLI_ghashIterator_getKey(iter);
316 MovieCacheItem *item= BLI_ghashIterator_getValue(iter);
320 cache->getdatafp(key->userkey, &framenr);
322 frames[a++]= framenr;
325 BLI_ghashIterator_step(iter);
328 BLI_ghashIterator_free(iter);
330 qsort(frames, totframe, sizeof(int), compare_int);
333 for(a= 0; a<totframe; a++) {
334 if(a && frames[a]-frames[a-1]!=1)
344 points= MEM_callocN(2*sizeof(int)*totseg, "movieclip cache segments");
347 for(a= 0, b= 0; a<totframe; a++) {
349 points[b++]= frames[a];
351 if(a && frames[a]-frames[a-1]!=1) {
352 points[b++]= frames[a-1];
353 points[b++]= frames[a];
357 points[b++]= frames[a];
365 cache->totseg= totseg;
366 cache->points= points;