From 1a5fa2b319e06ebbd2666987aa11240a371dcc09 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 16 Jun 2021 00:29:17 +0200 Subject: VSE: Improve animation evaluation performance Use lookup string callback function for `sequences_all` RNA property `rna_SequenceEditor_sequences_all_lookup_string` using a GHash for faster lookups. When names are changed or strips are added/removed the lookup is tagged invalid. The next time the lookup is used it will rebuild it. Reviewed By: sergey, jbakker Differential Revision: https://developer.blender.org/D11544 --- source/blender/sequencer/intern/sequence_lookup.c | 161 ++++++++++++++++++++++ source/blender/sequencer/intern/sequencer.c | 3 +- source/blender/sequencer/intern/strip_add.c | 34 ++--- source/blender/sequencer/intern/strip_edit.c | 9 ++ source/blender/sequencer/intern/utils.c | 9 +- 5 files changed, 195 insertions(+), 21 deletions(-) create mode 100644 source/blender/sequencer/intern/sequence_lookup.c (limited to 'source/blender/sequencer/intern') diff --git a/source/blender/sequencer/intern/sequence_lookup.c b/source/blender/sequencer/intern/sequence_lookup.c new file mode 100644 index 00000000000..72567dc394e --- /dev/null +++ b/source/blender/sequencer/intern/sequence_lookup.c @@ -0,0 +1,161 @@ +/* + * 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 "SEQ_sequencer.h" + +#include "DNA_listBase.h" +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" + +#include "SEQ_iterator.h" + +#include "BLI_ghash.h" +#include "BLI_string.h" +#include "BLI_sys_types.h" +#include "BLI_threads.h" +#include + +#include "MEM_guardedalloc.h" + +static ThreadMutex lookup_lock = BLI_MUTEX_INITIALIZER; + +typedef struct SequenceLookup { + GHash *by_name; + eSequenceLookupTag tag; +} SequenceLookup; + +static void seq_sequence_lookup_init(struct SequenceLookup *lookup) +{ + lookup->by_name = BLI_ghash_str_new(__func__); + lookup->tag |= SEQ_LOOKUP_TAG_INVALID; +} + +static void seq_sequence_lookup_build(const struct Scene *scene, struct SequenceLookup *lookup) +{ + SeqCollection *all_strips = SEQ_query_all_strips_recursive(&scene->ed->seqbase); + Sequence *seq; + SEQ_ITERATOR_FOREACH (seq, all_strips) { + BLI_ghash_insert(lookup->by_name, seq->name + 2, seq); + } + SEQ_collection_free(all_strips); + lookup->tag &= ~SEQ_LOOKUP_TAG_INVALID; +} + +static SequenceLookup *seq_sequence_lookup_new(void) +{ + SequenceLookup *lookup = MEM_callocN(sizeof(SequenceLookup), __func__); + seq_sequence_lookup_init(lookup); + return lookup; +} + +static void seq_sequence_lookup_free(struct SequenceLookup **lookup) +{ + if (*lookup == NULL) { + return; + } + + BLI_ghash_free((*lookup)->by_name, NULL, NULL); + (*lookup)->by_name = NULL; + MEM_freeN(*lookup); + *lookup = NULL; +} + +static void seq_sequence_lookup_rebuild(const struct Scene *scene, struct SequenceLookup **lookup) +{ + seq_sequence_lookup_free(lookup); + *lookup = seq_sequence_lookup_new(); + seq_sequence_lookup_build(scene, *lookup); +} + +static bool seq_sequence_lookup_is_valid(struct SequenceLookup *lookup) +{ + return (lookup->tag & SEQ_LOOKUP_TAG_INVALID) == 0; +} + +static void seq_sequence_lookup_update_if_needed(const struct Scene *scene, + struct SequenceLookup **lookup) +{ + if (!scene->ed) { + return; + } + if (*lookup && seq_sequence_lookup_is_valid(*lookup)) { + return; + } + + 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); + BLI_mutex_lock(&lookup_lock); + SequenceLookup *lookup = scene->ed->runtime.sequence_lookup; + seq_sequence_lookup_free(&lookup); + 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); + BLI_mutex_lock(&lookup_lock); + seq_sequence_lookup_update_if_needed(scene, &scene->ed->runtime.sequence_lookup); + SequenceLookup *lookup = scene->ed->runtime.sequence_lookup; + Sequence *seq = BLI_ghash_lookup(lookup->by_name, key); + BLI_mutex_unlock(&lookup_lock); + 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) { + return; + } + + BLI_mutex_lock(&lookup_lock); + SequenceLookup *lookup = scene->ed->runtime.sequence_lookup; + if (lookup != NULL) { + lookup->tag |= tag; + } + BLI_mutex_unlock(&lookup_lock); +} diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index d0bc41062a1..8cd67195c30 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -271,6 +271,7 @@ void SEQ_editing_free(Scene *scene, const bool do_id_user) SEQ_ALL_END; BLI_freelistN(&ed->metastack); + SEQ_sequence_lookup_free(scene); MEM_freeN(ed); scene->ed = NULL; @@ -514,7 +515,7 @@ static Sequence *seq_dupli(const Scene *scene_src, if (scene_src == scene_dst) { if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) { - SEQ_sequence_base_unique_name_recursive(&scene_dst->ed->seqbase, seqn); + SEQ_sequence_base_unique_name_recursive(scene_dst, &scene_dst->ed->seqbase, seqn); } } diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 888220b7111..142991eeacf 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -56,6 +56,7 @@ #include "IMB_metadata.h" #include "SEQ_add.h" +#include "SEQ_edit.h" #include "SEQ_effects.h" #include "SEQ_relations.h" #include "SEQ_render.h" @@ -98,33 +99,32 @@ 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(seqbase, seq); + SEQ_sequence_base_unique_name_recursive(scene, seqbase, seq); SEQ_time_update_sequence_bounds(scene, seq); SEQ_sort(seqbase); SEQ_relations_invalidate_cache_composite(scene, seq); } -static void seq_add_set_name(Sequence *seq, SeqLoadData *load_data) +static void seq_add_set_name(Scene *scene, Sequence *seq, SeqLoadData *load_data) { if (load_data->name[0] != '\0') { - BLI_strncpy(seq->name + 2, load_data->name, sizeof(seq->name) - 2); + SEQ_edit_sequence_name_set(scene, seq, load_data->name); } else { if (seq->type == SEQ_TYPE_SCENE) { - BLI_strncpy(seq->name + 2, load_data->scene->id.name + 2, sizeof(seq->name) - 2); + SEQ_edit_sequence_name_set(scene, seq, load_data->scene->id.name + 2); } else if (seq->type == SEQ_TYPE_MOVIECLIP) { - BLI_strncpy(seq->name + 2, load_data->clip->id.name + 2, sizeof(seq->name) - 2); + SEQ_edit_sequence_name_set(scene, seq, load_data->clip->id.name + 2); } else if (seq->type == SEQ_TYPE_MASK) { - BLI_strncpy(seq->name + 2, load_data->mask->id.name + 2, sizeof(seq->name) - 2); + SEQ_edit_sequence_name_set(scene, seq, load_data->mask->id.name + 2); } else if ((seq->type & SEQ_TYPE_EFFECT) != 0) { - BLI_strncpy(seq->name + 2, SEQ_sequence_give_name(seq), sizeof(seq->name) - 2); + SEQ_edit_sequence_name_set(scene, seq, SEQ_sequence_give_name(seq)); } else { /* Image, sound and movie. */ - BLI_strncpy_utf8(seq->name + 2, load_data->name, sizeof(seq->name) - 2); - BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2)); + SEQ_edit_sequence_name_set(scene, seq, load_data->name); } } } @@ -163,7 +163,7 @@ Sequence *SEQ_add_scene_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDat 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); - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); return seq; } @@ -184,7 +184,7 @@ Sequence *SEQ_add_movieclip_strip(Scene *scene, ListBase *seqbase, struct SeqLoa seq->clip = load_data->clip; seq->len = BKE_movieclip_get_duration(load_data->clip); id_us_ensure_real((ID *)load_data->clip); - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); return seq; } @@ -205,7 +205,7 @@ Sequence *SEQ_add_mask_strip(Scene *scene, ListBase *seqbase, struct SeqLoadData seq->mask = load_data->mask; seq->len = BKE_mask_get_duration(load_data->mask); id_us_ensure_real((ID *)load_data->mask); - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); return seq; } @@ -249,7 +249,7 @@ Sequence *SEQ_add_effect_strip(Scene *scene, ListBase *seqbase, struct SeqLoadDa } SEQ_relations_update_changed_seq_and_deps(scene, seq, 1, 1); /* Runs SEQ_time_update_sequence. */ - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); return seq; @@ -364,7 +364,7 @@ Sequence *SEQ_add_image_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL /* Set Last active directory. */ BLI_strncpy(scene->ed->act_imagedir, seq->strip->dir, sizeof(scene->ed->act_imagedir)); seq_add_set_view_transform(scene, seq, load_data); - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); return seq; @@ -426,7 +426,7 @@ Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL /* Set Last active directory. */ BLI_strncpy(scene->ed->act_sounddir, strip->dir, FILE_MAXDIR); - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); return seq; @@ -458,7 +458,7 @@ Sequence *SEQ_add_meta_strip(Scene *scene, ListBase *seqbase, SeqLoadData *load_ seqbase, load_data->start_frame, load_data->channel, SEQ_TYPE_META); /* Set name. */ - seq_add_set_name(seqm, load_data); + seq_add_set_name(scene, seqm, load_data); /* Set frames start and length. */ seqm->start = load_data->start_frame; @@ -590,7 +590,7 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL BLI_split_dirfile(load_data->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); seq_add_set_view_transform(scene, seq, load_data); - seq_add_set_name(seq, load_data); + seq_add_set_name(scene, seq, load_data); seq_add_generic_update(scene, seqbase, seq); MEM_freeN(anim_arr); diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c index 4de6ec3583c..3e6eb74fcb3 100644 --- a/source/blender/sequencer/intern/strip_edit.c +++ b/source/blender/sequencer/intern/strip_edit.c @@ -30,6 +30,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" #include "BLT_translation.h" @@ -202,6 +203,7 @@ void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase) } BLI_remlink(seqbase, seq); SEQ_sequence_free(scene, seq, true); + SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID); } } } @@ -468,3 +470,10 @@ bool SEQ_edit_remove_gaps(Scene *scene, } return true; } + +void SEQ_edit_sequence_name_set(Scene *scene, Sequence *seq, const char *new_name) +{ + BLI_strncpy_utf8(seq->name + 2, new_name, MAX_NAME - 2); + BLI_utf8_invalid_strip(seq->name + 2, strlen(seq->name + 2)); + SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID); +} diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c index 9aeb2961751..a287466dfb2 100644 --- a/source/blender/sequencer/intern/utils.c +++ b/source/blender/sequencer/intern/utils.c @@ -39,6 +39,7 @@ #include "BKE_main.h" #include "BKE_scene.h" +#include "SEQ_edit.h" #include "SEQ_iterator.h" #include "SEQ_relations.h" #include "SEQ_select.h" @@ -140,7 +141,9 @@ static int seqbase_unique_name_recursive_fn(Sequence *seq, void *arg_pt) return 1; } -void SEQ_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) +void SEQ_sequence_base_unique_name_recursive(struct Scene *scene, + ListBase *seqbasep, + Sequence *seq) { SeqUniqueInfo sui; char *dot; @@ -167,7 +170,7 @@ void SEQ_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) SEQ_seqbase_recursive_apply(seqbasep, seqbase_unique_name_recursive_fn, &sui); } - BLI_strncpy(seq->name + 2, sui.name_dest, sizeof(seq->name) - 2); + SEQ_edit_sequence_name_set(scene, seq, sui.name_dest); } static const char *give_seqname_by_type(int type) @@ -629,7 +632,7 @@ 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->ed->seqbase, seq); + SEQ_sequence_base_unique_name_recursive(scene, &scene->ed->seqbase, seq); SEQ_dupe_animdata(scene, name, seq->name + 2); if (seq->type == SEQ_TYPE_META) { -- cgit v1.2.3