Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/sequencer/intern')
-rw-r--r--source/blender/sequencer/intern/animation.c122
-rw-r--r--source/blender/sequencer/intern/clipboard.c22
-rw-r--r--source/blender/sequencer/intern/disk_cache.c699
-rw-r--r--source/blender/sequencer/intern/disk_cache.h56
-rw-r--r--source/blender/sequencer/intern/effects.c1430
-rw-r--r--source/blender/sequencer/intern/effects.h7
-rw-r--r--source/blender/sequencer/intern/image_cache.c672
-rw-r--r--source/blender/sequencer/intern/image_cache.h25
-rw-r--r--source/blender/sequencer/intern/iterator.c145
-rw-r--r--source/blender/sequencer/intern/modifier.c112
-rw-r--r--source/blender/sequencer/intern/multiview.c1
-rw-r--r--source/blender/sequencer/intern/multiview.h9
-rw-r--r--source/blender/sequencer/intern/prefetch.c23
-rw-r--r--source/blender/sequencer/intern/prefetch.h9
-rw-r--r--source/blender/sequencer/intern/proxy.c34
-rw-r--r--source/blender/sequencer/intern/proxy.h2
-rw-r--r--source/blender/sequencer/intern/render.c214
-rw-r--r--source/blender/sequencer/intern/render.h3
-rw-r--r--source/blender/sequencer/intern/sequence_lookup.c21
-rw-r--r--source/blender/sequencer/intern/sequencer.c192
-rw-r--r--source/blender/sequencer/intern/sequencer.h12
-rw-r--r--source/blender/sequencer/intern/sound.c21
-rw-r--r--source/blender/sequencer/intern/strip_add.c130
-rw-r--r--source/blender/sequencer/intern/strip_edit.c99
-rw-r--r--source/blender/sequencer/intern/strip_relations.c105
-rw-r--r--source/blender/sequencer/intern/strip_time.c130
-rw-r--r--source/blender/sequencer/intern/strip_time.h11
-rw-r--r--source/blender/sequencer/intern/strip_transform.c149
-rw-r--r--source/blender/sequencer/intern/utils.c43
-rw-r--r--source/blender/sequencer/intern/utils.h3
30 files changed, 1961 insertions, 2540 deletions
diff --git a/source/blender/sequencer/intern/animation.c b/source/blender/sequencer/intern/animation.c
new file mode 100644
index 00000000000..492b757a4b1
--- /dev/null
+++ b/source/blender/sequencer/intern/animation.c
@@ -0,0 +1,122 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2022 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup sequencer
+ */
+
+#include <string.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_fcurve.h"
+
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "DEG_depsgraph.h"
+
+#include "SEQ_animation.h"
+
+static bool seq_animation_curves_exist(Scene *scene)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL ||
+ BLI_listbase_is_empty(&scene->adt->action->curves)) {
+ return false;
+ }
+ return true;
+}
+
+/* r_prefix + [" + escaped_name + "] + \0 */
+#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1)
+
+static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name)
+{
+ char name_esc[SEQ_NAME_MAXSTR * 2];
+
+ BLI_str_escape(name_esc, name, sizeof(name_esc));
+ return BLI_snprintf_rlen(
+ str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
+}
+
+GSet *SEQ_fcurves_by_strip_get(const Sequence *seq, ListBase *fcurve_base)
+{
+ char rna_path[SEQ_RNAPATH_MAXSTR];
+ size_t rna_path_len = sequencer_rna_path_prefix(rna_path, seq->name + 2);
+
+ GSet *fcurves = BLI_gset_ptr_new(__func__);
+ LISTBASE_FOREACH (FCurve *, fcurve, fcurve_base) {
+ if (STREQLEN(fcurve->rna_path, rna_path, rna_path_len)) {
+ BLI_gset_add(fcurves, fcurve);
+ }
+ }
+
+ return fcurves;
+}
+
+#undef SEQ_RNAPATH_MAXSTR
+
+void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
+{
+ if (!seq_animation_curves_exist(scene) || ofs == 0) {
+ return;
+ }
+
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, &scene->adt->action->curves);
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ unsigned int i;
+ if (fcu->bezt) {
+ for (i = 0; i < fcu->totvert; i++) {
+ BezTriple *bezt = &fcu->bezt[i];
+ bezt->vec[0][0] += ofs;
+ bezt->vec[1][0] += ofs;
+ bezt->vec[2][0] += ofs;
+ }
+ }
+ if (fcu->fpt) {
+ for (i = 0; i < fcu->totvert; i++) {
+ FPoint *fpt = &fcu->fpt[i];
+ fpt->vec[0] += ofs;
+ }
+ }
+ }
+ GSET_FOREACH_END();
+ BLI_gset_free(fcurves, NULL);
+
+ DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION);
+}
+
+void SEQ_free_animdata(Scene *scene, Sequence *seq)
+{
+ if (!seq_animation_curves_exist(scene)) {
+ return;
+ }
+
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, &scene->adt->action->curves);
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ BLI_remlink(&scene->adt->action->curves, fcu);
+ BKE_fcurve_free(fcu);
+ }
+ GSET_FOREACH_END();
+ BLI_gset_free(fcurves, NULL);
+}
diff --git a/source/blender/sequencer/intern/clipboard.c b/source/blender/sequencer/intern/clipboard.c
index 05406c50303..886ee89595b 100644
--- a/source/blender/sequencer/intern/clipboard.c
+++ b/source/blender/sequencer/intern/clipboard.c
@@ -28,6 +28,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
@@ -35,6 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BKE_fcurve.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_scene.h"
@@ -58,6 +60,7 @@
*/
ListBase seqbase_clipboard;
+ListBase fcurves_clipboard;
int seqbase_clipboard_frame;
static char seq_clipboard_active_seq_name[SEQ_NAME_MAXSTR];
@@ -65,15 +68,17 @@ void seq_clipboard_pointers_free(struct ListBase *seqbase);
void SEQ_clipboard_free(void)
{
- Sequence *seq, *nseq;
-
seq_clipboard_pointers_free(&seqbase_clipboard);
- for (seq = seqbase_clipboard.first; seq; seq = nseq) {
- nseq = seq->next;
- seq_free_sequence_recurse(NULL, seq, false, true);
+ LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &seqbase_clipboard) {
+ seq_free_sequence_recurse(NULL, seq, false);
}
BLI_listbase_clear(&seqbase_clipboard);
+
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &fcurves_clipboard) {
+ BKE_fcurve_free(fcu);
+ }
+ BLI_listbase_clear(&fcurves_clipboard);
}
#define ID_PT (*id_pt)
@@ -194,13 +199,6 @@ void SEQ_clipboard_active_seq_name_store(Scene *scene)
}
}
-/**
- * Check if strip was active when it was copied. User should restrict this check to pasted strips
- * before ensuring original name, because strip name comparison is used to check.
- *
- * \param pasted_seq: Strip that is pasted(duplicated) from clipboard
- * \return true if strip was active, false otherwise
- */
bool SEQ_clipboard_pasted_seq_was_active(Sequence *pasted_seq)
{
return STREQ(pasted_seq->name, seq_clipboard_active_seq_name);
diff --git a/source/blender/sequencer/intern/disk_cache.c b/source/blender/sequencer/intern/disk_cache.c
new file mode 100644
index 00000000000..2db6a3cc8ee
--- /dev/null
+++ b/source/blender/sequencer/intern/disk_cache.c
@@ -0,0 +1,699 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup sequencer
+ */
+
+#include <memory.h>
+#include <stddef.h>
+#include <time.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_space_types.h" /* for FILE_MAX. */
+
+#include "IMB_colormanagement.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_endian_defines.h"
+#include "BLI_endian_switch.h"
+#include "BLI_fileops.h"
+#include "BLI_fileops_types.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_mempool.h"
+#include "BLI_path_util.h"
+#include "BLI_threads.h"
+
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "SEQ_prefetch.h"
+#include "SEQ_relations.h"
+#include "SEQ_render.h"
+#include "SEQ_sequencer.h"
+
+#include "disk_cache.h"
+#include "image_cache.h"
+#include "prefetch.h"
+#include "strip_time.h"
+
+/**
+ * Disk Cache Design Notes
+ * =======================
+ *
+ * Disk cache uses directory specified in user preferences
+ * For each cached non-temp image, image data and supplementary info are written to HDD.
+ * Multiple(DCACHE_IMAGES_PER_FILE) images share the same file.
+ * Each of these files contains header DiskCacheHeader followed by image data.
+ * Zlib compression with user definable level can be used to compress image data(per image)
+ * Images are written in order in which they are rendered.
+ * Overwriting of individual entry is not possible.
+ * Stored images are deleted by invalidation, or when size of all files exceeds maximum
+ * size specified in user preferences.
+ * To distinguish 2 blend files with same name, scene->ed->disk_cache_timestamp
+ * is used as UID. Blend file can still be copied manually which may cause conflict.
+ */
+
+/* Format string:
+ * `<cache type>-<resolution X>x<resolution Y>-<rendersize>%(<view_id>)-<frame no>.dcf`. */
+#define DCACHE_FNAME_FORMAT "%d-%dx%d-%d%%(%d)-%d.dcf"
+#define DCACHE_IMAGES_PER_FILE 100
+#define DCACHE_CURRENT_VERSION 2
+#define COLORSPACE_NAME_MAX 64 /* XXX: defined in IMB intern. */
+
+typedef struct DiskCacheHeaderEntry {
+ unsigned char encoding;
+ uint64_t frameno;
+ uint64_t size_compressed;
+ uint64_t size_raw;
+ uint64_t offset;
+ char colorspace_name[COLORSPACE_NAME_MAX];
+} DiskCacheHeaderEntry;
+
+typedef struct DiskCacheHeader {
+ DiskCacheHeaderEntry entry[DCACHE_IMAGES_PER_FILE];
+} DiskCacheHeader;
+
+typedef struct SeqDiskCache {
+ Main *bmain;
+ int64_t timestamp;
+ ListBase files;
+ ThreadMutex read_write_mutex;
+ size_t size_total;
+} SeqDiskCache;
+
+typedef struct DiskCacheFile {
+ struct DiskCacheFile *next, *prev;
+ char path[FILE_MAX];
+ char dir[FILE_MAXDIR];
+ char file[FILE_MAX];
+ BLI_stat_t fstat;
+ int cache_type;
+ int rectx;
+ int recty;
+ int render_size;
+ int view_id;
+ int start_frame;
+} DiskCacheFile;
+
+static ThreadMutex cache_create_lock = BLI_MUTEX_INITIALIZER;
+
+static char *seq_disk_cache_base_dir(void)
+{
+ return U.sequencer_disk_cache_dir;
+}
+
+static int seq_disk_cache_compression_level(void)
+{
+ switch (U.sequencer_disk_cache_compression) {
+ case USER_SEQ_DISK_CACHE_COMPRESSION_NONE:
+ return 0;
+ case USER_SEQ_DISK_CACHE_COMPRESSION_LOW:
+ return 1;
+ case USER_SEQ_DISK_CACHE_COMPRESSION_HIGH:
+ return 9;
+ }
+
+ return U.sequencer_disk_cache_compression;
+}
+
+static size_t seq_disk_cache_size_limit(void)
+{
+ return (size_t)U.sequencer_disk_cache_size_limit * (1024 * 1024 * 1024);
+}
+
+bool seq_disk_cache_is_enabled(Main *bmain)
+{
+ return (U.sequencer_disk_cache_dir[0] != '\0' && U.sequencer_disk_cache_size_limit != 0 &&
+ (U.sequencer_disk_cache_flag & SEQ_CACHE_DISK_CACHE_ENABLE) != 0 &&
+ bmain->filepath[0] != '\0');
+}
+
+static DiskCacheFile *seq_disk_cache_add_file_to_list(SeqDiskCache *disk_cache, const char *path)
+{
+
+ DiskCacheFile *cache_file = MEM_callocN(sizeof(DiskCacheFile), "SeqDiskCacheFile");
+ char dir[FILE_MAXDIR], file[FILE_MAX];
+ BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
+ BLI_strncpy(cache_file->path, path, sizeof(cache_file->path));
+ BLI_strncpy(cache_file->dir, dir, sizeof(cache_file->dir));
+ BLI_strncpy(cache_file->file, file, sizeof(cache_file->file));
+ sscanf(file,
+ DCACHE_FNAME_FORMAT,
+ &cache_file->cache_type,
+ &cache_file->rectx,
+ &cache_file->recty,
+ &cache_file->render_size,
+ &cache_file->view_id,
+ &cache_file->start_frame);
+ cache_file->start_frame *= DCACHE_IMAGES_PER_FILE;
+ BLI_addtail(&disk_cache->files, cache_file);
+ return cache_file;
+}
+
+static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
+{
+ struct direntry *filelist, *fl;
+ uint nbr, i;
+ disk_cache->size_total = 0;
+
+ i = nbr = BLI_filelist_dir_contents(path, &filelist);
+ fl = filelist;
+ while (i--) {
+ /* Don't follow links. */
+ const eFileAttributes file_attrs = BLI_file_attributes(fl->path);
+ if (file_attrs & FILE_ATTR_ANY_LINK) {
+ fl++;
+ continue;
+ }
+
+ char file[FILE_MAX];
+ BLI_split_dirfile(fl->path, NULL, file, 0, sizeof(file));
+
+ bool is_dir = BLI_is_dir(fl->path);
+ if (is_dir && !FILENAME_IS_CURRPAR(file)) {
+ char subpath[FILE_MAX];
+ BLI_strncpy(subpath, fl->path, sizeof(subpath));
+ BLI_path_slash_ensure(subpath);
+ seq_disk_cache_get_files(disk_cache, subpath);
+ }
+
+ if (!is_dir) {
+ const char *ext = BLI_path_extension(fl->path);
+ if (ext && ext[1] == 'd' && ext[2] == 'c' && ext[3] == 'f') {
+ DiskCacheFile *cache_file = seq_disk_cache_add_file_to_list(disk_cache, fl->path);
+ cache_file->fstat = fl->s;
+ disk_cache->size_total += cache_file->fstat.st_size;
+ }
+ }
+ fl++;
+ }
+ BLI_filelist_free(filelist, nbr);
+}
+
+static DiskCacheFile *seq_disk_cache_get_oldest_file(SeqDiskCache *disk_cache)
+{
+ DiskCacheFile *oldest_file = disk_cache->files.first;
+ if (oldest_file == NULL) {
+ return NULL;
+ }
+ for (DiskCacheFile *cache_file = oldest_file->next; cache_file; cache_file = cache_file->next) {
+ if (cache_file->fstat.st_mtime < oldest_file->fstat.st_mtime) {
+ oldest_file = cache_file;
+ }
+ }
+
+ return oldest_file;
+}
+
+static void seq_disk_cache_delete_file(SeqDiskCache *disk_cache, DiskCacheFile *file)
+{
+ disk_cache->size_total -= file->fstat.st_size;
+ BLI_delete(file->path, false, false);
+ BLI_remlink(&disk_cache->files, file);
+ MEM_freeN(file);
+}
+
+bool seq_disk_cache_enforce_limits(SeqDiskCache *disk_cache)
+{
+ BLI_mutex_lock(&disk_cache->read_write_mutex);
+ while (disk_cache->size_total > seq_disk_cache_size_limit()) {
+ DiskCacheFile *oldest_file = seq_disk_cache_get_oldest_file(disk_cache);
+
+ if (!oldest_file) {
+ /* We shouldn't enforce limits with no files, do re-scan. */
+ seq_disk_cache_get_files(disk_cache, seq_disk_cache_base_dir());
+ continue;
+ }
+
+ if (BLI_exists(oldest_file->path) == 0) {
+ /* File may have been manually deleted during runtime, do re-scan. */
+ BLI_freelistN(&disk_cache->files);
+ seq_disk_cache_get_files(disk_cache, seq_disk_cache_base_dir());
+ continue;
+ }
+
+ seq_disk_cache_delete_file(disk_cache, oldest_file);
+ }
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+
+ return true;
+}
+
+static DiskCacheFile *seq_disk_cache_get_file_entry_by_path(SeqDiskCache *disk_cache, char *path)
+{
+ DiskCacheFile *cache_file = disk_cache->files.first;
+
+ for (; cache_file; cache_file = cache_file->next) {
+ if (BLI_strcasecmp(cache_file->path, path) == 0) {
+ return cache_file;
+ }
+ }
+
+ return NULL;
+}
+
+/* Update file size and timestamp. */
+static void seq_disk_cache_update_file(SeqDiskCache *disk_cache, char *path)
+{
+ DiskCacheFile *cache_file;
+ int64_t size_before;
+ int64_t size_after;
+
+ cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
+ size_before = cache_file->fstat.st_size;
+
+ if (BLI_stat(path, &cache_file->fstat) == -1) {
+ BLI_assert(false);
+ memset(&cache_file->fstat, 0, sizeof(BLI_stat_t));
+ }
+
+ size_after = cache_file->fstat.st_size;
+ disk_cache->size_total += size_after - size_before;
+}
+
+/* Path format:
+ * <cache dir>/<project name>_seq_cache/<scene name>-<timestamp>/<seq name>/DCACHE_FNAME_FORMAT
+ */
+
+static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, size_t path_len)
+{
+ char cache_dir[FILE_MAX];
+ BLI_split_file_part(BKE_main_blendfile_path(disk_cache->bmain), cache_dir, sizeof(cache_dir));
+ /* Use suffix, so that the cache directory name does not conflict with the bmain's blend file. */
+ const char *suffix = "_seq_cache";
+ strncat(cache_dir, suffix, sizeof(cache_dir) - strlen(cache_dir) - 1);
+ BLI_strncpy(path, seq_disk_cache_base_dir(), path_len);
+ BLI_path_append(path, path_len, cache_dir);
+}
+
+static void seq_disk_cache_get_dir(
+ SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, char *path, size_t path_len)
+{
+ char scene_name[MAX_ID_NAME + 22]; /* + -%PRId64 */
+ char seq_name[SEQ_NAME_MAXSTR];
+ char project_dir[FILE_MAX];
+
+ seq_disk_cache_get_project_dir(disk_cache, project_dir, sizeof(project_dir));
+ sprintf(scene_name, "%s-%" PRId64, scene->id.name, disk_cache->timestamp);
+ BLI_strncpy(seq_name, seq->name, sizeof(seq_name));
+ BLI_filename_make_safe(scene_name);
+ BLI_filename_make_safe(seq_name);
+ BLI_strncpy(path, project_dir, path_len);
+ BLI_path_append(path, path_len, scene_name);
+ BLI_path_append(path, path_len, seq_name);
+}
+
+static void seq_disk_cache_get_file_path(SeqDiskCache *disk_cache,
+ SeqCacheKey *key,
+ char *path,
+ size_t path_len)
+{
+ seq_disk_cache_get_dir(disk_cache, key->context.scene, key->seq, path, path_len);
+ int frameno = (int)key->frame_index / DCACHE_IMAGES_PER_FILE;
+ char cache_filename[FILE_MAXFILE];
+ sprintf(cache_filename,
+ DCACHE_FNAME_FORMAT,
+ key->type,
+ key->context.rectx,
+ key->context.recty,
+ key->context.preview_render_size,
+ key->context.view_id,
+ frameno);
+
+ BLI_path_append(path, path_len, cache_filename);
+}
+
+static void seq_disk_cache_create_version_file(char *path)
+{
+ BLI_make_existing_file(path);
+
+ FILE *file = BLI_fopen(path, "w");
+ if (file) {
+ fprintf(file, "%d", DCACHE_CURRENT_VERSION);
+ fclose(file);
+ }
+}
+
+static void seq_disk_cache_handle_versioning(SeqDiskCache *disk_cache)
+{
+ char path[FILE_MAX];
+ char path_version_file[FILE_MAX];
+ int version = 0;
+
+ seq_disk_cache_get_project_dir(disk_cache, path, sizeof(path));
+ BLI_strncpy(path_version_file, path, sizeof(path_version_file));
+ BLI_path_append(path_version_file, sizeof(path_version_file), "cache_version");
+
+ if (BLI_exists(path) && BLI_is_dir(path)) {
+ FILE *file = BLI_fopen(path_version_file, "r");
+
+ if (file) {
+ const int num_items_read = fscanf(file, "%d", &version);
+ if (num_items_read == 0) {
+ version = -1;
+ }
+ fclose(file);
+ }
+
+ if (version != DCACHE_CURRENT_VERSION) {
+ BLI_delete(path, false, true);
+ seq_disk_cache_create_version_file(path_version_file);
+ }
+ }
+ else {
+ seq_disk_cache_create_version_file(path_version_file);
+ }
+}
+
+static void seq_disk_cache_delete_invalid_files(SeqDiskCache *disk_cache,
+ Scene *scene,
+ Sequence *seq,
+ int invalidate_types,
+ int range_start,
+ int range_end)
+{
+ DiskCacheFile *next_file, *cache_file = disk_cache->files.first;
+ char cache_dir[FILE_MAX];
+ seq_disk_cache_get_dir(disk_cache, scene, seq, cache_dir, sizeof(cache_dir));
+ BLI_path_slash_ensure(cache_dir);
+
+ while (cache_file) {
+ next_file = cache_file->next;
+ if (cache_file->cache_type & invalidate_types) {
+ if (STREQ(cache_dir, cache_file->dir)) {
+ int timeline_frame_start = seq_cache_frame_index_to_timeline_frame(
+ seq, cache_file->start_frame);
+ if (timeline_frame_start > range_start && timeline_frame_start <= range_end) {
+ seq_disk_cache_delete_file(disk_cache, cache_file);
+ }
+ }
+ }
+ cache_file = next_file;
+ }
+}
+
+void seq_disk_cache_invalidate(SeqDiskCache *disk_cache,
+ Scene *scene,
+ Sequence *seq,
+ Sequence *seq_changed,
+ int invalidate_types)
+{
+ int start;
+ int end;
+
+ BLI_mutex_lock(&disk_cache->read_write_mutex);
+
+ start = seq_changed->startdisp - DCACHE_IMAGES_PER_FILE;
+ end = seq_changed->enddisp;
+
+ seq_disk_cache_delete_invalid_files(disk_cache, scene, seq, invalidate_types, start, end);
+
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+}
+
+static size_t deflate_imbuf_to_file(ImBuf *ibuf,
+ FILE *file,
+ int level,
+ DiskCacheHeaderEntry *header_entry)
+{
+ void *data = (ibuf->rect != NULL) ? (void *)ibuf->rect : (void *)ibuf->rect_float;
+
+ /* Apply compression if wanted, otherwise just write directly to the file. */
+ if (level > 0) {
+ return BLI_file_zstd_from_mem_at_pos(
+ data, header_entry->size_raw, file, header_entry->offset, level);
+ }
+
+ fseek(file, header_entry->offset, SEEK_SET);
+ return fwrite(data, 1, header_entry->size_raw, file);
+}
+
+static size_t inflate_file_to_imbuf(ImBuf *ibuf, FILE *file, DiskCacheHeaderEntry *header_entry)
+{
+ void *data = (ibuf->rect != NULL) ? (void *)ibuf->rect : (void *)ibuf->rect_float;
+ char header[4];
+ fseek(file, header_entry->offset, SEEK_SET);
+ if (fread(header, 1, sizeof(header), file) != sizeof(header)) {
+ return 0;
+ }
+
+ /* Check if the data is compressed or raw. */
+ if (BLI_file_magic_is_zstd(header)) {
+ return BLI_file_unzstd_to_mem_at_pos(data, header_entry->size_raw, file, header_entry->offset);
+ }
+
+ fseek(file, header_entry->offset, SEEK_SET);
+ return fread(data, 1, header_entry->size_raw, file);
+}
+
+static bool seq_disk_cache_read_header(FILE *file, DiskCacheHeader *header)
+{
+ BLI_fseek(file, 0LL, SEEK_SET);
+ const size_t num_items_read = fread(header, sizeof(*header), 1, file);
+ if (num_items_read < 1) {
+ BLI_assert_msg(0, "unable to read disk cache header");
+ perror("unable to read disk cache header");
+ return false;
+ }
+
+ for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
+ if ((ENDIAN_ORDER == B_ENDIAN) && header->entry[i].encoding == 0) {
+ BLI_endian_switch_uint64(&header->entry[i].frameno);
+ BLI_endian_switch_uint64(&header->entry[i].offset);
+ BLI_endian_switch_uint64(&header->entry[i].size_compressed);
+ BLI_endian_switch_uint64(&header->entry[i].size_raw);
+ }
+ }
+
+ return true;
+}
+
+static size_t seq_disk_cache_write_header(FILE *file, DiskCacheHeader *header)
+{
+ BLI_fseek(file, 0LL, SEEK_SET);
+ return fwrite(header, sizeof(*header), 1, file);
+}
+
+static int seq_disk_cache_add_header_entry(SeqCacheKey *key, ImBuf *ibuf, DiskCacheHeader *header)
+{
+ int i;
+ uint64_t offset = sizeof(*header);
+
+ /* Lookup free entry, get offset for new data. */
+ for (i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
+ if (header->entry[i].size_compressed == 0) {
+ break;
+ }
+ }
+
+ /* Attempt to write beyond set entry limit.
+ * Reset file header and start writing from beginning.
+ */
+ if (i == DCACHE_IMAGES_PER_FILE) {
+ i = 0;
+ memset(header, 0, sizeof(*header));
+ }
+
+ /* Calculate offset for image data. */
+ if (i > 0) {
+ offset = header->entry[i - 1].offset + header->entry[i - 1].size_compressed;
+ }
+
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ header->entry[i].encoding = 255;
+ }
+ else {
+ header->entry[i].encoding = 0;
+ }
+
+ header->entry[i].offset = offset;
+ header->entry[i].frameno = key->frame_index;
+
+ /* Store colorspace name of ibuf. */
+ const char *colorspace_name;
+ if (ibuf->rect) {
+ header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels;
+ colorspace_name = IMB_colormanagement_get_rect_colorspace(ibuf);
+ }
+ else {
+ header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels * 4;
+ colorspace_name = IMB_colormanagement_get_float_colorspace(ibuf);
+ }
+ BLI_strncpy(
+ header->entry[i].colorspace_name, colorspace_name, sizeof(header->entry[i].colorspace_name));
+
+ return i;
+}
+
+static int seq_disk_cache_get_header_entry(SeqCacheKey *key, DiskCacheHeader *header)
+{
+ for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
+ if (header->entry[i].frameno == key->frame_index) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+bool seq_disk_cache_write_file(SeqDiskCache *disk_cache, SeqCacheKey *key, ImBuf *ibuf)
+{
+ BLI_mutex_lock(&disk_cache->read_write_mutex);
+
+ char path[FILE_MAX];
+
+ seq_disk_cache_get_file_path(disk_cache, key, path, sizeof(path));
+ BLI_make_existing_file(path);
+
+ FILE *file = BLI_fopen(path, "rb+");
+ if (!file) {
+ file = BLI_fopen(path, "wb+");
+ if (!file) {
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return false;
+ }
+ seq_disk_cache_add_file_to_list(disk_cache, path);
+ }
+
+ DiskCacheFile *cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
+ DiskCacheHeader header;
+ memset(&header, 0, sizeof(header));
+ /* #BLI_make_existing_file() above may create an empty file. This is fine, don't attempt reading
+ * the header in that case. */
+ if (cache_file->fstat.st_size != 0 && !seq_disk_cache_read_header(file, &header)) {
+ fclose(file);
+ seq_disk_cache_delete_file(disk_cache, cache_file);
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return false;
+ }
+ int entry_index = seq_disk_cache_add_header_entry(key, ibuf, &header);
+
+ size_t bytes_written = deflate_imbuf_to_file(
+ ibuf, file, seq_disk_cache_compression_level(), &header.entry[entry_index]);
+
+ if (bytes_written != 0) {
+ /* Last step is writing header, as image data can be overwritten,
+ * but missing data would cause problems.
+ */
+ header.entry[entry_index].size_compressed = bytes_written;
+ seq_disk_cache_write_header(file, &header);
+ seq_disk_cache_update_file(disk_cache, path);
+ fclose(file);
+
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return true;
+ }
+
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return false;
+}
+
+ImBuf *seq_disk_cache_read_file(SeqDiskCache *disk_cache, SeqCacheKey *key)
+{
+ BLI_mutex_lock(&disk_cache->read_write_mutex);
+
+ char path[FILE_MAX];
+ DiskCacheHeader header;
+
+ seq_disk_cache_get_file_path(disk_cache, key, path, sizeof(path));
+ BLI_make_existing_file(path);
+
+ FILE *file = BLI_fopen(path, "rb");
+ if (!file) {
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return NULL;
+ }
+
+ if (!seq_disk_cache_read_header(file, &header)) {
+ fclose(file);
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return NULL;
+ }
+ int entry_index = seq_disk_cache_get_header_entry(key, &header);
+
+ /* Item not found. */
+ if (entry_index < 0) {
+ fclose(file);
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return NULL;
+ }
+
+ ImBuf *ibuf;
+ uint64_t size_char = (uint64_t)key->context.rectx * key->context.recty * 4;
+ uint64_t size_float = (uint64_t)key->context.rectx * key->context.recty * 16;
+ size_t expected_size;
+
+ if (header.entry[entry_index].size_raw == size_char) {
+ expected_size = size_char;
+ ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rect);
+ IMB_colormanagement_assign_rect_colorspace(ibuf, header.entry[entry_index].colorspace_name);
+ }
+ else if (header.entry[entry_index].size_raw == size_float) {
+ expected_size = size_float;
+ ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rectfloat);
+ IMB_colormanagement_assign_float_colorspace(ibuf, header.entry[entry_index].colorspace_name);
+ }
+ else {
+ fclose(file);
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return NULL;
+ }
+
+ size_t bytes_read = inflate_file_to_imbuf(ibuf, file, &header.entry[entry_index]);
+
+ /* Sanity check. */
+ if (bytes_read != expected_size) {
+ fclose(file);
+ IMB_freeImBuf(ibuf);
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return NULL;
+ }
+ BLI_file_touch(path);
+ seq_disk_cache_update_file(disk_cache, path);
+ fclose(file);
+
+ BLI_mutex_unlock(&disk_cache->read_write_mutex);
+ return ibuf;
+}
+
+SeqDiskCache *seq_disk_cache_create(Main *bmain, Scene *scene)
+{
+ SeqDiskCache *disk_cache = MEM_callocN(sizeof(SeqDiskCache), "SeqDiskCache");
+ disk_cache->bmain = bmain;
+ BLI_mutex_init(&disk_cache->read_write_mutex);
+ seq_disk_cache_handle_versioning(disk_cache);
+ seq_disk_cache_get_files(disk_cache, seq_disk_cache_base_dir());
+ disk_cache->timestamp = scene->ed->disk_cache_timestamp;
+ BLI_mutex_unlock(&cache_create_lock);
+ return disk_cache;
+}
+
+void seq_disk_cache_free(SeqDiskCache *disk_cache)
+{
+ BLI_freelistN(&disk_cache->files);
+ BLI_mutex_end(&disk_cache->read_write_mutex);
+ MEM_freeN(disk_cache);
+}
diff --git a/source/blender/sequencer/intern/disk_cache.h b/source/blender/sequencer/intern/disk_cache.h
new file mode 100644
index 00000000000..a84bfaf5ea0
--- /dev/null
+++ b/source/blender/sequencer/intern/disk_cache.h
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup sequencer
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup sequencer
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ImBuf;
+struct Main;
+struct Scene;
+struct SeqCacheKey;
+struct SeqDiskCache;
+struct Sequence;
+
+struct SeqDiskCache *seq_disk_cache_create(struct Main *bmain, struct Scene *scene);
+void seq_disk_cache_free(struct SeqDiskCache *disk_cache);
+bool seq_disk_cache_is_enabled(struct Main *bmain);
+struct ImBuf *seq_disk_cache_read_file(struct SeqDiskCache *disk_cache, struct SeqCacheKey *key);
+bool seq_disk_cache_write_file(struct SeqDiskCache *disk_cache,
+ struct SeqCacheKey *key,
+ struct ImBuf *ibuf);
+bool seq_disk_cache_enforce_limits(struct SeqDiskCache *disk_cache);
+void seq_disk_cache_invalidate(struct SeqDiskCache *disk_cache,
+ struct Scene *scene,
+ struct Sequence *seq,
+ struct Sequence *seq_changed,
+ int invalidate_types);
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index 427a8835879..a35e83a8632 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -206,69 +206,22 @@ static void init_alpha_over_or_under(Sequence *seq)
seq->seq1 = seq2;
}
-static void do_alphaover_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
-{
- float fac2, mfac, fac, fac4;
- int xo;
- unsigned char *cp1, *cp2, *rt;
- float tempc[4], rt1[4], rt2[4];
-
- xo = x;
- cp1 = rect1;
- cp2 = rect2;
- rt = out;
-
- fac2 = facf0;
- fac4 = facf1;
-
- while (y--) {
- x = xo;
- while (x--) {
- /* rt = rt1 over rt2 (alpha from rt1) */
-
- straight_uchar_to_premul_float(rt1, cp1);
- straight_uchar_to_premul_float(rt2, cp2);
-
- fac = fac2;
- mfac = 1.0f - fac2 * rt1[3];
-
- if (fac <= 0.0f) {
- *((unsigned int *)rt) = *((unsigned int *)cp2);
- }
- else if (mfac <= 0.0f) {
- *((unsigned int *)rt) = *((unsigned int *)cp1);
- }
- else {
- tempc[0] = fac * rt1[0] + mfac * rt2[0];
- tempc[1] = fac * rt1[1] + mfac * rt2[1];
- tempc[2] = fac * rt1[2] + mfac * rt2[2];
- tempc[3] = fac * rt1[3] + mfac * rt2[3];
-
- premul_float_to_straight_uchar(rt, tempc);
- }
- cp1 += 4;
- cp2 += 4;
- rt += 4;
- }
+static void do_alphaover_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
+{
+ unsigned char *cp1 = rect1;
+ unsigned char *cp2 = rect2;
+ unsigned char *rt = out;
- if (y == 0) {
- break;
- }
- y--;
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ /* rt = rt1 over rt2 (alpha from rt1) */
- x = xo;
- while (x--) {
+ float tempc[4], rt1[4], rt2[4];
straight_uchar_to_premul_float(rt1, cp1);
straight_uchar_to_premul_float(rt2, cp2);
- fac = fac4;
- mfac = 1.0f - (fac4 * rt1[3]);
+ float mfac = 1.0f - fac * rt1[3];
if (fac <= 0.0f) {
*((unsigned int *)rt) = *((unsigned int *)cp2);
@@ -292,27 +245,17 @@ static void do_alphaover_effect_byte(float facf0,
}
static void do_alphaover_effect_float(
- float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
+ float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- float fac2, mfac, fac, fac4;
- int xo;
- float *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
-
- fac2 = facf0;
- fac4 = facf1;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- while (y--) {
- x = xo;
- while (x--) {
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
/* rt = rt1 over rt2 (alpha from rt1) */
- fac = fac2;
- mfac = 1.0f - (fac2 * rt1[3]);
+ float mfac = 1.0f - (fac * rt1[3]);
if (fac <= 0.0f) {
memcpy(rt, rt2, sizeof(float[4]));
@@ -330,41 +273,13 @@ static void do_alphaover_effect_float(
rt2 += 4;
rt += 4;
}
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- fac = fac4;
- mfac = 1.0f - (fac4 * rt1[3]);
-
- if (fac <= 0.0f) {
- memcpy(rt, rt2, sizeof(float[4]));
- }
- else if (mfac <= 0.0f) {
- memcpy(rt, rt1, sizeof(float[4]));
- }
- else {
- rt[0] = fac * rt1[0] + mfac * rt2[0];
- rt[1] = fac * rt1[1] + mfac * rt2[1];
- rt[2] = fac * rt1[2] + mfac * rt2[2];
- rt[3] = fac * rt1[3] + mfac * rt2[3];
- }
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
}
}
static void do_alphaover_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -378,7 +293,7 @@ static void do_alphaover_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_alphaover_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_alphaover_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -386,96 +301,47 @@ static void do_alphaover_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_alphaover_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_alphaover_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
/*********************** Alpha Under *************************/
-static void do_alphaunder_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
-{
- float fac2, fac, fac4;
- int xo;
- unsigned char *cp1, *cp2, *rt;
- float tempc[4], rt1[4], rt2[4];
-
- xo = x;
- cp1 = rect1;
- cp2 = rect2;
- rt = out;
-
- fac2 = facf0;
- fac4 = facf1;
-
- while (y--) {
- x = xo;
- while (x--) {
+static void do_alphaunder_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
+{
+ unsigned char *cp1 = rect1;
+ unsigned char *cp2 = rect2;
+ unsigned char *rt = out;
+
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
/* rt = rt1 under rt2 (alpha from rt2) */
+
+ float tempc[4], rt1[4], rt2[4];
straight_uchar_to_premul_float(rt1, cp1);
straight_uchar_to_premul_float(rt2, cp2);
/* this complex optimization is because the
* 'skybuf' can be crossed in
*/
- if (rt2[3] <= 0.0f && fac2 >= 1.0f) {
+ if (rt2[3] <= 0.0f && fac >= 1.0f) {
*((unsigned int *)rt) = *((unsigned int *)cp1);
}
else if (rt2[3] >= 1.0f) {
*((unsigned int *)rt) = *((unsigned int *)cp2);
}
else {
- fac = (fac2 * (1.0f - rt2[3]));
+ float temp_fac = (fac * (1.0f - rt2[3]));
if (fac <= 0) {
*((unsigned int *)rt) = *((unsigned int *)cp2);
}
else {
- tempc[0] = (fac * rt1[0] + rt2[0]);
- tempc[1] = (fac * rt1[1] + rt2[1]);
- tempc[2] = (fac * rt1[2] + rt2[2]);
- tempc[3] = (fac * rt1[3] + rt2[3]);
-
- premul_float_to_straight_uchar(rt, tempc);
- }
- }
- cp1 += 4;
- cp2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- straight_uchar_to_premul_float(rt1, cp1);
- straight_uchar_to_premul_float(rt2, cp2);
-
- if (rt2[3] <= 0.0f && fac4 >= 1.0f) {
- *((unsigned int *)rt) = *((unsigned int *)cp1);
- }
- else if (rt2[3] >= 1.0f) {
- *((unsigned int *)rt) = *((unsigned int *)cp2);
- }
- else {
- fac = (fac4 * (1.0f - rt2[3]));
-
- if (fac <= 0) {
- *((unsigned int *)rt) = *((unsigned int *)cp2);
- }
- else {
- tempc[0] = (fac * rt1[0] + rt2[0]);
- tempc[1] = (fac * rt1[1] + rt2[1]);
- tempc[2] = (fac * rt1[2] + rt2[2]);
- tempc[3] = (fac * rt1[3] + rt2[3]);
+ tempc[0] = (temp_fac * rt1[0] + rt2[0]);
+ tempc[1] = (temp_fac * rt1[1] + rt2[1]);
+ tempc[2] = (temp_fac * rt1[2] + rt2[2]);
+ tempc[3] = (temp_fac * rt1[3] + rt2[3]);
premul_float_to_straight_uchar(rt, tempc);
}
@@ -488,76 +354,36 @@ static void do_alphaunder_effect_byte(float facf0,
}
static void do_alphaunder_effect_float(
- float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
+ float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- float fac2, fac, fac4;
- int xo;
- float *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- fac2 = facf0;
- fac4 = facf1;
-
- while (y--) {
- x = xo;
- while (x--) {
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
/* rt = rt1 under rt2 (alpha from rt2) */
/* this complex optimization is because the
* 'skybuf' can be crossed in
*/
- if (rt2[3] <= 0 && fac2 >= 1.0f) {
+ if (rt2[3] <= 0 && fac >= 1.0f) {
memcpy(rt, rt1, sizeof(float[4]));
}
else if (rt2[3] >= 1.0f) {
memcpy(rt, rt2, sizeof(float[4]));
}
else {
- fac = fac2 * (1.0f - rt2[3]);
+ float temp_fac = fac * (1.0f - rt2[3]);
if (fac == 0) {
memcpy(rt, rt2, sizeof(float[4]));
}
else {
- rt[0] = fac * rt1[0] + rt2[0];
- rt[1] = fac * rt1[1] + rt2[1];
- rt[2] = fac * rt1[2] + rt2[2];
- rt[3] = fac * rt1[3] + rt2[3];
- }
- }
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- if (rt2[3] <= 0 && fac4 >= 1.0f) {
- memcpy(rt, rt1, sizeof(float[4]));
- }
- else if (rt2[3] >= 1.0f) {
- memcpy(rt, rt2, sizeof(float[4]));
- }
- else {
- fac = fac4 * (1.0f - rt2[3]);
-
- if (fac == 0) {
- memcpy(rt, rt2, sizeof(float[4]));
- }
- else {
- rt[0] = fac * rt1[0] + rt2[0];
- rt[1] = fac * rt1[1] + rt2[1];
- rt[2] = fac * rt1[2] + rt2[2];
- rt[3] = fac * rt1[3] + rt2[3];
+ rt[0] = temp_fac * rt1[0] + rt2[0];
+ rt[1] = temp_fac * rt1[1] + rt2[1];
+ rt[2] = temp_fac * rt1[2] + rt2[2];
+ rt[3] = temp_fac * rt1[3] + rt2[3];
}
}
rt1 += 4;
@@ -570,8 +396,7 @@ static void do_alphaunder_effect_float(
static void do_alphaunder_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -585,7 +410,7 @@ static void do_alphaunder_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_alphaunder_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_alphaunder_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -593,58 +418,28 @@ static void do_alphaunder_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_alphaunder_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_alphaunder_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
/*********************** Cross *************************/
-static void do_cross_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
+static void do_cross_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
- int fac1, fac2, fac3, fac4;
- int xo;
- unsigned char *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
+ unsigned char *rt1 = rect1;
+ unsigned char *rt2 = rect2;
+ unsigned char *rt = out;
- fac2 = (int)(256.0f * facf0);
- fac1 = 256 - fac2;
- fac4 = (int)(256.0f * facf1);
- fac3 = 256 - fac4;
+ int temp_fac = (int)(256.0f * fac);
+ int temp_mfac = 256 - temp_fac;
- while (y--) {
- x = xo;
- while (x--) {
- rt[0] = (fac1 * rt1[0] + fac2 * rt2[0]) >> 8;
- rt[1] = (fac1 * rt1[1] + fac2 * rt2[1]) >> 8;
- rt[2] = (fac1 * rt1[2] + fac2 * rt2[2]) >> 8;
- rt[3] = (fac1 * rt1[3] + fac2 * rt2[3]) >> 8;
-
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- rt[0] = (fac3 * rt1[0] + fac4 * rt2[0]) >> 8;
- rt[1] = (fac3 * rt1[1] + fac4 * rt2[1]) >> 8;
- rt[2] = (fac3 * rt1[2] + fac4 * rt2[2]) >> 8;
- rt[3] = (fac3 * rt1[3] + fac4 * rt2[3]) >> 8;
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ rt[0] = (temp_mfac * rt1[0] + temp_fac * rt2[0]) >> 8;
+ rt[1] = (temp_mfac * rt1[1] + temp_fac * rt2[1]) >> 8;
+ rt[2] = (temp_mfac * rt1[2] + temp_fac * rt2[2]) >> 8;
+ rt[3] = (temp_mfac * rt1[3] + temp_fac * rt2[3]) >> 8;
rt1 += 4;
rt2 += 4;
@@ -653,47 +448,20 @@ static void do_cross_effect_byte(float facf0,
}
}
-static void do_cross_effect_float(
- float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
+static void do_cross_effect_float(float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- float fac1, fac2, fac3, fac4;
- int xo;
- float *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- fac2 = facf0;
- fac1 = 1.0f - fac2;
- fac4 = facf1;
- fac3 = 1.0f - fac4;
+ float mfac = 1.0f - fac;
- while (y--) {
- x = xo;
- while (x--) {
- rt[0] = fac1 * rt1[0] + fac2 * rt2[0];
- rt[1] = fac1 * rt1[1] + fac2 * rt2[1];
- rt[2] = fac1 * rt1[2] + fac2 * rt2[2];
- rt[3] = fac1 * rt1[3] + fac2 * rt2[3];
-
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- rt[0] = fac3 * rt1[0] + fac4 * rt2[0];
- rt[1] = fac3 * rt1[1] + fac4 * rt2[1];
- rt[2] = fac3 * rt1[2] + fac4 * rt2[2];
- rt[3] = fac3 * rt1[3] + fac4 * rt2[3];
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ rt[0] = mfac * rt1[0] + fac * rt2[0];
+ rt[1] = mfac * rt1[1] + fac * rt2[1];
+ rt[2] = mfac * rt1[2] + fac * rt2[2];
+ rt[3] = mfac * rt1[3] + fac * rt2[3];
rt1 += 4;
rt2 += 4;
@@ -705,8 +473,7 @@ static void do_cross_effect_float(
static void do_cross_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -720,7 +487,7 @@ static void do_cross_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_cross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_cross_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -728,7 +495,7 @@ static void do_cross_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_cross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_cross_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
@@ -888,58 +655,26 @@ static void free_gammacross(Sequence *UNUSED(seq), const bool UNUSED(do_id_user)
{
}
-static void do_gammacross_effect_byte(float facf0,
- float UNUSED(facf1),
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
+static void do_gammacross_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
- float fac1, fac2;
- int xo;
- unsigned char *cp1, *cp2, *rt;
- float rt1[4], rt2[4], tempc[4];
-
- xo = x;
- cp1 = rect1;
- cp2 = rect2;
- rt = out;
-
- fac2 = facf0;
- fac1 = 1.0f - fac2;
-
- while (y--) {
- x = xo;
- while (x--) {
- straight_uchar_to_premul_float(rt1, cp1);
- straight_uchar_to_premul_float(rt2, cp2);
+ unsigned char *cp1 = rect1;
+ unsigned char *cp2 = rect2;
+ unsigned char *rt = out;
- tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
- tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
- tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
- tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
-
- premul_float_to_straight_uchar(rt, tempc);
- cp1 += 4;
- cp2 += 4;
- rt += 4;
- }
+ float mfac = 1.0f - fac;
- if (y == 0) {
- break;
- }
- y--;
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ float rt1[4], rt2[4], tempc[4];
- x = xo;
- while (x--) {
straight_uchar_to_premul_float(rt1, cp1);
straight_uchar_to_premul_float(rt2, cp2);
- tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
- tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
- tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
- tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+ tempc[0] = gammaCorrect(mfac * invGammaCorrect(rt1[0]) + fac * invGammaCorrect(rt2[0]));
+ tempc[1] = gammaCorrect(mfac * invGammaCorrect(rt1[1]) + fac * invGammaCorrect(rt2[1]));
+ tempc[2] = gammaCorrect(mfac * invGammaCorrect(rt1[2]) + fac * invGammaCorrect(rt2[2]));
+ tempc[3] = gammaCorrect(mfac * invGammaCorrect(rt1[3]) + fac * invGammaCorrect(rt2[3]));
premul_float_to_straight_uchar(rt, tempc);
cp1 += 4;
@@ -950,38 +685,17 @@ static void do_gammacross_effect_byte(float facf0,
}
static void do_gammacross_effect_float(
- float facf0, float UNUSED(facf1), int x, int y, float *rect1, float *rect2, float *out)
+ float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- float fac1, fac2;
- int xo;
- float *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- fac2 = facf0;
- fac1 = 1.0f - fac2;
-
- while (y--) {
- x = xo * 4;
- while (x--) {
- *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
- rt1++;
- rt2++;
- rt++;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo * 4;
- while (x--) {
- *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
+ float mfac = 1.0f - fac;
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ *rt = gammaCorrect(mfac * invGammaCorrect(*rt1) + fac * invGammaCorrect(*rt2));
rt1++;
rt2++;
rt++;
@@ -1003,8 +717,7 @@ static struct ImBuf *gammacross_init_execution(const SeqRenderData *context,
static void do_gammacross_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -1018,7 +731,7 @@ static void do_gammacross_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_gammacross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_gammacross_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -1026,57 +739,27 @@ static void do_gammacross_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_gammacross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_gammacross_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
/*********************** Add *************************/
-static void do_add_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
-{
- int xo, fac1, fac3;
- unsigned char *cp1, *cp2, *rt;
-
- xo = x;
- cp1 = rect1;
- cp2 = rect2;
- rt = out;
-
- fac1 = (int)(256.0f * facf0);
- fac3 = (int)(256.0f * facf1);
-
- while (y--) {
- x = xo;
-
- while (x--) {
- const int m = fac1 * (int)cp2[3];
- rt[0] = min_ii(cp1[0] + ((m * cp2[0]) >> 16), 255);
- rt[1] = min_ii(cp1[1] + ((m * cp2[1]) >> 16), 255);
- rt[2] = min_ii(cp1[2] + ((m * cp2[2]) >> 16), 255);
- rt[3] = cp1[3];
+static void do_add_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
+{
+ unsigned char *cp1 = rect1;
+ unsigned char *cp2 = rect2;
+ unsigned char *rt = out;
- cp1 += 4;
- cp2 += 4;
- rt += 4;
- }
+ int temp_fac = (int)(256.0f * fac);
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- const int m = fac3 * (int)cp2[3];
- rt[0] = min_ii(cp1[0] + ((m * cp2[0]) >> 16), 255);
- rt[1] = min_ii(cp1[1] + ((m * cp2[1]) >> 16), 255);
- rt[2] = min_ii(cp1[2] + ((m * cp2[2]) >> 16), 255);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ const int temp_fac2 = temp_fac * (int)cp2[3];
+ rt[0] = min_ii(cp1[0] + ((temp_fac2 * cp2[0]) >> 16), 255);
+ rt[1] = min_ii(cp1[1] + ((temp_fac2 * cp2[1]) >> 16), 255);
+ rt[2] = min_ii(cp1[2] + ((temp_fac2 * cp2[2]) >> 16), 255);
rt[3] = cp1[3];
cp1 += 4;
@@ -1086,46 +769,18 @@ static void do_add_effect_byte(float facf0,
}
}
-static void do_add_effect_float(
- float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
+static void do_add_effect_float(float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- int xo;
- float fac1, fac3;
- float *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
-
- fac1 = facf0;
- fac3 = facf1;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- while (y--) {
- x = xo;
- while (x--) {
- const float m = (1.0f - (rt1[3] * (1.0f - fac1))) * rt2[3];
- rt[0] = rt1[0] + m * rt2[0];
- rt[1] = rt1[1] + m * rt2[1];
- rt[2] = rt1[2] + m * rt2[2];
- rt[3] = rt1[3];
-
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- const float m = (1.0f - (rt1[3] * (1.0f - fac3))) * rt2[3];
- rt[0] = rt1[0] + m * rt2[0];
- rt[1] = rt1[1] + m * rt2[1];
- rt[2] = rt1[2] + m * rt2[2];
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ const float temp_fac = (1.0f - (rt1[3] * (1.0f - fac))) * rt2[3];
+ rt[0] = rt1[0] + temp_fac * rt2[0];
+ rt[1] = rt1[1] + temp_fac * rt2[1];
+ rt[2] = rt1[2] + temp_fac * rt2[2];
rt[3] = rt1[3];
rt1 += 4;
@@ -1138,8 +793,7 @@ static void do_add_effect_float(
static void do_add_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -1153,7 +807,7 @@ static void do_add_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_add_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_add_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -1161,56 +815,27 @@ static void do_add_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_add_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_add_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
/*********************** Sub *************************/
-static void do_sub_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
-{
- int xo, fac1, fac3;
- unsigned char *cp1, *cp2, *rt;
-
- xo = x;
- cp1 = rect1;
- cp2 = rect2;
- rt = out;
-
- fac1 = (int)(256.0f * facf0);
- fac3 = (int)(256.0f * facf1);
-
- while (y--) {
- x = xo;
- while (x--) {
- const int m = fac1 * (int)cp2[3];
- rt[0] = max_ii(cp1[0] - ((m * cp2[0]) >> 16), 0);
- rt[1] = max_ii(cp1[1] - ((m * cp2[1]) >> 16), 0);
- rt[2] = max_ii(cp1[2] - ((m * cp2[2]) >> 16), 0);
- rt[3] = cp1[3];
+static void do_sub_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
+{
+ unsigned char *cp1 = rect1;
+ unsigned char *cp2 = rect2;
+ unsigned char *rt = out;
- cp1 += 4;
- cp2 += 4;
- rt += 4;
- }
+ int temp_fac = (int)(256.0f * fac);
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- const int m = fac3 * (int)cp2[3];
- rt[0] = max_ii(cp1[0] - ((m * cp2[0]) >> 16), 0);
- rt[1] = max_ii(cp1[1] - ((m * cp2[1]) >> 16), 0);
- rt[2] = max_ii(cp1[2] - ((m * cp2[2]) >> 16), 0);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ const int temp_fac2 = temp_fac * (int)cp2[3];
+ rt[0] = max_ii(cp1[0] - ((temp_fac2 * cp2[0]) >> 16), 0);
+ rt[1] = max_ii(cp1[1] - ((temp_fac2 * cp2[1]) >> 16), 0);
+ rt[2] = max_ii(cp1[2] - ((temp_fac2 * cp2[2]) >> 16), 0);
rt[3] = cp1[3];
cp1 += 4;
@@ -1220,47 +845,20 @@ static void do_sub_effect_byte(float facf0,
}
}
-static void do_sub_effect_float(
- float UNUSED(facf0), float facf1, int x, int y, float *rect1, float *rect2, float *out)
+static void do_sub_effect_float(float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- int xo;
- float /* fac1, */ fac3_inv;
- float *rt1, *rt2, *rt;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
-
- /* UNUSED */
- // fac1 = facf0;
- fac3_inv = 1.0f - facf1;
-
- while (y--) {
- x = xo;
- while (x--) {
- const float m = (1.0f - (rt1[3] * fac3_inv)) * rt2[3];
- rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
- rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
- rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
- rt[3] = rt1[3];
-
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
+ float mfac = 1.0f - fac;
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- const float m = (1.0f - (rt1[3] * fac3_inv)) * rt2[3];
- rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
- rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
- rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ const float temp_fac = (1.0f - (rt1[3] * mfac)) * rt2[3];
+ rt[0] = max_ff(rt1[0] - temp_fac * rt2[0], 0.0f);
+ rt[1] = max_ff(rt1[1] - temp_fac * rt2[1], 0.0f);
+ rt[2] = max_ff(rt1[2] - temp_fac * rt2[2], 0.0f);
rt[3] = rt1[3];
rt1 += 4;
@@ -1273,8 +871,7 @@ static void do_sub_effect_float(
static void do_sub_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -1288,7 +885,7 @@ static void do_sub_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_sub_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_sub_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -1296,7 +893,7 @@ static void do_sub_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_sub_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_sub_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
@@ -1306,161 +903,95 @@ static void do_sub_effect(const SeqRenderData *context,
#define XOFF 8
#define YOFF 8
-static void do_drop_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect2i,
- unsigned char *rect1i,
- unsigned char *outi)
-{
- int temp, fac, fac1, fac2;
- unsigned char *rt1, *rt2, *out;
- int field = 1;
-
- const int width = x;
- const int height = y;
- const int xoff = min_ii(XOFF, width);
- const int yoff = min_ii(YOFF, height);
-
- fac1 = (int)(70.0f * facf0);
- fac2 = (int)(70.0f * facf1);
-
- rt2 = rect2i + yoff * 4 * width;
- rt1 = rect1i;
- out = outi;
- for (y = 0; y < height - yoff; y++) {
- if (field) {
- fac = fac1;
- }
- else {
- fac = fac2;
- }
- field = !field;
+static void do_drop_effect_byte(
+ float fac, int x, int y, unsigned char *rect2i, unsigned char *rect1i, unsigned char *outi)
+{
+ const int xoff = min_ii(XOFF, x);
+ const int yoff = min_ii(YOFF, y);
+
+ int temp_fac = (int)(70.0f * fac);
+ unsigned char *rt2 = rect2i + yoff * 4 * x;
+ unsigned char *rt1 = rect1i;
+ unsigned char *out = outi;
+ for (int i = 0; i < y - yoff; i++) {
memcpy(out, rt1, sizeof(*out) * xoff * 4);
rt1 += xoff * 4;
out += xoff * 4;
- for (x = xoff; x < width; x++) {
- temp = ((fac * rt2[3]) >> 8);
+ for (int j = xoff; j < x; j++) {
+ int temp_fac2 = ((temp_fac * rt2[3]) >> 8);
- *(out++) = MAX2(0, *rt1 - temp);
+ *(out++) = MAX2(0, *rt1 - temp_fac2);
rt1++;
- *(out++) = MAX2(0, *rt1 - temp);
+ *(out++) = MAX2(0, *rt1 - temp_fac2);
rt1++;
- *(out++) = MAX2(0, *rt1 - temp);
+ *(out++) = MAX2(0, *rt1 - temp_fac2);
rt1++;
- *(out++) = MAX2(0, *rt1 - temp);
+ *(out++) = MAX2(0, *rt1 - temp_fac2);
rt1++;
rt2 += 4;
}
rt2 += xoff * 4;
}
- memcpy(out, rt1, sizeof(*out) * yoff * 4 * width);
+ memcpy(out, rt1, sizeof(*out) * yoff * 4 * x);
}
static void do_drop_effect_float(
- float facf0, float facf1, int x, int y, float *rect2i, float *rect1i, float *outi)
-{
- float temp, fac, fac1, fac2;
- float *rt1, *rt2, *out;
- int field = 1;
-
- const int width = x;
- const int height = y;
- const int xoff = min_ii(XOFF, width);
- const int yoff = min_ii(YOFF, height);
-
- fac1 = 70.0f * facf0;
- fac2 = 70.0f * facf1;
-
- rt2 = rect2i + yoff * 4 * width;
- rt1 = rect1i;
- out = outi;
- for (y = 0; y < height - yoff; y++) {
- if (field) {
- fac = fac1;
- }
- else {
- fac = fac2;
- }
- field = !field;
+ float fac, int x, int y, float *rect2i, float *rect1i, float *outi)
+{
+ const int xoff = min_ii(XOFF, x);
+ const int yoff = min_ii(YOFF, y);
+ float temp_fac = 70.0f * fac;
+
+ float *rt2 = rect2i + yoff * 4 * x;
+ float *rt1 = rect1i;
+ float *out = outi;
+ for (int i = 0; i < y - yoff; i++) {
memcpy(out, rt1, sizeof(*out) * xoff * 4);
rt1 += xoff * 4;
out += xoff * 4;
- for (x = xoff; x < width; x++) {
- temp = fac * rt2[3];
+ for (int j = xoff; j < x; j++) {
+ float temp_fac2 = temp_fac * rt2[3];
- *(out++) = MAX2(0.0f, *rt1 - temp);
+ *(out++) = MAX2(0.0f, *rt1 - temp_fac2);
rt1++;
- *(out++) = MAX2(0.0f, *rt1 - temp);
+ *(out++) = MAX2(0.0f, *rt1 - temp_fac2);
rt1++;
- *(out++) = MAX2(0.0f, *rt1 - temp);
+ *(out++) = MAX2(0.0f, *rt1 - temp_fac2);
rt1++;
- *(out++) = MAX2(0.0f, *rt1 - temp);
+ *(out++) = MAX2(0.0f, *rt1 - temp_fac2);
rt1++;
rt2 += 4;
}
rt2 += xoff * 4;
}
- memcpy(out, rt1, sizeof(*out) * yoff * 4 * width);
+ memcpy(out, rt1, sizeof(*out) * yoff * 4 * x);
}
/*********************** Mul *************************/
-static void do_mul_effect_byte(float facf0,
- float facf1,
- int x,
- int y,
- unsigned char *rect1,
- unsigned char *rect2,
- unsigned char *out)
+static void do_mul_effect_byte(
+ float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
- int xo, fac1, fac3;
- unsigned char *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
+ unsigned char *rt1 = rect1;
+ unsigned char *rt2 = rect2;
+ unsigned char *rt = out;
- fac1 = (int)(256.0f * facf0);
- fac3 = (int)(256.0f * facf1);
+ int temp_fac = (int)(256.0f * fac);
/* Formula:
* `fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + axaux = c * px + py * s;` // + centx
* `yaux = -s * px + c * py;` // + centy */
- while (y--) {
-
- x = xo;
- while (x--) {
-
- rt[0] = rt1[0] + ((fac1 * rt1[0] * (rt2[0] - 255)) >> 16);
- rt[1] = rt1[1] + ((fac1 * rt1[1] * (rt2[1] - 255)) >> 16);
- rt[2] = rt1[2] + ((fac1 * rt1[2] * (rt2[2] - 255)) >> 16);
- rt[3] = rt1[3] + ((fac1 * rt1[3] * (rt2[3] - 255)) >> 16);
-
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
-
- rt[0] = rt1[0] + ((fac3 * rt1[0] * (rt2[0] - 255)) >> 16);
- rt[1] = rt1[1] + ((fac3 * rt1[1] * (rt2[1] - 255)) >> 16);
- rt[2] = rt1[2] + ((fac3 * rt1[2] * (rt2[2] - 255)) >> 16);
- rt[3] = rt1[3] + ((fac3 * rt1[3] * (rt2[3] - 255)) >> 16);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ rt[0] = rt1[0] + ((temp_fac * rt1[0] * (rt2[0] - 255)) >> 16);
+ rt[1] = rt1[1] + ((temp_fac * rt1[1] * (rt2[1] - 255)) >> 16);
+ rt[2] = rt1[2] + ((temp_fac * rt1[2] * (rt2[2] - 255)) >> 16);
+ rt[3] = rt1[3] + ((temp_fac * rt1[3] * (rt2[3] - 255)) >> 16);
rt1 += 4;
rt2 += 4;
@@ -1469,48 +1000,21 @@ static void do_mul_effect_byte(float facf0,
}
}
-static void do_mul_effect_float(
- float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
+static void do_mul_effect_float(float fac, int x, int y, float *rect1, float *rect2, float *out)
{
- int xo;
- float fac1, fac3;
- float *rt1, *rt2, *rt;
-
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
-
- fac1 = facf0;
- fac3 = facf1;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
/* Formula:
* `fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + a`. */
- while (y--) {
- x = xo;
- while (x--) {
- rt[0] = rt1[0] + fac1 * rt1[0] * (rt2[0] - 1.0f);
- rt[1] = rt1[1] + fac1 * rt1[1] * (rt2[1] - 1.0f);
- rt[2] = rt1[2] + fac1 * rt1[2] * (rt2[2] - 1.0f);
- rt[3] = rt1[3] + fac1 * rt1[3] * (rt2[3] - 1.0f);
-
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
-
- if (y == 0) {
- break;
- }
- y--;
-
- x = xo;
- while (x--) {
- rt[0] = rt1[0] + fac3 * rt1[0] * (rt2[0] - 1.0f);
- rt[1] = rt1[1] + fac3 * rt1[1] * (rt2[1] - 1.0f);
- rt[2] = rt1[2] + fac3 * rt1[2] * (rt2[2] - 1.0f);
- rt[3] = rt1[3] + fac3 * rt1[3] * (rt2[3] - 1.0f);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ rt[0] = rt1[0] + fac * rt1[0] * (rt2[0] - 1.0f);
+ rt[1] = rt1[1] + fac * rt1[1] * (rt2[1] - 1.0f);
+ rt[2] = rt1[2] + fac * rt1[2] * (rt2[2] - 1.0f);
+ rt[3] = rt1[3] + fac * rt1[3] * (rt2[3] - 1.0f);
rt1 += 4;
rt2 += 4;
@@ -1522,8 +1026,7 @@ static void do_mul_effect_float(
static void do_mul_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -1537,7 +1040,7 @@ static void do_mul_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_mul_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_mul_effect_float(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -1545,7 +1048,7 @@ static void do_mul_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_mul_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
+ do_mul_effect_byte(fac, context->rectx, total_lines, rect1, rect2, rect_out);
}
}
@@ -1555,8 +1058,7 @@ typedef void (*IMB_blend_func_byte)(unsigned char *dst,
const unsigned char *src2);
typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
-BLI_INLINE void apply_blend_function_byte(float facf0,
- float facf1,
+BLI_INLINE void apply_blend_function_byte(float fac,
int x,
int y,
unsigned char *rect1,
@@ -1564,33 +1066,16 @@ BLI_INLINE void apply_blend_function_byte(float facf0,
unsigned char *out,
IMB_blend_func_byte blend_function)
{
- int xo;
- unsigned char *rt1, *rt2, *rt;
- unsigned int achannel;
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
- while (y--) {
- for (x = xo; x > 0; x--) {
- achannel = rt1[3];
- rt1[3] = (unsigned int)achannel * facf0;
- blend_function(rt, rt1, rt2);
- rt1[3] = achannel;
- rt[3] = rt1[3];
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
- if (y == 0) {
- break;
- }
- y--;
- for (x = xo; x > 0; x--) {
- achannel = rt1[3];
- rt1[3] = (unsigned int)achannel * facf1;
+ unsigned char *rt1 = rect1;
+ unsigned char *rt2 = rect2;
+ unsigned char *rt = out;
+
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ unsigned int achannel = rt2[3];
+ rt2[3] = (unsigned int)achannel * fac;
blend_function(rt, rt1, rt2);
- rt1[3] = achannel;
+ rt2[3] = achannel;
rt[3] = rt1[3];
rt1 += 4;
rt2 += 4;
@@ -1599,8 +1084,7 @@ BLI_INLINE void apply_blend_function_byte(float facf0,
}
}
-BLI_INLINE void apply_blend_function_float(float facf0,
- float facf1,
+BLI_INLINE void apply_blend_function_float(float fac,
int x,
int y,
float *rect1,
@@ -1608,33 +1092,16 @@ BLI_INLINE void apply_blend_function_float(float facf0,
float *out,
IMB_blend_func_float blend_function)
{
- int xo;
- float *rt1, *rt2, *rt;
- float achannel;
- xo = x;
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
- while (y--) {
- for (x = xo; x > 0; x--) {
- achannel = rt1[3];
- rt1[3] = achannel * facf0;
- blend_function(rt, rt1, rt2);
- rt1[3] = achannel;
- rt[3] = rt1[3];
- rt1 += 4;
- rt2 += 4;
- rt += 4;
- }
- if (y == 0) {
- break;
- }
- y--;
- for (x = xo; x > 0; x--) {
- achannel = rt1[3];
- rt1[3] = achannel * facf1;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
+
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ float achannel = rt2[3];
+ rt2[3] = achannel * fac;
blend_function(rt, rt1, rt2);
- rt1[3] = achannel;
+ rt2[3] = achannel;
rt[3] = rt1[3];
rt1 += 4;
rt2 += 4;
@@ -1644,89 +1111,78 @@ BLI_INLINE void apply_blend_function_float(float facf0,
}
static void do_blend_effect_float(
- float facf0, float facf1, int x, int y, float *rect1, float *rect2, int btype, float *out)
+ float fac, int x, int y, float *rect1, float *rect2, int btype, float *out)
{
switch (btype) {
case SEQ_TYPE_ADD:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_add_float);
break;
case SEQ_TYPE_SUB:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_sub_float);
break;
case SEQ_TYPE_MUL:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_mul_float);
break;
case SEQ_TYPE_DARKEN:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_darken_float);
break;
case SEQ_TYPE_COLOR_BURN:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_burn_float);
break;
case SEQ_TYPE_LINEAR_BURN:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_linearburn_float);
break;
case SEQ_TYPE_SCREEN:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_screen_float);
break;
case SEQ_TYPE_LIGHTEN:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_lighten_float);
break;
case SEQ_TYPE_DODGE:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_dodge_float);
break;
case SEQ_TYPE_OVERLAY:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_overlay_float);
break;
case SEQ_TYPE_SOFT_LIGHT:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_softlight_float);
break;
case SEQ_TYPE_HARD_LIGHT:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_hardlight_float);
break;
case SEQ_TYPE_PIN_LIGHT:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_pinlight_float);
break;
case SEQ_TYPE_LIN_LIGHT:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_linearlight_float);
break;
case SEQ_TYPE_VIVID_LIGHT:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_vividlight_float);
break;
case SEQ_TYPE_BLEND_COLOR:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_color_float);
break;
case SEQ_TYPE_HUE:
- apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_hue_float);
break;
case SEQ_TYPE_SATURATION:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_saturation_float);
break;
case SEQ_TYPE_VALUE:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_luminosity_float);
break;
case SEQ_TYPE_DIFFERENCE:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_difference_float);
break;
case SEQ_TYPE_EXCLUSION:
- apply_blend_function_float(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_float);
+ apply_blend_function_float(fac, x, y, rect1, rect2, out, blend_color_exclusion_float);
break;
default:
break;
}
}
-static void do_blend_effect_byte(float facf0,
- float facf1,
+static void do_blend_effect_byte(float fac,
int x,
int y,
unsigned char *rect1,
@@ -1736,73 +1192,67 @@ static void do_blend_effect_byte(float facf0,
{
switch (btype) {
case SEQ_TYPE_ADD:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_add_byte);
break;
case SEQ_TYPE_SUB:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_sub_byte);
break;
case SEQ_TYPE_MUL:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_mul_byte);
break;
case SEQ_TYPE_DARKEN:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_darken_byte);
break;
case SEQ_TYPE_COLOR_BURN:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_burn_byte);
break;
case SEQ_TYPE_LINEAR_BURN:
- apply_blend_function_byte(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_linearburn_byte);
break;
case SEQ_TYPE_SCREEN:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_screen_byte);
break;
case SEQ_TYPE_LIGHTEN:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_lighten_byte);
break;
case SEQ_TYPE_DODGE:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_dodge_byte);
break;
case SEQ_TYPE_OVERLAY:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_overlay_byte);
break;
case SEQ_TYPE_SOFT_LIGHT:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_softlight_byte);
break;
case SEQ_TYPE_HARD_LIGHT:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_hardlight_byte);
break;
case SEQ_TYPE_PIN_LIGHT:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_pinlight_byte);
break;
case SEQ_TYPE_LIN_LIGHT:
- apply_blend_function_byte(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_linearlight_byte);
break;
case SEQ_TYPE_VIVID_LIGHT:
- apply_blend_function_byte(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_vividlight_byte);
break;
case SEQ_TYPE_BLEND_COLOR:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_color_byte);
break;
case SEQ_TYPE_HUE:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_hue_byte);
break;
case SEQ_TYPE_SATURATION:
- apply_blend_function_byte(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_saturation_byte);
break;
case SEQ_TYPE_VALUE:
- apply_blend_function_byte(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_luminosity_byte);
break;
case SEQ_TYPE_DIFFERENCE:
- apply_blend_function_byte(
- facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_difference_byte);
break;
case SEQ_TYPE_EXCLUSION:
- apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_byte);
+ apply_blend_function_byte(fac, x, y, rect1, rect2, out, blend_color_exclusion_byte);
break;
default:
break;
@@ -1812,8 +1262,7 @@ static void do_blend_effect_byte(float facf0,
static void do_blend_mode_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -1826,14 +1275,14 @@ static void do_blend_mode_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_blend_effect_float(
- facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
+ fac, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_blend_effect_byte(
- facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
+ fac, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
}
}
/*********************** Color Mix Effect *************************/
@@ -1853,8 +1302,7 @@ static void init_colormix_effect(Sequence *seq)
static void do_colormix_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float UNUSED(facf0),
- float UNUSED(facf1),
+ float UNUSED(fac),
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -1862,24 +1310,24 @@ static void do_colormix_effect(const SeqRenderData *context,
int total_lines,
ImBuf *out)
{
- float facf;
+ float fac;
ColorMixVars *data = seq->effectdata;
- facf = data->factor;
+ fac = data->factor;
if (out->rect_float) {
float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_blend_effect_float(
- facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
+ fac, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
do_blend_effect_byte(
- facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
+ fac, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
}
}
@@ -1930,7 +1378,7 @@ static float in_band(float width, float dist, int side, int dir)
return alpha;
}
-static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float facf0)
+static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float fac)
{
float posx, posy, hyp, hyp2, angle, hwidth, b1, b2, b3, pointdist;
/* some future stuff */
@@ -1950,18 +1398,18 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f
angle = wipezone->angle;
if (wipe->forward) {
- posx = facf0 * xo;
- posy = facf0 * yo;
+ posx = fac * xo;
+ posy = fac * yo;
}
else {
- posx = xo - facf0 * xo;
- posy = yo - facf0 * yo;
+ posx = xo - fac * xo;
+ posy = yo - fac * yo;
}
switch (wipe->wipetype) {
case DO_SINGLE_WIPE:
- width = min_ii(wipezone->width, facf0 * yo);
- width = min_ii(width, yo - facf0 * yo);
+ width = min_ii(wipezone->width, fac * yo);
+ width = min_ii(width, yo - fac * yo);
if (angle == 0.0f) {
b1 = posy;
@@ -2000,7 +1448,7 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f
case DO_DOUBLE_WIPE:
if (!wipe->forward) {
- facf0 = 1.0f - facf0; /* Go the other direction */
+ fac = 1.0f - fac; /* Go the other direction */
}
width = wipezone->width; /* calculate the blur width */
@@ -2053,9 +1501,9 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f
* temp3: angle of low side of blur
* temp4: angle of high side of blur
*/
- output = 1.0f - facf0;
+ output = 1.0f - fac;
widthf = wipe->edgeWidth * 2.0f * (float)M_PI;
- temp1 = 2.0f * (float)M_PI * facf0;
+ temp1 = 2.0f * (float)M_PI * fac;
if (wipe->forward) {
temp1 = 2.0f * (float)M_PI - temp1;
@@ -2076,12 +1524,12 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f
}
if (wipe->forward) {
- temp3 = temp1 - (widthf * 0.5f) * facf0;
- temp4 = temp1 + (widthf * 0.5f) * (1 - facf0);
+ temp3 = temp1 - (widthf * 0.5f) * fac;
+ temp4 = temp1 + (widthf * 0.5f) * (1 - fac);
}
else {
- temp3 = temp1 - (widthf * 0.5f) * (1 - facf0);
- temp4 = temp1 + (widthf * 0.5f) * facf0;
+ temp3 = temp1 - (widthf * 0.5f) * (1 - fac);
+ temp4 = temp1 + (widthf * 0.5f) * fac;
}
if (temp3 < 0) {
temp3 = 0;
@@ -2118,13 +1566,13 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f
}
if (!wipe->forward) {
- facf0 = 1 - facf0;
+ fac = 1 - fac;
}
width = wipezone->width;
hwidth = width * 0.5f;
- temp1 = (halfx - (halfx)*facf0);
+ temp1 = (halfx - (halfx)*fac);
pointdist = hypotf(temp1, temp1);
temp2 = hypotf(halfx - x, halfy - y);
@@ -2175,8 +1623,7 @@ static void copy_wipe_effect(Sequence *dst, Sequence *src, const int UNUSED(flag
}
static void do_wipe_effect_byte(Sequence *seq,
- float facf0,
- float UNUSED(facf1),
+ float fac,
int x,
int y,
unsigned char *rect1,
@@ -2185,20 +1632,15 @@ static void do_wipe_effect_byte(Sequence *seq,
{
WipeZone wipezone;
WipeVars *wipe = (WipeVars *)seq->effectdata;
- int xo, yo;
- unsigned char *cp1, *cp2, *rt;
-
precalc_wipe_zone(&wipezone, wipe, x, y);
- cp1 = rect1;
- cp2 = rect2;
- rt = out;
+ unsigned char *cp1 = rect1;
+ unsigned char *cp2 = rect2;
+ unsigned char *rt = out;
- xo = x;
- yo = y;
- for (y = 0; y < yo; y++) {
- for (x = 0; x < xo; x++) {
- float check = check_zone(&wipezone, x, y, seq, facf0);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ float check = check_zone(&wipezone, x, y, seq, fac);
if (check) {
if (cp1) {
float rt1[4], rt2[4], tempc[4];
@@ -2246,31 +1688,20 @@ static void do_wipe_effect_byte(Sequence *seq,
}
}
-static void do_wipe_effect_float(Sequence *seq,
- float facf0,
- float UNUSED(facf1),
- int x,
- int y,
- float *rect1,
- float *rect2,
- float *out)
+static void do_wipe_effect_float(
+ Sequence *seq, float fac, int x, int y, float *rect1, float *rect2, float *out)
{
WipeZone wipezone;
WipeVars *wipe = (WipeVars *)seq->effectdata;
- int xo, yo;
- float *rt1, *rt2, *rt;
-
precalc_wipe_zone(&wipezone, wipe, x, y);
- rt1 = rect1;
- rt2 = rect2;
- rt = out;
+ float *rt1 = rect1;
+ float *rt2 = rect2;
+ float *rt = out;
- xo = x;
- yo = y;
- for (y = 0; y < yo; y++) {
- for (x = 0; x < xo; x++) {
- float check = check_zone(&wipezone, x, y, seq, facf0);
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ float check = check_zone(&wipezone, x, y, seq, fac);
if (check) {
if (rt1) {
rt[0] = rt1[0] * check + rt2[0] * (1 - check);
@@ -2314,8 +1745,7 @@ static void do_wipe_effect_float(Sequence *seq,
static ImBuf *do_wipe_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
@@ -2324,8 +1754,7 @@ static ImBuf *do_wipe_effect(const SeqRenderData *context,
if (out->rect_float) {
do_wipe_effect_float(seq,
- facf0,
- facf1,
+ fac,
context->rectx,
context->recty,
ibuf1->rect_float,
@@ -2334,8 +1763,7 @@ static ImBuf *do_wipe_effect(const SeqRenderData *context,
}
else {
do_wipe_effect_byte(seq,
- facf0,
- facf1,
+ fac,
context->rectx,
context->recty,
(unsigned char *)ibuf1->rect,
@@ -2442,8 +1870,7 @@ static void transform_image(int x,
static void do_transform_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float UNUSED(facf0),
- float UNUSED(facf1),
+ float UNUSED(fac),
ImBuf *ibuf1,
ImBuf *UNUSED(ibuf2),
ImBuf *UNUSED(ibuf3),
@@ -2451,7 +1878,6 @@ static void do_transform_effect(const SeqRenderData *context,
int total_lines,
ImBuf *out)
{
- Scene *scene = context->scene;
TransformVars *transform = (TransformVars *)seq->effectdata;
float scale_x, scale_y, translate_x, translate_y, rotate_radians;
@@ -2469,10 +1895,14 @@ static void do_transform_effect(const SeqRenderData *context,
/* Translate */
if (!transform->percent) {
- float rd_s = (scene->r.size / 100.0f);
+ /* Compensate text size for preview render size. */
+ double proxy_size_comp = context->scene->r.size / 100.0;
+ if (context->preview_render_size != SEQ_RENDER_SIZE_SCENE) {
+ proxy_size_comp = SEQ_rendersize_to_scale_factor(context->preview_render_size);
+ }
- translate_x = transform->xIni * rd_s + (x / 2.0f);
- translate_y = transform->yIni * rd_s + (y / 2.0f);
+ translate_x = transform->xIni * proxy_size_comp + (x / 2.0f);
+ translate_y = transform->yIni * proxy_size_comp + (y / 2.0f);
}
else {
translate_x = x * (transform->xIni / 100.0f) + (x / 2.0f);
@@ -2728,8 +2158,7 @@ static void copy_glow_effect(Sequence *dst, Sequence *src, const int UNUSED(flag
static void do_glow_effect_byte(Sequence *seq,
int render_size,
- float facf0,
- float UNUSED(facf1),
+ float fac,
int x,
int y,
unsigned char *rect1,
@@ -2746,7 +2175,7 @@ static void do_glow_effect_byte(Sequence *seq,
IMB_buffer_float_premultiply(inbuf, x, y);
RVIsolateHighlights_float(
- inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
+ inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * fac, glow->fClamp);
RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
if (!glow->bNoComp) {
RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
@@ -2762,8 +2191,7 @@ static void do_glow_effect_byte(Sequence *seq,
static void do_glow_effect_float(Sequence *seq,
int render_size,
- float facf0,
- float UNUSED(facf1),
+ float fac,
int x,
int y,
float *rect1,
@@ -2775,7 +2203,7 @@ static void do_glow_effect_float(Sequence *seq,
GlowVars *glow = (GlowVars *)seq->effectdata;
RVIsolateHighlights_float(
- inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
+ inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * fac, glow->fClamp);
RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
if (!glow->bNoComp) {
RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
@@ -2785,8 +2213,7 @@ static void do_glow_effect_float(Sequence *seq,
static ImBuf *do_glow_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
@@ -2798,8 +2225,7 @@ static ImBuf *do_glow_effect(const SeqRenderData *context,
if (out->rect_float) {
do_glow_effect_float(seq,
render_size,
- facf0,
- facf1,
+ fac,
context->rectx,
context->recty,
ibuf1->rect_float,
@@ -2809,8 +2235,7 @@ static ImBuf *do_glow_effect(const SeqRenderData *context,
else {
do_glow_effect_byte(seq,
render_size,
- facf0,
- facf1,
+ fac,
context->rectx,
context->recty,
(unsigned char *)ibuf1->rect,
@@ -2852,7 +2277,7 @@ static void copy_solid_color(Sequence *dst, Sequence *src, const int UNUSED(flag
dst->effectdata = MEM_dupallocN(src->effectdata);
}
-static int early_out_color(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_color(Sequence *UNUSED(seq), float UNUSED(fac))
{
return EARLY_NO_INPUT;
}
@@ -2860,8 +2285,7 @@ static int early_out_color(Sequence *UNUSED(seq), float UNUSED(facf0), float UNU
static ImBuf *do_solid_color(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float UNUSED(fac),
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
@@ -2870,75 +2294,50 @@ static ImBuf *do_solid_color(const SeqRenderData *context,
SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
- unsigned char *rect;
- float *rect_float;
- int x; /*= context->rectx;*/ /*UNUSED*/
- int y; /*= context->recty;*/ /*UNUSED*/
+ int x = out->x;
+ int y = out->y;
if (out->rect) {
- unsigned char col0[3];
- unsigned char col1[3];
-
- col0[0] = facf0 * cv->col[0] * 255;
- col0[1] = facf0 * cv->col[1] * 255;
- col0[2] = facf0 * cv->col[2] * 255;
+ unsigned char color[4];
+ color[0] = cv->col[0] * 255;
+ color[1] = cv->col[1] * 255;
+ color[2] = cv->col[2] * 255;
+ color[3] = 255;
- col1[0] = facf1 * cv->col[0] * 255;
- col1[1] = facf1 * cv->col[1] * 255;
- col1[2] = facf1 * cv->col[2] * 255;
+ unsigned char *rect = (unsigned char *)out->rect;
- rect = (unsigned char *)out->rect;
-
- for (y = 0; y < out->y; y++) {
- for (x = 0; x < out->x; x++, rect += 4) {
- rect[0] = col0[0];
- rect[1] = col0[1];
- rect[2] = col0[2];
- rect[3] = 255;
- }
- y++;
- if (y < out->y) {
- for (x = 0; x < out->x; x++, rect += 4) {
- rect[0] = col1[0];
- rect[1] = col1[1];
- rect[2] = col1[2];
- rect[3] = 255;
- }
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ rect[0] = color[0];
+ rect[1] = color[1];
+ rect[2] = color[2];
+ rect[3] = color[3];
+ rect += 4;
}
}
}
else if (out->rect_float) {
- float col0[3];
- float col1[3];
-
- col0[0] = facf0 * cv->col[0];
- col0[1] = facf0 * cv->col[1];
- col0[2] = facf0 * cv->col[2];
+ float color[4];
+ color[0] = cv->col[0];
+ color[1] = cv->col[1];
+ color[2] = cv->col[2];
+ color[3] = 255;
- col1[0] = facf1 * cv->col[0];
- col1[1] = facf1 * cv->col[1];
- col1[2] = facf1 * cv->col[2];
+ float *rect_float = out->rect_float;
- rect_float = out->rect_float;
-
- for (y = 0; y < out->y; y++) {
- for (x = 0; x < out->x; x++, rect_float += 4) {
- rect_float[0] = col0[0];
- rect_float[1] = col0[1];
- rect_float[2] = col0[2];
- rect_float[3] = 1.0;
- }
- y++;
- if (y < out->y) {
- for (x = 0; x < out->x; x++, rect_float += 4) {
- rect_float[0] = col1[0];
- rect_float[1] = col1[1];
- rect_float[2] = col1[2];
- rect_float[3] = 1.0;
- }
+ for (int i = 0; i < y; i++) {
+ for (int j = 0; j < x; j++) {
+ rect_float[0] = color[0];
+ rect_float[1] = color[1];
+ rect_float[2] = color[2];
+ rect_float[3] = color[3];
+ rect_float += 4;
}
}
}
+
+ out->planes = R_IMF_PLANES_RGB;
+
return out;
}
@@ -2950,7 +2349,7 @@ static int num_inputs_multicam(void)
return 0;
}
-static int early_out_multicam(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_multicam(Sequence *UNUSED(seq), float UNUSED(fac))
{
return EARLY_NO_INPUT;
}
@@ -2958,8 +2357,7 @@ static int early_out_multicam(Sequence *UNUSED(seq), float UNUSED(facf0), float
static ImBuf *do_multicam(const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
- float UNUSED(facf0),
- float UNUSED(facf1),
+ float UNUSED(fac),
ImBuf *UNUSED(ibuf1),
ImBuf *UNUSED(ibuf2),
ImBuf *UNUSED(ibuf3))
@@ -2994,7 +2392,7 @@ static int num_inputs_adjustment(void)
return 0;
}
-static int early_out_adjustment(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_adjustment(Sequence *UNUSED(seq), float UNUSED(fac))
{
return EARLY_NO_INPUT;
}
@@ -3038,8 +2436,7 @@ static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, fl
static ImBuf *do_adjustment(const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
- float UNUSED(facf0),
- float UNUSED(facf1),
+ float UNUSED(fac),
ImBuf *UNUSED(ibuf1),
ImBuf *UNUSED(ibuf2),
ImBuf *UNUSED(ibuf3))
@@ -3105,7 +2502,7 @@ static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(fla
v->frameMap = NULL;
}
-static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(fac))
{
return EARLY_DO_EFFECT;
}
@@ -3129,8 +2526,6 @@ static FCurve *seq_effect_speed_speed_factor_curve_get(Scene *scene, Sequence *s
return id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
}
-/* Build frame map when speed in mode #SEQ_SPEED_MULTIPLY is animated.
- * This is, because `target_frame` value is integrated over time. */
void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq)
{
if ((seq->seq1 == NULL) || (seq->len < 1)) {
@@ -3169,7 +2564,6 @@ static void seq_effect_speed_frame_map_ensure(Scene *scene, Sequence *seq)
seq_effect_speed_rebuild_map(scene, seq);
}
-/* Override timeline_frame when rendering speed effect input. */
float seq_speed_effect_target_frame_get(Scene *scene,
Sequence *seq_speed,
float timeline_frame,
@@ -3240,8 +2634,7 @@ static float speed_effect_interpolation_ratio_get(Scene *scene,
static ImBuf *do_speed_effect(const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
@@ -3252,10 +2645,10 @@ static ImBuf *do_speed_effect(const SeqRenderData *context,
if (s->flags & SEQ_SPEED_USE_INTERPOLATION) {
out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
- facf0 = facf1 = speed_effect_interpolation_ratio_get(context->scene, seq, timeline_frame);
+ fac = speed_effect_interpolation_ratio_get(context->scene, seq, timeline_frame);
/* Current frame is ibuf1, next frame is ibuf2. */
out = seq_render_effect_execute_threaded(
- &cross_effect, context, NULL, timeline_frame, facf0, facf1, ibuf1, ibuf2, ibuf3);
+ &cross_effect, context, NULL, timeline_frame, fac, ibuf1, ibuf2, ibuf3);
return out;
}
@@ -3268,8 +2661,7 @@ static ImBuf *do_speed_effect(const SeqRenderData *context,
static void do_overdrop_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(timeline_frame),
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *UNUSED(ibuf3),
@@ -3286,8 +2678,8 @@ static void do_overdrop_effect(const SeqRenderData *context,
slice_get_float_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
- do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
+ do_drop_effect_float(fac, x, y, rect1, rect2, rect_out);
+ do_alphaover_effect_float(fac, x, y, rect1, rect2, rect_out);
}
else {
unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
@@ -3295,8 +2687,8 @@ static void do_overdrop_effect(const SeqRenderData *context,
slice_get_byte_buffers(
context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
- do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
+ do_drop_effect_byte(fac, x, y, rect1, rect2, rect_out);
+ do_alphaover_effect_byte(fac, x, y, rect1, rect2, rect_out);
}
}
@@ -3334,7 +2726,7 @@ static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src, const int UN
dst->effectdata = MEM_dupallocN(src->effectdata);
}
-static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_gaussian_blur(Sequence *seq, float UNUSED(fac))
{
GaussianBlurVars *data = seq->effectdata;
if (data->size_x == 0.0f && data->size_y == 0) {
@@ -3688,8 +3080,7 @@ static void *render_effect_execute_do_y_thread(void *thread_data_v)
static ImBuf *do_gaussian_blur_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float UNUSED(facf0),
- float UNUSED(facf1),
+ float UNUSED(fac),
ImBuf *ibuf1,
ImBuf *UNUSED(ibuf2),
ImBuf *UNUSED(ibuf3))
@@ -3738,7 +3129,7 @@ static void init_text_effect(Sequence *seq)
data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
data->text_font = NULL;
data->text_blf_id = -1;
- data->text_size = 60;
+ data->text_size = 60.0f;
copy_v4_fl(data->color, 1.0f);
data->shadow_color[3] = 0.7f;
@@ -3836,10 +3227,10 @@ static int num_inputs_text(void)
return 0;
}
-static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_text(Sequence *seq, float UNUSED(fac))
{
TextVars *data = seq->effectdata;
- if (data->text[0] == 0 || data->text_size < 1 ||
+ if (data->text[0] == 0 || data->text_size < 1.0f ||
((data->color[3] == 0.0f) &&
(data->shadow_color[3] == 0.0f || (data->flag & SEQ_TEXT_SHADOW) == 0))) {
return EARLY_USE_INPUT_1;
@@ -3850,8 +3241,7 @@ static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1
static ImBuf *do_text_effect(const SeqRenderData *context,
Sequence *seq,
float UNUSED(timeline_frame),
- float UNUSED(facf0),
- float UNUSED(facf1),
+ float UNUSED(fac),
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
@@ -3954,12 +3344,12 @@ static ImBuf *do_text_effect(const SeqRenderData *context,
fonty = line_height;
BLF_position(font, x + max_ii(fontx / 55, 1), y - max_ii(fonty / 30, 1), 0.0f);
BLF_buffer_col(font, data->shadow_color);
- BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_buffer(font, data->text, sizeof(data->text));
}
BLF_position(font, x, y, 0.0f);
BLF_buffer_col(font, data->color);
- BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_buffer(font, data->text, sizeof(data->text));
BLF_buffer(font, NULL, NULL, 0, 0, 0, NULL);
@@ -3997,44 +3387,47 @@ static void free_effect_default(Sequence *seq, const bool UNUSED(do_id_user))
MEM_SAFE_FREE(seq->effectdata);
}
-static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
+static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(fac))
{
return EARLY_DO_EFFECT;
}
-static int early_out_fade(Sequence *UNUSED(seq), float facf0, float facf1)
+static int early_out_fade(Sequence *UNUSED(seq), float fac)
{
- if (facf0 == 0.0f && facf1 == 0.0f) {
+ if (fac == 0.0f) {
return EARLY_USE_INPUT_1;
}
- if (facf0 == 1.0f && facf1 == 1.0f) {
+ if (fac == 1.0f) {
return EARLY_USE_INPUT_2;
}
return EARLY_DO_EFFECT;
}
-static int early_out_mul_input2(Sequence *UNUSED(seq), float facf0, float facf1)
+static int early_out_mul_input2(Sequence *UNUSED(seq), float fac)
{
- if (facf0 == 0.0f && facf1 == 0.0f) {
+ if (fac == 0.0f) {
return EARLY_USE_INPUT_1;
}
return EARLY_DO_EFFECT;
}
-static void get_default_fac_noop(Sequence *UNUSED(seq),
- float UNUSED(timeline_frame),
- float *facf0,
- float *facf1)
+static int early_out_mul_input1(Sequence *UNUSED(seq), float fac)
+{
+ if (fac == 0.0f) {
+ return EARLY_USE_INPUT_2;
+ }
+ return EARLY_DO_EFFECT;
+}
+
+static void get_default_fac_noop(Sequence *UNUSED(seq), float UNUSED(timeline_frame), float *fac)
{
- *facf0 = *facf1 = 1.0;
+ *fac = 1.0f;
}
-static void get_default_fac_fade(Sequence *seq, float timeline_frame, float *facf0, float *facf1)
+static void get_default_fac_fade(Sequence *seq, float timeline_frame, float *fac)
{
- *facf0 = (float)(timeline_frame - seq->startdisp);
- *facf1 = (float)(*facf0 + 0.5f);
- *facf0 /= seq->len;
- *facf1 /= seq->len;
+ *fac = (float)(timeline_frame - seq->startdisp);
+ *fac /= seq->len;
}
static struct ImBuf *init_execution(const SeqRenderData *context,
@@ -4131,6 +3524,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.multithreaded = true;
rval.init = init_alpha_over_or_under;
rval.execute_slice = do_alphaover_effect;
+ rval.early_out = early_out_mul_input1;
break;
case SEQ_TYPE_OVERDROP:
rval.multithreaded = true;
diff --git a/source/blender/sequencer/intern/effects.h b/source/blender/sequencer/intern/effects.h
index 25ba4d8956e..c63f8f7a404 100644
--- a/source/blender/sequencer/intern/effects.h
+++ b/source/blender/sequencer/intern/effects.h
@@ -39,7 +39,14 @@ struct Sequence;
*/
struct SeqEffectHandle seq_effect_get_sequence_blend(struct Sequence *seq);
+/**
+ * Build frame map when speed in mode #SEQ_SPEED_MULTIPLY is animated.
+ * This is, because `target_frame` value is integrated over time.
+ */
void seq_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq);
+/**
+ * Override timeline_frame when rendering speed effect input.
+ */
float seq_speed_effect_target_frame_get(struct Scene *scene,
struct Sequence *seq,
float timeline_frame,
diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c
index 86c198075e9..51e4613f088 100644
--- a/source/blender/sequencer/intern/image_cache.c
+++ b/source/blender/sequencer/intern/image_cache.c
@@ -50,9 +50,9 @@
#include "SEQ_prefetch.h"
#include "SEQ_relations.h"
-#include "SEQ_render.h"
#include "SEQ_sequencer.h"
+#include "disk_cache.h"
#include "image_cache.h"
#include "prefetch.h"
#include "strip_time.h"
@@ -80,67 +80,10 @@
* entries one by one in reverse order to their creation.
*
* User can exclude caching of some images. Such entries will have is_temp_cache set.
- *
- *
- * Disk Cache Design Notes
- * =======================
- *
- * Disk cache uses directory specified in user preferences
- * For each cached non-temp image, image data and supplementary info are written to HDD.
- * Multiple(DCACHE_IMAGES_PER_FILE) images share the same file.
- * Each of these files contains header DiskCacheHeader followed by image data.
- * Zlib compression with user definable level can be used to compress image data(per image)
- * Images are written in order in which they are rendered.
- * Overwriting of individual entry is not possible.
- * Stored images are deleted by invalidation, or when size of all files exceeds maximum
- * size specified in user preferences.
- * To distinguish 2 blend files with same name, scene->ed->disk_cache_timestamp
- * is used as UID. Blend file can still be copied manually which may cause conflict.
- *
*/
-/* <cache type>-<resolution X>x<resolution Y>-<rendersize>%(<view_id>)-<frame no>.dcf */
-#define DCACHE_FNAME_FORMAT "%d-%dx%d-%d%%(%d)-%d.dcf"
-#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;
- uint64_t frameno;
- uint64_t size_compressed;
- uint64_t size_raw;
- uint64_t offset;
- char colorspace_name[COLORSPACE_NAME_MAX];
-} DiskCacheHeaderEntry;
-
-typedef struct DiskCacheHeader {
- DiskCacheHeaderEntry entry[DCACHE_IMAGES_PER_FILE];
-} DiskCacheHeader;
-
-typedef struct SeqDiskCache {
- Main *bmain;
- int64_t timestamp;
- ListBase files;
- ThreadMutex read_write_mutex;
- size_t size_total;
-} SeqDiskCache;
-
-typedef struct DiskCacheFile {
- struct DiskCacheFile *next, *prev;
- char path[FILE_MAX];
- char dir[FILE_MAXDIR];
- char file[FILE_MAX];
- BLI_stat_t fstat;
- int cache_type;
- int rectx;
- int recty;
- int render_size;
- int view_id;
- int start_frame;
-} DiskCacheFile;
-
typedef struct SeqCache {
Main *bmain;
struct GHash *hash;
@@ -148,7 +91,7 @@ typedef struct SeqCache {
struct BLI_mempool *keys_pool;
struct BLI_mempool *items_pool;
struct SeqCacheKey *last_key;
- SeqDiskCache *disk_cache;
+ struct SeqDiskCache *disk_cache;
int thumbnail_count;
} SeqCache;
@@ -157,577 +100,7 @@ typedef struct SeqCacheItem {
struct ImBuf *ibuf;
} SeqCacheItem;
-typedef struct SeqCacheKey {
- struct SeqCache *cache_owner;
- void *userkey;
- struct SeqCacheKey *link_prev; /* Used for linking intermediate items to final frame. */
- struct SeqCacheKey *link_next; /* Used for linking intermediate items to final frame. */
- struct Sequence *seq;
- SeqRenderData context;
- float frame_index; /* Usually same as timeline_frame. Mapped to media for RAW entries. */
- float timeline_frame; /* Only for reference - used for freeing when cache is full. */
- float cost; /* In short: render time(s) divided by playback frame duration(s) */
- bool is_temp_cache; /* this cache entry will be freed before rendering next frame */
- /* ID of task for assigning temp cache entries to particular task(thread, etc.) */
- eSeqTaskId task_id;
- int type;
-} SeqCacheKey;
-
static ThreadMutex cache_create_lock = BLI_MUTEX_INITIALIZER;
-static float seq_cache_timeline_frame_to_frame_index(Sequence *seq,
- float timeline_frame,
- int type);
-static float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index);
-
-static char *seq_disk_cache_base_dir(void)
-{
- return U.sequencer_disk_cache_dir;
-}
-
-static int seq_disk_cache_compression_level(void)
-{
- switch (U.sequencer_disk_cache_compression) {
- case USER_SEQ_DISK_CACHE_COMPRESSION_NONE:
- return 0;
- case USER_SEQ_DISK_CACHE_COMPRESSION_LOW:
- return 1;
- case USER_SEQ_DISK_CACHE_COMPRESSION_HIGH:
- return 9;
- }
-
- return U.sequencer_disk_cache_compression;
-}
-
-static size_t seq_disk_cache_size_limit(void)
-{
- return (size_t)U.sequencer_disk_cache_size_limit * (1024 * 1024 * 1024);
-}
-
-static bool seq_disk_cache_is_enabled(Main *bmain)
-{
- return (U.sequencer_disk_cache_dir[0] != '\0' && U.sequencer_disk_cache_size_limit != 0 &&
- (U.sequencer_disk_cache_flag & SEQ_CACHE_DISK_CACHE_ENABLE) != 0 &&
- bmain->name[0] != '\0');
-}
-
-static DiskCacheFile *seq_disk_cache_add_file_to_list(SeqDiskCache *disk_cache, const char *path)
-{
-
- DiskCacheFile *cache_file = MEM_callocN(sizeof(DiskCacheFile), "SeqDiskCacheFile");
- char dir[FILE_MAXDIR], file[FILE_MAX];
- BLI_split_dirfile(path, dir, file, sizeof(dir), sizeof(file));
- BLI_strncpy(cache_file->path, path, sizeof(cache_file->path));
- BLI_strncpy(cache_file->dir, dir, sizeof(cache_file->dir));
- BLI_strncpy(cache_file->file, file, sizeof(cache_file->file));
- sscanf(file,
- DCACHE_FNAME_FORMAT,
- &cache_file->cache_type,
- &cache_file->rectx,
- &cache_file->recty,
- &cache_file->render_size,
- &cache_file->view_id,
- &cache_file->start_frame);
- cache_file->start_frame *= DCACHE_IMAGES_PER_FILE;
- BLI_addtail(&disk_cache->files, cache_file);
- return cache_file;
-}
-
-static void seq_disk_cache_get_files(SeqDiskCache *disk_cache, char *path)
-{
- struct direntry *filelist, *fl;
- uint nbr, i;
- disk_cache->size_total = 0;
-
- i = nbr = BLI_filelist_dir_contents(path, &filelist);
- fl = filelist;
- while (i--) {
- /* Don't follow links. */
- const eFileAttributes file_attrs = BLI_file_attributes(fl->path);
- if (file_attrs & FILE_ATTR_ANY_LINK) {
- fl++;
- continue;
- }
-
- char file[FILE_MAX];
- BLI_split_dirfile(fl->path, NULL, file, 0, sizeof(file));
-
- bool is_dir = BLI_is_dir(fl->path);
- if (is_dir && !FILENAME_IS_CURRPAR(file)) {
- char subpath[FILE_MAX];
- BLI_strncpy(subpath, fl->path, sizeof(subpath));
- BLI_path_slash_ensure(subpath);
- seq_disk_cache_get_files(disk_cache, subpath);
- }
-
- if (!is_dir) {
- const char *ext = BLI_path_extension(fl->path);
- if (ext && ext[1] == 'd' && ext[2] == 'c' && ext[3] == 'f') {
- DiskCacheFile *cache_file = seq_disk_cache_add_file_to_list(disk_cache, fl->path);
- cache_file->fstat = fl->s;
- disk_cache->size_total += cache_file->fstat.st_size;
- }
- }
- fl++;
- }
- BLI_filelist_free(filelist, nbr);
-}
-
-static DiskCacheFile *seq_disk_cache_get_oldest_file(SeqDiskCache *disk_cache)
-{
- DiskCacheFile *oldest_file = disk_cache->files.first;
- if (oldest_file == NULL) {
- return NULL;
- }
- for (DiskCacheFile *cache_file = oldest_file->next; cache_file; cache_file = cache_file->next) {
- if (cache_file->fstat.st_mtime < oldest_file->fstat.st_mtime) {
- oldest_file = cache_file;
- }
- }
-
- return oldest_file;
-}
-
-static void seq_disk_cache_delete_file(SeqDiskCache *disk_cache, DiskCacheFile *file)
-{
- disk_cache->size_total -= file->fstat.st_size;
- BLI_delete(file->path, false, false);
- BLI_remlink(&disk_cache->files, file);
- MEM_freeN(file);
-}
-
-static bool seq_disk_cache_enforce_limits(SeqDiskCache *disk_cache)
-{
- BLI_mutex_lock(&disk_cache->read_write_mutex);
- while (disk_cache->size_total > seq_disk_cache_size_limit()) {
- DiskCacheFile *oldest_file = seq_disk_cache_get_oldest_file(disk_cache);
-
- if (!oldest_file) {
- /* We shouldn't enforce limits with no files, do re-scan. */
- seq_disk_cache_get_files(disk_cache, seq_disk_cache_base_dir());
- continue;
- }
-
- if (BLI_exists(oldest_file->path) == 0) {
- /* File may have been manually deleted during runtime, do re-scan. */
- BLI_freelistN(&disk_cache->files);
- seq_disk_cache_get_files(disk_cache, seq_disk_cache_base_dir());
- continue;
- }
-
- seq_disk_cache_delete_file(disk_cache, oldest_file);
- }
- BLI_mutex_unlock(&disk_cache->read_write_mutex);
-
- return true;
-}
-
-static DiskCacheFile *seq_disk_cache_get_file_entry_by_path(SeqDiskCache *disk_cache, char *path)
-{
- DiskCacheFile *cache_file = disk_cache->files.first;
-
- for (; cache_file; cache_file = cache_file->next) {
- if (BLI_strcasecmp(cache_file->path, path) == 0) {
- return cache_file;
- }
- }
-
- return NULL;
-}
-
-/* Update file size and timestamp. */
-static void seq_disk_cache_update_file(SeqDiskCache *disk_cache, char *path)
-{
- DiskCacheFile *cache_file;
- int64_t size_before;
- int64_t size_after;
-
- cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
- size_before = cache_file->fstat.st_size;
-
- if (BLI_stat(path, &cache_file->fstat) == -1) {
- BLI_assert(false);
- memset(&cache_file->fstat, 0, sizeof(BLI_stat_t));
- }
-
- size_after = cache_file->fstat.st_size;
- disk_cache->size_total += size_after - size_before;
-}
-
-/* Path format:
- * <cache dir>/<project name>_seq_cache/<scene name>-<timestamp>/<seq name>/DCACHE_FNAME_FORMAT
- */
-
-static void seq_disk_cache_get_project_dir(SeqDiskCache *disk_cache, char *path, size_t path_len)
-{
- char cache_dir[FILE_MAX];
- BLI_split_file_part(BKE_main_blendfile_path(disk_cache->bmain), cache_dir, sizeof(cache_dir));
- /* Use suffix, so that the cache directory name does not conflict with the bmain's blend file. */
- const char *suffix = "_seq_cache";
- strncat(cache_dir, suffix, sizeof(cache_dir) - strlen(cache_dir) - 1);
- BLI_strncpy(path, seq_disk_cache_base_dir(), path_len);
- BLI_path_append(path, path_len, cache_dir);
-}
-
-static void seq_disk_cache_get_dir(
- SeqDiskCache *disk_cache, Scene *scene, Sequence *seq, char *path, size_t path_len)
-{
- char scene_name[MAX_ID_NAME + 22]; /* + -%PRId64 */
- char seq_name[SEQ_NAME_MAXSTR];
- char project_dir[FILE_MAX];
-
- seq_disk_cache_get_project_dir(disk_cache, project_dir, sizeof(project_dir));
- sprintf(scene_name, "%s-%" PRId64, scene->id.name, disk_cache->timestamp);
- BLI_strncpy(seq_name, seq->name, sizeof(seq_name));
- BLI_filename_make_safe(scene_name);
- BLI_filename_make_safe(seq_name);
- BLI_strncpy(path, project_dir, path_len);
- BLI_path_append(path, path_len, scene_name);
- BLI_path_append(path, path_len, seq_name);
-}
-
-static void seq_disk_cache_get_file_path(SeqDiskCache *disk_cache,
- SeqCacheKey *key,
- char *path,
- size_t path_len)
-{
- seq_disk_cache_get_dir(disk_cache, key->context.scene, key->seq, path, path_len);
- int frameno = (int)key->frame_index / DCACHE_IMAGES_PER_FILE;
- char cache_filename[FILE_MAXFILE];
- sprintf(cache_filename,
- DCACHE_FNAME_FORMAT,
- key->type,
- key->context.rectx,
- key->context.recty,
- key->context.preview_render_size,
- key->context.view_id,
- frameno);
-
- BLI_path_append(path, path_len, cache_filename);
-}
-
-static void seq_disk_cache_create_version_file(char *path)
-{
- BLI_make_existing_file(path);
-
- FILE *file = BLI_fopen(path, "w");
- if (file) {
- fprintf(file, "%d", DCACHE_CURRENT_VERSION);
- fclose(file);
- }
-}
-
-static void seq_disk_cache_handle_versioning(SeqDiskCache *disk_cache)
-{
- char path[FILE_MAX];
- char path_version_file[FILE_MAX];
- int version = 0;
-
- seq_disk_cache_get_project_dir(disk_cache, path, sizeof(path));
- BLI_strncpy(path_version_file, path, sizeof(path_version_file));
- BLI_path_append(path_version_file, sizeof(path_version_file), "cache_version");
-
- if (BLI_exists(path) && BLI_is_dir(path)) {
- FILE *file = BLI_fopen(path_version_file, "r");
-
- if (file) {
- const int num_items_read = fscanf(file, "%d", &version);
- if (num_items_read == 0) {
- version = -1;
- }
- fclose(file);
- }
-
- if (version != DCACHE_CURRENT_VERSION) {
- BLI_delete(path, false, true);
- seq_disk_cache_create_version_file(path_version_file);
- }
- }
- else {
- seq_disk_cache_create_version_file(path_version_file);
- }
-}
-
-static void seq_disk_cache_delete_invalid_files(SeqDiskCache *disk_cache,
- Scene *scene,
- Sequence *seq,
- int invalidate_types,
- int range_start,
- int range_end)
-{
- DiskCacheFile *next_file, *cache_file = disk_cache->files.first;
- char cache_dir[FILE_MAX];
- seq_disk_cache_get_dir(disk_cache, scene, seq, cache_dir, sizeof(cache_dir));
- BLI_path_slash_ensure(cache_dir);
-
- while (cache_file) {
- next_file = cache_file->next;
- if (cache_file->cache_type & invalidate_types) {
- if (STREQ(cache_dir, cache_file->dir)) {
- int timeline_frame_start = seq_cache_frame_index_to_timeline_frame(
- seq, cache_file->start_frame);
- if (timeline_frame_start > range_start && timeline_frame_start <= range_end) {
- seq_disk_cache_delete_file(disk_cache, cache_file);
- }
- }
- }
- cache_file = next_file;
- }
-}
-
-static void seq_disk_cache_invalidate(Scene *scene,
- Sequence *seq,
- Sequence *seq_changed,
- int invalidate_types)
-{
- int start;
- int end;
- SeqDiskCache *disk_cache = scene->ed->cache->disk_cache;
-
- BLI_mutex_lock(&disk_cache->read_write_mutex);
-
- start = seq_changed->startdisp - DCACHE_IMAGES_PER_FILE;
- end = seq_changed->enddisp;
-
- seq_disk_cache_delete_invalid_files(disk_cache, scene, seq, invalidate_types, start, end);
-
- BLI_mutex_unlock(&disk_cache->read_write_mutex);
-}
-
-static size_t deflate_imbuf_to_file(ImBuf *ibuf,
- FILE *file,
- int level,
- DiskCacheHeaderEntry *header_entry)
-{
- void *data = (ibuf->rect != NULL) ? (void *)ibuf->rect : (void *)ibuf->rect_float;
-
- /* Apply compression if wanted, otherwise just write directly to the file. */
- if (level > 0) {
- return BLI_file_zstd_from_mem_at_pos(
- data, header_entry->size_raw, file, header_entry->offset, level);
- }
-
- fseek(file, header_entry->offset, SEEK_SET);
- return fwrite(data, 1, header_entry->size_raw, file);
-}
-
-static size_t inflate_file_to_imbuf(ImBuf *ibuf, FILE *file, DiskCacheHeaderEntry *header_entry)
-{
- void *data = (ibuf->rect != NULL) ? (void *)ibuf->rect : (void *)ibuf->rect_float;
- char header[4];
- fseek(file, header_entry->offset, SEEK_SET);
- if (fread(header, 1, sizeof(header), file) != sizeof(header)) {
- return 0;
- }
-
- /* Check if the data is compressed or raw. */
- if (BLI_file_magic_is_zstd(header)) {
- return BLI_file_unzstd_to_mem_at_pos(data, header_entry->size_raw, file, header_entry->offset);
- }
-
- fseek(file, header_entry->offset, SEEK_SET);
- return fread(data, 1, header_entry->size_raw, file);
-}
-
-static bool seq_disk_cache_read_header(FILE *file, DiskCacheHeader *header)
-{
- BLI_fseek(file, 0LL, SEEK_SET);
- const size_t num_items_read = fread(header, sizeof(*header), 1, file);
- if (num_items_read < 1) {
- BLI_assert_msg(0, "unable to read disk cache header");
- perror("unable to read disk cache header");
- return false;
- }
-
- for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
- if ((ENDIAN_ORDER == B_ENDIAN) && header->entry[i].encoding == 0) {
- BLI_endian_switch_uint64(&header->entry[i].frameno);
- BLI_endian_switch_uint64(&header->entry[i].offset);
- BLI_endian_switch_uint64(&header->entry[i].size_compressed);
- BLI_endian_switch_uint64(&header->entry[i].size_raw);
- }
- }
-
- return true;
-}
-
-static size_t seq_disk_cache_write_header(FILE *file, DiskCacheHeader *header)
-{
- BLI_fseek(file, 0LL, SEEK_SET);
- return fwrite(header, sizeof(*header), 1, file);
-}
-
-static int seq_disk_cache_add_header_entry(SeqCacheKey *key, ImBuf *ibuf, DiskCacheHeader *header)
-{
- int i;
- uint64_t offset = sizeof(*header);
-
- /* Lookup free entry, get offset for new data. */
- for (i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
- if (header->entry[i].size_compressed == 0) {
- break;
- }
- }
-
- /* Attempt to write beyond set entry limit.
- * Reset file header and start writing from beginning.
- */
- if (i == DCACHE_IMAGES_PER_FILE) {
- i = 0;
- memset(header, 0, sizeof(*header));
- }
-
- /* Calculate offset for image data. */
- if (i > 0) {
- offset = header->entry[i - 1].offset + header->entry[i - 1].size_compressed;
- }
-
- if (ENDIAN_ORDER == B_ENDIAN) {
- header->entry[i].encoding = 255;
- }
- else {
- header->entry[i].encoding = 0;
- }
-
- header->entry[i].offset = offset;
- header->entry[i].frameno = key->frame_index;
-
- /* Store colorspace name of ibuf. */
- const char *colorspace_name;
- if (ibuf->rect) {
- header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels;
- colorspace_name = IMB_colormanagement_get_rect_colorspace(ibuf);
- }
- else {
- header->entry[i].size_raw = ibuf->x * ibuf->y * ibuf->channels * 4;
- colorspace_name = IMB_colormanagement_get_float_colorspace(ibuf);
- }
- BLI_strncpy(
- header->entry[i].colorspace_name, colorspace_name, sizeof(header->entry[i].colorspace_name));
-
- return i;
-}
-
-static int seq_disk_cache_get_header_entry(SeqCacheKey *key, DiskCacheHeader *header)
-{
- for (int i = 0; i < DCACHE_IMAGES_PER_FILE; i++) {
- if (header->entry[i].frameno == key->frame_index) {
- return i;
- }
- }
-
- return -1;
-}
-
-static bool seq_disk_cache_write_file(SeqDiskCache *disk_cache, SeqCacheKey *key, ImBuf *ibuf)
-{
- char path[FILE_MAX];
-
- seq_disk_cache_get_file_path(disk_cache, key, path, sizeof(path));
- BLI_make_existing_file(path);
-
- FILE *file = BLI_fopen(path, "rb+");
- if (!file) {
- file = BLI_fopen(path, "wb+");
- if (!file) {
- return false;
- }
- seq_disk_cache_add_file_to_list(disk_cache, path);
- }
-
- DiskCacheFile *cache_file = seq_disk_cache_get_file_entry_by_path(disk_cache, path);
- DiskCacheHeader header;
- memset(&header, 0, sizeof(header));
- /* #BLI_make_existing_file() above may create an empty file. This is fine, don't attempt reading
- * the header in that case. */
- if (cache_file->fstat.st_size != 0 && !seq_disk_cache_read_header(file, &header)) {
- fclose(file);
- seq_disk_cache_delete_file(disk_cache, cache_file);
- return false;
- }
- int entry_index = seq_disk_cache_add_header_entry(key, ibuf, &header);
-
- size_t bytes_written = deflate_imbuf_to_file(
- ibuf, file, seq_disk_cache_compression_level(), &header.entry[entry_index]);
-
- if (bytes_written != 0) {
- /* Last step is writing header, as image data can be overwritten,
- * but missing data would cause problems.
- */
- header.entry[entry_index].size_compressed = bytes_written;
- seq_disk_cache_write_header(file, &header);
- seq_disk_cache_update_file(disk_cache, path);
- fclose(file);
-
- return true;
- }
-
- return false;
-}
-
-static ImBuf *seq_disk_cache_read_file(SeqDiskCache *disk_cache, SeqCacheKey *key)
-{
- char path[FILE_MAX];
- DiskCacheHeader header;
-
- seq_disk_cache_get_file_path(disk_cache, key, path, sizeof(path));
- BLI_make_existing_file(path);
-
- FILE *file = BLI_fopen(path, "rb");
- if (!file) {
- return NULL;
- }
-
- if (!seq_disk_cache_read_header(file, &header)) {
- fclose(file);
- return NULL;
- }
- int entry_index = seq_disk_cache_get_header_entry(key, &header);
-
- /* Item not found. */
- if (entry_index < 0) {
- fclose(file);
- return NULL;
- }
-
- ImBuf *ibuf;
- uint64_t size_char = (uint64_t)key->context.rectx * key->context.recty * 4;
- uint64_t size_float = (uint64_t)key->context.rectx * key->context.recty * 16;
- size_t expected_size;
-
- if (header.entry[entry_index].size_raw == size_char) {
- expected_size = size_char;
- ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rect);
- IMB_colormanagement_assign_rect_colorspace(ibuf, header.entry[entry_index].colorspace_name);
- }
- else if (header.entry[entry_index].size_raw == size_float) {
- expected_size = size_float;
- ibuf = IMB_allocImBuf(key->context.rectx, key->context.recty, 32, IB_rectfloat);
- IMB_colormanagement_assign_float_colorspace(ibuf, header.entry[entry_index].colorspace_name);
- }
- else {
- fclose(file);
- return NULL;
- }
-
- size_t bytes_read = inflate_file_to_imbuf(ibuf, file, &header.entry[entry_index]);
-
- /* Sanity check. */
- if (bytes_read != expected_size) {
- fclose(file);
- IMB_freeImBuf(ibuf);
- return NULL;
- }
- BLI_file_touch(path);
- seq_disk_cache_update_file(disk_cache, path);
- fclose(file);
-
- return ibuf;
-}
-
-#undef DCACHE_FNAME_FORMAT
-#undef DCACHE_IMAGES_PER_FILE
-#undef COLORSPACE_NAME_MAX
-#undef DCACHE_CURRENT_VERSION
static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
{
@@ -778,14 +151,14 @@ 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 || type == SEQ_CACHE_STORE_THUMBNAIL) {
+ if (ELEM(type, SEQ_CACHE_STORE_RAW, SEQ_CACHE_STORE_THUMBNAIL)) {
return seq_give_frame_index(seq, timeline_frame);
}
return timeline_frame - seq->start;
}
-static float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index)
+float seq_cache_frame_index_to_timeline_frame(Sequence *seq, float frame_index)
{
return frame_index + seq->start;
}
@@ -1080,9 +453,6 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene)
return finalkey;
}
-/* Find only "base" keys.
- * Sources(other types) for a frame must be freed all at once.
- */
bool seq_cache_recycle_item(Scene *scene)
{
SeqCache *cache = seq_cache_get_from_scene(scene);
@@ -1131,28 +501,6 @@ static void seq_cache_set_temp_cache_linked(Scene *scene, SeqCacheKey *base)
}
}
-static void seq_disk_cache_create(Main *bmain, Scene *scene)
-{
- BLI_mutex_lock(&cache_create_lock);
- SeqCache *cache = seq_cache_get_from_scene(scene);
-
- if (cache == NULL) {
- return;
- }
-
- if (cache->disk_cache != NULL) {
- return;
- }
-
- cache->disk_cache = MEM_callocN(sizeof(SeqDiskCache), "SeqDiskCache");
- cache->disk_cache->bmain = bmain;
- BLI_mutex_init(&cache->disk_cache->read_write_mutex);
- seq_disk_cache_handle_versioning(cache->disk_cache);
- seq_disk_cache_get_files(cache->disk_cache, seq_disk_cache_base_dir());
- cache->disk_cache->timestamp = scene->ed->disk_cache_timestamp;
- BLI_mutex_unlock(&cache_create_lock);
-}
-
static void seq_cache_create(Main *bmain, Scene *scene)
{
BLI_mutex_lock(&cache_create_lock);
@@ -1246,9 +594,7 @@ void seq_cache_destruct(Scene *scene)
BLI_mutex_end(&cache->iterator_mutex);
if (cache->disk_cache != NULL) {
- BLI_freelistN(&cache->disk_cache->files);
- BLI_mutex_end(&cache->disk_cache->read_write_mutex);
- MEM_freeN(cache->disk_cache);
+ seq_disk_cache_free(cache->disk_cache);
}
MEM_freeN(cache);
@@ -1297,7 +643,7 @@ void seq_cache_cleanup_sequence(Scene *scene,
}
if (seq_disk_cache_is_enabled(cache->bmain) && cache->disk_cache != NULL) {
- seq_disk_cache_invalidate(scene, seq, seq_changed, invalidate_types);
+ seq_disk_cache_invalidate(cache->disk_cache, scene, seq, seq_changed, invalidate_types);
}
seq_cache_lock(scene);
@@ -1434,12 +780,10 @@ struct ImBuf *seq_cache_get(const SeqRenderData *context,
/* Try disk cache: */
if (seq_disk_cache_is_enabled(context->bmain)) {
if (cache->disk_cache == NULL) {
- seq_disk_cache_create(context->bmain, context->scene);
+ cache->disk_cache = seq_disk_cache_create(context->bmain, context->scene);
}
- BLI_mutex_lock(&cache->disk_cache->read_write_mutex);
ibuf = seq_disk_cache_read_file(cache->disk_cache, &key);
- BLI_mutex_unlock(&cache->disk_cache->read_write_mutex);
if (ibuf == NULL) {
return NULL;
@@ -1550,9 +894,7 @@ void seq_cache_put(
seq_disk_cache_create(context->bmain, context->scene);
}
- BLI_mutex_lock(&cache->disk_cache->read_write_mutex);
seq_disk_cache_write_file(cache->disk_cache, key, i);
- BLI_mutex_unlock(&cache->disk_cache->read_write_mutex);
seq_disk_cache_enforce_limits(cache->disk_cache);
}
}
diff --git a/source/blender/sequencer/intern/image_cache.h b/source/blender/sequencer/intern/image_cache.h
index 60031311985..65732b5d83d 100644
--- a/source/blender/sequencer/intern/image_cache.h
+++ b/source/blender/sequencer/intern/image_cache.h
@@ -27,15 +27,29 @@
extern "C" {
#endif
+#include "SEQ_render.h" /* Needed for #eSeqTaskId. */
+
struct ImBuf;
struct Main;
struct Scene;
struct SeqRenderData;
struct Sequence;
-#ifdef __cplusplus
-}
-#endif
+typedef struct SeqCacheKey {
+ struct SeqCache *cache_owner;
+ void *userkey;
+ struct SeqCacheKey *link_prev; /* Used for linking intermediate items to final frame. */
+ struct SeqCacheKey *link_next; /* Used for linking intermediate items to final frame. */
+ struct Sequence *seq;
+ struct SeqRenderData context;
+ float frame_index; /* Usually same as timeline_frame. Mapped to media for RAW entries. */
+ float timeline_frame; /* Only for reference - used for freeing when cache is full. */
+ float cost; /* In short: render time(s) divided by playback frame duration(s) */
+ bool is_temp_cache; /* this cache entry will be freed before rendering next frame */
+ /* ID of task for assigning temp cache entries to particular task(thread, etc.) */
+ eSeqTaskId task_id;
+ int type;
+} SeqCacheKey;
struct ImBuf *seq_cache_get(const struct SeqRenderData *context,
struct Sequence *seq,
@@ -56,6 +70,10 @@ bool seq_cache_put_if_possible(const struct SeqRenderData *context,
float timeline_frame,
int type,
struct ImBuf *nval);
+/**
+ * Find only "base" keys.
+ * Sources(other types) for a frame must be freed all at once.
+ */
bool seq_cache_recycle_item(struct Scene *scene);
void seq_cache_free_temp_cache(struct Scene *scene, short id, int timeline_frame);
void seq_cache_destruct(struct Scene *scene);
@@ -67,6 +85,7 @@ void seq_cache_cleanup_sequence(struct Scene *scene,
bool force_seq_changed_range);
void seq_cache_thumbnail_cleanup(Scene *scene, rctf *view_area);
bool seq_cache_is_full(void);
+float seq_cache_frame_index_to_timeline_frame(struct Sequence *seq, float frame_index);
#ifdef __cplusplus
}
diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c
index 2429405350b..6cd53f08b3a 100644
--- a/source/blender/sequencer/intern/iterator.c
+++ b/source/blender/sequencer/intern/iterator.c
@@ -44,18 +44,6 @@
/** \Iterator API
* \{ */
-/**
- * Utility function for SEQ_ITERATOR_FOREACH macro.
- * Ensure, that iterator is initialized. During initialization return pointer to collection element
- * and step gset iterator. When this function is called after iterator has been initialized, it
- * will do nothing and return true.
- *
- * \param collection: collection to iterate
- * \param iterator: iterator to be initialized
- * \param r_seq: pointer to Sequence pointer
- *
- * \return false when iterator can not be initialized, true otherwise
- */
bool SEQ_iterator_ensure(SeqCollection *collection, SeqIterator *iterator, Sequence **r_seq)
{
if (iterator->iterator_initialized) {
@@ -76,14 +64,6 @@ bool SEQ_iterator_ensure(SeqCollection *collection, SeqIterator *iterator, Seque
return true;
}
-/**
- * Utility function for SEQ_ITERATOR_FOREACH macro.
- * Yield collection element
- *
- * \param iterator: iterator to be initialized
- *
- * \return collection element or NULL when iteration has ended
- */
Sequence *SEQ_iterator_yield(SeqIterator *iterator)
{
Sequence *seq = BLI_gsetIterator_done(&iterator->gsi) ? NULL :
@@ -108,36 +88,17 @@ static bool seq_for_each_recursive(ListBase *seqbase, SeqForEachFunc callback, v
return true;
}
-/**
- * Utility function to recursively iterate through all sequence strips in a `seqbase` list.
- * Uses callback to do operations on each sequence element.
- * The callback can stop the iteration if needed.
- *
- * \param seqbase: #ListBase of sequences to be iterated over.
- * \param callback: query function callback, returns false if iteration should stop.
- * \param user_data: pointer to user data that can be used in the callback function.
- */
void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *user_data)
{
seq_for_each_recursive(seqbase, callback, user_data);
}
-/**
- * Free strip collection.
- *
- * \param collection: collection to be freed
- */
void SEQ_collection_free(SeqCollection *collection)
{
BLI_gset_free(collection->set, NULL);
MEM_freeN(collection);
}
-/**
- * Create new empty strip collection.
- *
- * \return empty strip collection.
- */
SeqCollection *SEQ_collection_create(const char *name)
{
SeqCollection *collection = MEM_callocN(sizeof(SeqCollection), name);
@@ -146,30 +107,16 @@ SeqCollection *SEQ_collection_create(const char *name)
return collection;
}
-/**
- * Return number of items in collection.
- */
uint SEQ_collection_len(const SeqCollection *collection)
{
return BLI_gset_len(collection->set);
}
-/**
- * Check if seq is in collection.
- */
bool SEQ_collection_has_strip(const Sequence *seq, const SeqCollection *collection)
{
return BLI_gset_haskey(collection->set, seq);
}
-/**
- * Query strips from seqbase. seq_reference is used by query function as filter condition.
- *
- * \param seq_reference: reference strip for query function
- * \param seqbase: ListBase in which strips are queried
- * \param seq_query_func: query function callback
- * \return strip collection
- */
SeqCollection *SEQ_query_by_reference(Sequence *seq_reference,
ListBase *seqbase,
void seq_query_func(Sequence *seq_reference,
@@ -180,40 +127,22 @@ SeqCollection *SEQ_query_by_reference(Sequence *seq_reference,
seq_query_func(seq_reference, seqbase, collection);
return collection;
}
-/**
- * Add strip to collection.
- *
- * \param seq: strip to be added
- * \param collection: collection to which strip will be added
- * \return false if strip is already in set, otherwise true
- */
bool SEQ_collection_append_strip(Sequence *seq, SeqCollection *collection)
{
- if (BLI_gset_lookup(collection->set, seq) != NULL) {
+ void **key;
+ if (BLI_gset_ensure_p_ex(collection->set, seq, &key)) {
return false;
}
- BLI_gset_insert(collection->set, seq);
+
+ *key = (void *)seq;
return true;
}
-/**
- * Remove strip from collection.
- *
- * \param seq: strip to be removed
- * \param collection: collection from which strip will be removed
- * \return true if strip exists in set and it was removed from set, otherwise false
- */
bool SEQ_collection_remove_strip(Sequence *seq, SeqCollection *collection)
{
return BLI_gset_remove(collection->set, seq, NULL);
}
-/**
- * Move strips from collection_src to collection_dst. Source collection will be freed.
- *
- * \param collection_dst: destination collection
- * \param collection_src: source collection
- */
void SEQ_collection_merge(SeqCollection *collection_dst, SeqCollection *collection_src)
{
Sequence *seq;
@@ -223,13 +152,6 @@ void SEQ_collection_merge(SeqCollection *collection_dst, SeqCollection *collecti
SEQ_collection_free(collection_src);
}
-/**
- * Remove strips from collection that are also in `exclude_elements`. Source collection will be
- * freed.
- *
- * \param collection: collection from which strips are removed
- * \param exclude_elements: collection of strips to be removed
- */
void SEQ_collection_exclude(SeqCollection *collection, SeqCollection *exclude_elements)
{
Sequence *seq;
@@ -239,14 +161,6 @@ void SEQ_collection_exclude(SeqCollection *collection, SeqCollection *exclude_el
SEQ_collection_free(exclude_elements);
}
-/**
- * Expand collection by running SEQ_query() for each strip, which will be used as reference.
- * Results of these queries will be merged into provided collection.
- *
- * \param seqbase: ListBase in which strips are queried
- * \param collection: SeqCollection to be expanded
- * \param seq_query_func: query function callback
- */
void SEQ_collection_expand(ListBase *seqbase,
SeqCollection *collection,
void seq_query_func(Sequence *seq_reference,
@@ -265,12 +179,6 @@ void SEQ_collection_expand(ListBase *seqbase,
SEQ_collection_merge(collection, query_matches);
}
-/**
- * Duplicate collection
- *
- * \param collection: collection to be duplicated
- * \return duplicate of collection
- */
SeqCollection *SEQ_collection_duplicate(SeqCollection *collection)
{
SeqCollection *duplicate = SEQ_collection_create(__func__);
@@ -293,12 +201,6 @@ static void query_all_strips_recursive(ListBase *seqbase, SeqCollection *collect
}
}
-/**
- * Query all strips in seqbase and nested meta strips.
- *
- * \param seqbase: ListBase in which strips are queried
- * \return strip collection
- */
SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
@@ -311,25 +213,15 @@ SeqCollection *SEQ_query_all_strips_recursive(ListBase *seqbase)
return collection;
}
-/**
- * Query all strips in seqbase. This does not include strips nested in meta strips.
- *
- * \param seqbase: ListBase in which strips are queried
- * \return strip collection
- */
SeqCollection *SEQ_query_all_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
- query_all_strips_recursive(seqbase, collection);
+ LISTBASE_FOREACH (Sequence *, seq, seqbase) {
+ SEQ_collection_append_strip(seq, collection);
+ }
return collection;
}
-/**
- * Query all selected strips in seqbase.
- *
- * \param seqbase: ListBase in which strips are queried
- * \return strip collection
- */
SeqCollection *SEQ_query_selected_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
@@ -430,14 +322,6 @@ static void collection_filter_rendered_strips(SeqCollection *collection)
}
}
-/**
- * Query strips that are rendered at \a timeline_frame when \a displayed channel is viewed
- *
- * \param seqbase: ListBase in which strips are queried
- * \param timeline_frame: viewed frame
- * \param displayed_channel: viewed channel. when set to 0, no channel filter is applied
- * \return strip collection
- */
SeqCollection *SEQ_query_rendered_strips(ListBase *seqbase,
const int timeline_frame,
const int displayed_channel)
@@ -450,12 +334,6 @@ SeqCollection *SEQ_query_rendered_strips(ListBase *seqbase,
return collection;
}
-/**
- * Query all unselected strips in seqbase.
- *
- * \param seqbase: ListBase in which strips are queried
- * \return strip collection
- */
SeqCollection *SEQ_query_unselected_strips(ListBase *seqbase)
{
SeqCollection *collection = SEQ_collection_create(__func__);
@@ -468,15 +346,6 @@ SeqCollection *SEQ_query_unselected_strips(ListBase *seqbase)
return collection;
}
-/**
- * Query all effect strips that are directly or indirectly connected to seq_reference.
- * This includes all effects of seq_reference, strips used by another inputs and their effects, so
- * that whole chain is fully independent of other strips.
- *
- * \param seq_reference: reference strip
- * \param seqbase: ListBase in which strips are queried
- * \param collection: collection to be filled
- */
void SEQ_query_strip_effect_chain(Sequence *seq_reference,
ListBase *seqbase,
SeqCollection *collection)
diff --git a/source/blender/sequencer/intern/modifier.c b/source/blender/sequencer/intern/modifier.c
index 07d09f4ae17..00ae88232fd 100644
--- a/source/blender/sequencer/intern/modifier.c
+++ b/source/blender/sequencer/intern/modifier.c
@@ -216,7 +216,7 @@ static void modifier_apply_threaded(ImBuf *ibuf,
/** \name Color Balance Modifier
* \{ */
-static StripColorBalance calc_cb(StripColorBalance *cb_)
+static StripColorBalance calc_cb_lgg(StripColorBalance *cb_)
{
StripColorBalance cb = *cb_;
int c;
@@ -262,8 +262,52 @@ static StripColorBalance calc_cb(StripColorBalance *cb_)
return cb;
}
+static StripColorBalance calc_cb_sop(StripColorBalance *cb_)
+{
+ StripColorBalance cb = *cb_;
+ int c;
+
+ for (c = 0; c < 3; c++) {
+ if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_SLOPE) {
+ if (cb.slope[c] != 0.0f) {
+ cb.slope[c] = 1.0f / cb.slope[c];
+ }
+ else {
+ cb.slope[c] = 1000000;
+ }
+ }
+
+ if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_OFFSET) {
+ cb.offset[c] = -1.0f * (cb.offset[c] - 1.0f);
+ }
+ else {
+ cb.offset[c] = cb.offset[c] - 1.0f;
+ }
+
+ if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_POWER)) {
+ if (cb.power[c] != 0.0f) {
+ cb.power[c] = 1.0f / cb.power[c];
+ }
+ else {
+ cb.power[c] = 1000000;
+ }
+ }
+ }
+
+ return cb;
+}
+
+static StripColorBalance calc_cb(StripColorBalance *cb_)
+{
+ if (cb_->method == SEQ_COLOR_BALANCE_METHOD_LIFTGAMMAGAIN) {
+ return calc_cb_lgg(cb_);
+ }
+ /* `cb_->method == SEQ_COLOR_BALANCE_METHOD_SLOPEOFFSETPOWER`. */
+ return calc_cb_sop(cb_);
+}
+
/* NOTE: lift is actually 2-lift. */
-MINLINE float color_balance_fl(
+MINLINE float color_balance_fl_lgg(
float in, const float lift, const float gain, const float gamma, const float mul)
{
float x = (((in - 1.0f) * lift) + 1.0f) * gain;
@@ -278,12 +322,40 @@ MINLINE float color_balance_fl(
return x;
}
-static void make_cb_table_float(float lift, float gain, float gamma, float *table, float mul)
+MINLINE float color_balance_fl_sop(float in,
+ const float slope,
+ const float offset,
+ const float power,
+ const float pivot,
+ float mul)
{
- int y;
+ float x = in * slope + offset;
+
+ /* prevent NaN */
+ if (x < 0.0f) {
+ x = 0.0f;
+ }
- for (y = 0; y < 256; y++) {
- float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
+ x = powf(x / pivot, power) * pivot;
+ x *= mul;
+ CLAMP(x, FLT_MIN, FLT_MAX);
+ return x;
+}
+
+static void make_cb_table_float_lgg(float lift, float gain, float gamma, float *table, float mul)
+{
+ for (int y = 0; y < 256; y++) {
+ float v = color_balance_fl_lgg((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
+
+ table[y] = v;
+ }
+}
+
+static void make_cb_table_float_sop(
+ float slope, float offset, float power, float pivot, float *table, float mul)
+{
+ for (int y = 0; y < 256; y++) {
+ float v = color_balance_fl_sop((float)y * (1.0f / 255.0f), slope, offset, power, pivot, mul);
table[y] = v;
}
@@ -310,7 +382,13 @@ static void color_balance_byte_byte(StripColorBalance *cb_,
straight_uchar_to_premul_float(p, cp);
for (c = 0; c < 3; c++) {
- float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+ float t;
+ if (cb.method == SEQ_COLOR_BALANCE_METHOD_LIFTGAMMAGAIN) {
+ t = color_balance_fl_lgg(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+ }
+ else {
+ t = color_balance_fl_sop(p[c], cb.slope[c], cb.offset[c], cb.power[c], 1.0, mul);
+ }
if (m) {
float m_normal = (float)m[c] / 255.0f;
@@ -352,7 +430,12 @@ static void color_balance_byte_float(StripColorBalance *cb_,
cb = calc_cb(cb_);
for (c = 0; c < 3; c++) {
- make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
+ if (cb.method == SEQ_COLOR_BALANCE_METHOD_LIFTGAMMAGAIN) {
+ make_cb_table_float_lgg(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
+ }
+ else {
+ make_cb_table_float_sop(cb.slope[c], cb.offset[c], cb.power[c], 1.0, cb_tab[c], mul);
+ }
}
for (i = 0; i < 256; i++) {
@@ -397,7 +480,13 @@ static void color_balance_float_float(StripColorBalance *cb_,
while (p < e) {
int c;
for (c = 0; c < 3; c++) {
- float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+ float t;
+ if (cb_->method == SEQ_COLOR_BALANCE_METHOD_LIFTGAMMAGAIN) {
+ t = color_balance_fl_lgg(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
+ }
+ else {
+ t = color_balance_fl_sop(p[c], cb.slope[c], cb.offset[c], cb.power[c], 1.0, mul);
+ }
if (m) {
p[c] = p[c] * (1.0f - m[c]) + t * m[c];
@@ -507,11 +596,15 @@ static void colorBalance_init_data(SequenceModifierData *smd)
int c;
cbmd->color_multiply = 1.0f;
+ cbmd->color_balance.method = 0;
for (c = 0; c < 3; c++) {
cbmd->color_balance.lift[c] = 1.0f;
cbmd->color_balance.gamma[c] = 1.0f;
cbmd->color_balance.gain[c] = 1.0f;
+ cbmd->color_balance.slope[c] = 1.0f;
+ cbmd->color_balance.offset[c] = 1.0f;
+ cbmd->color_balance.power[c] = 1.0f;
}
}
@@ -1068,6 +1161,7 @@ static void maskmodifier_apply(struct SequenceModifierData *UNUSED(smd), ImBuf *
// SequencerMaskModifierData *bcmd = (SequencerMaskModifierData *)smd;
modifier_apply_threaded(ibuf, mask, maskmodifier_apply_threaded, NULL);
+ ibuf->planes = R_IMF_PLANES_RGBA;
}
static SequenceModifierTypeInfo seqModifier_Mask = {
diff --git a/source/blender/sequencer/intern/multiview.c b/source/blender/sequencer/intern/multiview.c
index e120234ed8b..68d2a33fd5c 100644
--- a/source/blender/sequencer/intern/multiview.c
+++ b/source/blender/sequencer/intern/multiview.c
@@ -40,7 +40,6 @@ void seq_anim_add_suffix(Scene *scene, struct anim *anim, const int view_id)
IMB_suffix_anim(anim, suffix);
}
-/* the number of files will vary according to the stereo format */
int seq_num_files(Scene *scene, char views_format, const bool is_multiview)
{
if (!is_multiview) {
diff --git a/source/blender/sequencer/intern/multiview.h b/source/blender/sequencer/intern/multiview.h
index bbc66c6f84c..79d99c88b50 100644
--- a/source/blender/sequencer/intern/multiview.h
+++ b/source/blender/sequencer/intern/multiview.h
@@ -36,14 +36,17 @@ struct Scene;
* **********************************************************************
*/
-void seq_anim_add_suffix(struct Scene *scene, struct anim *anim, const int view_id);
+void seq_anim_add_suffix(struct Scene *scene, struct anim *anim, int view_id);
void seq_multiview_name(struct Scene *scene,
- const int view_id,
+ int view_id,
const char *prefix,
const char *ext,
char *r_path,
size_t r_size);
-int seq_num_files(struct Scene *scene, char views_format, const bool is_multiview);
+/**
+ * The number of files will vary according to the stereo format.
+ */
+int seq_num_files(struct Scene *scene, char views_format, bool is_multiview);
#ifdef __cplusplus
}
diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c
index 3e0b4738db1..42affae26ed 100644
--- a/source/blender/sequencer/intern/prefetch.c
+++ b/source/blender/sequencer/intern/prefetch.c
@@ -162,14 +162,12 @@ static Sequence *sequencer_prefetch_get_original_sequence(Sequence *seq, ListBas
return NULL;
}
-/* for cache context swapping */
Sequence *seq_prefetch_get_original_sequence(Sequence *seq, Scene *scene)
{
Editing *ed = scene->ed;
return sequencer_prefetch_get_original_sequence(seq, &ed->seqbase);
}
-/* for cache context swapping */
SeqRenderData *seq_prefetch_get_original_context(const SeqRenderData *context)
{
PrefetchJob *pfjob = seq_prefetch_job_get(context->scene);
@@ -268,9 +266,6 @@ void SEQ_prefetch_stop_all(void)
}
}
-/* Use also to update scene and context changes
- * This function should almost always be called by cache invalidation, not directly.
- */
void SEQ_prefetch_stop(Scene *scene)
{
PrefetchJob *pfjob;
@@ -333,6 +328,20 @@ static void seq_prefetch_update_scene(Scene *scene)
seq_prefetch_init_depsgraph(pfjob);
}
+static void seq_prefetch_update_active_seqbase(PrefetchJob *pfjob)
+{
+ MetaStack *ms_orig = SEQ_meta_stack_active_get(SEQ_editing_get(pfjob->scene));
+ Editing *ed_eval = SEQ_editing_get(pfjob->scene_eval);
+
+ if (ms_orig != NULL) {
+ Sequence *meta_eval = seq_prefetch_get_original_sequence(ms_orig->parseq, pfjob->scene_eval);
+ SEQ_seqbase_active_set(ed_eval, &meta_eval->seqbase);
+ }
+ else {
+ SEQ_seqbase_active_set(ed_eval, &ed_eval->seqbase);
+ }
+}
+
static void seq_prefetch_resume(Scene *scene)
{
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
@@ -491,7 +500,7 @@ static void *seq_prefetch_frames(void *job)
*/
pfjob->scene_eval->ed->prefetch_job = pfjob;
- ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(pfjob->scene));
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(pfjob->scene_eval));
if (seq_prefetch_must_skip_frame(pfjob, seqbase)) {
pfjob->num_frames_prefetched++;
continue;
@@ -554,6 +563,7 @@ static PrefetchJob *seq_prefetch_start_ex(const SeqRenderData *context, float cf
seq_prefetch_update_scene(context->scene);
seq_prefetch_update_context(context);
+ seq_prefetch_update_active_seqbase(pfjob);
BLI_threadpool_remove(&pfjob->threads, pfjob);
BLI_threadpool_insert(&pfjob->threads, pfjob);
@@ -561,7 +571,6 @@ static PrefetchJob *seq_prefetch_start_ex(const SeqRenderData *context, float cf
return pfjob;
}
-/* Start or resume prefetching. */
void seq_prefetch_start(const SeqRenderData *context, float timeline_frame)
{
Scene *scene = context->scene;
diff --git a/source/blender/sequencer/intern/prefetch.h b/source/blender/sequencer/intern/prefetch.h
index 8cfc6bf90bd..8cc5f6d35d1 100644
--- a/source/blender/sequencer/intern/prefetch.h
+++ b/source/blender/sequencer/intern/prefetch.h
@@ -35,11 +35,20 @@ struct Sequence;
}
#endif
+/**
+ * Start or resume prefetching.
+ */
void seq_prefetch_start(const struct SeqRenderData *context, float timeline_frame);
void seq_prefetch_free(struct Scene *scene);
bool seq_prefetch_job_is_running(struct Scene *scene);
void seq_prefetch_get_time_range(struct Scene *scene, int *start, int *end);
+/**
+ * For cache context swapping.
+ */
struct SeqRenderData *seq_prefetch_get_original_context(const struct SeqRenderData *context);
+/**
+ * For cache context swapping.
+ */
struct Sequence *seq_prefetch_get_original_sequence(struct Sequence *seq, struct Scene *scene);
#ifdef __cplusplus
diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c
index 2bc294c91cd..5982f89a287 100644
--- a/source/blender/sequencer/intern/proxy.c
+++ b/source/blender/sequencer/intern/proxy.c
@@ -34,6 +34,7 @@
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
+#include "BLI_session_uuid.h"
#include "BLI_string.h"
#ifdef WIN32
@@ -54,6 +55,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_metadata.h"
+#include "SEQ_iterator.h"
#include "SEQ_proxy.h"
#include "SEQ_relations.h"
#include "SEQ_render.h"
@@ -79,6 +81,7 @@ typedef struct SeqIndexBuildContext {
Depsgraph *depsgraph;
Scene *scene;
Sequence *seq, *orig_seq;
+ SessionUUID orig_seq_uuid;
} SeqIndexBuildContext;
int SEQ_rendersize_to_proxysize(int render_size)
@@ -412,7 +415,8 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
Scene *scene,
Sequence *seq,
struct GSet *file_list,
- ListBase *queue)
+ ListBase *queue,
+ bool build_only_on_bad_performance)
{
SeqIndexBuildContext *context;
Sequence *nseq;
@@ -458,6 +462,7 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
context->depsgraph = depsgraph;
context->scene = scene;
context->orig_seq = seq;
+ context->orig_seq_uuid = seq->runtime.session_uuid;
context->seq = nseq;
context->view_id = i; /* only for images */
@@ -472,7 +477,8 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
context->size_flags,
context->quality,
context->overwrite,
- file_list);
+ file_list,
+ build_only_on_bad_performance);
}
if (!context->index_context) {
MEM_freeN(context);
@@ -560,6 +566,18 @@ void SEQ_proxy_rebuild(SeqIndexBuildContext *context,
}
}
+static bool seq_orig_free_anims(Sequence *seq_iter, void *data)
+{
+ SessionUUID orig_seq_uuid = ((SeqIndexBuildContext *)data)->orig_seq_uuid;
+
+ if (BLI_session_uuid_is_equal(&seq_iter->runtime.session_uuid, &orig_seq_uuid)) {
+ for (StripAnim *sanim = seq_iter->anims.first; sanim; sanim = sanim->next) {
+ IMB_close_anim_proxies(sanim->anim);
+ }
+ }
+ return true;
+}
+
void SEQ_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
{
if (context->index_context) {
@@ -569,14 +587,13 @@ void SEQ_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
IMB_close_anim_proxies(sanim->anim);
}
- for (sanim = context->orig_seq->anims.first; sanim; sanim = sanim->next) {
- IMB_close_anim_proxies(sanim->anim);
- }
+ /* `context->seq_orig` may have been removed during building. */
+ SEQ_for_each_callback(&context->scene->ed->seqbase, seq_orig_free_anims, context);
IMB_anim_index_rebuild_finish(context->index_context, stop);
}
- seq_free_sequence_recurse(NULL, context->seq, true, true);
+ seq_free_sequence_recurse(NULL, context->seq, true);
MEM_freeN(context);
}
@@ -586,10 +603,7 @@ void SEQ_proxy_set(struct Sequence *seq, bool value)
if (value) {
seq->flag |= SEQ_USE_PROXY;
if (seq->strip->proxy == NULL) {
- seq->strip->proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy");
- seq->strip->proxy->quality = 50;
- seq->strip->proxy->build_tc_flags = SEQ_PROXY_TC_ALL;
- seq->strip->proxy->build_size_flags = SEQ_PROXY_IMAGE_SIZE_25;
+ seq->strip->proxy = seq_strip_proxy_alloc();
}
}
else {
diff --git a/source/blender/sequencer/intern/proxy.h b/source/blender/sequencer/intern/proxy.h
index a65fdcd42fe..e92cd8de429 100644
--- a/source/blender/sequencer/intern/proxy.h
+++ b/source/blender/sequencer/intern/proxy.h
@@ -36,7 +36,7 @@ struct anim;
struct ImBuf *seq_proxy_fetch(const struct SeqRenderData *context,
struct Sequence *seq,
int timeline_frame);
-bool seq_proxy_get_custom_file_fname(struct Sequence *seq, char *name, const int view_id);
+bool seq_proxy_get_custom_file_fname(struct Sequence *seq, char *name, int view_id);
void free_proxy_seq(Sequence *seq);
void seq_proxy_index_dir_set(struct anim *anim, const char *base_dir);
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index cf3f9d5cba5..482425e70d3 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -29,6 +29,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
+#include "DNA_defaults.h"
#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
@@ -69,6 +70,7 @@
#include "SEQ_iterator.h"
#include "SEQ_modifier.h"
#include "SEQ_proxy.h"
+#include "SEQ_relations.h"
#include "SEQ_render.h"
#include "SEQ_sequencer.h"
#include "SEQ_time.h"
@@ -96,6 +98,7 @@ SequencerDrawView sequencer_view3d_fn = NULL; /* NULL in background mode */
/* -------------------------------------------------------------------- */
/** \name Color-space utility functions
* \{ */
+
void seq_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
{
#if 0
@@ -212,6 +215,7 @@ void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4
/* -------------------------------------------------------------------- */
/** \name Rendering utility functions
* \{ */
+
void SEQ_render_new_render_data(Main *bmain,
struct Depsgraph *depsgraph,
Scene *scene,
@@ -300,25 +304,24 @@ int seq_get_shown_sequences(ListBase *seqbase,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Preprocessing and effects
- * \{ */
-/*
- * input preprocessing for SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP and SEQ_TYPE_SCENE
+/** \name Preprocessing & Effects
+ *
+ * Input preprocessing for SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP and SEQ_TYPE_SCENE.
*
* Do all the things you can't really do afterwards using sequence effects
- * (read: before rescaling to render resolution has been done)
+ * (read: before re-scaling to render resolution has been done).
*
* Order is important!
*
- * - Deinterlace
- * - Crop and transform in image source coordinate space
- * - Flip X + Flip Y (could be done afterwards, backward compatibility)
- * - Promote image to float data (affects pipeline operations afterwards)
+ * - De-interlace.
+ * - Crop and transform in image source coordinate space.
+ * - Flip X + Flip Y (could be done afterwards, backward compatibility).
+ * - Promote image to float data (affects pipeline operations afterwards).
* - Color balance (is most efficient in the byte -> float
* (future: half -> float should also work fine!)
- * case, if done on load, since we can use lookup tables)
- * - Premultiply
- */
+ * case, if done on load, since we can use lookup tables).
+ * - Pre-multiply.
+ * \{ */
static bool sequencer_use_transform(const Sequence *seq)
{
@@ -402,7 +405,7 @@ static void sequencer_image_crop_transform_matrix(const Sequence *seq,
const ImBuf *out,
const float image_scale_factor,
const float preview_scale_factor,
- float r_transform_matrix[3][3])
+ float r_transform_matrix[4][4])
{
const StripTransform *transform = seq->strip->transform;
const float scale_x = transform->scale_x * image_scale_factor;
@@ -411,13 +414,16 @@ static void sequencer_image_crop_transform_matrix(const Sequence *seq,
const float image_center_offs_y = (out->y - in->y) / 2;
const float translate_x = transform->xofs * preview_scale_factor + image_center_offs_x;
const float translate_y = transform->yofs * preview_scale_factor + image_center_offs_y;
- const float pivot[2] = {in->x * transform->origin[0], in->y * transform->origin[1]};
- loc_rot_size_to_mat3(r_transform_matrix,
- (const float[]){translate_x, translate_y},
- transform->rotation,
- (const float[]){scale_x, scale_y});
- transform_pivot_set_m3(r_transform_matrix, pivot);
- invert_m3(r_transform_matrix);
+ const float pivot[3] = {in->x * transform->origin[0], in->y * transform->origin[1], 0.0f};
+
+ float rotation_matrix[3][3];
+ axis_angle_to_mat3_single(rotation_matrix, 'Z', transform->rotation);
+ loc_rot_size_to_mat4(r_transform_matrix,
+ (const float[]){translate_x, translate_y, 0.0f},
+ rotation_matrix,
+ (const float[]){scale_x, scale_y, 1.0f});
+ transform_pivot_set_m4(r_transform_matrix, pivot);
+ invert_m4(r_transform_matrix);
}
static void sequencer_image_crop_init(const Sequence *seq,
@@ -437,26 +443,64 @@ static void sequencer_image_crop_init(const Sequence *seq,
static void sequencer_thumbnail_transform(ImBuf *in, ImBuf *out)
{
float image_scale_factor = (float)out->x / in->x;
- float transform_matrix[3][3];
+ float transform_matrix[4][4];
/* Set to keep same loc,scale,rot but change scale to thumb size limit. */
const float scale_x = 1 * image_scale_factor;
const float scale_y = 1 * image_scale_factor;
const float image_center_offs_x = (out->x - in->x) / 2;
const float image_center_offs_y = (out->y - in->y) / 2;
- const float pivot[2] = {in->x / 2, in->y / 2};
- loc_rot_size_to_mat3(transform_matrix,
- (const float[]){image_center_offs_x, image_center_offs_y},
- 0,
- (const float[]){scale_x, scale_y});
- transform_pivot_set_m3(transform_matrix, pivot);
- invert_m3(transform_matrix);
-
- /* No crop. */
- rctf source_crop;
- BLI_rctf_init(&source_crop, 0, in->x, 0, in->y);
+ const float pivot[3] = {in->x / 2, in->y / 2, 0.0f};
+
+ float rotation_matrix[3][3];
+ unit_m3(rotation_matrix);
+ loc_rot_size_to_mat4(transform_matrix,
+ (const float[]){image_center_offs_x, image_center_offs_y, 0.0f},
+ rotation_matrix,
+ (const float[]){scale_x, scale_y, 1.0f});
+ transform_pivot_set_m4(transform_matrix, pivot);
+ invert_m4(transform_matrix);
+
+ IMB_transform(in, out, IMB_TRANSFORM_MODE_REGULAR, IMB_FILTER_NEAREST, transform_matrix, NULL);
+}
- IMB_transform(in, out, transform_matrix, &source_crop, IMB_FILTER_NEAREST);
+/* Check whether transform introduces transparent ares in the result (happens when the transformed
+ * image does not fully cover the render frame).
+ *
+ * The check is done by checking whether all corners of viewport fit inside of the transformed
+ * image. If they do not the image will have transparent areas. */
+static bool seq_image_transform_transparency_gained(const SeqRenderData *context, Sequence *seq)
+{
+ Scene *scene = context->scene;
+ const int x = context->rectx;
+ const int y = context->recty;
+
+ float seq_image_quad[4][2];
+ SEQ_image_transform_final_quad_get(scene, seq, seq_image_quad);
+ for (int i = 0; i < 4; i++) {
+ add_v2_v2(seq_image_quad[i], (float[]){x / 2, y / 2});
+ }
+
+ return !isect_point_quad_v2((float[]){x, y},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]) ||
+ !isect_point_quad_v2((float[]){0, y},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]) ||
+ !isect_point_quad_v2((float[]){x, 0},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]) ||
+ !isect_point_quad_v2((float[]){0, 0},
+ seq_image_quad[0],
+ seq_image_quad[1],
+ seq_image_quad[2],
+ seq_image_quad[3]);
}
static void sequencer_preprocess_transform_crop(
@@ -470,7 +514,7 @@ static void sequencer_preprocess_transform_crop(
const bool do_scale_to_render_size = seq_need_scale_to_render_size(seq, is_proxy_image);
const float image_scale_factor = do_scale_to_render_size ? 1.0f : preview_scale_factor;
- float transform_matrix[3][3];
+ float transform_matrix[4][4];
sequencer_image_crop_transform_matrix(
seq, in, out, image_scale_factor, preview_scale_factor, transform_matrix);
@@ -482,7 +526,14 @@ static void sequencer_preprocess_transform_crop(
const eIMBInterpolationFilterMode filter = context->for_render ? IMB_FILTER_BILINEAR :
IMB_FILTER_NEAREST;
- IMB_transform(in, out, transform_matrix, &source_crop, filter);
+ IMB_transform(in, out, IMB_TRANSFORM_MODE_CROP_SRC, filter, transform_matrix, &source_crop);
+
+ if (!seq_image_transform_transparency_gained(context, seq)) {
+ out->planes = in->planes;
+ }
+ else {
+ out->planes = R_IMF_PLANES_RGBA;
+ }
}
static void multibuf(ImBuf *ibuf, const float fmul)
@@ -518,6 +569,10 @@ static void multibuf(ImBuf *ibuf, const float fmul)
rt_float += 4;
}
}
+
+ if (ELEM(ibuf->planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB) && fmul < 1.0f) {
+ ibuf->planes = R_IMF_PLANES_RGBA;
+ }
}
static ImBuf *input_preprocess(const SeqRenderData *context,
@@ -629,7 +684,7 @@ typedef struct RenderEffectInitData {
struct SeqEffectHandle *sh;
const SeqRenderData *context;
Sequence *seq;
- float timeline_frame, facf0, facf1;
+ float timeline_frame, fac;
ImBuf *ibuf1, *ibuf2, *ibuf3;
ImBuf *out;
@@ -639,7 +694,7 @@ typedef struct RenderEffectThread {
struct SeqEffectHandle *sh;
const SeqRenderData *context;
Sequence *seq;
- float timeline_frame, facf0, facf1;
+ float timeline_frame, fac;
ImBuf *ibuf1, *ibuf2, *ibuf3;
ImBuf *out;
@@ -658,8 +713,7 @@ static void render_effect_execute_init_handle(void *handle_v,
handle->context = init_data->context;
handle->seq = init_data->seq;
handle->timeline_frame = init_data->timeline_frame;
- handle->facf0 = init_data->facf0;
- handle->facf1 = init_data->facf1;
+ handle->fac = init_data->fac;
handle->ibuf1 = init_data->ibuf1;
handle->ibuf2 = init_data->ibuf2;
handle->ibuf3 = init_data->ibuf3;
@@ -676,8 +730,7 @@ static void *render_effect_execute_do_thread(void *thread_data_v)
thread_data->sh->execute_slice(thread_data->context,
thread_data->seq,
thread_data->timeline_frame,
- thread_data->facf0,
- thread_data->facf1,
+ thread_data->fac,
thread_data->ibuf1,
thread_data->ibuf2,
thread_data->ibuf3,
@@ -692,8 +745,7 @@ ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh,
const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
- float facf0,
- float facf1,
+ float fac,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
@@ -705,8 +757,7 @@ ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh,
init_data.context = context;
init_data.seq = seq;
init_data.timeline_frame = timeline_frame;
- init_data.facf0 = facf0;
- init_data.facf1 = facf1;
+ init_data.fac = fac;
init_data.ibuf1 = ibuf1;
init_data.ibuf2 = ibuf2;
init_data.ibuf3 = ibuf3;
@@ -727,7 +778,7 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
float timeline_frame)
{
Scene *scene = context->scene;
- float fac, facf;
+ float fac;
int early_out;
int i;
struct SeqEffectHandle sh = SEQ_effect_handle_get(seq);
@@ -749,24 +800,23 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
}
if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
- sh.get_default_fac(seq, timeline_frame, &fac, &facf);
- facf = fac;
+ sh.get_default_fac(seq, timeline_frame, &fac);
}
else {
fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "effect_fader", 0, NULL);
if (fcu) {
- fac = facf = evaluate_fcurve(fcu, timeline_frame);
+ fac = evaluate_fcurve(fcu, timeline_frame);
}
else {
- fac = facf = seq->effect_fader;
+ fac = seq->effect_fader;
}
}
- early_out = sh.early_out(seq, fac, facf);
+ early_out = sh.early_out(seq, fac);
switch (early_out) {
case EARLY_NO_INPUT:
- out = sh.execute(context, seq, timeline_frame, fac, facf, NULL, NULL, NULL);
+ out = sh.execute(context, seq, timeline_frame, fac, NULL, NULL, NULL);
break;
case EARLY_DO_EFFECT:
for (i = 0; i < 3; i++) {
@@ -785,10 +835,10 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
if (ibuf[0] && (ibuf[1] || SEQ_effect_get_num_inputs(seq->type) == 1)) {
if (sh.multithreaded) {
out = seq_render_effect_execute_threaded(
- &sh, context, seq, timeline_frame, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
+ &sh, context, seq, timeline_frame, fac, ibuf[0], ibuf[1], ibuf[2]);
}
else {
- out = sh.execute(context, seq, timeline_frame, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
+ out = sh.execute(context, seq, timeline_frame, fac, ibuf[0], ibuf[1], ibuf[2]);
}
}
break;
@@ -814,11 +864,13 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
return out;
}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Individual strip rendering functions
* \{ */
+
/**
* Render individual view for multi-view or single (default view) for mono-view.
*/
@@ -1137,15 +1189,13 @@ static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context,
bool *r_is_proxy_image)
{
ImBuf *ibuf = NULL;
- MovieClipUser user;
+ MovieClipUser user = *DNA_struct_default_get(MovieClipUser);
IMB_Proxy_Size psize = SEQ_rendersize_to_proxysize(context->preview_render_size);
if (!seq->clip) {
return NULL;
}
- memset(&user, 0, sizeof(MovieClipUser));
-
BKE_movieclip_user_set_frame(&user, frame_index + seq->anim_startofs + seq->clip->start_frame);
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
@@ -1174,7 +1224,8 @@ static ImBuf *seq_render_movieclip_strip(const SeqRenderData *context,
/* Try to get a proxy image. */
ibuf = seq_get_movieclip_ibuf(seq, user);
- if (ibuf != NULL && psize != IMB_PROXY_NONE) {
+ /* If clip doesn't use proxies, it will fallback to full size render of original file. */
+ if (ibuf != NULL && psize != IMB_PROXY_NONE && BKE_movieclip_proxy_enabled(seq->clip)) {
*r_is_proxy_image = true;
}
@@ -1560,11 +1611,13 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context,
return ibuf;
}
+
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Strip stack rendering functions
+/** \name Strip Stack Rendering Functions
* \{ */
+
static ImBuf *do_render_strip_uncached(const SeqRenderData *context,
SeqRenderState *state,
Sequence *seq,
@@ -1715,8 +1768,8 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq)
static int seq_get_early_out_for_blend_mode(Sequence *seq)
{
struct SeqEffectHandle sh = seq_effect_get_sequence_blend(seq);
- float facf = seq->blend_opacity / 100.0f;
- int early_out = sh.early_out(seq, facf, facf);
+ float fac = seq->blend_opacity / 100.0f;
+ int early_out = sh.early_out(seq, fac);
if (ELEM(early_out, EARLY_DO_EFFECT, EARLY_NO_INPUT)) {
return early_out;
@@ -1738,25 +1791,25 @@ static ImBuf *seq_render_strip_stack_apply_effect(
{
ImBuf *out;
struct SeqEffectHandle sh = seq_effect_get_sequence_blend(seq);
- float facf = seq->blend_opacity / 100.0f;
+ float fac = seq->blend_opacity / 100.0f;
int swap_input = seq_must_swap_input_in_blend_mode(seq);
if (swap_input) {
if (sh.multithreaded) {
out = seq_render_effect_execute_threaded(
- &sh, context, seq, timeline_frame, facf, facf, ibuf2, ibuf1, NULL);
+ &sh, context, seq, timeline_frame, fac, ibuf2, ibuf1, NULL);
}
else {
- out = sh.execute(context, seq, timeline_frame, facf, facf, ibuf2, ibuf1, NULL);
+ out = sh.execute(context, seq, timeline_frame, fac, ibuf2, ibuf1, NULL);
}
}
else {
if (sh.multithreaded) {
out = seq_render_effect_execute_threaded(
- &sh, context, seq, timeline_frame, facf, facf, ibuf1, ibuf2, NULL);
+ &sh, context, seq, timeline_frame, fac, ibuf1, ibuf2, NULL);
}
else {
- out = sh.execute(context, seq, timeline_frame, facf, facf, ibuf1, ibuf2, NULL);
+ out = sh.execute(context, seq, timeline_frame, fac, ibuf1, ibuf2, NULL);
}
}
@@ -1796,6 +1849,20 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context,
early_out = seq_get_early_out_for_blend_mode(seq);
+ /* Early out for alpha over. It requires image to be rendered, so it can't use
+ * `seq_get_early_out_for_blend_mode`. */
+ if (out == NULL && seq->blend_mode == SEQ_TYPE_ALPHAOVER && seq->blend_opacity == 100.0f) {
+ ImBuf *test = seq_render_strip(context, state, seq, timeline_frame);
+ if (ELEM(test->planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB)) {
+ early_out = EARLY_USE_INPUT_2;
+ }
+ else {
+ early_out = EARLY_DO_EFFECT;
+ }
+ /* Free the image. It is stored in cache, so this doesn't affect performance. */
+ IMB_freeImBuf(test);
+ }
+
switch (early_out) {
case EARLY_NO_INPUT:
case EARLY_USE_INPUT_2:
@@ -1820,6 +1887,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context,
}
break;
}
+
if (out) {
break;
}
@@ -1845,11 +1913,6 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context,
return out;
}
-/**
- * \return The image buffer or NULL.
- *
- * \note The returned #ImBuf has its reference increased, free after usage!
- */
ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, int chanshown)
{
Scene *scene = context->scene;
@@ -1882,6 +1945,8 @@ ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame,
}
seq_cache_free_temp_cache(context->scene, context->task_id, timeline_frame);
+ /* Make sure we only keep the `anim` data for strips that are in view. */
+ SEQ_relations_free_all_anim_ibufs(context->scene, timeline_frame);
if (count && !out) {
BLI_mutex_lock(&seq_render_mutex);
@@ -1958,7 +2023,6 @@ static ImBuf *seq_get_uncached_thumbnail(const SeqRenderData *context,
return scaled_ibuf;
}
-/* Get cached thumbnails. */
ImBuf *SEQ_get_thumbnail(
const SeqRenderData *context, Sequence *seq, float timeline_frame, rcti *crop, bool clipped)
{
@@ -1983,7 +2047,6 @@ ImBuf *SEQ_get_thumbnail(
return ibuf_cropped;
}
-/* Render the series of thumbnails and store in cache. */
void SEQ_render_thumbnails(const SeqRenderData *context,
Sequence *seq,
Sequence *seq_orig,
@@ -2028,8 +2091,6 @@ void SEQ_render_thumbnails(const SeqRenderData *context,
}
}
-/* Get frame step for equally spaced thumbnails. These thumbnails should always be present in
- * memory, so they can be used when zooming.*/
int SEQ_render_thumbnails_guaranteed_set_frame_step_get(const Sequence *seq)
{
const int content_len = (seq->enddisp - seq->startdisp - seq->startstill - seq->endstill);
@@ -2037,12 +2098,11 @@ int SEQ_render_thumbnails_guaranteed_set_frame_step_get(const Sequence *seq)
/* Arbitrary, but due to performance reasons should be as low as possible. */
const int thumbnails_base_set_count = min_ii(content_len / 100, 30);
if (thumbnails_base_set_count <= 0) {
- return 0;
+ return content_len;
}
return content_len / thumbnails_base_set_count;
}
-/* Render set of evenly spaced thumbnails that are drawn when zooming. */
void SEQ_render_thumbnails_base_set(const SeqRenderData *context,
Sequence *seq,
Sequence *seq_orig,
diff --git a/source/blender/sequencer/intern/render.h b/source/blender/sequencer/intern/render.h
index a0cdf24d84b..eb1f71769a6 100644
--- a/source/blender/sequencer/intern/render.h
+++ b/source/blender/sequencer/intern/render.h
@@ -54,8 +54,7 @@ struct ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh,
const struct SeqRenderData *context,
struct Sequence *seq,
float timeline_frame,
- float facf0,
- float facf1,
+ float fac,
struct ImBuf *ibuf1,
struct ImBuf *ibuf2,
struct ImBuf *ibuf3);
diff --git a/source/blender/sequencer/intern/sequence_lookup.c b/source/blender/sequencer/intern/sequence_lookup.c
index 25b42957d99..8d451d59e92 100644
--- a/source/blender/sequencer/intern/sequence_lookup.c
+++ b/source/blender/sequencer/intern/sequence_lookup.c
@@ -105,11 +105,6 @@ static void seq_sequence_lookup_update_if_needed(const struct Scene *scene,
seq_sequence_lookup_rebuild(scene, lookup);
}
-/**
- * Free lookup hash data.
- *
- * \param scene: scene that owns lookup hash
- */
void SEQ_sequence_lookup_free(const Scene *scene)
{
BLI_assert(scene->ed);
@@ -119,16 +114,6 @@ void SEQ_sequence_lookup_free(const Scene *scene)
BLI_mutex_unlock(&lookup_lock);
}
-/**
- * Find a sequence with a given name.
- * If lookup hash doesn't exist, it will be created. If hash is tagged as invalid, it will be
- * rebuilt.
- *
- * \param scene: scene that owns lookup hash
- * \param key: Sequence name without SQ prefix (seq->name + 2)
- *
- * \return pointer to Sequence
- */
Sequence *SEQ_sequence_lookup_by_name(const Scene *scene, const char *key)
{
BLI_assert(scene->ed);
@@ -140,12 +125,6 @@ Sequence *SEQ_sequence_lookup_by_name(const Scene *scene, const char *key)
return seq;
}
-/**
- * Find a sequence with a given name.
- *
- * \param scene: scene that owns lookup hash
- * \param tag: tag to set
- */
void SEQ_sequence_lookup_tag(const Scene *scene, eSequenceLookupTag tag)
{
if (!scene->ed) {
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c
index 3478c2d4f97..1c7fe927381 100644
--- a/source/blender/sequencer/intern/sequencer.c
+++ b/source/blender/sequencer/intern/sequencer.c
@@ -34,10 +34,7 @@
#include "DNA_sound_types.h"
#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BKE_animsys.h"
-#include "BKE_fcurve.h"
#include "BKE_idprop.h"
#include "BKE_lib_id.h"
#include "BKE_sound.h"
@@ -65,12 +62,19 @@
#include "sequencer.h"
#include "utils.h"
-static void seq_free_animdata(Scene *scene, Sequence *seq);
-
/* -------------------------------------------------------------------- */
/** \name Allocate / Free Functions
* \{ */
+StripProxy *seq_strip_proxy_alloc(void)
+{
+ StripProxy *strip_proxy = MEM_callocN(sizeof(struct StripProxy), "StripProxy");
+ strip_proxy->quality = 50;
+ strip_proxy->build_tc_flags = SEQ_PROXY_TC_ALL;
+ strip_proxy->tc = SEQ_PROXY_TC_RECORD_RUN;
+ return strip_proxy;
+}
+
static Strip *seq_strip_alloc(int type)
{
Strip *strip = MEM_callocN(sizeof(Strip), "strip");
@@ -140,6 +144,7 @@ Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int
seq->pitch = 1.0f;
seq->scene_sound = NULL;
seq->type = type;
+ seq->blend_mode = SEQ_TYPE_ALPHAOVER;
seq->strip = seq_strip_alloc(type);
seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format");
@@ -155,8 +160,7 @@ Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int
static void seq_sequence_free_ex(Scene *scene,
Sequence *seq,
const bool do_cache,
- const bool do_id_user,
- const bool do_clean_animdata)
+ const bool do_id_user)
{
if (seq->strip) {
seq_free_strip(seq->strip);
@@ -190,11 +194,6 @@ static void seq_sequence_free_ex(Scene *scene,
if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
BKE_sound_remove_scene_sound(scene, seq->scene_sound);
}
-
- /* XXX This must not be done in BKE code. */
- if (do_clean_animdata) {
- seq_free_animdata(scene, seq);
- }
}
if (seq->prop) {
@@ -222,26 +221,21 @@ static void seq_sequence_free_ex(Scene *scene,
MEM_freeN(seq);
}
-void SEQ_sequence_free(Scene *scene, Sequence *seq, const bool do_clean_animdata)
+void SEQ_sequence_free(Scene *scene, Sequence *seq)
{
- seq_sequence_free_ex(scene, seq, true, true, do_clean_animdata);
+ seq_sequence_free_ex(scene, seq, true, true);
}
-/* cache must be freed before calling this function
- * since it leaves the seqbase in an invalid state */
-void seq_free_sequence_recurse(Scene *scene,
- Sequence *seq,
- const bool do_id_user,
- const bool do_clean_animdata)
+void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_user)
{
Sequence *iseq, *iseq_next;
for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) {
iseq_next = iseq->next;
- seq_free_sequence_recurse(scene, iseq, do_id_user, do_clean_animdata);
+ seq_free_sequence_recurse(scene, iseq, do_id_user);
}
- seq_sequence_free_ex(scene, seq, false, do_id_user, do_clean_animdata);
+ seq_sequence_free_ex(scene, seq, false, do_id_user);
}
Editing *SEQ_editing_get(const Scene *scene)
@@ -277,7 +271,7 @@ void SEQ_editing_free(Scene *scene, const bool do_id_user)
/* handle cache freeing above */
LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &ed->seqbase) {
- seq_free_sequence_recurse(scene, seq, do_id_user, false);
+ seq_free_sequence_recurse(scene, seq, do_id_user);
}
BLI_freelistN(&ed->metastack);
@@ -388,12 +382,6 @@ int SEQ_tool_settings_pivot_point_get(Scene *scene)
return tool_settings->pivot_point;
}
-/**
- * Get seqbase that is being viewed currently. This can be main seqbase or meta strip seqbase
- *
- * \param ed: sequence editor data
- * \return pointer to active seqbase. returns NULL if ed is NULL
- */
ListBase *SEQ_active_seqbase_get(const Editing *ed)
{
if (ed == NULL) {
@@ -403,24 +391,11 @@ ListBase *SEQ_active_seqbase_get(const Editing *ed)
return ed->seqbasep;
}
-/**
- * Set seqbase that is being viewed currently. This can be main seqbase or meta strip seqbase
- *
- * \param ed: sequence editor data
- * \param seqbase: ListBase with strips
- */
void SEQ_seqbase_active_set(Editing *ed, ListBase *seqbase)
{
ed->seqbasep = seqbase;
}
-/**
- * Create and initialize #MetaStack, append it to `ed->metastack` ListBase
- *
- * \param ed: sequence editor data
- * \param seq_meta: meta strip
- * \return pointer to created meta stack
- */
MetaStack *SEQ_meta_stack_alloc(Editing *ed, Sequence *seq_meta)
{
MetaStack *ms = MEM_mallocN(sizeof(MetaStack), "metastack");
@@ -431,26 +406,18 @@ MetaStack *SEQ_meta_stack_alloc(Editing *ed, Sequence *seq_meta)
return ms;
}
-/**
- * Free #MetaStack and remove it from `ed->metastack` ListBase.
- *
- * \param ed: sequence editor data
- * \param ms: meta stack
- */
void SEQ_meta_stack_free(Editing *ed, MetaStack *ms)
{
BLI_remlink(&ed->metastack, ms);
MEM_freeN(ms);
}
-/**
- * Get #MetaStack that corresponds to current level that is being viewed
- *
- * \param ed: sequence editor data
- * \return pointer to meta stack
- */
MetaStack *SEQ_meta_stack_active_get(const Editing *ed)
{
+ if (ed == NULL) {
+ return NULL;
+ }
+
return ed->metastack.last;
}
@@ -459,6 +426,7 @@ MetaStack *SEQ_meta_stack_active_get(const Editing *ed)
/* -------------------------------------------------------------------- */
/** \name Duplicate Functions
* \{ */
+
static Sequence *seq_dupli(const Scene *scene_src,
Scene *scene_dst,
ListBase *new_seq_list,
@@ -650,118 +618,6 @@ bool SEQ_valid_strip_channel(Sequence *seq)
return true;
}
-/* r_prefix + [" + escaped_name + "] + \0 */
-#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1)
-
-static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name)
-{
- char name_esc[SEQ_NAME_MAXSTR * 2];
-
- BLI_str_escape(name_esc, name, sizeof(name_esc));
- return BLI_snprintf_rlen(
- str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
-}
-
-/* XXX: hackish function needed for transforming strips! TODO: have some better solution. */
-void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
-{
- char str[SEQ_RNAPATH_MAXSTR];
- size_t str_len;
- FCurve *fcu;
-
- if (scene->adt == NULL || ofs == 0 || scene->adt->action == NULL) {
- return;
- }
-
- str_len = sequencer_rna_path_prefix(str, seq->name + 2);
-
- for (fcu = scene->adt->action->curves.first; fcu; fcu = fcu->next) {
- if (STREQLEN(fcu->rna_path, str, str_len)) {
- unsigned int i;
- if (fcu->bezt) {
- for (i = 0; i < fcu->totvert; i++) {
- BezTriple *bezt = &fcu->bezt[i];
- bezt->vec[0][0] += ofs;
- bezt->vec[1][0] += ofs;
- bezt->vec[2][0] += ofs;
- }
- }
- if (fcu->fpt) {
- for (i = 0; i < fcu->totvert; i++) {
- FPoint *fpt = &fcu->fpt[i];
- fpt->vec[0] += ofs;
- }
- }
- }
- }
-
- DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION);
-}
-
-void SEQ_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst)
-{
- char str_from[SEQ_RNAPATH_MAXSTR];
- size_t str_from_len;
- FCurve *fcu;
- FCurve *fcu_last;
- FCurve *fcu_cpy;
- ListBase lb = {NULL, NULL};
-
- if (scene->adt == NULL || scene->adt->action == NULL) {
- return;
- }
-
- str_from_len = sequencer_rna_path_prefix(str_from, name_src);
-
- fcu_last = scene->adt->action->curves.last;
-
- for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) {
- if (STREQLEN(fcu->rna_path, str_from, str_from_len)) {
- fcu_cpy = BKE_fcurve_copy(fcu);
- BLI_addtail(&lb, fcu_cpy);
- }
- }
-
- /* notice validate is 0, keep this because the seq may not be added to the scene yet */
- BKE_animdata_fix_paths_rename(
- &scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name_src, name_dst, 0, 0, 0);
-
- /* add the original fcurves back */
- BLI_movelisttolist(&scene->adt->action->curves, &lb);
-}
-
-/* XXX: hackish function needed to remove all fcurves belonging to a sequencer strip. */
-static void seq_free_animdata(Scene *scene, Sequence *seq)
-{
- char str[SEQ_RNAPATH_MAXSTR];
- size_t str_len;
- FCurve *fcu;
-
- if (scene->adt == NULL || scene->adt->action == NULL) {
- return;
- }
-
- str_len = sequencer_rna_path_prefix(str, seq->name + 2);
-
- fcu = scene->adt->action->curves.first;
-
- while (fcu) {
- if (STREQLEN(fcu->rna_path, str, str_len)) {
- FCurve *next_fcu = fcu->next;
-
- BLI_remlink(&scene->adt->action->curves, fcu);
- BKE_fcurve_free(fcu);
-
- fcu = next_fcu;
- }
- else {
- fcu = fcu->next;
- }
- }
-}
-
-#undef SEQ_RNAPATH_MAXSTR
-
SequencerToolSettings *SEQ_tool_settings_copy(SequencerToolSettings *tool_settings)
{
SequencerToolSettings *tool_settings_copy = MEM_dupallocN(tool_settings);
@@ -1069,10 +925,6 @@ static bool seq_update_seq_cb(Sequence *seq, void *user_data)
return true;
}
-/* Evaluate parts of sequences which needs to be done as a part of a dependency graph evaluation.
- * This does NOT include actual rendering of the strips, but rather makes them up-to-date for
- * animation playback and makes them ready for the sequencer's rendering pipeline to render them.
- */
void SEQ_eval_sequences(Depsgraph *depsgraph, Scene *scene, ListBase *seqbase)
{
DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene);
diff --git a/source/blender/sequencer/intern/sequencer.h b/source/blender/sequencer/intern/sequencer.h
index e43535d14ee..2a82f966f02 100644
--- a/source/blender/sequencer/intern/sequencer.h
+++ b/source/blender/sequencer/intern/sequencer.h
@@ -29,11 +29,13 @@ extern "C" {
struct Scene;
struct Sequence;
-
-void seq_free_sequence_recurse(struct Scene *scene,
- struct Sequence *seq,
- const bool do_id_user,
- const bool do_clean_animdata);
+struct StripProxy;
+/**
+ * Cache must be freed before calling this function
+ * since it leaves the seqbase in an invalid state.
+ */
+void seq_free_sequence_recurse(struct Scene *scene, struct Sequence *seq, bool do_id_user);
+struct StripProxy *seq_strip_proxy_alloc(void);
#ifdef __cplusplus
}
diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c
index c53aacddcfe..0788003fb12 100644
--- a/source/blender/sequencer/intern/sound.c
+++ b/source/blender/sequencer/intern/sound.c
@@ -31,6 +31,7 @@
#include "DNA_sound_types.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -51,23 +52,27 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene,
for (seq = seqbase->first; seq; seq = seq->next) {
if (seq->type == SEQ_TYPE_META) {
if (sequencer_refresh_sound_length_recursive(bmain, scene, &seq->seqbase)) {
- SEQ_time_update_sequence(scene, seq);
+ SEQ_time_update_sequence(scene, seqbase, seq);
changed = true;
}
}
else if (seq->type == SEQ_TYPE_SOUND_RAM && seq->sound) {
- const float length = BKE_sound_get_length(bmain, seq->sound);
+ SoundInfo info;
+ if (!BKE_sound_info_get(bmain, seq->sound, &info)) {
+ continue;
+ }
+
int old = seq->len;
float fac;
- seq->len = (int)ceil((double)length * FPS);
+ seq->len = MAX2(1, round((info.length - seq->sound->offset_time) * FPS));
fac = (float)seq->len / (float)old;
old = seq->startofs;
seq->startofs *= fac;
seq->endofs *= fac;
seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */
- SEQ_time_update_sequence(scene, seq);
+ SEQ_time_update_sequence(scene, seqbase, seq);
changed = true;
}
}
@@ -111,12 +116,8 @@ void SEQ_sound_update_bounds(Scene *scene, Sequence *seq)
/* We have to take into account start frame of the sequence's scene! */
int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra;
- BKE_sound_move_scene_sound(scene,
- seq->scene_sound,
- seq->startdisp,
- seq->enddisp,
- startofs,
- seq->sound->offset_time);
+ BKE_sound_move_scene_sound(
+ scene, seq->scene_sound, seq->startdisp, seq->enddisp, startofs, 0.0);
}
}
else {
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index aa3f7c92dd8..f342765eec9 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -70,16 +70,6 @@
#include "proxy.h"
#include "utils.h"
-/**
- * Initialize common SeqLoadData members
- *
- * \param load_data: SeqLoadData to be initialized
- * \param name: strip name (can be NULL)
- * \param path: path to file that is used as strip input (can be NULL)
- * \param start_frame: timeline frame where strip will be created
- * \param channel: timeline channel where strip will be created
- *
- */
void SEQ_add_load_data_init(SeqLoadData *load_data,
const char *name,
const char *path,
@@ -100,7 +90,7 @@ void SEQ_add_load_data_init(SeqLoadData *load_data,
static void seq_add_generic_update(Scene *scene, ListBase *seqbase, Sequence *seq)
{
SEQ_sequence_base_unique_name_recursive(scene, &scene->ed->seqbase, seq);
- SEQ_time_update_sequence_bounds(scene, seq);
+ SEQ_time_update_sequence(scene, seqbase, seq);
SEQ_sort(seqbase);
SEQ_relations_invalidate_cache_composite(scene, seq);
}
@@ -147,19 +137,10 @@ static void seq_add_set_view_transform(Scene *scene, Sequence *seq, SeqLoadData
}
}
-/**
- * Add scene strip.
- *
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_SCENE);
- seq->blend_mode = SEQ_TYPE_CROSS;
seq->scene = load_data->scene;
seq->len = load_data->scene->r.efra - load_data->scene->r.sfra + 1;
id_us_ensure_real((ID *)load_data->scene);
@@ -168,19 +149,10 @@ Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDat
return seq;
}
-/**
- * Add movieclip strip.
- *
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MOVIECLIP);
- seq->blend_mode = SEQ_TYPE_CROSS;
seq->clip = load_data->clip;
seq->len = BKE_movieclip_get_duration(load_data->clip);
id_us_ensure_real((ID *)load_data->clip);
@@ -189,19 +161,10 @@ Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoa
return seq;
}
-/**
- * Add mask strip.
- *
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_MASK);
- seq->blend_mode = SEQ_TYPE_CROSS;
seq->mask = load_data->mask;
seq->len = BKE_mask_get_duration(load_data->mask);
id_us_ensure_real((ID *)load_data->mask);
@@ -210,14 +173,6 @@ Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData
return seq;
}
-/**
- * Add effect strip.
- *
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData *load_data)
{
Sequence *seq = SEQ_sequence_alloc(
@@ -230,16 +185,7 @@ Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDa
seq->seq2 = load_data->effect.seq2;
seq->seq3 = load_data->effect.seq3;
- if (seq->type == SEQ_TYPE_COLOR) {
- seq->blend_mode = SEQ_TYPE_CROSS;
- }
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
- seq->blend_mode = SEQ_TYPE_CROSS;
- }
- else if (seq->type == SEQ_TYPE_TEXT) {
- seq->blend_mode = SEQ_TYPE_ALPHAOVER;
- }
- else if (SEQ_effect_get_num_inputs(seq->type) == 1) {
+ if (SEQ_effect_get_num_inputs(seq->type) == 1) {
seq->blend_mode = seq->seq1->blend_mode;
}
@@ -248,42 +194,23 @@ Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDa
SEQ_transform_set_right_handle_frame(seq, load_data->effect.end_frame);
}
- SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */
seq_add_set_name(scene, seq, load_data);
seq_add_generic_update(scene, seqbase, seq);
return seq;
}
-/**
- * Set directory used by image strip.
- *
- * \param seq: image strip to be changed
- * \param path: directory path
- */
void SEQ_add_image_set_directory(Sequence *seq, char *path)
{
BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
}
-/**
- * Set directory used by image strip.
- *
- * \param seq: image strip to be changed
- * \param strip_frame: frame index of strip to be changed
- * \param filename: image filename (only filename, not complete path)
- */
void SEQ_add_image_load_file(Sequence *seq, size_t strip_frame, char *filename)
{
StripElem *se = SEQ_render_give_stripelem(seq, seq->start + strip_frame);
BLI_strncpy(se->name, filename, sizeof(se->name));
}
-/**
- * Set image strip alpha mode
- *
- * \param seq: image strip to be changed
- */
void SEQ_add_image_init_alpha_mode(Sequence *seq)
{
if (seq->strip && seq->strip->stripdata) {
@@ -313,21 +240,10 @@ void SEQ_add_image_init_alpha_mode(Sequence *seq)
}
}
-/**
- * Add image strip.
- * NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences
- *
- * \param main: Main reference
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
{
Sequence *seq = SEQ_sequence_alloc(
seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_IMAGE);
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
seq->len = load_data->image.len;
Strip *strip = seq->strip;
strip->stripdata = MEM_callocN(load_data->image.len * sizeof(StripElem), "stripelem");
@@ -371,17 +287,6 @@ Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL
}
#ifdef WITH_AUDASPACE
-/**
- * Add sound strip.
- * NOTE: Use SEQ_add_image_set_directory() and SEQ_add_image_load_file() to load image sequences
- *
- * \param main: Main reference
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
-
Sequence *SEQ_add_sound_strip(Main *bmain,
Scene *scene,
ListBase *seqbase,
@@ -451,15 +356,6 @@ Sequence *SEQ_add_sound_strip(Main *UNUSED(bmain),
}
#endif // WITH_AUDASPACE
-/**
- * Add meta strip.
- *
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
-
Sequence *SEQ_add_meta_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_data)
{
/* Allocate sequence. */
@@ -472,20 +368,11 @@ Sequence *SEQ_add_meta_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_
/* Set frames start and length. */
seqm->start = load_data->start_frame;
seqm->len = 1;
- SEQ_time_update_sequence(scene, seqm);
+ SEQ_time_update_sequence(scene, seqbase, seqm);
return seqm;
}
-/**
- * Add movie strip.
- *
- * \param main: Main reference
- * \param scene: Scene where strips will be added
- * \param seqbase: ListBase where strips will be added
- * \param load_data: SeqLoadData with information necessary to create strip
- * \return created strip
- */
Sequence *SEQ_add_movie_strip(
Main *bmain, Scene *scene, ListBase *seqbase, SeqLoadData *load_data, double *r_start_offset)
{
@@ -588,8 +475,6 @@ Sequence *SEQ_add_movie_strip(
}
}
- seq->blend_mode = SEQ_TYPE_CROSS; /* so alpha adjustment fade to the strip below */
-
if (anim_arr[0] != NULL) {
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
@@ -624,7 +509,6 @@ Sequence *SEQ_add_movie_strip(
return seq;
}
-/* NOTE: caller should run SEQ_time_update_sequence(scene, seq) after. */
void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const bool lock_range)
{
char path[FILE_MAX];
@@ -644,7 +528,9 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
if (lock_range) {
/* keep so we don't have to move the actual start and end points (only the data) */
- SEQ_time_update_sequence_bounds(scene, seq);
+ Editing *ed = SEQ_editing_get(scene);
+ ListBase *seqbase = SEQ_get_seqbase_by_seq(&ed->seqbase, seq);
+ SEQ_time_update_sequence(scene, seqbase, seq);
prev_startdisp = seq->startdisp;
prev_enddisp = seq->enddisp;
}
@@ -794,7 +680,9 @@ void SEQ_add_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, const boo
SEQ_transform_fix_single_image_seq_offsets(seq);
}
- SEQ_time_update_sequence(scene, seq);
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
+ SEQ_time_update_sequence(scene, seqbase, seq);
+ SEQ_relations_invalidate_cache_raw(scene, seq);
}
void SEQ_add_movie_reload_if_needed(struct Main *bmain,
diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c
index cfac243e68f..0479d3012fa 100644
--- a/source/blender/sequencer/intern/strip_edit.c
+++ b/source/blender/sequencer/intern/strip_edit.c
@@ -43,6 +43,7 @@
#include "utils.h"
#include "SEQ_add.h"
+#include "SEQ_animation.h"
#include "SEQ_edit.h"
#include "SEQ_effects.h"
#include "SEQ_iterator.h"
@@ -175,7 +176,6 @@ static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Se
}
}
-/* Flag seq and its users (effects) for removal. */
void SEQ_edit_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
{
if (seq == NULL || (seq->flag & SEQ_FLAG_DELETE) != 0) {
@@ -193,7 +193,6 @@ void SEQ_edit_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq)
sequencer_flag_users_for_removal(scene, seqbase, seq);
}
-/* Remove all flagged sequences, return true if sequence is removed. */
void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
{
LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase) {
@@ -201,8 +200,9 @@ void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
if (seq->type == SEQ_TYPE_META) {
SEQ_edit_remove_flagged_sequences(scene, &seq->seqbase);
}
+ SEQ_free_animdata(scene, seq);
BLI_remlink(seqbase, seq);
- SEQ_sequence_free(scene, seq, true);
+ SEQ_sequence_free(scene, seq);
SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID);
}
}
@@ -221,6 +221,24 @@ static bool seq_exists_in_seqbase(Sequence *seq, ListBase *seqbase)
return false;
}
+bool SEQ_edit_move_strip_to_seqbase(Scene *scene,
+ ListBase *seqbase,
+ Sequence *seq,
+ ListBase *dst_seqbase)
+{
+ /* Move to meta. */
+ BLI_remlink(seqbase, seq);
+ BLI_addtail(dst_seqbase, seq);
+ SEQ_relations_invalidate_cache_preprocessed(scene, seq);
+
+ /* Update meta. */
+ if (SEQ_transform_test_overlap(dst_seqbase, seq)) {
+ SEQ_transform_seqbase_shuffle(dst_seqbase, seq, scene);
+ }
+
+ return true;
+}
+
bool SEQ_edit_move_strip_to_meta(Scene *scene,
Sequence *src_seq,
Sequence *dst_seqm,
@@ -262,16 +280,7 @@ bool SEQ_edit_move_strip_to_meta(Scene *scene,
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, collection) {
/* Move to meta. */
- BLI_remlink(seqbase, seq);
- BLI_addtail(&dst_seqm->seqbase, seq);
- SEQ_relations_invalidate_cache_preprocessed(scene, seq);
-
- /* Update meta. */
- SEQ_time_update_meta_strip_range(scene, dst_seqm);
- SEQ_time_update_sequence(scene, dst_seqm);
- if (SEQ_transform_test_overlap(&dst_seqm->seqbase, seq)) {
- SEQ_transform_seqbase_shuffle(&dst_seqm->seqbase, seq, scene);
- }
+ SEQ_edit_move_strip_to_seqbase(scene, seqbase, seq, &dst_seqm->seqbase);
}
SEQ_collection_free(collection);
@@ -359,6 +368,7 @@ static bool seq_edit_split_effect_intersect_check(const Sequence *seq, const int
static void seq_edit_split_handle_strip_offsets(Main *bmain,
Scene *scene,
+ ListBase *seqbase,
Sequence *left_seq,
Sequence *right_seq,
const int timeline_frame,
@@ -374,7 +384,7 @@ static void seq_edit_split_handle_strip_offsets(Main *bmain,
SEQ_add_reload_new_file(bmain, scene, right_seq, false);
break;
}
- SEQ_time_update_sequence(scene, right_seq);
+ SEQ_time_update_sequence(scene, seqbase, right_seq);
}
if (seq_edit_split_effect_intersect_check(left_seq, timeline_frame)) {
@@ -387,7 +397,7 @@ static void seq_edit_split_handle_strip_offsets(Main *bmain,
SEQ_add_reload_new_file(bmain, scene, left_seq, false);
break;
}
- SEQ_time_update_sequence(scene, left_seq);
+ SEQ_time_update_sequence(scene, seqbase, left_seq);
}
}
@@ -442,17 +452,6 @@ static bool seq_edit_split_operation_permitted_check(SeqCollection *strips,
return true;
}
-/**
- * Split Sequence at timeline_frame in two.
- *
- * \param bmain: Main in which Sequence is located
- * \param scene: Scene in which Sequence is located
- * \param seqbase: ListBase in which Sequence is located
- * \param seq: Sequence to be split
- * \param timeline_frame: frame at which seq is split.
- * \param method: affects type of offset to be applied to resize Sequence
- * \return The newly created sequence strip. This is always Sequence on right side.
- */
Sequence *SEQ_edit_strip_split(Main *bmain,
Scene *scene,
ListBase *seqbase,
@@ -492,54 +491,46 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
ListBase right_strips = {NULL, NULL};
SEQ_sequence_base_dupli_recursive(scene, scene, &right_strips, &left_strips, SEQ_DUPE_ALL, 0);
- /* Split strips. */
Sequence *left_seq = left_strips.first;
Sequence *right_seq = right_strips.first;
- Sequence *return_seq = right_strips.first;
+ Sequence *return_seq = NULL;
- /* Strips can't be tagged while in detached `seqbase`. Collect all strips which needs to be
- * deleted and delay tagging until they are moved back to `seqbase` in `Editing`. */
- SeqCollection *strips_to_delete = SEQ_collection_create(__func__);
+ /* Move strips from detached `ListBase`, otherwise they can't be flagged for removal,
+ * SEQ_time_update_sequence can fail to update meta strips and they can't be renamed.
+ * This is because these functions check all strips in `Editing` to manage relationships. */
+ BLI_movelisttolist(seqbase, &left_strips);
+ BLI_movelisttolist(seqbase, &right_strips);
+ /* Split strips. */
while (left_seq && right_seq) {
if (left_seq->startdisp >= timeline_frame) {
- SEQ_collection_append_strip(left_seq, strips_to_delete);
+ SEQ_edit_flag_for_removal(scene, seqbase, left_seq);
}
if (right_seq->enddisp <= timeline_frame) {
- SEQ_collection_append_strip(right_seq, strips_to_delete);
+ SEQ_edit_flag_for_removal(scene, seqbase, right_seq);
+ }
+ else if (return_seq == NULL) {
+ /* Store return value - pointer to strip that will not be removed. */
+ return_seq = right_seq;
}
- seq_edit_split_handle_strip_offsets(bmain, scene, left_seq, right_seq, timeline_frame, method);
+ seq_edit_split_handle_strip_offsets(
+ bmain, scene, seqbase, left_seq, right_seq, timeline_frame, method);
left_seq = left_seq->next;
right_seq = right_seq->next;
}
- seq = right_strips.first;
- BLI_movelisttolist(seqbase, &left_strips);
- BLI_movelisttolist(seqbase, &right_strips);
+ SEQ_edit_remove_flagged_sequences(scene, seqbase);
- for (; seq; seq = seq->next) {
- SEQ_ensure_unique_name(seq, scene);
+ /* Rename duplicated strips. */
+ Sequence *seq_rename = return_seq;
+ for (; seq_rename; seq_rename = seq_rename->next) {
+ SEQ_ensure_unique_name(seq_rename, scene);
}
- Sequence *seq_delete;
- SEQ_ITERATOR_FOREACH (seq_delete, strips_to_delete) {
- SEQ_edit_flag_for_removal(scene, seqbase, seq_delete);
- }
- SEQ_edit_remove_flagged_sequences(scene, seqbase);
- SEQ_collection_free(strips_to_delete);
return return_seq;
}
-/**
- * Find gap after initial_frame and move strips on right side to close the gap
- *
- * \param scene: Scene in which strips are located
- * \param seqbase: ListBase in which strips are located
- * \param initial_frame: frame on timeline from where gaps are searched for
- * \param remove_all_gaps: remove all gaps instead of one gap
- * \return true if gap is removed, otherwise false
- */
bool SEQ_edit_remove_gaps(Scene *scene,
ListBase *seqbase,
const int initial_frame,
diff --git a/source/blender/sequencer/intern/strip_relations.c b/source/blender/sequencer/intern/strip_relations.c
index 9822bfe38f9..7e7fc9e6bf7 100644
--- a/source/blender/sequencer/intern/strip_relations.c
+++ b/source/blender/sequencer/intern/strip_relations.c
@@ -29,6 +29,7 @@
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_session_uuid.h"
#include "BKE_main.h"
@@ -281,101 +282,44 @@ void SEQ_relations_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render)
}
}
-static bool update_changed_seq_recurs(
- Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
+static void sequencer_all_free_anim_ibufs(Editing *ed,
+ ListBase *seqbase,
+ int timeline_frame,
+ const int frame_range[2])
{
- Sequence *subseq;
- bool free_imbuf = false;
-
- /* recurse downwards to see if this seq depends on the changed seq */
-
- if (seq == NULL) {
- return false;
- }
-
- if (seq == changed_seq) {
- free_imbuf = true;
- }
-
- for (subseq = seq->seqbase.first; subseq; subseq = subseq->next) {
- if (update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change)) {
- free_imbuf = true;
- }
- }
-
- if (seq->seq1) {
- if (update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change)) {
- free_imbuf = true;
- }
- }
- if (seq->seq2 && (seq->seq2 != seq->seq1)) {
- if (update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change)) {
- free_imbuf = true;
- }
- }
- if (seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) {
- if (update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change)) {
- free_imbuf = true;
+ for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) {
+ if (!SEQ_time_strip_intersects_frame(seq, timeline_frame) ||
+ !((frame_range[0] <= timeline_frame) && (frame_range[1] > timeline_frame))) {
+ SEQ_relations_sequence_free_anim(seq);
}
- }
+ if (seq->type == SEQ_TYPE_META) {
+ int meta_range[2];
- if (free_imbuf) {
- if (ibuf_change) {
- if (seq->type == SEQ_TYPE_MOVIE) {
- SEQ_relations_sequence_free_anim(seq);
+ MetaStack *ms = SEQ_meta_stack_active_get(ed);
+ if (ms != NULL && ms->parseq == seq) {
+ meta_range[0] = -MAXFRAME;
+ meta_range[1] = MAXFRAME;
}
- else if (seq->type == SEQ_TYPE_SPEED) {
- seq_effect_speed_rebuild_map(scene, seq);
+ else {
+ /* Limit frame range to meta strip. */
+ meta_range[0] = max_ii(frame_range[0], seq->startdisp);
+ meta_range[1] = min_ii(frame_range[1], seq->enddisp);
}
- }
- if (len_change) {
- SEQ_time_update_sequence(scene, seq);
+ sequencer_all_free_anim_ibufs(ed, &seq->seqbase, timeline_frame, meta_range);
}
}
-
- return free_imbuf;
-}
-
-void SEQ_relations_update_changed_seq_and_deps(Scene *scene,
- Sequence *changed_seq,
- int len_change,
- int ibuf_change)
-{
- Editing *ed = SEQ_editing_get(scene);
- Sequence *seq;
-
- if (ed == NULL) {
- return;
- }
-
- for (seq = ed->seqbase.first; seq; seq = seq->next) {
- update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
- }
}
-/* Unused */
-static void sequencer_all_free_anim_ibufs(ListBase *seqbase, int timeline_frame)
-{
- for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) {
- if (!SEQ_time_strip_intersects_frame(seq, timeline_frame)) {
- SEQ_relations_sequence_free_anim(seq);
- }
- if (seq->type == SEQ_TYPE_META) {
- sequencer_all_free_anim_ibufs(&seq->seqbase, timeline_frame);
- }
- }
-}
-
-/* Unused */
void SEQ_relations_free_all_anim_ibufs(Scene *scene, int timeline_frame)
{
Editing *ed = SEQ_editing_get(scene);
if (ed == NULL) {
return;
}
- sequencer_all_free_anim_ibufs(&ed->seqbase, timeline_frame);
- SEQ_cache_cleanup(scene);
+
+ const int frame_range[2] = {-MAXFRAME, MAXFRAME};
+ sequencer_all_free_anim_ibufs(ed, &ed->seqbase, timeline_frame, frame_range);
}
static Sequence *sequencer_check_scene_recursion(Scene *scene, ListBase *seqbase)
@@ -428,7 +372,6 @@ bool SEQ_relations_check_scene_recursion(Scene *scene, ReportList *reports)
return false;
}
-/* Check if "seq_main" (indirectly) uses strip "seq". */
bool SEQ_relations_render_loop_check(Sequence *seq_main, Sequence *seq)
{
if (seq_main == NULL || seq == NULL) {
@@ -455,7 +398,6 @@ bool SEQ_relations_render_loop_check(Sequence *seq_main, Sequence *seq)
return false;
}
-/* Function to free imbuf and anim data on changes */
void SEQ_relations_sequence_free_anim(Sequence *seq)
{
while (seq->anims.last) {
@@ -508,7 +450,6 @@ void SEQ_relations_check_uuids_unique_and_report(const Scene *scene)
BLI_gset_free(used_uuids, NULL);
}
-/* Return immediate parent meta of sequence */
struct Sequence *SEQ_find_metastrip_by_sequence(ListBase *seqbase, Sequence *meta, Sequence *seq)
{
Sequence *iseq;
diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c
index fd6c0805c23..31ee20cb6ca 100644
--- a/source/blender/sequencer/intern/strip_time.c
+++ b/source/blender/sequencer/intern/strip_time.c
@@ -131,12 +131,17 @@ static void seq_update_sound_bounds_recursive_impl(Scene *scene,
endofs = seq->start + seq->len - end;
}
+ double offset_time = 0.0f;
+ if (seq->sound != NULL) {
+ offset_time = seq->sound->offset_time;
+ }
+
BKE_sound_move_scene_sound(scene,
seq->scene_sound,
seq->start + startofs,
seq->start + seq->len - endofs,
startofs + seq->anim_startofs,
- seq->sound->offset_time);
+ offset_time);
}
}
}
@@ -148,7 +153,7 @@ void seq_update_sound_bounds_recursive(Scene *scene, Sequence *metaseq)
scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq));
}
-void SEQ_time_update_sequence_bounds(Scene *scene, Sequence *seq)
+static void seq_time_update_sequence_bounds(Scene *scene, Sequence *seq)
{
if (seq->startofs && seq->startstill) {
seq->startstill = 0;
@@ -188,6 +193,10 @@ static void seq_time_update_meta_strip(Scene *scene, Sequence *seq_meta)
void SEQ_time_update_meta_strip_range(Scene *scene, Sequence *seq_meta)
{
+ if (seq_meta == NULL) {
+ return;
+ }
+
seq_time_update_meta_strip(scene, seq_meta);
/* Prevent meta-strip to move in timeline. */
@@ -195,7 +204,7 @@ void SEQ_time_update_meta_strip_range(Scene *scene, Sequence *seq_meta)
SEQ_transform_set_right_handle_frame(seq_meta, seq_meta->enddisp);
}
-void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
+void SEQ_time_update_sequence(Scene *scene, ListBase *seqbase, Sequence *seq)
{
Sequence *seqm;
@@ -203,7 +212,7 @@ void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
seqm = seq->seqbase.first;
while (seqm) {
if (seqm->seqbase.first) {
- SEQ_time_update_sequence(scene, seqm);
+ SEQ_time_update_sequence(scene, &seqm->seqbase, seqm);
}
seqm = seqm->next;
}
@@ -241,21 +250,83 @@ void SEQ_time_update_sequence(Scene *scene, Sequence *seq)
seq->len = seq->enddisp - seq->startdisp;
}
else {
- SEQ_time_update_sequence_bounds(scene, seq);
+ seq_time_update_sequence_bounds(scene, seq);
}
}
+ else if (seq->type == SEQ_TYPE_META) {
+ seq_time_update_meta_strip(scene, seq);
+ }
else {
- if (seq->type == SEQ_TYPE_META) {
- seq_time_update_meta_strip(scene, seq);
+ seq_time_update_sequence_bounds(scene, seq);
+ }
+
+ Editing *ed = SEQ_editing_get(scene);
+
+ /* Strip is inside meta strip */
+ if (seqbase != &ed->seqbase) {
+ Sequence *meta = SEQ_get_meta_by_seqbase(&ed->seqbase, seqbase);
+ SEQ_time_update_meta_strip_range(scene, meta);
+ }
+
+ seq_time_update_sequence_bounds(scene, seq);
+}
+
+static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq)
+{
+ Sequence *subseq;
+ bool do_update = false;
+
+ /* recurse downwards to see if this seq depends on the changed seq */
+
+ if (seq == NULL) {
+ return false;
+ }
+
+ if (seq == changed_seq) {
+ do_update = true;
+ }
+
+ for (subseq = seq->seqbase.first; subseq; subseq = subseq->next) {
+ if (update_changed_seq_recurs(scene, subseq, changed_seq)) {
+ do_update = true;
}
+ }
- Editing *ed = SEQ_editing_get(scene);
- MetaStack *ms = SEQ_meta_stack_active_get(ed);
- if (ms != NULL) {
- SEQ_time_update_meta_strip_range(scene, ms->parseq);
+ if (seq->seq1) {
+ if (update_changed_seq_recurs(scene, seq->seq1, changed_seq)) {
+ do_update = true;
+ }
+ }
+ if (seq->seq2 && (seq->seq2 != seq->seq1)) {
+ if (update_changed_seq_recurs(scene, seq->seq2, changed_seq)) {
+ do_update = true;
+ }
+ }
+ if (seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) {
+ if (update_changed_seq_recurs(scene, seq->seq3, changed_seq)) {
+ do_update = true;
}
+ }
+
+ if (do_update) {
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
+ SEQ_time_update_sequence(scene, seqbase, seq);
+ }
+
+ return do_update;
+}
+
+void SEQ_time_update_recursive(Scene *scene, Sequence *changed_seq)
+{
+ Editing *ed = SEQ_editing_get(scene);
+ Sequence *seq;
+
+ if (ed == NULL) {
+ return;
+ }
- SEQ_time_update_sequence_bounds(scene, seq);
+ for (seq = ed->seqbase.first; seq; seq = seq->next) {
+ update_changed_seq_recurs(scene, seq, changed_seq);
}
}
@@ -367,20 +438,16 @@ float SEQ_time_sequence_get_fps(Scene *scene, Sequence *seq)
return 0.0f;
}
-/**
- * Define boundary rectangle of sequencer timeline and fill in rect data
- *
- * \param scene: Scene in which strips are located
- * \param seqbase: ListBase in which strips are located
- * \param rect: data structure describing rectangle, that will be filled in by this function
- */
-void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
+void SEQ_timeline_init_boundbox(const Scene *scene, rctf *rect)
{
rect->xmin = scene->r.sfra;
rect->xmax = scene->r.efra + 1;
rect->ymin = 0.0f;
rect->ymax = 8.0f;
+}
+void SEQ_timeline_expand_boundbox(const ListBase *seqbase, rctf *rect)
+{
if (seqbase == NULL) {
return;
}
@@ -398,6 +465,12 @@ void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *re
}
}
+void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
+{
+ SEQ_timeline_init_boundbox(scene, rect);
+ SEQ_timeline_expand_boundbox(seqbase, rect);
+}
+
static bool strip_exists_at_frame(SeqCollection *all_strips, const int timeline_frame)
{
Sequence *seq;
@@ -409,14 +482,6 @@ static bool strip_exists_at_frame(SeqCollection *all_strips, const int timeline_
return false;
}
-/**
- * Find first gap between strips after initial_frame and describe it by filling data of r_gap_info
- *
- * \param scene: Scene in which strips are located
- * \param seqbase: ListBase in which strips are located
- * \param initial_frame: frame on timeline from where gaps are searched for
- * \param r_gap_info: data structure describing gap, that will be filled in by this function
- */
void seq_time_gap_info_get(const Scene *scene,
ListBase *seqbase,
const int initial_frame,
@@ -462,15 +527,6 @@ void seq_time_gap_info_get(const Scene *scene,
}
}
-/**
- * Test if strip intersects with timeline frame.
- * NOTE: This checks if strip would be rendered at this frame. For rendering it is assumed, that
- * timeline frame has width of 1 frame and therefore ends at timeline_frame + 1
- *
- * \param seq: Sequence to be checked
- * \param timeline_frame: absolute frame position
- * \return true if strip intersects with timeline frame.
- */
bool SEQ_time_strip_intersects_frame(const Sequence *seq, const int timeline_frame)
{
return (seq->startdisp <= timeline_frame) && (seq->enddisp > timeline_frame);
diff --git a/source/blender/sequencer/intern/strip_time.h b/source/blender/sequencer/intern/strip_time.h
index ca9a935bc96..4fe8d03e641 100644
--- a/source/blender/sequencer/intern/strip_time.h
+++ b/source/blender/sequencer/intern/strip_time.h
@@ -40,9 +40,18 @@ typedef struct GapInfo {
int gap_length; /* Length of the gap. */
bool gap_exists; /* False if there are no gaps. */
} GapInfo;
+
+/**
+ * Find first gap between strips after initial_frame and describe it by filling data of r_gap_info
+ *
+ * \param scene: Scene in which strips are located.
+ * \param seqbase: ListBase in which strips are located.
+ * \param initial_frame: frame on timeline from where gaps are searched for.
+ * \param r_gap_info: data structure describing gap, that will be filled in by this function.
+ */
void seq_time_gap_info_get(const struct Scene *scene,
struct ListBase *seqbase,
- const int initial_frame,
+ int initial_frame,
struct GapInfo *r_gap_info);
#ifdef __cplusplus
diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c
index 54ca4ef487f..432fc1c166f 100644
--- a/source/blender/sequencer/intern/strip_transform.c
+++ b/source/blender/sequencer/intern/strip_transform.c
@@ -33,6 +33,7 @@
#include "BKE_scene.h"
#include "BKE_sound.h"
+#include "SEQ_animation.h"
#include "SEQ_effects.h"
#include "SEQ_iterator.h"
#include "SEQ_relations.h"
@@ -86,8 +87,6 @@ void SEQ_transform_set_right_handle_frame(Sequence *seq, int val)
}
}
-/* used so we can do a quick check for single image seq
- * since they work a bit differently to normal image seq's (during transform) */
bool SEQ_transform_single_image_check(Sequence *seq)
{
return ((seq->len == 1) &&
@@ -95,7 +94,6 @@ bool SEQ_transform_single_image_check(Sequence *seq)
((seq->type & SEQ_TYPE_EFFECT) && SEQ_effect_get_num_inputs(seq->type) == 0)));
}
-/* check if the selected seq's reference unselected seq's */
bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase)
{
Sequence *seq;
@@ -137,10 +135,6 @@ bool SEQ_transform_seqbase_isolated_sel_check(ListBase *seqbase)
return true;
}
-/**
- * Use to impose limits when dragging/extending - so impossible situations don't happen.
- * Can't use the #SEQ_LEFTSEL and #SEQ_LEFTSEL directly because the strip may be in a meta-strip.
- */
void SEQ_transform_handle_xlimits(Sequence *seq, int leftflag, int rightflag)
{
if (leftflag) {
@@ -253,10 +247,10 @@ void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delt
SEQ_transform_set_right_handle_frame(seq, seq->enddisp + delta);
}
- SEQ_time_update_sequence(evil_scene, seq);
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(evil_scene));
+ SEQ_time_update_sequence(evil_scene, seqbase, seq);
}
-/* return 0 if there weren't enough space */
bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
Sequence *test,
Scene *evil_scene,
@@ -266,7 +260,7 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
BLI_assert(ELEM(channel_delta, -1, 1));
test->machine += channel_delta;
- SEQ_time_update_sequence(evil_scene, test);
+ SEQ_time_update_sequence(evil_scene, seqbasep, test);
while (SEQ_transform_test_overlap(seqbasep, test)) {
if ((channel_delta > 0) ? (test->machine >= MAXSEQ) : (test->machine < 1)) {
break;
@@ -275,7 +269,7 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
test->machine += channel_delta;
/* XXX: I don't think this is needed since were only moving vertically, Campbell. */
- SEQ_time_update_sequence(evil_scene, test);
+ SEQ_time_update_sequence(evil_scene, seqbasep, test);
}
if (!SEQ_valid_strip_channel(test)) {
@@ -295,7 +289,7 @@ bool SEQ_transform_seqbase_shuffle_ex(ListBase *seqbasep,
new_frame = new_frame + (test->start - test->startdisp); /* adjust by the startdisp */
SEQ_transform_translate_sequence(evil_scene, test, new_frame - test->start);
- SEQ_time_update_sequence(evil_scene, test);
+ SEQ_time_update_sequence(evil_scene, seqbasep, test);
return false;
}
@@ -355,7 +349,7 @@ static int shuffle_seq_time_offset(SeqCollection *strips_to_shuffle,
}
SEQ_ITERATOR_FOREACH (seq, strips_to_shuffle) {
- SEQ_time_update_sequence_bounds(scene, seq); /* corrects dummy startdisp/enddisp values */
+ SEQ_time_update_sequence(scene, seqbasep, seq); /* corrects dummy startdisp/enddisp values */
}
return tot_ofs;
@@ -392,14 +386,6 @@ bool SEQ_transform_seqbase_shuffle_time(SeqCollection *strips_to_shuffle,
return offset ? false : true;
}
-/**
- * Move strips and markers (if not locked) that start after timeline_frame by delta frames
- *
- * \param scene: Scene in which strips are located
- * \param seqbase: ListBase in which strips are located
- * \param delta: offset in frames to be applied
- * \param timeline_frame: frame on timeline from where strips are moved
- */
void SEQ_transform_offset_after_frame(Scene *scene,
ListBase *seqbase,
const int delta,
@@ -408,7 +394,7 @@ void SEQ_transform_offset_after_frame(Scene *scene,
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
if (seq->startdisp >= timeline_frame) {
SEQ_transform_translate_sequence(scene, seq, delta);
- SEQ_time_update_sequence(scene, seq);
+ SEQ_time_update_sequence(scene, seqbase, seq);
SEQ_relations_invalidate_cache_preprocessed(scene, seq);
}
}
@@ -435,14 +421,6 @@ void SEQ_image_transform_mirror_factor_get(const Sequence *seq, float r_mirror[2
}
}
-/**
- * Get strip transform origin offset from image center
- * Note: This function does not apply axis mirror.
- *
- * \param scene: Scene in which strips are located
- * \param seq: Sequence to calculate image transform origin
- * \param r_origin: return value
- */
void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene,
const Sequence *seq,
float r_origin[2])
@@ -462,60 +440,89 @@ void SEQ_image_transform_origin_offset_pixelspace_get(const Scene *scene,
r_origin[0] = (image_size[0] * transform->origin[0]) - (image_size[0] * 0.5f) + transform->xofs;
r_origin[1] = (image_size[1] * transform->origin[1]) - (image_size[1] * 0.5f) + transform->yofs;
+ const float viewport_pixel_aspect[2] = {scene->r.xasp / scene->r.yasp, 1.0f};
float mirror[2];
SEQ_image_transform_mirror_factor_get(seq, mirror);
mul_v2_v2(r_origin, mirror);
+ mul_v2_v2(r_origin, viewport_pixel_aspect);
}
-/**
- * Get strip transform origin offset from image center
- *
- * \param scene: Scene in which strips are located
- * \param seq: Sequence to calculate image transform origin
- * \param r_origin: return value
- */
-
-void SEQ_image_transform_final_quad_get(const Scene *scene,
- const Sequence *seq,
- float r_quad[4][2])
+static void seq_image_transform_quad_get_ex(const Scene *scene,
+ const Sequence *seq,
+ bool apply_rotation,
+ float r_quad[4][2])
{
StripTransform *transform = seq->strip->transform;
StripCrop *crop = seq->strip->crop;
- int imgage_size[2] = {scene->r.xsch, scene->r.ysch};
+ int image_size[2] = {scene->r.xsch, scene->r.ysch};
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) {
- imgage_size[0] = seq->strip->stripdata->orig_width;
- imgage_size[1] = seq->strip->stripdata->orig_height;
+ image_size[0] = seq->strip->stripdata->orig_width;
+ image_size[1] = seq->strip->stripdata->orig_height;
+ }
+
+ float transform_matrix[4][4];
+ float rotation_matrix[3][3];
+ axis_angle_to_mat3_single(rotation_matrix, 'Z', apply_rotation ? transform->rotation : 0.0f);
+ loc_rot_size_to_mat4(transform_matrix,
+ (const float[]){transform->xofs, transform->yofs, 0.0f},
+ rotation_matrix,
+ (const float[]){transform->scale_x, transform->scale_y, 1.0f});
+ const float origin[2] = {image_size[0] * transform->origin[0],
+ image_size[1] * transform->origin[1]};
+ const float pivot[3] = {origin[0] - (image_size[0] / 2), origin[1] - (image_size[1] / 2), 0.0f};
+ transform_pivot_set_m4(transform_matrix, pivot);
+
+ float quad_temp[4][3];
+ for (int i = 0; i < 4; i++) {
+ zero_v2(quad_temp[i]);
}
- float transform_matrix[3][3];
- loc_rot_size_to_mat3(transform_matrix,
- (const float[]){transform->xofs, transform->yofs},
- transform->rotation,
- (const float[]){transform->scale_x, transform->scale_y});
- const float origin[2] = {imgage_size[0] * transform->origin[0],
- imgage_size[1] * transform->origin[1]};
- const float pivot[2] = {origin[0] - (imgage_size[0] / 2), origin[1] - (imgage_size[1] / 2)};
- transform_pivot_set_m3(transform_matrix, pivot);
-
- r_quad[0][0] = (imgage_size[0] / 2) - crop->right;
- r_quad[0][1] = (imgage_size[1] / 2) - crop->top;
- r_quad[1][0] = (imgage_size[0] / 2) - crop->right;
- r_quad[1][1] = (-imgage_size[1] / 2) + crop->bottom;
- r_quad[2][0] = (-imgage_size[0] / 2) + crop->left;
- r_quad[2][1] = (-imgage_size[1] / 2) + crop->bottom;
- r_quad[3][0] = (-imgage_size[0] / 2) + crop->left;
- r_quad[3][1] = (imgage_size[1] / 2) - crop->top;
-
- mul_m3_v2(transform_matrix, r_quad[0]);
- mul_m3_v2(transform_matrix, r_quad[1]);
- mul_m3_v2(transform_matrix, r_quad[2]);
- mul_m3_v2(transform_matrix, r_quad[3]);
+ quad_temp[0][0] = (image_size[0] / 2) - crop->right;
+ quad_temp[0][1] = (image_size[1] / 2) - crop->top;
+ quad_temp[1][0] = (image_size[0] / 2) - crop->right;
+ quad_temp[1][1] = (-image_size[1] / 2) + crop->bottom;
+ quad_temp[2][0] = (-image_size[0] / 2) + crop->left;
+ quad_temp[2][1] = (-image_size[1] / 2) + crop->bottom;
+ quad_temp[3][0] = (-image_size[0] / 2) + crop->left;
+ quad_temp[3][1] = (image_size[1] / 2) - crop->top;
float mirror[2];
SEQ_image_transform_mirror_factor_get(seq, mirror);
- mul_v2_v2(r_quad[0], mirror);
- mul_v2_v2(r_quad[1], mirror);
- mul_v2_v2(r_quad[2], mirror);
- mul_v2_v2(r_quad[3], mirror);
+
+ const float viewport_pixel_aspect[2] = {scene->r.xasp / scene->r.yasp, 1.0f};
+
+ for (int i = 0; i < 4; i++) {
+ mul_m4_v3(transform_matrix, quad_temp[i]);
+ mul_v2_v2(quad_temp[i], mirror);
+ mul_v2_v2(quad_temp[i], viewport_pixel_aspect);
+ copy_v2_v2(r_quad[i], quad_temp[i]);
+ }
+}
+
+void SEQ_image_transform_quad_get(const Scene *scene,
+ const Sequence *seq,
+ bool apply_rotation,
+ float r_quad[4][2])
+{
+ seq_image_transform_quad_get_ex(scene, seq, apply_rotation, r_quad);
+}
+
+void SEQ_image_transform_final_quad_get(const Scene *scene,
+ const Sequence *seq,
+ float r_quad[4][2])
+{
+ seq_image_transform_quad_get_ex(scene, seq, true, r_quad);
+}
+
+void SEQ_image_preview_unit_to_px(const Scene *scene, const float co_src[2], float co_dst[2])
+{
+ co_dst[0] = co_src[0] * scene->r.xsch;
+ co_dst[1] = co_src[1] * scene->r.ysch;
+}
+
+void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], float co_dst[2])
+{
+ co_dst[0] = co_src[0] / scene->r.xsch;
+ co_dst[1] = co_src[1] / scene->r.ysch;
}
diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c
index 8421aab5217..140aa2d67c5 100644
--- a/source/blender/sequencer/intern/utils.c
+++ b/source/blender/sequencer/intern/utils.c
@@ -35,10 +35,12 @@
#include "BLI_blenlib.h"
+#include "BKE_animsys.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_scene.h"
+#include "SEQ_animation.h"
#include "SEQ_edit.h"
#include "SEQ_iterator.h"
#include "SEQ_relations.h"
@@ -55,13 +57,6 @@
#include "proxy.h"
#include "utils.h"
-/**
- * Sort strips in provided seqbase. Effect strips are trailing the list and they are sorted by
- * channel position as well.
- * This is important for SEQ_time_update_sequence to work properly
- *
- * \param seqbase: ListBase with strips
- */
void SEQ_sort(ListBase *seqbase)
{
if (seqbase == NULL) {
@@ -432,7 +427,6 @@ const Sequence *SEQ_get_topmost_sequence(const Scene *scene, int frame)
return best_seq;
}
-/* in cases where we don't know the sequence's listbase */
ListBase *SEQ_get_seqbase_by_seq(ListBase *seqbase, Sequence *seq)
{
Sequence *iseq;
@@ -450,10 +444,21 @@ ListBase *SEQ_get_seqbase_by_seq(ListBase *seqbase, Sequence *seq)
return NULL;
}
-/**
- * Only use as last resort when the StripElem is available but no the Sequence.
- * (needed for RNA)
- */
+Sequence *SEQ_get_meta_by_seqbase(ListBase *seqbase_main, ListBase *meta_seqbase)
+{
+ SeqCollection *strips = SEQ_query_all_strips_recursive(seqbase_main);
+
+ Sequence *seq = NULL;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ if (seq->type == SEQ_TYPE_META && &seq->seqbase == meta_seqbase) {
+ break;
+ }
+ }
+
+ SEQ_collection_free(strips);
+ return seq;
+}
+
Sequence *SEQ_sequence_from_strip_elem(ListBase *seqbase, StripElem *se)
{
Sequence *iseq;
@@ -510,10 +515,10 @@ void SEQ_alpha_mode_from_file_extension(Sequence *seq)
}
}
-/* called on draw, needs to be fast,
- * we could cache and use a flag if we want to make checks for file paths resolving for eg. */
bool SEQ_sequence_has_source(const Sequence *seq)
{
+ /* Called on draw, needs to be fast,
+ * we could cache and use a flag if we want to make checks for file paths resolving for eg. */
switch (seq->type) {
case SEQ_TYPE_MASK:
return (seq->mask != NULL);
@@ -574,20 +579,14 @@ void SEQ_set_scale_to_fit(const Sequence *seq,
}
}
-/**
- * Ensure, that provided Sequence has unique name. If animation data exists for this Sequence, it
- * will be duplicated and mapped onto new name
- *
- * \param seq: Sequence which name will be ensured to be unique
- * \param scene: Scene in which name must be unique
- */
void SEQ_ensure_unique_name(Sequence *seq, Scene *scene)
{
char name[SEQ_NAME_MAXSTR];
BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
SEQ_sequence_base_unique_name_recursive(scene, &scene->ed->seqbase, seq);
- SEQ_dupe_animdata(scene, name, seq->name + 2);
+ BKE_animdata_fix_paths_rename(
+ &scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name, seq->name + 2, 0, 0, 0);
if (seq->type == SEQ_TYPE_META) {
LISTBASE_FOREACH (Sequence *, seq_child, &seq->seqbase) {
diff --git a/source/blender/sequencer/intern/utils.h b/source/blender/sequencer/intern/utils.h
index 7aee7d229c9..b5aa66804c6 100644
--- a/source/blender/sequencer/intern/utils.h
+++ b/source/blender/sequencer/intern/utils.h
@@ -27,10 +27,13 @@
extern "C" {
#endif
+struct ListBase;
struct Scene;
bool sequencer_seq_generates_image(struct Sequence *seq);
void seq_open_anim_file(struct Scene *scene, struct Sequence *seq, bool openfile);
+Sequence *SEQ_get_meta_by_seqbase(struct ListBase *seqbase_main, struct ListBase *meta_seqbase);
+
#ifdef __cplusplus
}
#endif