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/strip_time.c')
-rw-r--r--source/blender/sequencer/intern/strip_time.c193
1 files changed, 127 insertions, 66 deletions
diff --git a/source/blender/sequencer/intern/strip_time.c b/source/blender/sequencer/intern/strip_time.c
index 4d6efb1639b..d4357fe28b6 100644
--- a/source/blender/sequencer/intern/strip_time.c
+++ b/source/blender/sequencer/intern/strip_time.c
@@ -31,14 +31,32 @@
#include "strip_time.h"
#include "utils.h"
-float seq_give_frame_index(Sequence *seq, float timeline_frame)
+static float seq_time_media_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
+{
+ if ((seq->flag & SEQ_AUTO_PLAYBACK_RATE) == 0) {
+ return 1.0f;
+ }
+ if (seq->media_playback_rate == 0.0f) {
+ return 1.0f;
+ }
+
+ float scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base;
+ return seq->media_playback_rate / scene_playback_rate;
+}
+
+static float seq_time_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
+{
+ return seq_time_media_playback_rate_factor_get(scene, seq) * seq->speed_factor;
+}
+
+float seq_give_frame_index(const Scene *scene, Sequence *seq, float timeline_frame)
{
float frame_index;
- int sta = seq->start;
- int end = seq->start + seq->len - 1;
+ float sta = SEQ_time_start_frame_get(seq);
+ float end = SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq) - 1;
if (seq->type & SEQ_TYPE_EFFECT) {
- end = SEQ_time_right_handle_frame_get(seq);
+ end = SEQ_time_right_handle_frame_get(scene, seq);
}
if (end < sta) {
@@ -46,29 +64,16 @@ float seq_give_frame_index(Sequence *seq, float timeline_frame)
}
if (seq->flag & SEQ_REVERSE_FRAMES) {
- /* Reverse frame in this sequence. */
- if (timeline_frame <= sta) {
- frame_index = end - sta;
- }
- else if (timeline_frame >= end) {
- frame_index = 0;
- }
- else {
- frame_index = end - timeline_frame;
- }
+ frame_index = end - timeline_frame;
}
else {
- if (timeline_frame <= sta) {
- frame_index = 0;
- }
- else if (timeline_frame >= end) {
- frame_index = end - sta;
- }
- else {
- frame_index = timeline_frame - sta;
- }
+ frame_index = timeline_frame - sta;
}
+ /* Clamp frame index to strip frame range. */
+ frame_index = clamp_f(frame_index, 0, end - sta);
+ frame_index *= seq_time_playback_rate_factor_get(scene, seq);
+
if (seq->strobe < 1.0f) {
seq->strobe = 1.0f;
}
@@ -149,14 +154,14 @@ void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta)
return;
}
- const int strip_start = SEQ_time_left_handle_frame_get(seq_meta);
- const int strip_end = SEQ_time_right_handle_frame_get(seq_meta);
+ const int strip_start = SEQ_time_left_handle_frame_get(scene, seq_meta);
+ const int strip_end = SEQ_time_right_handle_frame_get(scene, seq_meta);
int min = MAXFRAME * 2;
int max = -MAXFRAME * 2;
LISTBASE_FOREACH (Sequence *, seq, &seq_meta->seqbase) {
- min = min_ii(SEQ_time_left_handle_frame_get(seq), min);
- max = max_ii(SEQ_time_right_handle_frame_get(seq), max);
+ min = min_ii(SEQ_time_left_handle_frame_get(scene, seq), min);
+ max = max_ii(SEQ_time_right_handle_frame_get(scene, seq), max);
}
seq_meta->start = min + seq_meta->anim_startofs;
@@ -171,25 +176,25 @@ void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta)
SEQ_time_right_handle_frame_set(scene, seq_meta, strip_end);
}
-void seq_time_effect_range_set(Sequence *seq)
+void seq_time_effect_range_set(const Scene *scene, Sequence *seq)
{
if (seq->seq1 == NULL && seq->seq2 == NULL) {
return;
}
if (seq->seq1 && seq->seq2) { /* 2 - input effect. */
- seq->startdisp = max_ii(SEQ_time_left_handle_frame_get(seq->seq1),
- SEQ_time_left_handle_frame_get(seq->seq2));
- seq->enddisp = min_ii(SEQ_time_right_handle_frame_get(seq->seq1),
- SEQ_time_right_handle_frame_get(seq->seq2));
+ seq->startdisp = max_ii(SEQ_time_left_handle_frame_get(scene, seq->seq1),
+ SEQ_time_left_handle_frame_get(scene, seq->seq2));
+ seq->enddisp = min_ii(SEQ_time_right_handle_frame_get(scene, seq->seq1),
+ SEQ_time_right_handle_frame_get(scene, seq->seq2));
}
else if (seq->seq1) { /* Single input effect. */
- seq->startdisp = SEQ_time_right_handle_frame_get(seq->seq1);
- seq->enddisp = SEQ_time_left_handle_frame_get(seq->seq1);
+ seq->startdisp = SEQ_time_right_handle_frame_get(scene, seq->seq1);
+ seq->enddisp = SEQ_time_left_handle_frame_get(scene, seq->seq1);
}
else if (seq->seq2) { /* Strip may be missing one of inputs. */
- seq->startdisp = SEQ_time_right_handle_frame_get(seq->seq2);
- seq->enddisp = SEQ_time_left_handle_frame_get(seq->seq2);
+ seq->startdisp = SEQ_time_right_handle_frame_get(scene, seq->seq2);
+ seq->enddisp = SEQ_time_left_handle_frame_get(scene, seq->seq2);
}
if (seq->startdisp > seq->enddisp) {
@@ -210,7 +215,7 @@ void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effe
Sequence *seq;
/* First pass: Update length of immediate effects. */
SEQ_ITERATOR_FOREACH (seq, effects) {
- seq_time_effect_range_set(seq);
+ seq_time_effect_range_set(scene, seq);
}
/* Second pass: Recursive call to update effects in chain and in order, so they inherit length
@@ -255,14 +260,14 @@ int SEQ_time_find_next_prev_edit(Scene *scene,
}
if (do_center) {
- seq_frames[0] = (SEQ_time_left_handle_frame_get(seq) +
- SEQ_time_right_handle_frame_get(seq)) /
+ seq_frames[0] = (SEQ_time_left_handle_frame_get(scene, seq) +
+ SEQ_time_right_handle_frame_get(scene, seq)) /
2;
seq_frames_tot = 1;
}
else {
- seq_frames[0] = SEQ_time_left_handle_frame_get(seq);
- seq_frames[1] = SEQ_time_right_handle_frame_get(seq);
+ seq_frames[0] = SEQ_time_left_handle_frame_get(scene, seq);
+ seq_frames[1] = SEQ_time_right_handle_frame_get(scene, seq);
seq_frames_tot = 2;
}
@@ -339,18 +344,18 @@ void SEQ_timeline_init_boundbox(const Scene *scene, rctf *rect)
rect->ymax = 8.0f;
}
-void SEQ_timeline_expand_boundbox(const ListBase *seqbase, rctf *rect)
+void SEQ_timeline_expand_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
{
if (seqbase == NULL) {
return;
}
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
- if (rect->xmin > SEQ_time_left_handle_frame_get(seq) - 1) {
- rect->xmin = SEQ_time_left_handle_frame_get(seq) - 1;
+ if (rect->xmin > SEQ_time_left_handle_frame_get(scene, seq) - 1) {
+ rect->xmin = SEQ_time_left_handle_frame_get(scene, seq) - 1;
}
- if (rect->xmax < SEQ_time_right_handle_frame_get(seq) + 1) {
- rect->xmax = SEQ_time_right_handle_frame_get(seq) + 1;
+ if (rect->xmax < SEQ_time_right_handle_frame_get(scene, seq) + 1) {
+ rect->xmax = SEQ_time_right_handle_frame_get(scene, seq) + 1;
}
if (rect->ymax < seq->machine) {
rect->ymax = seq->machine;
@@ -361,14 +366,16 @@ void SEQ_timeline_expand_boundbox(const ListBase *seqbase, rctf *rect)
void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
{
SEQ_timeline_init_boundbox(scene, rect);
- SEQ_timeline_expand_boundbox(seqbase, rect);
+ SEQ_timeline_expand_boundbox(scene, seqbase, rect);
}
-static bool strip_exists_at_frame(SeqCollection *all_strips, const int timeline_frame)
+static bool strip_exists_at_frame(const Scene *scene,
+ SeqCollection *all_strips,
+ const int timeline_frame)
{
Sequence *seq;
SEQ_ITERATOR_FOREACH (seq, all_strips) {
- if (SEQ_time_strip_intersects_frame(seq, timeline_frame)) {
+ if (SEQ_time_strip_intersects_frame(scene, seq, timeline_frame)) {
return true;
}
}
@@ -390,10 +397,10 @@ void seq_time_gap_info_get(const Scene *scene,
SeqCollection *collection = SEQ_query_all_strips(seqbase);
- if (!strip_exists_at_frame(collection, initial_frame)) {
+ if (!strip_exists_at_frame(scene, collection, initial_frame)) {
/* Search backward for gap_start_frame. */
for (; timeline_frame >= sfra; timeline_frame--) {
- if (strip_exists_at_frame(collection, timeline_frame)) {
+ if (strip_exists_at_frame(scene, collection, timeline_frame)) {
break;
}
}
@@ -403,7 +410,7 @@ void seq_time_gap_info_get(const Scene *scene,
else {
/* Search forward for gap_start_frame. */
for (; timeline_frame <= efra; timeline_frame++) {
- if (!strip_exists_at_frame(collection, timeline_frame)) {
+ if (!strip_exists_at_frame(scene, collection, timeline_frame)) {
r_gap_info->gap_start_frame = timeline_frame;
break;
}
@@ -411,7 +418,7 @@ void seq_time_gap_info_get(const Scene *scene,
}
/* Search forward for gap_end_frame. */
for (; timeline_frame <= efra; timeline_frame++) {
- if (strip_exists_at_frame(collection, timeline_frame)) {
+ if (strip_exists_at_frame(scene, collection, timeline_frame)) {
const int gap_end_frame = timeline_frame;
r_gap_info->gap_length = gap_end_frame - r_gap_info->gap_start_frame;
r_gap_info->gap_exists = true;
@@ -420,28 +427,67 @@ void seq_time_gap_info_get(const Scene *scene,
}
}
-bool SEQ_time_strip_intersects_frame(const Sequence *seq, const int timeline_frame)
+bool SEQ_time_strip_intersects_frame(const Scene *scene,
+ const Sequence *seq,
+ const int timeline_frame)
+{
+ return (SEQ_time_left_handle_frame_get(scene, seq) <= timeline_frame) &&
+ (SEQ_time_right_handle_frame_get(scene, seq) > timeline_frame);
+}
+
+void SEQ_time_speed_factor_set(const Scene *scene, Sequence *seq, const float speed_factor)
+{
+ const float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq);
+ const float unity_start_offset = seq->startofs * seq->speed_factor;
+ const float unity_end_offset = seq->endofs * seq->speed_factor;
+
+ /* Left handle is pivot point for content scaling - it must always show same frame. */
+ seq->speed_factor = speed_factor;
+ seq->startofs = unity_start_offset / speed_factor;
+ seq->start = left_handle_frame - seq->startofs;
+ seq->endofs = unity_end_offset / speed_factor;
+
+ SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
+ seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
+}
+
+bool SEQ_time_has_left_still_frames(const Scene *scene, const Sequence *seq)
+{
+ return SEQ_time_left_handle_frame_get(scene, seq) < SEQ_time_start_frame_get(seq);
+}
+
+bool SEQ_time_has_right_still_frames(const Scene *scene, const Sequence *seq)
+{
+ return SEQ_time_right_handle_frame_get(scene, seq) >
+ SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq);
+}
+
+bool SEQ_time_has_still_frames(const Scene *scene, const Sequence *seq)
{
- return (SEQ_time_left_handle_frame_get(seq) <= timeline_frame) &&
- (SEQ_time_right_handle_frame_get(seq) > timeline_frame);
+ return SEQ_time_has_right_still_frames(scene, seq) || SEQ_time_has_left_still_frames(scene, seq);
}
-bool SEQ_time_has_left_still_frames(const Sequence *seq)
+/* Length of strip content in frames. This is number of original frames adjusted by playback rate
+ * factor */
+int SEQ_time_strip_length_get(const Scene *scene, const Sequence *seq)
{
- return seq->startofs < 0;
+ return seq->len / seq_time_playback_rate_factor_get(scene, seq);
}
-bool SEQ_time_has_right_still_frames(const Sequence *seq)
+/* Return timeline frame, where strip content starts. */
+float SEQ_time_start_frame_get(const Sequence *seq)
{
- return seq->endofs < 0;
+ return seq->start;
}
-bool SEQ_time_has_still_frames(const Sequence *seq)
+void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
{
- return SEQ_time_has_right_still_frames(seq) || SEQ_time_has_left_still_frames(seq);
+ seq->start = timeline_frame;
+ SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
+ seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
}
-int SEQ_time_left_handle_frame_get(const Sequence *seq)
+int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq)
{
if (seq->seq1 || seq->seq2) {
return seq->startdisp;
@@ -450,27 +496,42 @@ int SEQ_time_left_handle_frame_get(const Sequence *seq)
return seq->start + seq->startofs;
}
-int SEQ_time_right_handle_frame_get(const Sequence *seq)
+int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
{
if (seq->seq1 || seq->seq2) {
return seq->enddisp;
}
- return seq->start + seq->len - seq->endofs;
+ return seq->start + SEQ_time_strip_length_get(scene, seq) - seq->endofs;
}
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int val)
{
+ const float right_handle_orig_frame = SEQ_time_right_handle_frame_get(scene, seq);
+
+ if (val >= right_handle_orig_frame) {
+ val = right_handle_orig_frame - 1;
+ }
+
seq->startofs = val - seq->start;
seq->startdisp = val; /* Only to make files usable in older versions. */
+
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
}
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int val)
{
- seq->endofs = seq->start + seq->len - val;
+ const float strip_content_end_frame = seq->start + SEQ_time_strip_length_get(scene, seq);
+ const float left_handle_orig_frame = SEQ_time_left_handle_frame_get(scene, seq);
+
+ if (val <= left_handle_orig_frame) {
+ val = left_handle_orig_frame + 1;
+ }
+
+ seq->endofs = strip_content_end_frame - val;
seq->enddisp = val; /* Only to make files usable in older versions. */
+
SEQ_time_update_meta_strip_range(scene, seq_sequence_lookup_meta_by_seq(scene, seq));
seq_time_update_effects_strip_range(scene, seq_sequence_lookup_effects_by_seq(scene, seq));
}