Blender  V2.93
image_cache.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Peter Schlaile <peter [at] schlaile [dot] de> 2010
17  */
18 
23 #include <memory.h>
24 #include <stddef.h>
25 #include <time.h>
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "DNA_scene_types.h"
30 #include "DNA_sequence_types.h"
31 #include "DNA_space_types.h" /* for FILE_MAX. */
32 
33 #include "IMB_colormanagement.h"
34 #include "IMB_imbuf.h"
35 #include "IMB_imbuf_types.h"
36 
37 #include "BLI_blenlib.h"
38 #include "BLI_endian_switch.h"
39 #include "BLI_fileops.h"
40 #include "BLI_fileops_types.h"
41 #include "BLI_ghash.h"
42 #include "BLI_listbase.h"
43 #include "BLI_mempool.h"
44 #include "BLI_path_util.h"
45 #include "BLI_threads.h"
46 
47 #include "BKE_global.h"
48 #include "BKE_main.h"
49 #include "BKE_scene.h"
50 
51 #include "SEQ_prefetch.h"
52 #include "SEQ_relations.h"
53 #include "SEQ_render.h"
54 #include "SEQ_sequencer.h"
55 
56 #include "image_cache.h"
57 #include "prefetch.h"
58 #include "strip_time.h"
59 
102 /* <cache type>-<resolution X>x<resolution Y>-<rendersize>%(<view_id>)-<frame no>.dcf */
103 #define DCACHE_FNAME_FORMAT "%d-%dx%d-%d%%(%d)-%d.dcf"
104 #define DCACHE_IMAGES_PER_FILE 100
105 #define DCACHE_CURRENT_VERSION 1
106 #define COLORSPACE_NAME_MAX 64 /* XXX: defined in imb intern */
107 
108 typedef struct DiskCacheHeaderEntry {
109  unsigned char encoding;
116 
117 typedef struct DiskCacheHeader {
120 
121 typedef struct SeqDiskCache {
126  size_t size_total;
128 
129 typedef struct DiskCacheFile {
131  char path[FILE_MAX];
133  char file[FILE_MAX];
136  int rectx;
137  int recty;
139  int view_id;
142 
143 typedef struct SeqCache {
145  struct GHash *hash;
152 
153 typedef struct SeqCacheItem {
155  struct ImBuf *ibuf;
157 
158 typedef struct SeqCacheKey {
160  void *userkey;
161  struct SeqCacheKey *link_prev; /* Used for linking intermediate items to final frame. */
162  struct SeqCacheKey *link_next; /* Used for linking intermediate items to final frame. */
163  struct Sequence *seq;
165  float frame_index; /* Usually same as timeline_frame. Mapped to media for RAW entries. */
166  float timeline_frame; /* Only for reference - used for freeing when cache is full. */
167  float cost; /* In short: render time(s) divided by playback frame duration(s) */
168  bool is_temp_cache; /* this cache entry will be freed before rendering next frame */
169  /* ID of task for assigning temp cache entries to particular task(thread, etc.) */
171  int type;
173 
176  float timeline_frame,
177  int type);
178 static float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index);
179 
180 static char *seq_disk_cache_base_dir(void)
181 {
182  return U.sequencer_disk_cache_dir;
183 }
184 
186 {
187  switch (U.sequencer_disk_cache_compression) {
189  return 0;
191  return 1;
193  return 9;
194  }
195 
196  return U.sequencer_disk_cache_compression;
197 }
198 
199 static size_t seq_disk_cache_size_limit(void)
200 {
201  return (size_t)U.sequencer_disk_cache_size_limit * (1024 * 1024 * 1024);
202 }
203 
204 static bool seq_disk_cache_is_enabled(Main *bmain)
205 {
206  return (U.sequencer_disk_cache_dir[0] != '\0' && U.sequencer_disk_cache_size_limit != 0 &&
207  (U.sequencer_disk_cache_flag & SEQ_CACHE_DISK_CACHE_ENABLE) != 0 &&
208  bmain->name[0] != '\0');
209 }
210 
211 static DiskCacheFile *seq_disk_cache_add_file_to_list(SeqDiskCache *disk_cache, const char *path)
212 {
213 
214  DiskCacheFile *cache_file = MEM_callocN(sizeof(DiskCacheFile), "SeqDiskCacheFile");
215  char dir[FILE_MAXDIR], file[FILE_MAX];
216  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
217  BLI_strncpy(cache_file->path, path, sizeof(cache_file->path));
218  BLI_strncpy(cache_file->dir, dir, sizeof(cache_file->dir));
219  BLI_strncpy(cache_file->file, file, sizeof(cache_file->file));
220  sscanf(file,
222  &cache_file->cache_type,
223  &cache_file->rectx,
224  &cache_file->recty,
225  &cache_file->render_size,
226  &cache_file->view_id,
227  &cache_file->start_frame);
228  cache_file->start_frame *= DCACHE_IMAGES_PER_FILE;
229  BLI_addtail(&disk_cache->files, cache_file);
230  return cache_file;
231 }
232 
233 static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
234 {
235  struct direntry *filelist, *fl;
236  uint nbr, i;
237  disk_cache->size_total = 0;
238 
239  i = nbr = BLI_filelist_dir_contents(path, &filelist);
240  fl = filelist;
241  while (i--) {
242  /* Don't follow links. */
243  const eFileAttributes file_attrs = BLI_file_attributes(fl->path);
244  if (file_attrs & FILE_ATTR_ANY_LINK) {
245  fl++;
246  continue;
247  }
248 
249  char file[FILE_MAX];
250  BLI_split_dirfile(fl->path, NULL, file, 0, sizeof(file));
251 
252  bool is_dir = BLI_is_dir(fl->path);
253  if (is_dir && !FILENAME_IS_CURRPAR(file)) {
254  char subpath[FILE_MAX];
255  BLI_strncpy(subpath, fl->path, sizeof(subpath));
256  BLI_path_slash_ensure(subpath);
257  seq_disk_cache_get_files(disk_cache, subpath);
258  }
259 
260  if (!is_dir) {
261  const char *ext = BLI_path_extension(fl->path);
262  if (ext && ext[1] == 'd' && ext[2] == 'c' && ext[3] == 'f') {
263  DiskCacheFile *cache_file = seq_disk_cache_add_file_to_list(disk_cache, fl->path);
264  cache_file->fstat = fl->s;
265  disk_cache->size_total += cache_file->fstat.st_size;
266  }
267  }
268  fl++;
269  }
270  BLI_filelist_free(filelist, nbr);
271 }
272 
274 {
275  DiskCacheFile *oldest_file = disk_cache->files.first;
276  if (oldest_file == NULL) {
277  return NULL;
278  }
279  for (DiskCacheFile *cache_file = oldest_file->next; cache_file; cache_file = cache_file->next) {
280  if (cache_file->fstat.st_mtime < oldest_file->fstat.st_mtime) {
281  oldest_file = cache_file;
282  }
283  }
284 
285  return oldest_file;
286 }
287 
289 {
290  disk_cache->size_total -= file->fstat.st_size;
291  BLI_delete(file->path, false, false);
292  BLI_remlink(&disk_cache->files, file);
293  MEM_freeN(file);
294 }
295 
297 {
298  BLI_mutex_lock(&disk_cache->read_write_mutex);
299  while (disk_cache->size_total > seq_disk_cache_size_limit()) {
300  DiskCacheFile *oldest_file = seq_disk_cache_get_oldest_file(disk_cache);
301 
302  if (!oldest_file) {
303  /* We shouldn't enforce limits with no files, do re-scan. */
305  continue;
306  }
307 
308  if (BLI_exists(oldest_file->path) == 0) {
309  /* File may have been manually deleted during runtime, do re-scan. */
310  BLI_freelistN(&disk_cache->files);
312  continue;
313  }
314 
315  seq_disk_cache_delete_file(disk_cache, oldest_file);
316  }
317  BLI_mutex_unlock(&disk_cache->read_write_mutex);
318 
319  return true;
320 }
321 
323 {
324  DiskCacheFile *cache_file = disk_cache->files.first;
325 
326  for (; cache_file; cache_file = cache_file->next) {
327  if (BLI_strcasecmp(cache_file->path, path) == 0) {
328  return cache_file;
329  }
330  }
331 
332  return NULL;
333 }
334 
335 /* Update file size and timestamp. */
336 static void seq_disk_cache_update_file(SeqDiskCache *disk_cache, char *path)
337 {
338  DiskCacheFile *cache_file;
339  int64_t size_before;
340  int64_t size_after;
341 
342  cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
343  size_before = cache_file->fstat.st_size;
344 
345  if (BLI_stat(path, &cache_file->fstat) == -1) {
346  BLI_assert(false);
347  memset(&cache_file->fstat, 0, sizeof(BLI_stat_t));
348  }
349 
350  size_after = cache_file->fstat.st_size;
351  disk_cache->size_total += size_after - size_before;
352 }
353 
354 /* Path format:
355  * <cache dir>/<project name>_seq_cache/<scene name>-<timestamp>/<seq name>/DCACHE_FNAME_FORMAT
356  */
357 
358 static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, size_t path_len)
359 {
360  char cache_dir[FILE_MAX];
361  BLI_split_file_part(BKE_main_blendfile_path(disk_cache->bmain), cache_dir, sizeof(cache_dir));
362  /* Use suffix, so that the cache directory name does not conflict with the bmain's blend file. */
363  const char *suffix = "_seq_cache";
364  strncat(cache_dir, suffix, sizeof(cache_dir) - strlen(cache_dir) - 1);
366  BLI_path_append(path, path_len, cache_dir);
367 }
368 
370  SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, char *path, size_t path_len)
371 {
372  char scene_name[MAX_ID_NAME + 22]; /* + -%PRId64 */
373  char seq_name[SEQ_NAME_MAXSTR];
374  char project_dir[FILE_MAX];
375 
376  seq_disk_cache_get_project_dir(disk_cache, project_dir, sizeof(project_dir));
377  sprintf(scene_name, "%s-%" PRId64, scene->id.name, disk_cache->timestamp);
378  BLI_strncpy(seq_name, seq->name, sizeof(seq_name));
379  BLI_filename_make_safe(scene_name);
380  BLI_filename_make_safe(seq_name);
381  BLI_strncpy(path, project_dir, path_len);
382  BLI_path_append(path, path_len, scene_name);
383  BLI_path_append(path, path_len, seq_name);
384 }
385 
387  SeqCacheKey *key,
388  char *path,
389  size_t path_len)
390 {
391  seq_disk_cache_get_dir(disk_cache, key->context.scene, key->seq, path, path_len);
392  int frameno = (int)key->frame_index / DCACHE_IMAGES_PER_FILE;
393  char cache_filename[FILE_MAXFILE];
394  sprintf(cache_filename,
396  key->type,
397  key->context.rectx,
398  key->context.recty,
400  key->context.view_id,
401  frameno);
402 
403  BLI_path_append(path, path_len, cache_filename);
404 }
405 
407 {
409 
410  FILE *file = BLI_fopen(path, "w");
411  if (file) {
412  fprintf(file, "%d", DCACHE_CURRENT_VERSION);
413  fclose(file);
414  }
415 }
416 
418 {
419  char path[FILE_MAX];
420  char path_version_file[FILE_MAX];
421  int version = 0;
422 
423  seq_disk_cache_get_project_dir(disk_cache, path, sizeof(path));
424  BLI_strncpy(path_version_file, path, sizeof(path_version_file));
425  BLI_path_append(path_version_file, sizeof(path_version_file), "cache_version");
426 
427  if (BLI_exists(path) && BLI_is_dir(path)) {
428  FILE *file = BLI_fopen(path_version_file, "r");
429 
430  if (file) {
431  const int num_items_read = fscanf(file, "%d", &version);
432  if (num_items_read == 0) {
433  version = -1;
434  }
435  fclose(file);
436  }
437 
438  if (version != DCACHE_CURRENT_VERSION) {
439  BLI_delete(path, false, true);
440  seq_disk_cache_create_version_file(path_version_file);
441  }
442  }
443  else {
444  seq_disk_cache_create_version_file(path_version_file);
445  }
446 }
447 
449  Scene *scene,
450  Sequence *seq,
451  int invalidate_types,
452  int range_start,
453  int range_end)
454 {
455  DiskCacheFile *next_file, *cache_file = disk_cache->files.first;
456  char cache_dir[FILE_MAX];
457  seq_disk_cache_get_dir(disk_cache, scene, seq, cache_dir, sizeof(cache_dir));
458  BLI_path_slash_ensure(cache_dir);
459 
460  while (cache_file) {
461  next_file = cache_file->next;
462  if (cache_file->cache_type & invalidate_types) {
463  if (STREQ(cache_dir, cache_file->dir)) {
464  int timeline_frame_start = seq_cache_frame_index_to_timeline_frame(
465  seq, cache_file->start_frame);
466  if (timeline_frame_start > range_start && timeline_frame_start <= range_end) {
467  seq_disk_cache_delete_file(disk_cache, cache_file);
468  }
469  }
470  }
471  cache_file = next_file;
472  }
473 }
474 
476  Sequence *seq,
477  Sequence *seq_changed,
478  int invalidate_types)
479 {
480  int start;
481  int end;
482  SeqDiskCache *disk_cache = scene->ed->cache->disk_cache;
483 
484  BLI_mutex_lock(&disk_cache->read_write_mutex);
485 
486  start = seq_changed->startdisp - DCACHE_IMAGES_PER_FILE;
487  end = seq_changed->enddisp;
488 
489  seq_disk_cache_delete_invalid_files(disk_cache, scene, seq, invalidate_types, start, end);
490 
491  BLI_mutex_unlock(&disk_cache->read_write_mutex);
492 }
493 
494 static size_t deflate_imbuf_to_file(ImBuf *ibuf,
495  FILE *file,
496  int level,
497  DiskCacheHeaderEntry *header_entry)
498 {
499  if (ibuf->rect) {
501  ibuf->rect, header_entry->size_raw, file, header_entry->offset, level);
502  }
503 
505  ibuf->rect_float, header_entry->size_raw, file, header_entry->offset, level);
506 }
507 
508 static size_t inflate_file_to_imbuf(ImBuf *ibuf, FILE *file, DiskCacheHeaderEntry *header_entry)
509 {
510  if (ibuf->rect) {
512  ibuf->rect, header_entry->size_raw, file, header_entry->offset);
513  }
514 
516  ibuf->rect_float, header_entry->size_raw, file, header_entry->offset);
517 }
518 
520 {
521  fseek(file, 0, 0);
522  const size_t num_items_read = fread(header, sizeof(*header), 1, file);
523  if (num_items_read < 1) {
524  BLI_assert(!"unable to read disk cache header");
525  perror("unable to read disk cache header");
526  return false;
527  }
528 
529  for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
530  if ((ENDIAN_ORDER == B_ENDIAN) && header->entry[i].encoding == 0) {
535  }
536  }
537 
538  return true;
539 }
540 
541 static size_t seq_disk_cache_write_header(FILE *file, DiskCacheHeader *header)
542 {
543  fseek(file, 0, 0);
544  return fwrite(header, sizeof(*header), 1, file);
545 }
546 
548 {
549  int i;
550  uint64_t offset = sizeof(*header);
551 
552  /* Lookup free entry, get offset for new data. */
553  for (i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
554  if (header->entry[i].size_compressed == 0) {
555  break;
556  }
557  }
558 
559  /* Attempt to write beyond set entry limit.
560  * Reset file header and start writing from beginning.
561  */
562  if (i == DCACHE_IMAGES_PER_FILE) {
563  i = 0;
564  memset(header, 0, sizeof(*header));
565  }
566 
567  /* Calculate offset for image data. */
568  if (i > 0) {
569  offset = header->entry[i - 1].offset + header->entry[i - 1].size_compressed;
570  }
571 
572  if (ENDIAN_ORDER == B_ENDIAN) {
573  header->entry[i].encoding = 255;
574  }
575  else {
576  header->entry[i].encoding = 0;
577  }
578 
579  header->entry[i].offset = offset;
580  header->entry[i].frameno = key->frame_index;
581 
582  /* Store colorspace name of ibuf. */
583  const char *colorspace_name;
584  if (ibuf->rect) {
585  header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels;
586  colorspace_name = IMB_colormanagement_get_rect_colorspace(ibuf);
587  }
588  else {
589  header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels * 4;
590  colorspace_name = IMB_colormanagement_get_float_colorspace(ibuf);
591  }
592  BLI_strncpy(
593  header->entry[i].colorspace_name, colorspace_name, sizeof(header->entry[i].colorspace_name));
594 
595  return i;
596 }
597 
599 {
600  for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
601  if (header->entry[i].frameno == key->frame_index) {
602  return i;
603  }
604  }
605 
606  return -1;
607 }
608 
609 static bool seq_disk_cache_write_file(SeqDiskCache *disk_cache, SeqCacheKey *key, ImBuf *ibuf)
610 {
611  char path[FILE_MAX];
612 
613  seq_disk_cache_get_file_path(disk_cache, key, path, sizeof(path));
615 
616  FILE *file = BLI_fopen(path, "rb+");
617  if (!file) {
618  file = BLI_fopen(path, "wb+");
619  if (!file) {
620  return false;
621  }
623  }
624 
625  DiskCacheFile *cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
626  DiskCacheHeader header;
627  memset(&header, 0, sizeof(header));
628  /* #BLI_make_existing_file() above may create an empty file. This is fine, don't attempt reading
629  * the header in that case. */
630  if (cache_file->fstat.st_size != 0 && !seq_disk_cache_read_header(file, &header)) {
631  fclose(file);
632  seq_disk_cache_delete_file(disk_cache, cache_file);
633  return false;
634  }
635  int entry_index = seq_disk_cache_add_header_entry(key, ibuf, &header);
636 
637  size_t bytes_written = deflate_imbuf_to_file(
638  ibuf, file, seq_disk_cache_compression_level(), &header.entry[entry_index]);
639 
640  if (bytes_written != 0) {
641  /* Last step is writing header, as image data can be overwritten,
642  * but missing data would cause problems.
643  */
644  header.entry[entry_index].size_compressed = bytes_written;
646  seq_disk_cache_update_file(disk_cache, path);
647  fclose(file);
648 
649  return true;
650  }
651 
652  return false;
653 }
654 
656 {
657  char path[FILE_MAX];
658  DiskCacheHeader header;
659 
660  seq_disk_cache_get_file_path(disk_cache, key, path, sizeof(path));
662 
663  FILE *file = BLI_fopen(path, "rb");
664  if (!file) {
665  return NULL;
666  }
667 
668  if (!seq_disk_cache_read_header(file, &header)) {
669  fclose(file);
670  return NULL;
671  }
672  int entry_index = seq_disk_cache_get_header_entry(key, &header);
673 
674  /* Item not found. */
675  if (entry_index < 0) {
676  fclose(file);
677  return NULL;
678  }
679 
680  ImBuf *ibuf;
681  uint64_t size_char = (uint64_t)key->context.rectx * key->context.recty * 4;
682  uint64_t size_float = (uint64_t)key->context.rectx * key->context.recty * 16;
683  size_t expected_size;
684 
685  if (header.entry[entry_index].size_raw == size_char) {
686  expected_size = size_char;
687  ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rect);
689  }
690  else if (header.entry[entry_index].size_raw == size_float) {
691  expected_size = size_float;
692  ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rectfloat);
694  }
695  else {
696  fclose(file);
697  return NULL;
698  }
699 
700  size_t bytes_read = inflate_file_to_imbuf(ibuf, file, &header.entry[entry_index]);
701 
702  /* Sanity check. */
703  if (bytes_read != expected_size) {
704  fclose(file);
705  IMB_freeImBuf(ibuf);
706  return NULL;
707  }
709  seq_disk_cache_update_file(disk_cache, path);
710  fclose(file);
711 
712  return ibuf;
713 }
714 
715 #undef DCACHE_FNAME_FORMAT
716 #undef DCACHE_IMAGES_PER_FILE
717 #undef COLORSPACE_NAME_MAX
718 #undef DCACHE_CURRENT_VERSION
719 
720 static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
721 {
722  return ((a->preview_render_size != b->preview_render_size) || (a->rectx != b->rectx) ||
723  (a->recty != b->recty) || (a->bmain != b->bmain) || (a->scene != b->scene) ||
724  (a->motion_blur_shutter != b->motion_blur_shutter) ||
725  (a->motion_blur_samples != b->motion_blur_samples) ||
726  (a->scene->r.views_format != b->scene->r.views_format) || (a->view_id != b->view_id));
727 }
728 
729 static unsigned int seq_hash_render_data(const SeqRenderData *a)
730 {
731  unsigned int rval = a->rectx + a->recty;
732 
733  rval ^= a->preview_render_size;
734  rval ^= ((intptr_t)a->bmain) << 6;
735  rval ^= ((intptr_t)a->scene) << 6;
736  rval ^= (int)(a->motion_blur_shutter * 100.0f) << 10;
737  rval ^= a->motion_blur_samples << 16;
738  rval ^= ((a->scene->r.views_format * 2) + a->view_id) << 24;
739 
740  return rval;
741 }
742 
743 static unsigned int seq_cache_hashhash(const void *key_)
744 {
745  const SeqCacheKey *key = key_;
746  unsigned int rval = seq_hash_render_data(&key->context);
747 
748  rval ^= *(const unsigned int *)&key->frame_index;
749  rval += key->type;
750  rval ^= ((intptr_t)key->seq) << 6;
751 
752  return rval;
753 }
754 
755 static bool seq_cache_hashcmp(const void *a_, const void *b_)
756 {
757  const SeqCacheKey *a = a_;
758  const SeqCacheKey *b = b_;
759 
760  return ((a->seq != b->seq) || (a->frame_index != b->frame_index) || (a->type != b->type) ||
761  seq_cmp_render_data(&a->context, &b->context));
762 }
763 
764 static float seq_cache_timeline_frame_to_frame_index(Sequence *seq, float timeline_frame, int type)
765 {
766  /* With raw images, map timeline_frame to strip input media frame range. This means that static
767  * images or extended frame range of movies will only generate one cache entry. No special
768  * treatment in converting frame index to timeline_frame is needed. */
769  if (type == SEQ_CACHE_STORE_RAW) {
770  return seq_give_frame_index(seq, timeline_frame);
771  }
772 
773  return timeline_frame - seq->start;
774 }
775 
776 static float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index)
777 {
778  return frame_index + seq->start;
779 }
780 
782 {
783  if (scene && scene->ed && scene->ed->cache) {
784  return scene->ed->cache;
785  }
786 
787  return NULL;
788 }
789 
791 {
793 
794  if (cache) {
796  }
797 }
798 
800 {
802 
803  if (cache) {
805  }
806 }
807 
808 static size_t seq_cache_get_mem_total(void)
809 {
810  return ((size_t)U.memcachelimit) * 1024 * 1024;
811 }
812 
813 static void seq_cache_keyfree(void *val)
814 {
815  SeqCacheKey *key = val;
817 }
818 
819 static void seq_cache_valfree(void *val)
820 {
821  SeqCacheItem *item = (SeqCacheItem *)val;
822 
823  if (item->ibuf) {
824  IMB_freeImBuf(item->ibuf);
825  }
826 
828 }
829 
831 {
832  int flag;
833  if (key->seq->cache_flag & SEQ_CACHE_OVERRIDE) {
834  flag = key->seq->cache_flag;
835  }
836  else {
837  flag = scene->ed->cache_flag;
838  }
839 
840  /* SEQ_CACHE_STORE_FINAL_OUT can not be overridden by strip cache */
842 
843  return flag;
844 }
845 
846 static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf)
847 {
849  SeqCacheItem *item;
850  item = BLI_mempool_alloc(cache->items_pool);
851  item->cache_owner = cache;
852  item->ibuf = ibuf;
853 
854  const int stored_types_flag = get_stored_types_flag(scene, key);
855 
856  /* Item stored for later use. */
857  if (stored_types_flag & key->type) {
858  key->is_temp_cache = false;
859  key->link_prev = cache->last_key;
860  }
861 
862  /* Store pointer to last cached key. */
863  SeqCacheKey *temp_last_key = cache->last_key;
864 
865  if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) {
866  IMB_refImBuf(ibuf);
867 
868  if (!key->is_temp_cache) {
869  cache->last_key = key;
870  }
871  }
872 
873  /* Set last_key's reference to this key so we can look up chain backwards.
874  * Item is already put in cache, so cache->last_key points to current key.
875  */
876  if (!key->is_temp_cache && temp_last_key) {
877  temp_last_key->link_next = cache->last_key;
878  }
879 
880  /* Reset linking. */
881  if (key->type == SEQ_CACHE_STORE_FINAL_OUT) {
882  cache->last_key = NULL;
883  }
884 }
885 
887 {
888  SeqCacheItem *item = BLI_ghash_lookup(cache->hash, key);
889 
890  if (item && item->ibuf) {
891  IMB_refImBuf(item->ibuf);
892 
893  return item->ibuf;
894  }
895 
896  return NULL;
897 }
898 
899 static void seq_cache_relink_keys(SeqCacheKey *link_next, SeqCacheKey *link_prev)
900 {
901  if (link_next) {
902  link_next->link_prev = link_prev;
903  }
904  if (link_prev) {
905  link_prev->link_next = link_next;
906  }
907 }
908 
909 /* Choose a key out of 2 candidates(leftmost and rightmost items)
910  * to recycle based on currently used strategy */
912 {
913  SeqCacheKey *finalkey = NULL;
914 
915  /* Ideally, cache would not need to check the state of prefetching task
916  * that is tricky to do however, because prefetch would need to know,
917  * if a key, that is about to be created would be removed by itself.
918  *
919  * This can happen because only FINAL_OUT item insertion will trigger recycling
920  * but that is also the point, where prefetch can be suspended.
921  *
922  * We could use temp cache as a shield and later make it a non-temporary entry,
923  * but it is not worth of increasing system complexity.
924  */
926  int pfjob_start, pfjob_end;
927  seq_prefetch_get_time_range(scene, &pfjob_start, &pfjob_end);
928 
929  if (lkey) {
930  if (lkey->timeline_frame < pfjob_start || lkey->timeline_frame > pfjob_end) {
931  return lkey;
932  }
933  }
934 
935  if (rkey) {
936  if (rkey->timeline_frame < pfjob_start || rkey->timeline_frame > pfjob_end) {
937  return rkey;
938  }
939  }
940 
941  return NULL;
942  }
943 
944  if (rkey && lkey) {
945  if (lkey->timeline_frame > rkey->timeline_frame) {
946  SeqCacheKey *swapkey = lkey;
947  lkey = rkey;
948  rkey = swapkey;
949  }
950 
951  int l_diff = scene->r.cfra - lkey->timeline_frame;
952  int r_diff = rkey->timeline_frame - scene->r.cfra;
953 
954  if (l_diff > r_diff) {
955  finalkey = lkey;
956  }
957  else {
958  finalkey = rkey;
959  }
960  }
961  else {
962  if (lkey) {
963  finalkey = lkey;
964  }
965  else {
966  finalkey = rkey;
967  }
968  }
969  return finalkey;
970 }
971 
973 {
975  if (!cache) {
976  return;
977  }
978 
979  SeqCacheKey *next = base->link_next;
980 
981  while (base) {
982  if (!BLI_ghash_haskey(cache->hash, base)) {
983  break; /* Key has already been removed from cache. */
984  }
985 
986  SeqCacheKey *prev = base->link_prev;
987  if (prev != NULL && prev->link_next != base) {
988  /* Key has been removed and replaced and doesn't belong to this chain anymore. */
989  base->link_prev = NULL;
990  break;
991  }
992 
994  base = prev;
995  }
996 
997  base = next;
998  while (base) {
999  if (!BLI_ghash_haskey(cache->hash, base)) {
1000  break; /* Key has already been removed from cache. */
1001  }
1002 
1003  next = base->link_next;
1004  if (next != NULL && next->link_prev != base) {
1005  /* Key has been removed and replaced and doesn't belong to this chain anymore. */
1006  base->link_next = NULL;
1007  break;
1008  }
1009 
1011  base = next;
1012  }
1013 }
1014 
1016 {
1018  SeqCacheKey *finalkey = NULL;
1019  /* Leftmost key. */
1020  SeqCacheKey *lkey = NULL;
1021  /* Rightmost key. */
1022  SeqCacheKey *rkey = NULL;
1023  SeqCacheKey *key = NULL;
1024 
1025  GHashIterator gh_iter;
1026  BLI_ghashIterator_init(&gh_iter, cache->hash);
1027  int total_count = 0;
1028 
1029  while (!BLI_ghashIterator_done(&gh_iter)) {
1030  key = BLI_ghashIterator_getKey(&gh_iter);
1031  SeqCacheItem *item = BLI_ghashIterator_getValue(&gh_iter);
1032  BLI_ghashIterator_step(&gh_iter);
1033 
1034  /* This shouldn't happen, but better be safe than sorry. */
1035  if (!item->ibuf) {
1037  /* Can not continue iterating after linked remove. */
1038  BLI_ghashIterator_init(&gh_iter, cache->hash);
1039  continue;
1040  }
1041 
1042  if (key->is_temp_cache || key->link_next != NULL) {
1043  continue;
1044  }
1045 
1046  total_count++;
1047 
1048  if (lkey) {
1049  if (key->timeline_frame < lkey->timeline_frame) {
1050  lkey = key;
1051  }
1052  }
1053  else {
1054  lkey = key;
1055  }
1056  if (rkey) {
1057  if (key->timeline_frame > rkey->timeline_frame) {
1058  rkey = key;
1059  }
1060  }
1061  else {
1062  rkey = key;
1063  }
1064  }
1065 
1066  finalkey = seq_cache_choose_key(scene, lkey, rkey);
1067 
1068  return finalkey;
1069 }
1070 
1071 /* Find only "base" keys.
1072  * Sources(other types) for a frame must be freed all at once.
1073  */
1075 {
1077  if (!cache) {
1078  return false;
1079  }
1080 
1082 
1083  while (seq_cache_is_full()) {
1085 
1086  if (finalkey) {
1087  seq_cache_recycle_linked(scene, finalkey);
1088  }
1089  else {
1091  return false;
1092  }
1093  }
1095  return true;
1096 }
1097 
1099 {
1101 
1102  if (!cache || !base) {
1103  return;
1104  }
1105 
1106  SeqCacheKey *next = base->link_next;
1107 
1108  while (base) {
1109  SeqCacheKey *prev = base->link_prev;
1110  base->is_temp_cache = true;
1111  base = prev;
1112  }
1113 
1114  base = next;
1115  while (base) {
1116  next = base->link_next;
1117  base->is_temp_cache = true;
1118  base = next;
1119  }
1120 }
1121 
1122 static void seq_disk_cache_create(Main *bmain, Scene *scene)
1123 {
1126 
1127  if (cache == NULL) {
1128  return;
1129  }
1130 
1131  if (cache->disk_cache != NULL) {
1132  return;
1133  }
1134 
1135  cache->disk_cache = MEM_callocN(sizeof(SeqDiskCache), "SeqDiskCache");
1136  cache->disk_cache->bmain = bmain;
1142 }
1143 
1144 static void seq_cache_create(Main *bmain, Scene *scene)
1145 {
1147  if (scene->ed->cache == NULL) {
1148  SeqCache *cache = MEM_callocN(sizeof(SeqCache), "SeqCache");
1149  cache->keys_pool = BLI_mempool_create(sizeof(SeqCacheKey), 0, 64, BLI_MEMPOOL_NOP);
1150  cache->items_pool = BLI_mempool_create(sizeof(SeqCacheItem), 0, 64, BLI_MEMPOOL_NOP);
1151  cache->hash = BLI_ghash_new(seq_cache_hashhash, seq_cache_hashcmp, "SeqCache hash");
1152  cache->last_key = NULL;
1153  cache->bmain = bmain;
1154  BLI_mutex_init(&cache->iterator_mutex);
1155  scene->ed->cache = cache;
1156 
1157  if (scene->ed->disk_cache_timestamp == 0) {
1159  }
1160  }
1162 }
1163 
1165  const SeqRenderData *context,
1166  Sequence *seq,
1167  const float timeline_frame,
1168  const int type)
1169 {
1171  key->seq = seq;
1172  key->context = *context;
1173  key->frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type);
1174  key->timeline_frame = timeline_frame;
1175  key->type = type;
1176  key->link_prev = NULL;
1177  key->link_next = NULL;
1178  key->is_temp_cache = true;
1179  key->task_id = context->task_id;
1180 }
1181 
1183  const SeqRenderData *context,
1184  Sequence *seq,
1185  const float timeline_frame,
1186  const int type)
1187 {
1188  SeqCacheKey *key = BLI_mempool_alloc(cache->keys_pool);
1189  seq_cache_populate_key(key, context, seq, timeline_frame, type);
1190  return key;
1191 }
1192 
1193 /* ***************************** API ****************************** */
1194 
1195 void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame)
1196 {
1198  if (!cache) {
1199  return;
1200  }
1201 
1203 
1204  GHashIterator gh_iter;
1205  BLI_ghashIterator_init(&gh_iter, cache->hash);
1206  while (!BLI_ghashIterator_done(&gh_iter)) {
1207  SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
1208  BLI_ghashIterator_step(&gh_iter);
1209 
1210  if (key->is_temp_cache && key->task_id == id) {
1211  /* Use frame_index here to avoid freeing raw images if they are used for multiple frames. */
1212  float frame_index = seq_cache_timeline_frame_to_frame_index(
1213  key->seq, timeline_frame, key->type);
1214  if (frame_index != key->frame_index || timeline_frame > key->seq->enddisp ||
1215  timeline_frame < key->seq->startdisp) {
1217  }
1218  }
1219  }
1221 }
1222 
1224 {
1226  if (!cache) {
1227  return;
1228  }
1229 
1233  BLI_mutex_end(&cache->iterator_mutex);
1234 
1235  if (cache->disk_cache != NULL) {
1236  BLI_freelistN(&cache->disk_cache->files);
1238  MEM_freeN(cache->disk_cache);
1239  }
1240 
1241  MEM_freeN(cache);
1242  scene->ed->cache = NULL;
1243 }
1244 
1246 {
1247  for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
1249  }
1250 }
1252 {
1254 
1256  if (!cache) {
1257  return;
1258  }
1259 
1261 
1262  GHashIterator gh_iter;
1263  BLI_ghashIterator_init(&gh_iter, cache->hash);
1264  while (!BLI_ghashIterator_done(&gh_iter)) {
1265  SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
1266 
1267  BLI_ghashIterator_step(&gh_iter);
1269  }
1270  cache->last_key = NULL;
1272 }
1273 
1275  Sequence *seq,
1276  Sequence *seq_changed,
1277  int invalidate_types,
1278  bool force_seq_changed_range)
1279 {
1281  if (!cache) {
1282  return;
1283  }
1284 
1285  if (seq_disk_cache_is_enabled(cache->bmain) && cache->disk_cache != NULL) {
1286  seq_disk_cache_invalidate(scene, seq, seq_changed, invalidate_types);
1287  }
1288 
1290 
1291  int range_start = seq_changed->startdisp;
1292  int range_end = seq_changed->enddisp;
1293 
1294  if (!force_seq_changed_range) {
1295  if (seq->startdisp > range_start) {
1296  range_start = seq->startdisp;
1297  }
1298 
1299  if (seq->enddisp < range_end) {
1300  range_end = seq->enddisp;
1301  }
1302  }
1303 
1304  int invalidate_composite = invalidate_types & SEQ_CACHE_STORE_FINAL_OUT;
1305  int invalidate_source = invalidate_types & (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED |
1307 
1308  GHashIterator gh_iter;
1309  BLI_ghashIterator_init(&gh_iter, cache->hash);
1310  while (!BLI_ghashIterator_done(&gh_iter)) {
1311  SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
1312  BLI_ghashIterator_step(&gh_iter);
1313 
1314  /* Clean all final and composite in intersection of seq and seq_changed. */
1315  if (key->type & invalidate_composite && key->timeline_frame >= range_start &&
1316  key->timeline_frame <= range_end) {
1317  if (key->link_next || key->link_prev) {
1319  }
1320 
1322  }
1323 
1324  if (key->type & invalidate_source && key->seq == seq &&
1325  key->timeline_frame >= seq_changed->startdisp &&
1326  key->timeline_frame <= seq_changed->enddisp) {
1327  if (key->link_next || key->link_prev) {
1329  }
1330 
1332  }
1333  }
1334  cache->last_key = NULL;
1336 }
1337 
1339  Sequence *seq,
1340  float timeline_frame,
1341  int type)
1342 {
1343 
1344  if (context->skip_cache || context->is_proxy_render || !seq) {
1345  return NULL;
1346  }
1347 
1348  Scene *scene = context->scene;
1349 
1350  if (context->is_prefetch_render) {
1352  scene = context->scene;
1354  }
1355 
1356  if (!seq) {
1357  return NULL;
1358  }
1359 
1360  if (!scene->ed->cache) {
1361  seq_cache_create(context->bmain, scene);
1362  }
1363 
1366  ImBuf *ibuf = NULL;
1367  SeqCacheKey key;
1368 
1369  /* Try RAM cache: */
1370  if (cache && seq) {
1371  seq_cache_populate_key(&key, context, seq, timeline_frame, type);
1372  ibuf = seq_cache_get_ex(cache, &key);
1373  }
1375 
1376  if (ibuf) {
1377  return ibuf;
1378  }
1379 
1380  /* Try disk cache: */
1381  if (seq_disk_cache_is_enabled(context->bmain)) {
1382  if (cache->disk_cache == NULL) {
1383  seq_disk_cache_create(context->bmain, context->scene);
1384  }
1385 
1387  ibuf = seq_disk_cache_read_file(cache->disk_cache, &key);
1389 
1390  if (ibuf == NULL) {
1391  return NULL;
1392  }
1393 
1394  /* Store read image in RAM. Only recycle item for final type. */
1396  SeqCacheKey *new_key = seq_cache_allocate_key(cache, context, seq, timeline_frame, type);
1397  seq_cache_put_ex(scene, new_key, ibuf);
1398  }
1399  }
1400 
1401  return ibuf;
1402 }
1403 
1405  const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *ibuf)
1406 {
1407  Scene *scene = context->scene;
1408 
1409  if (context->is_prefetch_render) {
1411  scene = context->scene;
1413  }
1414 
1415  if (!seq) {
1416  return false;
1417  }
1418 
1420  seq_cache_put(context, seq, timeline_frame, type, ibuf);
1421  return true;
1422  }
1423 
1425  scene->ed->cache->last_key = NULL;
1426  return false;
1427 }
1428 
1430  const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i)
1431 {
1432  if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) {
1433  return;
1434  }
1435 
1436  Scene *scene = context->scene;
1437 
1438  if (context->is_prefetch_render) {
1440  scene = context->scene;
1442  BLI_assert(seq != NULL);
1443  }
1444 
1445  /* Prevent reinserting, it breaks cache key linking. */
1446  ImBuf *test = seq_cache_get(context, seq, timeline_frame, type);
1447  if (test) {
1448  IMB_freeImBuf(test);
1449  return;
1450  }
1451 
1452  if (!scene->ed->cache) {
1453  seq_cache_create(context->bmain, scene);
1454  }
1455 
1458  SeqCacheKey *key = seq_cache_allocate_key(cache, context, seq, timeline_frame, type);
1459  seq_cache_put_ex(scene, key, i);
1461 
1462  if (!key->is_temp_cache) {
1463  if (seq_disk_cache_is_enabled(context->bmain)) {
1464  if (cache->disk_cache == NULL) {
1465  seq_disk_cache_create(context->bmain, context->scene);
1466  }
1467 
1469  seq_disk_cache_write_file(cache->disk_cache, key, i);
1472  }
1473  }
1474 }
1475 
1477  struct Scene *scene,
1478  void *userdata,
1479  bool callback_init(void *userdata, size_t item_count),
1480  bool callback_iter(void *userdata, struct Sequence *seq, int timeline_frame, int cache_type))
1481 {
1483  if (!cache) {
1484  return;
1485  }
1486 
1488  bool interrupt = callback_init(userdata, BLI_ghash_len(cache->hash));
1489 
1490  GHashIterator gh_iter;
1491  BLI_ghashIterator_init(&gh_iter, cache->hash);
1492 
1493  while (!BLI_ghashIterator_done(&gh_iter) && !interrupt) {
1494  SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
1495  BLI_ghashIterator_step(&gh_iter);
1496 
1497  interrupt = callback_iter(userdata, key->seq, key->timeline_frame, key->type);
1498  }
1499 
1500  cache->last_key = NULL;
1502 }
1503 
1505 {
1507 }
#define B_ENDIAN
Definition: BKE_global.h:208
#define ENDIAN_ORDER
Definition: BKE_global.h:213
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_NONNULL(1)
File and directory operations.
eFileAttributes BLI_file_attributes(const char *path)
Definition: storage.c:230
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:349
size_t BLI_ungzip_file_to_mem_at_pos(void *buf, size_t len, FILE *file, size_t gz_stream_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:213
bool BLI_file_touch(const char *file) ATTR_NONNULL()
Definition: fileops.c:294
#define FILE_ATTR_ANY_LINK
Definition: BLI_fileops.h:99
void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries)
Definition: BLI_filelist.c:467
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_delete(const char *file, bool dir, bool recursive) ATTR_NONNULL()
Definition: fileops.c:1037
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist)
Definition: BLI_filelist.c:238
size_t BLI_gzip_mem_to_file_at_pos(void *buf, size_t len, FILE *file, size_t gz_stream_offset, int compression_level) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:166
struct stat BLI_stat_t
Definition: BLI_fileops.h:67
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:436
eFileAttributes
Definition: BLI_fileops.h:80
FILE * BLI_fopen(const char *filename, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:1003
Some types for dealing with directories.
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:146
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:768
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition: BLI_ghash.c:1086
BLI_INLINE bool BLI_ghashIterator_done(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:158
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:150
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:718
unsigned int BLI_ghash_len(GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:744
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:941
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:900
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
Definition: BLI_ghash.c:1065
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:77
void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int totelem, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_mempool.c:268
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:334
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:757
const char * BLI_path_extension(const char *filepath) ATTR_NONNULL()
Definition: path_util.c:1699
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1347
#define FILE_MAXFILE
#define FILE_MAX
void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1716
#define FILENAME_IS_CURRPAR(_n)
int BLI_path_slash_ensure(char *string) ATTR_NONNULL()
Definition: path_util.c:1981
bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1)
Definition: path_util.c:299
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
Definition: path_util.c:1654
void BLI_split_file_part(const char *string, char *file, const size_t filelen)
Definition: path_util.c:1690
#define FILE_MAXDIR
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:666
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:416
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:396
#define BLI_MUTEX_INITIALIZER
Definition: BLI_threads.h:84
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:401
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:406
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:83
#define STREQ(a, b)
#define MAX_ID_NAME
Definition: DNA_ID.h:269
#define SEQ_NAME_MAXSTR
@ SEQ_CACHE_STORE_PREPROCESSED
@ SEQ_CACHE_STORE_RAW
@ SEQ_CACHE_STORE_FINAL_OUT
@ SEQ_CACHE_STORE_COMPOSITE
@ SEQ_CACHE_DISK_CACHE_ENABLE
@ SEQ_CACHE_PREFETCH_ENABLE
@ SEQ_CACHE_OVERRIDE
@ USER_SEQ_DISK_CACHE_COMPRESSION_HIGH
@ USER_SEQ_DISK_CACHE_COMPRESSION_LOW
@ USER_SEQ_DISK_CACHE_COMPRESSION_NONE
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
const char * IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf)
void IMB_colormanagement_assign_float_colorspace(struct ImBuf *ibuf, const char *name)
void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name)
const char * IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf)
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
void IMB_refImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:239
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
@ IB_rect
Read Guarded memory(de)allocation.
eSeqTaskId
Definition: SEQ_render.h:35
unsigned int U
Definition: btGjkEpa3.h:78
FILE * file
double time
Scene scene
#define DCACHE_IMAGES_PER_FILE
Definition: image_cache.c:104
static unsigned int seq_cache_hashhash(const void *key_)
Definition: image_cache.c:743
static void seq_disk_cache_handle_versioning(SeqDiskCache *disk_cache)
Definition: image_cache.c:417
static void seq_disk_cache_delete_invalid_files(SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, int invalidate_types, int range_start, int range_end)
Definition: image_cache.c:448
static DiskCacheFile * seq_disk_cache_get_file_entry_by_path(SeqDiskCache *disk_cache, char *path)
Definition: image_cache.c:322
static void seq_cache_recycle_linked(Scene *scene, SeqCacheKey *base)
Definition: image_cache.c:972
void SEQ_cache_cleanup(Scene *scene)
Definition: image_cache.c:1251
static void seq_disk_cache_get_file_path(SeqDiskCache *disk_cache, SeqCacheKey *key, char *path, size_t path_len)
Definition: image_cache.c:386
static int seq_disk_cache_compression_level(void)
Definition: image_cache.c:185
static void seq_cache_create(Main *bmain, Scene *scene)
Definition: image_cache.c:1144
static void seq_cache_unlock(Scene *scene)
Definition: image_cache.c:799
bool seq_cache_put_if_possible(const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *ibuf)
Definition: image_cache.c:1404
bool seq_cache_is_full(void)
Definition: image_cache.c:1504
static int get_stored_types_flag(Scene *scene, SeqCacheKey *key)
Definition: image_cache.c:830
static ImBuf * seq_disk_cache_read_file(SeqDiskCache *disk_cache, SeqCacheKey *key)
Definition: image_cache.c:655
static void seq_disk_cache_update_file(SeqDiskCache *disk_cache, char *path)
Definition: image_cache.c:336
static float seq_cache_timeline_frame_to_frame_index(Sequence *seq, float timeline_frame, int type)
Definition: image_cache.c:764
static void seq_cache_set_temp_cache_linked(Scene *scene, SeqCacheKey *base)
Definition: image_cache.c:1098
static unsigned int seq_hash_render_data(const SeqRenderData *a)
Definition: image_cache.c:729
static void seq_cache_valfree(void *val)
Definition: image_cache.c:819
static DiskCacheFile * seq_disk_cache_get_oldest_file(SeqDiskCache *disk_cache)
Definition: image_cache.c:273
static void seq_disk_cache_delete_file(SeqDiskCache *disk_cache, DiskCacheFile *file)
Definition: image_cache.c:288
static bool seq_disk_cache_read_header(FILE *file, DiskCacheHeader *header)
Definition: image_cache.c:519
struct DiskCacheFile DiskCacheFile
void seq_cache_put(const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i)
Definition: image_cache.c:1429
#define COLORSPACE_NAME_MAX
Definition: image_cache.c:106
struct SeqDiskCache SeqDiskCache
static SeqCache * seq_cache_get_from_scene(Scene *scene)
Definition: image_cache.c:781
static SeqCacheKey * seq_cache_allocate_key(SeqCache *cache, const SeqRenderData *context, Sequence *seq, const float timeline_frame, const int type)
Definition: image_cache.c:1182
static ImBuf * seq_cache_get_ex(SeqCache *cache, SeqCacheKey *key)
Definition: image_cache.c:886
static SeqCacheKey * seq_cache_get_item_for_removal(Scene *scene)
Definition: image_cache.c:1015
static void seq_cache_relink_keys(SeqCacheKey *link_next, SeqCacheKey *link_prev)
Definition: image_cache.c:899
static void seq_disk_cache_create_version_file(char *path)
Definition: image_cache.c:406
void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame)
Definition: image_cache.c:1195
static char * seq_disk_cache_base_dir(void)
Definition: image_cache.c:180
static void seq_disk_cache_invalidate(Scene *scene, Sequence *seq, Sequence *seq_changed, int invalidate_types)
Definition: image_cache.c:475
void SEQ_cache_iterate(struct Scene *scene, void *userdata, bool callback_init(void *userdata, size_t item_count), bool callback_iter(void *userdata, struct Sequence *seq, int timeline_frame, int cache_type))
Definition: image_cache.c:1476
static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, size_t path_len)
Definition: image_cache.c:358
static size_t deflate_imbuf_to_file(ImBuf *ibuf, FILE *file, int level, DiskCacheHeaderEntry *header_entry)
Definition: image_cache.c:494
static size_t seq_disk_cache_size_limit(void)
Definition: image_cache.c:199
static SeqCacheKey * seq_cache_choose_key(Scene *scene, SeqCacheKey *lkey, SeqCacheKey *rkey)
Definition: image_cache.c:911
static bool seq_disk_cache_is_enabled(Main *bmain)
Definition: image_cache.c:204
static ThreadMutex cache_create_lock
Definition: image_cache.c:174
static DiskCacheFile * seq_disk_cache_add_file_to_list(SeqDiskCache *disk_cache, const char *path)
Definition: image_cache.c:211
static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
Definition: image_cache.c:720
static int seq_disk_cache_get_header_entry(SeqCacheKey *key, DiskCacheHeader *header)
Definition: image_cache.c:598
static size_t seq_disk_cache_write_header(FILE *file, DiskCacheHeader *header)
Definition: image_cache.c:541
struct ImBuf * seq_cache_get(const SeqRenderData *context, Sequence *seq, float timeline_frame, int type)
Definition: image_cache.c:1338
struct SeqCacheKey SeqCacheKey
static void seq_cache_keyfree(void *val)
Definition: image_cache.c:813
static float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index)
Definition: image_cache.c:776
static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf)
Definition: image_cache.c:846
#define DCACHE_FNAME_FORMAT
Definition: image_cache.c:103
void seq_cache_cleanup_sequence(Scene *scene, Sequence *seq, Sequence *seq_changed, int invalidate_types, bool force_seq_changed_range)
Definition: image_cache.c:1274
static size_t inflate_file_to_imbuf(ImBuf *ibuf, FILE *file, DiskCacheHeaderEntry *header_entry)
Definition: image_cache.c:508
static bool seq_disk_cache_write_file(SeqDiskCache *disk_cache, SeqCacheKey *key, ImBuf *ibuf)
Definition: image_cache.c:609
static int seq_disk_cache_add_header_entry(SeqCacheKey *key, ImBuf *ibuf, DiskCacheHeader *header)
Definition: image_cache.c:547
static void seq_disk_cache_get_dir(SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, char *path, size_t path_len)
Definition: image_cache.c:369
static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
Definition: image_cache.c:233
static bool seq_cache_hashcmp(const void *a_, const void *b_)
Definition: image_cache.c:755
struct DiskCacheHeaderEntry DiskCacheHeaderEntry
void seq_cache_cleanup_all(Main *bmain)
Definition: image_cache.c:1245
#define DCACHE_CURRENT_VERSION
Definition: image_cache.c:105
static bool seq_disk_cache_enforce_limits(SeqDiskCache *disk_cache)
Definition: image_cache.c:296
static void seq_cache_lock(Scene *scene)
Definition: image_cache.c:790
static void seq_disk_cache_create(Main *bmain, Scene *scene)
Definition: image_cache.c:1122
void seq_cache_destruct(Scene *scene)
Definition: image_cache.c:1223
static void seq_cache_populate_key(SeqCacheKey *key, const SeqRenderData *context, Sequence *seq, const float timeline_frame, const int type)
Definition: image_cache.c:1164
static size_t seq_cache_get_mem_total(void)
Definition: image_cache.c:808
struct DiskCacheHeader DiskCacheHeader
struct SeqCache SeqCache
bool seq_cache_recycle_item(Scene *scene)
Definition: image_cache.c:1074
struct SeqCacheItem SeqCacheItem
#define PRId64
Definition: inttypes.h:81
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_get_memory_in_use)(void)
Definition: mallocn.c:59
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static ulong * next
static unsigned a[3]
Definition: RandGen.cpp:92
void seq_prefetch_get_time_range(Scene *scene, int *start, int *end)
Definition: prefetch.c:198
bool seq_prefetch_job_is_running(Scene *scene)
Definition: prefetch.c:123
void SEQ_prefetch_stop(Scene *scene)
Definition: prefetch.c:272
Sequence * seq_prefetch_get_original_sequence(Sequence *seq, Scene *scene)
Definition: prefetch.c:164
SeqRenderData * seq_prefetch_get_original_context(const SeqRenderData *context)
Definition: prefetch.c:171
struct SELECTID_Context context
Definition: select_engine.c:47
__int64 int64_t
Definition: stdint.h:92
_W64 int intptr_t
Definition: stdint.h:121
unsigned __int64 uint64_t
Definition: stdint.h:93
float seq_give_frame_index(Sequence *seq, float timeline_frame)
Definition: strip_time.c:48
struct DiskCacheFile * prev
Definition: image_cache.c:130
char file[FILE_MAX]
Definition: image_cache.c:133
struct DiskCacheFile * next
Definition: image_cache.c:130
char path[FILE_MAX]
Definition: image_cache.c:131
char dir[FILE_MAXDIR]
Definition: image_cache.c:132
BLI_stat_t fstat
Definition: image_cache.c:134
char colorspace_name[COLORSPACE_NAME_MAX]
Definition: image_cache.c:114
uint64_t size_compressed
Definition: image_cache.c:111
unsigned char encoding
Definition: image_cache.c:109
DiskCacheHeaderEntry entry[DCACHE_IMAGES_PER_FILE]
Definition: image_cache.c:118
int64_t disk_cache_timestamp
struct SeqCache * cache
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
void * userdata
int channels
unsigned int * rect
float * rect_float
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase scenes
Definition: BKE_main.h:146
char name[1024]
Definition: BKE_main.h:118
short views_format
struct Editing * ed
struct RenderData r
struct SeqCache * cache_owner
Definition: image_cache.c:154
struct ImBuf * ibuf
Definition: image_cache.c:155
struct SeqCacheKey * link_next
Definition: image_cache.c:162
float timeline_frame
Definition: image_cache.c:166
float frame_index
Definition: image_cache.c:165
eSeqTaskId task_id
Definition: image_cache.c:170
struct Sequence * seq
Definition: image_cache.c:163
bool is_temp_cache
Definition: image_cache.c:168
void * userkey
Definition: image_cache.c:160
struct SeqCache * cache_owner
Definition: image_cache.c:159
SeqRenderData context
Definition: image_cache.c:164
struct SeqCacheKey * link_prev
Definition: image_cache.c:161
ThreadMutex iterator_mutex
Definition: image_cache.c:146
struct GHash * hash
Definition: image_cache.c:145
struct SeqCacheKey * last_key
Definition: image_cache.c:149
struct BLI_mempool * items_pool
Definition: image_cache.c:148
struct BLI_mempool * keys_pool
Definition: image_cache.c:147
SeqDiskCache * disk_cache
Definition: image_cache.c:150
Main * bmain
Definition: image_cache.c:144
int64_t timestamp
Definition: image_cache.c:123
ThreadMutex read_write_mutex
Definition: image_cache.c:125
Main * bmain
Definition: image_cache.c:122
size_t size_total
Definition: image_cache.c:126
ListBase files
Definition: image_cache.c:124
int preview_render_size
Definition: SEQ_render.h:46
struct Main * bmain
Definition: SEQ_render.h:41
struct Scene * scene
Definition: SEQ_render.h:43
float motion_blur_shutter
Definition: SEQ_render.h:50
int motion_blur_samples
Definition: SEQ_render.h:49
struct stat s
const char * path