Files
test2/source/blender/sequencer/intern/sequence_lookup.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

195 lines
5.5 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2021 Blender Foundation. All rights reserved. */
/** \file
* \ingroup sequencer
*/
#include "SEQ_sequencer.h"
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
#include "sequencer.h"
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "SEQ_iterator.h"
#include "BLI_ghash.h"
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_sys_types.h"
#include "BLI_threads.h"
#include <string.h>
#include "MEM_guardedalloc.h"
static ThreadMutex lookup_lock = BLI_MUTEX_INITIALIZER;
typedef struct SequenceLookup {
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
GHash *seq_by_name;
GHash *meta_by_seq;
GHash *effects_by_seq;
eSequenceLookupTag tag;
} SequenceLookup;
static void seq_sequence_lookup_init(struct SequenceLookup *lookup)
{
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
lookup->seq_by_name = BLI_ghash_str_new(__func__);
lookup->meta_by_seq = BLI_ghash_ptr_new(__func__);
lookup->effects_by_seq = BLI_ghash_ptr_new(__func__);
lookup->tag |= SEQ_LOOKUP_TAG_INVALID;
}
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
static void seq_sequence_lookup_append_effect(Sequence *input,
Sequence *effect,
struct SequenceLookup *lookup)
{
if (input == NULL) {
return;
}
SeqCollection *effects = BLI_ghash_lookup(lookup->effects_by_seq, input);
if (effects == NULL) {
effects = SEQ_collection_create(__func__);
BLI_ghash_insert(lookup->effects_by_seq, input, effects);
}
SEQ_collection_append_strip(effect, effects);
}
static void seq_sequence_lookup_build_effect(Sequence *seq, struct SequenceLookup *lookup)
{
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
if ((seq->type & SEQ_TYPE_EFFECT) == 0) {
return;
}
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
seq_sequence_lookup_append_effect(seq->seq1, seq, lookup);
seq_sequence_lookup_append_effect(seq->seq2, seq, lookup);
}
static void seq_sequence_lookup_build_from_seqbase(Sequence *parent_meta,
const ListBase *seqbase,
struct SequenceLookup *lookup)
{
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
BLI_ghash_insert(lookup->seq_by_name, seq->name + 2, seq);
BLI_ghash_insert(lookup->meta_by_seq, seq, parent_meta);
seq_sequence_lookup_build_effect(seq, lookup);
if (seq->type == SEQ_TYPE_META) {
seq_sequence_lookup_build_from_seqbase(seq, &seq->seqbase, lookup);
}
}
}
static void seq_sequence_lookup_build(const struct Scene *scene, struct SequenceLookup *lookup)
{
Editing *ed = SEQ_editing_get(scene);
seq_sequence_lookup_build_from_seqbase(NULL, &ed->seqbase, lookup);
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;
}
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
BLI_ghash_free((*lookup)->seq_by_name, NULL, NULL);
BLI_ghash_free((*lookup)->meta_by_seq, NULL, NULL);
BLI_ghash_free((*lookup)->effects_by_seq, NULL, SEQ_collection_free_void_p);
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
(*lookup)->seq_by_name = NULL;
(*lookup)->meta_by_seq = NULL;
(*lookup)->effects_by_seq = 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(const 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);
}
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);
}
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
Sequence *SEQ_sequence_lookup_seq_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->seq_by_name, key);
BLI_mutex_unlock(&lookup_lock);
return seq;
}
Sequence *seq_sequence_lookup_meta_by_seq(const Scene *scene, const Sequence *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;
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
Sequence *seq = BLI_ghash_lookup(lookup->meta_by_seq, key);
BLI_mutex_unlock(&lookup_lock);
return seq;
}
VSE: Make time operations self-contained This patch makes it possible to manipulate strips without need to use update functions to recalculate effect and meta strips. Prior to this change function `SEQ_time_update_sequence` had to be used to update mainly effects and meta strips. This was implemented in a way that relied on sorted list of strips, which can't always be done and in rare cases this approach failed. In case of meta strips, `seqbase` had to be passed and compared with "active" one to determine whether meta strip should be updated or not. This is especially weak system that is prone to bugs when functions are used by python API functions. Finally, other strip types had startdisp` and `enddisp` fields updated by this function and a lot of code relied on these fields even if strip start, length and offsets are available. This is completely unnecessary. Implemented changes: All effects and meta strips are updated when strip handles are moved or strip is translated, without need to call any update function. Function `SEQ_time_update_sequence` has been split to `SEQ_time_update_meta_strip_range` and `seq_time_update_effects_strip_range`. These functions should be only used within sequencer module code. Meta update is used for versioning, which is only reason for it not being declared internally. Sequence fields `startdisp` and `enddisp` are now only used for effects to store strip start and end points. These fields should be used only internally within sequencer module code. Use function `SEQ_time_*_handle_frame_get` to get strip start and end points. To update effects and meta strips with reasonable performance, cache for "parent" meta strip and attached effects is added to `SequenceLookup` cache, so it shares invalidation mechanisms. All caches are populated during single iteration. There should be no functional changes. Differential Revision: https://developer.blender.org/D14990
2022-06-02 01:39:40 +02:00
SeqCollection *seq_sequence_lookup_effects_by_seq(const Scene *scene, const Sequence *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;
SeqCollection *effects = BLI_ghash_lookup(lookup->effects_by_seq, key);
BLI_mutex_unlock(&lookup_lock);
return effects;
}
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);
}