Blender  V3.3
disk_cache.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
8 #include <memory.h>
9 #include <stddef.h>
10 #include <time.h>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "DNA_scene_types.h"
15 #include "DNA_sequence_types.h"
16 #include "DNA_space_types.h" /* for FILE_MAX. */
17 
18 #include "IMB_colormanagement.h"
19 #include "IMB_imbuf.h"
20 #include "IMB_imbuf_types.h"
21 
22 #include "BLI_blenlib.h"
23 #include "BLI_endian_defines.h"
24 #include "BLI_endian_switch.h"
25 #include "BLI_fileops.h"
26 #include "BLI_fileops_types.h"
27 #include "BLI_ghash.h"
28 #include "BLI_listbase.h"
29 #include "BLI_mempool.h"
30 #include "BLI_path_util.h"
31 #include "BLI_threads.h"
32 
33 #include "BKE_main.h"
34 #include "BKE_scene.h"
35 
36 #include "SEQ_prefetch.h"
37 #include "SEQ_relations.h"
38 #include "SEQ_render.h"
39 #include "SEQ_sequencer.h"
40 #include "SEQ_time.h"
41 
42 #include "disk_cache.h"
43 #include "image_cache.h"
44 #include "prefetch.h"
45 #include "strip_time.h"
46 
64 /* Format string:
65  * `<cache type>-<resolution X>x<resolution Y>-<rendersize>%(<view_id>)-<frame no>.dcf`. */
66 #define DCACHE_FNAME_FORMAT "%d-%dx%d-%d%%(%d)-%d.dcf"
67 #define DCACHE_IMAGES_PER_FILE 100
68 #define DCACHE_CURRENT_VERSION 2
69 #define COLORSPACE_NAME_MAX 64 /* XXX: defined in IMB intern. */
70 
71 typedef struct DiskCacheHeaderEntry {
72  unsigned char encoding;
79 
80 typedef struct DiskCacheHeader {
83 
84 typedef struct SeqDiskCache {
89  size_t size_total;
91 
92 typedef struct DiskCacheFile {
93  struct DiskCacheFile *next, *prev;
94  char path[FILE_MAX];
96  char file[FILE_MAX];
99  int rectx;
100  int recty;
102  int view_id;
105 
107 
108 static char *seq_disk_cache_base_dir(void)
109 {
110  return U.sequencer_disk_cache_dir;
111 }
112 
114 {
115  switch (U.sequencer_disk_cache_compression) {
117  return 0;
119  return 1;
121  return 9;
122  }
123 
124  return U.sequencer_disk_cache_compression;
125 }
126 
127 static size_t seq_disk_cache_size_limit(void)
128 {
129  return (size_t)U.sequencer_disk_cache_size_limit * (1024 * 1024 * 1024);
130 }
131 
133 {
134  return (U.sequencer_disk_cache_dir[0] != '\0' && U.sequencer_disk_cache_size_limit != 0 &&
135  (U.sequencer_disk_cache_flag & SEQ_CACHE_DISK_CACHE_ENABLE) != 0 &&
136  bmain->filepath[0] != '\0');
137 }
138 
140 {
141 
142  DiskCacheFile *cache_file = MEM_callocN(sizeof(DiskCacheFile), "SeqDiskCacheFile");
143  char dir[FILE_MAXDIR], file[FILE_MAX];
144  BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
145  BLI_strncpy(cache_file->path, path, sizeof(cache_file->path));
146  BLI_strncpy(cache_file->dir, dir, sizeof(cache_file->dir));
147  BLI_strncpy(cache_file->file, file, sizeof(cache_file->file));
148  sscanf(file,
150  &cache_file->cache_type,
151  &cache_file->rectx,
152  &cache_file->recty,
153  &cache_file->render_size,
154  &cache_file->view_id,
155  &cache_file->start_frame);
156  cache_file->start_frame *= DCACHE_IMAGES_PER_FILE;
157  BLI_addtail(&disk_cache->files, cache_file);
158  return cache_file;
159 }
160 
161 static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
162 {
163  struct direntry *filelist, *fl;
164  uint i;
165  disk_cache->size_total = 0;
166 
167  const int filelist_num = BLI_filelist_dir_contents(path, &filelist);
168  i = filelist_num;
169  fl = filelist;
170  while (i--) {
171  /* Don't follow links. */
172  const eFileAttributes file_attrs = BLI_file_attributes(fl->path);
173  if (file_attrs & FILE_ATTR_ANY_LINK) {
174  fl++;
175  continue;
176  }
177 
178  char file[FILE_MAX];
179  BLI_split_dirfile(fl->path, NULL, file, 0, sizeof(file));
180 
181  bool is_dir = BLI_is_dir(fl->path);
182  if (is_dir && !FILENAME_IS_CURRPAR(file)) {
183  char subpath[FILE_MAX];
184  BLI_strncpy(subpath, fl->path, sizeof(subpath));
185  BLI_path_slash_ensure(subpath);
186  seq_disk_cache_get_files(disk_cache, subpath);
187  }
188 
189  if (!is_dir) {
190  const char *ext = BLI_path_extension(fl->path);
191  if (ext && ext[1] == 'd' && ext[2] == 'c' && ext[3] == 'f') {
192  DiskCacheFile *cache_file = seq_disk_cache_add_file_to_list(disk_cache, fl->path);
193  cache_file->fstat = fl->s;
194  disk_cache->size_total += cache_file->fstat.st_size;
195  }
196  }
197  fl++;
198  }
199  BLI_filelist_free(filelist, filelist_num);
200 }
201 
203 {
204  DiskCacheFile *oldest_file = disk_cache->files.first;
205  if (oldest_file == NULL) {
206  return NULL;
207  }
208  for (DiskCacheFile *cache_file = oldest_file->next; cache_file; cache_file = cache_file->next) {
209  if (cache_file->fstat.st_mtime < oldest_file->fstat.st_mtime) {
210  oldest_file = cache_file;
211  }
212  }
213 
214  return oldest_file;
215 }
216 
218 {
219  disk_cache->size_total -= file->fstat.st_size;
220  BLI_delete(file->path, false, false);
221  BLI_remlink(&disk_cache->files, file);
222  MEM_freeN(file);
223 }
224 
226 {
227  BLI_mutex_lock(&disk_cache->read_write_mutex);
228  while (disk_cache->size_total > seq_disk_cache_size_limit()) {
229  DiskCacheFile *oldest_file = seq_disk_cache_get_oldest_file(disk_cache);
230 
231  if (!oldest_file) {
232  /* We shouldn't enforce limits with no files, do re-scan. */
234  continue;
235  }
236 
237  if (BLI_exists(oldest_file->path) == 0) {
238  /* File may have been manually deleted during runtime, do re-scan. */
239  BLI_freelistN(&disk_cache->files);
241  continue;
242  }
243 
244  seq_disk_cache_delete_file(disk_cache, oldest_file);
245  }
246  BLI_mutex_unlock(&disk_cache->read_write_mutex);
247 
248  return true;
249 }
250 
252 {
253  DiskCacheFile *cache_file = disk_cache->files.first;
254 
255  for (; cache_file; cache_file = cache_file->next) {
256  if (BLI_strcasecmp(cache_file->path, path) == 0) {
257  return cache_file;
258  }
259  }
260 
261  return NULL;
262 }
263 
264 /* Update file size and timestamp. */
265 static void seq_disk_cache_update_file(SeqDiskCache *disk_cache, char *path)
266 {
267  DiskCacheFile *cache_file;
268  int64_t size_before;
269  int64_t size_after;
270 
271  cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
272  size_before = cache_file->fstat.st_size;
273 
274  if (BLI_stat(path, &cache_file->fstat) == -1) {
275  BLI_assert(false);
276  memset(&cache_file->fstat, 0, sizeof(BLI_stat_t));
277  }
278 
279  size_after = cache_file->fstat.st_size;
280  disk_cache->size_total += size_after - size_before;
281 }
282 
283 /* Path format:
284  * <cache dir>/<project name>_seq_cache/<scene name>-<timestamp>/<seq name>/DCACHE_FNAME_FORMAT
285  */
286 
287 static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, size_t path_len)
288 {
289  char cache_dir[FILE_MAX];
290  BLI_split_file_part(BKE_main_blendfile_path(disk_cache->bmain), cache_dir, sizeof(cache_dir));
291  /* Use suffix, so that the cache directory name does not conflict with the bmain's blend file. */
292  const char *suffix = "_seq_cache";
293  strncat(cache_dir, suffix, sizeof(cache_dir) - strlen(cache_dir) - 1);
295  BLI_path_append(path, path_len, cache_dir);
296 }
297 
299  SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, char *path, size_t path_len)
300 {
301  char scene_name[MAX_ID_NAME + 22]; /* + -%PRId64 */
302  char seq_name[SEQ_NAME_MAXSTR];
303  char project_dir[FILE_MAX];
304 
305  seq_disk_cache_get_project_dir(disk_cache, project_dir, sizeof(project_dir));
306  sprintf(scene_name, "%s-%" PRId64, scene->id.name, disk_cache->timestamp);
307  BLI_strncpy(seq_name, seq->name, sizeof(seq_name));
308  BLI_filename_make_safe(scene_name);
309  BLI_filename_make_safe(seq_name);
310  BLI_strncpy(path, project_dir, path_len);
311  BLI_path_append(path, path_len, scene_name);
312  BLI_path_append(path, path_len, seq_name);
313 }
314 
316  SeqCacheKey *key,
317  char *path,
318  size_t path_len)
319 {
320  seq_disk_cache_get_dir(disk_cache, key->context.scene, key->seq, path, path_len);
321  int frameno = (int)key->frame_index / DCACHE_IMAGES_PER_FILE;
322  char cache_filename[FILE_MAXFILE];
323  sprintf(cache_filename,
325  key->type,
326  key->context.rectx,
327  key->context.recty,
329  key->context.view_id,
330  frameno);
331 
332  BLI_path_append(path, path_len, cache_filename);
333 }
334 
336 {
338 
339  FILE *file = BLI_fopen(path, "w");
340  if (file) {
341  fprintf(file, "%d", DCACHE_CURRENT_VERSION);
342  fclose(file);
343  }
344 }
345 
347 {
348  char filepath[FILE_MAX];
349  char path_version_file[FILE_MAX];
350  int version = 0;
351 
352  seq_disk_cache_get_project_dir(disk_cache, filepath, sizeof(filepath));
353  BLI_strncpy(path_version_file, filepath, sizeof(path_version_file));
354  BLI_path_append(path_version_file, sizeof(path_version_file), "cache_version");
355 
356  if (BLI_exists(filepath) && BLI_is_dir(filepath)) {
357  FILE *file = BLI_fopen(path_version_file, "r");
358 
359  if (file) {
360  const int num_items_read = fscanf(file, "%d", &version);
361  if (num_items_read == 0) {
362  version = -1;
363  }
364  fclose(file);
365  }
366 
367  if (version != DCACHE_CURRENT_VERSION) {
368  BLI_delete(filepath, false, true);
369  seq_disk_cache_create_version_file(path_version_file);
370  }
371  }
372  else {
373  seq_disk_cache_create_version_file(path_version_file);
374  }
375 }
376 
378  Scene *scene,
379  Sequence *seq,
380  int invalidate_types,
381  int range_start,
382  int range_end)
383 {
384  DiskCacheFile *next_file, *cache_file = disk_cache->files.first;
385  char cache_dir[FILE_MAX];
386  seq_disk_cache_get_dir(disk_cache, scene, seq, cache_dir, sizeof(cache_dir));
387  BLI_path_slash_ensure(cache_dir);
388 
389  while (cache_file) {
390  next_file = cache_file->next;
391  if (cache_file->cache_type & invalidate_types) {
392  if (STREQ(cache_dir, cache_file->dir)) {
393  int timeline_frame_start = seq_cache_frame_index_to_timeline_frame(
394  seq, cache_file->start_frame);
395  if (timeline_frame_start > range_start && timeline_frame_start <= range_end) {
396  seq_disk_cache_delete_file(disk_cache, cache_file);
397  }
398  }
399  }
400  cache_file = next_file;
401  }
402 }
403 
405  Scene *scene,
406  Sequence *seq,
407  Sequence *seq_changed,
408  int invalidate_types)
409 {
410  int start;
411  int end;
412 
413  BLI_mutex_lock(&disk_cache->read_write_mutex);
414 
416  end = SEQ_time_right_handle_frame_get(scene, seq_changed);
417 
418  seq_disk_cache_delete_invalid_files(disk_cache, scene, seq, invalidate_types, start, end);
419 
420  BLI_mutex_unlock(&disk_cache->read_write_mutex);
421 }
422 
423 static size_t deflate_imbuf_to_file(ImBuf *ibuf,
424  FILE *file,
425  int level,
426  DiskCacheHeaderEntry *header_entry)
427 {
428  void *data = (ibuf->rect != NULL) ? (void *)ibuf->rect : (void *)ibuf->rect_float;
429 
430  /* Apply compression if wanted, otherwise just write directly to the file. */
431  if (level > 0) {
433  data, header_entry->size_raw, file, header_entry->offset, level);
434  }
435 
436  fseek(file, header_entry->offset, SEEK_SET);
437  return fwrite(data, 1, header_entry->size_raw, file);
438 }
439 
440 static size_t inflate_file_to_imbuf(ImBuf *ibuf, FILE *file, DiskCacheHeaderEntry *header_entry)
441 {
442  void *data = (ibuf->rect != NULL) ? (void *)ibuf->rect : (void *)ibuf->rect_float;
443  char header[4];
444  fseek(file, header_entry->offset, SEEK_SET);
445  if (fread(header, 1, sizeof(header), file) != sizeof(header)) {
446  return 0;
447  }
448 
449  /* Check if the data is compressed or raw. */
450  if (BLI_file_magic_is_zstd(header)) {
451  return BLI_file_unzstd_to_mem_at_pos(data, header_entry->size_raw, file, header_entry->offset);
452  }
453 
454  fseek(file, header_entry->offset, SEEK_SET);
455  return fread(data, 1, header_entry->size_raw, file);
456 }
457 
459 {
460  BLI_fseek(file, 0LL, SEEK_SET);
461  const size_t num_items_read = fread(header, sizeof(*header), 1, file);
462  if (num_items_read < 1) {
463  BLI_assert_msg(0, "unable to read disk cache header");
464  perror("unable to read disk cache header");
465  return false;
466  }
467 
468  for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
469  if ((ENDIAN_ORDER == B_ENDIAN) && header->entry[i].encoding == 0) {
474  }
475  }
476 
477  return true;
478 }
479 
480 static size_t seq_disk_cache_write_header(FILE *file, DiskCacheHeader *header)
481 {
482  BLI_fseek(file, 0LL, SEEK_SET);
483  return fwrite(header, sizeof(*header), 1, file);
484 }
485 
487 {
488  int i;
489  uint64_t offset = sizeof(*header);
490 
491  /* Lookup free entry, get offset for new data. */
492  for (i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
493  if (header->entry[i].size_compressed == 0) {
494  break;
495  }
496  }
497 
498  /* Attempt to write beyond set entry limit.
499  * Reset file header and start writing from beginning.
500  */
501  if (i == DCACHE_IMAGES_PER_FILE) {
502  i = 0;
503  memset(header, 0, sizeof(*header));
504  }
505 
506  /* Calculate offset for image data. */
507  if (i > 0) {
508  offset = header->entry[i - 1].offset + header->entry[i - 1].size_compressed;
509  }
510 
511  if (ENDIAN_ORDER == B_ENDIAN) {
512  header->entry[i].encoding = 255;
513  }
514  else {
515  header->entry[i].encoding = 0;
516  }
517 
518  header->entry[i].offset = offset;
519  header->entry[i].frameno = key->frame_index;
520 
521  /* Store colorspace name of ibuf. */
522  const char *colorspace_name;
523  if (ibuf->rect) {
524  header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels;
525  colorspace_name = IMB_colormanagement_get_rect_colorspace(ibuf);
526  }
527  else {
528  header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels * 4;
529  colorspace_name = IMB_colormanagement_get_float_colorspace(ibuf);
530  }
531  BLI_strncpy(
532  header->entry[i].colorspace_name, colorspace_name, sizeof(header->entry[i].colorspace_name));
533 
534  return i;
535 }
536 
538 {
539  for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
540  if (header->entry[i].frameno == key->frame_index) {
541  return i;
542  }
543  }
544 
545  return -1;
546 }
547 
549 {
550  BLI_mutex_lock(&disk_cache->read_write_mutex);
551 
552  char filepath[FILE_MAX];
553 
554  seq_disk_cache_get_file_path(disk_cache, key, filepath, sizeof(filepath));
555  BLI_make_existing_file(filepath);
556 
557  FILE *file = BLI_fopen(filepath, "rb+");
558  if (!file) {
559  file = BLI_fopen(filepath, "wb+");
560  if (!file) {
561  BLI_mutex_unlock(&disk_cache->read_write_mutex);
562  return false;
563  }
564  seq_disk_cache_add_file_to_list(disk_cache, filepath);
565  }
566 
567  DiskCacheFile *cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, filepath);
568  DiskCacheHeader header;
569  memset(&header, 0, sizeof(header));
570  /* #BLI_make_existing_file() above may create an empty file. This is fine, don't attempt reading
571  * the header in that case. */
572  if (cache_file->fstat.st_size != 0 && !seq_disk_cache_read_header(file, &header)) {
573  fclose(file);
574  seq_disk_cache_delete_file(disk_cache, cache_file);
575  BLI_mutex_unlock(&disk_cache->read_write_mutex);
576  return false;
577  }
578  int entry_index = seq_disk_cache_add_header_entry(key, ibuf, &header);
579 
580  size_t bytes_written = deflate_imbuf_to_file(
581  ibuf, file, seq_disk_cache_compression_level(), &header.entry[entry_index]);
582 
583  if (bytes_written != 0) {
584  /* Last step is writing header, as image data can be overwritten,
585  * but missing data would cause problems.
586  */
587  header.entry[entry_index].size_compressed = bytes_written;
589  seq_disk_cache_update_file(disk_cache, filepath);
590  fclose(file);
591 
592  BLI_mutex_unlock(&disk_cache->read_write_mutex);
593  return true;
594  }
595 
596  BLI_mutex_unlock(&disk_cache->read_write_mutex);
597  return false;
598 }
599 
601 {
602  BLI_mutex_lock(&disk_cache->read_write_mutex);
603 
604  char filepath[FILE_MAX];
605  DiskCacheHeader header;
606 
607  seq_disk_cache_get_file_path(disk_cache, key, filepath, sizeof(filepath));
608  BLI_make_existing_file(filepath);
609 
610  FILE *file = BLI_fopen(filepath, "rb");
611  if (!file) {
612  BLI_mutex_unlock(&disk_cache->read_write_mutex);
613  return NULL;
614  }
615 
616  if (!seq_disk_cache_read_header(file, &header)) {
617  fclose(file);
618  BLI_mutex_unlock(&disk_cache->read_write_mutex);
619  return NULL;
620  }
621  int entry_index = seq_disk_cache_get_header_entry(key, &header);
622 
623  /* Item not found. */
624  if (entry_index < 0) {
625  fclose(file);
626  BLI_mutex_unlock(&disk_cache->read_write_mutex);
627  return NULL;
628  }
629 
630  ImBuf *ibuf;
631  uint64_t size_char = (uint64_t)key->context.rectx * key->context.recty * 4;
632  uint64_t size_float = (uint64_t)key->context.rectx * key->context.recty * 16;
633  size_t expected_size;
634 
635  if (header.entry[entry_index].size_raw == size_char) {
636  expected_size = size_char;
637  ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rect);
639  }
640  else if (header.entry[entry_index].size_raw == size_float) {
641  expected_size = size_float;
642  ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rectfloat);
644  }
645  else {
646  fclose(file);
647  BLI_mutex_unlock(&disk_cache->read_write_mutex);
648  return NULL;
649  }
650 
651  size_t bytes_read = inflate_file_to_imbuf(ibuf, file, &header.entry[entry_index]);
652 
653  /* Sanity check. */
654  if (bytes_read != expected_size) {
655  fclose(file);
656  IMB_freeImBuf(ibuf);
657  BLI_mutex_unlock(&disk_cache->read_write_mutex);
658  return NULL;
659  }
660  BLI_file_touch(filepath);
661  seq_disk_cache_update_file(disk_cache, filepath);
662  fclose(file);
663 
664  BLI_mutex_unlock(&disk_cache->read_write_mutex);
665  return ibuf;
666 }
667 
669 {
670  SeqDiskCache *disk_cache = MEM_callocN(sizeof(SeqDiskCache), "SeqDiskCache");
671  disk_cache->bmain = bmain;
672  BLI_mutex_init(&disk_cache->read_write_mutex);
675  disk_cache->timestamp = scene->ed->disk_cache_timestamp;
677  return disk_cache;
678 }
679 
681 {
682  BLI_freelistN(&disk_cache->files);
683  BLI_mutex_end(&disk_cache->read_write_mutex);
684  MEM_freeN(disk_cache);
685 }
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define B_ENDIAN
#define ENDIAN_ORDER
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:198
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:314
size_t BLI_file_zstd_from_mem_at_pos(void *buf, size_t len, FILE *file, size_t file_offset, int compression_level) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:49
bool BLI_file_touch(const char *file) ATTR_NONNULL()
Definition: fileops.c:192
#define FILE_ATTR_ANY_LINK
Definition: BLI_fileops.h:105
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
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:934
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist)
Definition: BLI_filelist.c:218
size_t BLI_file_unzstd_to_mem_at_pos(void *buf, size_t len, FILE *file, size_t file_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:96
bool BLI_file_magic_is_zstd(const char header[4])
Definition: fileops.c:140
struct stat BLI_stat_t
Definition: BLI_fileops.h:73
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:397
void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries)
Definition: BLI_filelist.c:420
eFileAttributes
Definition: BLI_fileops.h:86
int BLI_fseek(FILE *stream, int64_t offset, int whence)
Definition: storage.c:160
Some types for dealing with directories.
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
const char * BLI_path_extension(const char *filepath) ATTR_NONNULL()
Definition: path_util.c:1500
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1197
#define FILE_MAXFILE
void BLI_split_dirfile(const char *string, char *dir, char *file, size_t dirlen, size_t filelen)
Definition: path_util.c:1465
#define FILE_MAX
#define FILENAME_IS_CURRPAR(_n)
void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1514
int BLI_path_slash_ensure(char *string) ATTR_NONNULL()
Definition: path_util.c:1780
bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1)
Definition: path_util.c:309
void BLI_split_file_part(const char *string, char *file, size_t filelen)
Definition: path_util.c:1495
#define FILE_MAXDIR
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:623
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned int uint
Definition: BLI_sys_types.h:67
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:388
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:368
#define BLI_MUTEX_INITIALIZER
Definition: BLI_threads.h:83
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:373
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:378
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:82
#define STREQ(a, b)
#define MAX_ID_NAME
Definition: DNA_ID.h:337
#define SEQ_NAME_MAXSTR
@ SEQ_CACHE_DISK_CACHE_ENABLE
@ USER_SEQ_DISK_CACHE_COMPRESSION_HIGH
@ USER_SEQ_DISK_CACHE_COMPRESSION_LOW
@ USER_SEQ_DISK_CACHE_COMPRESSION_NONE
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:500
Contains defines and structs used throughout the imbuf module.
@ IB_rectfloat
@ IB_rect
Read Guarded memory(de)allocation.
unsigned int U
Definition: btGjkEpa3.h:78
FILE * file
Scene scene
SeqDiskCache * seq_disk_cache_create(Main *bmain, Scene *scene)
Definition: disk_cache.c:668
#define DCACHE_IMAGES_PER_FILE
Definition: disk_cache.c:67
static void seq_disk_cache_handle_versioning(SeqDiskCache *disk_cache)
Definition: disk_cache.c:346
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: disk_cache.c:377
static DiskCacheFile * seq_disk_cache_get_file_entry_by_path(SeqDiskCache *disk_cache, char *path)
Definition: disk_cache.c:251
ImBuf * seq_disk_cache_read_file(SeqDiskCache *disk_cache, SeqCacheKey *key)
Definition: disk_cache.c:600
static void seq_disk_cache_get_file_path(SeqDiskCache *disk_cache, SeqCacheKey *key, char *path, size_t path_len)
Definition: disk_cache.c:315
static int seq_disk_cache_compression_level(void)
Definition: disk_cache.c:113
static void seq_disk_cache_update_file(SeqDiskCache *disk_cache, char *path)
Definition: disk_cache.c:265
static DiskCacheFile * seq_disk_cache_get_oldest_file(SeqDiskCache *disk_cache)
Definition: disk_cache.c:202
static void seq_disk_cache_delete_file(SeqDiskCache *disk_cache, DiskCacheFile *file)
Definition: disk_cache.c:217
static bool seq_disk_cache_read_header(FILE *file, DiskCacheHeader *header)
Definition: disk_cache.c:458
struct DiskCacheFile DiskCacheFile
#define COLORSPACE_NAME_MAX
Definition: disk_cache.c:69
struct SeqDiskCache SeqDiskCache
static void seq_disk_cache_create_version_file(char *path)
Definition: disk_cache.c:335
static char * seq_disk_cache_base_dir(void)
Definition: disk_cache.c:108
void seq_disk_cache_invalidate(SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, Sequence *seq_changed, int invalidate_types)
Definition: disk_cache.c:404
static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, size_t path_len)
Definition: disk_cache.c:287
static size_t deflate_imbuf_to_file(ImBuf *ibuf, FILE *file, int level, DiskCacheHeaderEntry *header_entry)
Definition: disk_cache.c:423
static size_t seq_disk_cache_size_limit(void)
Definition: disk_cache.c:127
static ThreadMutex cache_create_lock
Definition: disk_cache.c:106
static DiskCacheFile * seq_disk_cache_add_file_to_list(SeqDiskCache *disk_cache, const char *path)
Definition: disk_cache.c:139
static int seq_disk_cache_get_header_entry(SeqCacheKey *key, DiskCacheHeader *header)
Definition: disk_cache.c:537
static size_t seq_disk_cache_write_header(FILE *file, DiskCacheHeader *header)
Definition: disk_cache.c:480
#define DCACHE_FNAME_FORMAT
Definition: disk_cache.c:66
static size_t inflate_file_to_imbuf(ImBuf *ibuf, FILE *file, DiskCacheHeaderEntry *header_entry)
Definition: disk_cache.c:440
void seq_disk_cache_free(SeqDiskCache *disk_cache)
Definition: disk_cache.c:680
static int seq_disk_cache_add_header_entry(SeqCacheKey *key, ImBuf *ibuf, DiskCacheHeader *header)
Definition: disk_cache.c:486
static void seq_disk_cache_get_dir(SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, char *path, size_t path_len)
Definition: disk_cache.c:298
static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
Definition: disk_cache.c:161
struct DiskCacheHeaderEntry DiskCacheHeaderEntry
#define DCACHE_CURRENT_VERSION
Definition: disk_cache.c:68
bool seq_disk_cache_enforce_limits(SeqDiskCache *disk_cache)
Definition: disk_cache.c:225
bool seq_disk_cache_write_file(SeqDiskCache *disk_cache, SeqCacheKey *key, ImBuf *ibuf)
Definition: disk_cache.c:548
bool seq_disk_cache_is_enabled(Main *bmain)
Definition: disk_cache.c:132
struct DiskCacheHeader DiskCacheHeader
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index)
Definition: image_cache.c:151
#define PRId64
Definition: inttypes.h:78
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
__int64 int64_t
Definition: stdint.h:89
unsigned __int64 uint64_t
Definition: stdint.h:90
int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq)
Definition: strip_time.c:506
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:515
struct DiskCacheFile * prev
Definition: disk_cache.c:93
char file[FILE_MAX]
Definition: disk_cache.c:96
struct DiskCacheFile * next
Definition: disk_cache.c:93
char path[FILE_MAX]
Definition: disk_cache.c:94
char dir[FILE_MAXDIR]
Definition: disk_cache.c:95
BLI_stat_t fstat
Definition: disk_cache.c:97
char colorspace_name[COLORSPACE_NAME_MAX]
Definition: disk_cache.c:77
uint64_t size_compressed
Definition: disk_cache.c:74
unsigned char encoding
Definition: disk_cache.c:72
DiskCacheHeaderEntry entry[DCACHE_IMAGES_PER_FILE]
Definition: disk_cache.c:81
int64_t disk_cache_timestamp
char name[66]
Definition: DNA_ID.h:378
int channels
unsigned int * rect
float * rect_float
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
char filepath[1024]
Definition: BKE_main.h:124
struct Editing * ed
float frame_index
Definition: image_cache.h:29
struct Sequence * seq
Definition: image_cache.h:27
struct SeqRenderData context
Definition: image_cache.h:28
int64_t timestamp
Definition: disk_cache.c:86
ThreadMutex read_write_mutex
Definition: disk_cache.c:88
Main * bmain
Definition: disk_cache.c:85
size_t size_total
Definition: disk_cache.c:89
ListBase files
Definition: disk_cache.c:87
int preview_render_size
Definition: SEQ_render.h:33
struct Scene * scene
Definition: SEQ_render.h:30
struct stat s
const char * path