diff options
Diffstat (limited to 'source/blender/sequencer/intern/image_cache.c')
-rw-r--r-- | source/blender/sequencer/intern/image_cache.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 86bd840ce31..86c198075e9 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -104,6 +104,7 @@ #define DCACHE_IMAGES_PER_FILE 100 #define DCACHE_CURRENT_VERSION 2 #define COLORSPACE_NAME_MAX 64 /* XXX: defined in imb intern */ +#define THUMB_CACHE_LIMIT 5000 typedef struct DiskCacheHeaderEntry { unsigned char encoding; @@ -148,6 +149,7 @@ typedef struct SeqCache { struct BLI_mempool *items_pool; struct SeqCacheKey *last_key; SeqDiskCache *disk_cache; + int thumbnail_count; } SeqCache; typedef struct SeqCacheItem { @@ -776,7 +778,7 @@ static float seq_cache_timeline_frame_to_frame_index(Sequence *seq, float timeli /* With raw images, map timeline_frame to strip input media frame range. This means that static * images or extended frame range of movies will only generate one cache entry. No special * treatment in converting frame index to timeline_frame is needed. */ - if (type == SEQ_CACHE_STORE_RAW) { + if (type == SEQ_CACHE_STORE_RAW || type == SEQ_CACHE_STORE_THUMBNAIL) { return seq_give_frame_index(seq, timeline_frame); } @@ -875,7 +877,7 @@ static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf) if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) { IMB_refImBuf(ibuf); - if (!key->is_temp_cache) { + if (!key->is_temp_cache || key->type != SEQ_CACHE_STORE_THUMBNAIL) { cache->last_key = key; } } @@ -1161,6 +1163,7 @@ static void seq_cache_create(Main *bmain, Scene *scene) cache->hash = BLI_ghash_new(seq_cache_hashhash, seq_cache_hashcmp, "SeqCache hash"); cache->last_key = NULL; cache->bmain = bmain; + cache->thumbnail_count = 0; BLI_mutex_init(&cache->iterator_mutex); scene->ed->cache = cache; @@ -1217,7 +1220,7 @@ void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - if (key->is_temp_cache && key->task_id == id) { + if (key->is_temp_cache && key->task_id == id && key->type != SEQ_CACHE_STORE_THUMBNAIL) { /* Use frame_index here to avoid freeing raw images if they are used for multiple frames. */ float frame_index = seq_cache_timeline_frame_to_frame_index( key->seq, timeline_frame, key->type); @@ -1278,6 +1281,7 @@ void SEQ_cache_cleanup(Scene *scene) BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree); } cache->last_key = NULL; + cache->thumbnail_count = 0; seq_cache_unlock(scene); } @@ -1345,6 +1349,46 @@ void seq_cache_cleanup_sequence(Scene *scene, seq_cache_unlock(scene); } +void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area_safe) +{ + /* Add offsets to the left and right end to keep some frames in cache. */ + view_area_safe->xmax += 200; + view_area_safe->xmin -= 200; + view_area_safe->ymin -= 1; + view_area_safe->ymax += 1; + + SeqCache *cache = seq_cache_get_from_scene(scene); + if (!cache) { + return; + } + + GHashIterator gh_iter; + BLI_ghashIterator_init(&gh_iter, cache->hash); + while (!BLI_ghashIterator_done(&gh_iter)) { + SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); + BLI_ghashIterator_step(&gh_iter); + + const int frame_index = key->timeline_frame - key->seq->startdisp; + const int frame_step = SEQ_render_thumbnails_guaranteed_set_frame_step_get(key->seq); + const int relative_base_frame = round_fl_to_int((frame_index / (float)frame_step)) * + frame_step; + const int nearest_guaranted_absolute_frame = relative_base_frame + key->seq->startdisp; + + if (nearest_guaranted_absolute_frame == key->timeline_frame) { + continue; + } + + if ((key->type & SEQ_CACHE_STORE_THUMBNAIL) && + (key->timeline_frame > view_area_safe->xmax || + key->timeline_frame < view_area_safe->xmin || key->seq->machine > view_area_safe->ymax || + key->seq->machine < view_area_safe->ymin)) { + BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree); + cache->thumbnail_count--; + } + } + cache->last_key = NULL; +} + struct ImBuf *seq_cache_get(const SeqRenderData *context, Sequence *seq, float timeline_frame, @@ -1436,6 +1480,37 @@ bool seq_cache_put_if_possible( return false; } +void seq_cache_thumbnail_put( + const SeqRenderData *context, Sequence *seq, float timeline_frame, ImBuf *i, rctf *view_area) +{ + Scene *scene = context->scene; + + if (!scene->ed->cache) { + seq_cache_create(context->bmain, scene); + } + + seq_cache_lock(scene); + SeqCache *cache = seq_cache_get_from_scene(scene); + SeqCacheKey *key = seq_cache_allocate_key( + cache, context, seq, timeline_frame, SEQ_CACHE_STORE_THUMBNAIL); + + /* Prevent reinserting, it breaks cache key linking. */ + if (BLI_ghash_haskey(cache->hash, key)) { + seq_cache_unlock(scene); + return; + } + + /* Limit cache to THUMB_CACHE_LIMIT (5000) images stored. */ + if (cache->thumbnail_count >= THUMB_CACHE_LIMIT) { + rctf view_area_safe = *view_area; + seq_cache_thumbnail_cleanup(scene, &view_area_safe); + } + + seq_cache_put_ex(scene, key, i); + cache->thumbnail_count++; + seq_cache_unlock(scene); +} + void seq_cache_put( const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i) { |