Blender  V3.3
strip_time.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved.
3  * 2003-2009 Blender Foundation.
4  * 2005-2006 Peter Schlaile <peter [at] schlaile [dot] de> */
5 
10 #include "DNA_scene_types.h"
11 #include "DNA_sequence_types.h"
12 
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 
16 #include "BKE_movieclip.h"
17 #include "BKE_scene.h"
18 #include "BKE_sound.h"
19 
20 #include "DNA_sound_types.h"
21 #include "IMB_imbuf.h"
22 
23 #include "SEQ_channels.h"
24 #include "SEQ_iterator.h"
25 #include "SEQ_render.h"
26 #include "SEQ_sequencer.h"
27 #include "SEQ_time.h"
28 #include "SEQ_transform.h"
29 
30 #include "sequencer.h"
31 #include "strip_time.h"
32 #include "utils.h"
33 
35 {
36  if ((seq->flag & SEQ_AUTO_PLAYBACK_RATE) == 0) {
37  return 1.0f;
38  }
39  if (seq->media_playback_rate == 0.0f) {
40  return 1.0f;
41  }
42 
43  float scene_playback_rate = (float)scene->r.frs_sec / scene->r.frs_sec_base;
44  return seq->media_playback_rate / scene_playback_rate;
45 }
46 
47 static float seq_time_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
48 {
50 }
51 
52 float seq_give_frame_index(const Scene *scene, Sequence *seq, float timeline_frame)
53 {
54  float frame_index;
55  float sta = SEQ_time_start_frame_get(seq);
56  float end = SEQ_time_start_frame_get(seq) + SEQ_time_strip_length_get(scene, seq) - 1;
57 
58  if (seq->type & SEQ_TYPE_EFFECT) {
60  }
61 
62  if (end < sta) {
63  return -1;
64  }
65 
66  if (seq->flag & SEQ_REVERSE_FRAMES) {
67  frame_index = end - timeline_frame;
68  }
69  else {
70  frame_index = timeline_frame - sta;
71  }
72 
73  /* Clamp frame index to strip frame range. */
74  frame_index = clamp_f(frame_index, 0, end - sta);
75  frame_index *= seq_time_playback_rate_factor_get(scene, seq);
76 
77  if (seq->strobe < 1.0f) {
78  seq->strobe = 1.0f;
79  }
80 
81  if (seq->strobe > 1.0f) {
82  frame_index -= fmodf((double)frame_index, (double)seq->strobe);
83  }
84 
85  return frame_index;
86 }
87 
88 static int metaseq_start(Sequence *metaseq)
89 {
90  return metaseq->start + metaseq->startofs;
91 }
92 
93 static int metaseq_end(Sequence *metaseq)
94 {
95  return metaseq->start + metaseq->len - metaseq->endofs;
96 }
97 
99  Sequence *metaseq,
100  int start,
101  int end)
102 {
103  Sequence *seq;
104 
105  /* For sound we go over full meta tree to update bounds of the sound strips,
106  * since sound is played outside of evaluating the imbufs. */
107  for (seq = metaseq->seqbase.first; seq; seq = seq->next) {
108  if (seq->type == SEQ_TYPE_META) {
110  scene, seq, max_ii(start, metaseq_start(seq)), min_ii(end, metaseq_end(seq)));
111  }
112  else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
113  if (seq->scene_sound) {
114  int startofs = seq->startofs;
115  int endofs = seq->endofs;
116  if (seq->startofs + seq->start < start) {
117  startofs = start - seq->start;
118  }
119 
120  if (seq->start + seq->len - seq->endofs > end) {
121  endofs = seq->start + seq->len - end;
122  }
123 
124  double offset_time = 0.0f;
125  if (seq->sound != NULL) {
126  offset_time = seq->sound->offset_time;
127  }
128 
130  seq->scene_sound,
131  seq->start + startofs,
132  seq->start + seq->len - endofs,
133  startofs + seq->anim_startofs,
134  offset_time);
135  }
136  }
137  }
138 }
139 
141 {
143  scene, metaseq, metaseq_start(metaseq), metaseq_end(metaseq));
144 }
145 
146 /* Update meta strip content start and end, update sound playback range. */
148 {
149  if (seq_meta == NULL) {
150  return;
151  }
152 
153  if (BLI_listbase_is_empty(&seq_meta->seqbase)) {
154  return;
155  }
156 
157  const int strip_start = SEQ_time_left_handle_frame_get(scene, seq_meta);
158  const int strip_end = SEQ_time_right_handle_frame_get(scene, seq_meta);
159 
160  int min = MAXFRAME * 2;
161  int max = -MAXFRAME * 2;
162  LISTBASE_FOREACH (Sequence *, seq, &seq_meta->seqbase) {
165  }
166 
167  seq_meta->start = min + seq_meta->anim_startofs;
168  seq_meta->len = max - min;
169  seq_meta->len -= seq_meta->anim_startofs;
170  seq_meta->len -= seq_meta->anim_endofs;
171 
172  /* Functions `SEQ_time_*_handle_frame_set()` can not be used here, because they are clamped, so
173  * change must be done at once. */
174  seq_meta->startofs = strip_start - seq_meta->start;
175  seq_meta->startdisp = strip_start; /* Only to make files usable in older versions. */
176  seq_meta->endofs = seq_meta->start + SEQ_time_strip_length_get(scene, seq_meta) - strip_end;
177  seq_meta->enddisp = strip_end; /* Only to make files usable in older versions. */
178 
182 }
183 
185 {
186  if (seq->seq1 == NULL && seq->seq2 == NULL) {
187  return;
188  }
189 
190  if (seq->seq1 && seq->seq2) { /* 2 - input effect. */
195  }
196  else if (seq->seq1) { /* Single input effect. */
199  }
200  else if (seq->seq2) { /* Strip may be missing one of inputs. */
203  }
204 
205  if (seq->startdisp > seq->enddisp) {
206  SWAP(int, seq->startdisp, seq->enddisp);
207  }
208 
209  /* Values unusable for effects, these should be always 0. */
210  seq->startofs = seq->endofs = seq->anim_startofs = seq->anim_endofs = 0;
211  seq->start = seq->startdisp;
212  seq->len = seq->enddisp - seq->startdisp;
213 }
214 
215 /* Update strip startdisp and enddisp (n-input effects have no len to calculate these). */
217 {
218  if (effects == NULL) {
219  return;
220  }
221 
222  Sequence *seq;
223  /* First pass: Update length of immediate effects. */
224  SEQ_ITERATOR_FOREACH (seq, effects) {
226  }
227 
228  /* Second pass: Recursive call to update effects in chain and in order, so they inherit length
229  * correctly. */
230  SEQ_ITERATOR_FOREACH (seq, effects) {
232  }
233 }
234 
236  int timeline_frame,
237  const short side,
238  const bool do_skip_mute,
239  const bool do_center,
240  const bool do_unselected)
241 {
244  Sequence *seq;
245 
246  int dist, best_dist, best_frame = timeline_frame;
247  int seq_frames[2], seq_frames_tot;
248 
249  /* In case where both is passed,
250  * frame just finds the nearest end while frame_left the nearest start. */
251 
252  best_dist = MAXFRAME * 2;
253 
254  if (ed == NULL) {
255  return timeline_frame;
256  }
257 
258  for (seq = ed->seqbasep->first; seq; seq = seq->next) {
259  int i;
260 
261  if (do_skip_mute && SEQ_render_is_muted(channels, seq)) {
262  continue;
263  }
264 
265  if (do_unselected && (seq->flag & SELECT)) {
266  continue;
267  }
268 
269  if (do_center) {
270  seq_frames[0] = (SEQ_time_left_handle_frame_get(scene, seq) +
272  2;
273  seq_frames_tot = 1;
274  }
275  else {
276  seq_frames[0] = SEQ_time_left_handle_frame_get(scene, seq);
277  seq_frames[1] = SEQ_time_right_handle_frame_get(scene, seq);
278 
279  seq_frames_tot = 2;
280  }
281 
282  for (i = 0; i < seq_frames_tot; i++) {
283  const int seq_frame = seq_frames[i];
284 
285  dist = MAXFRAME * 2;
286 
287  switch (side) {
288  case SEQ_SIDE_LEFT:
289  if (seq_frame < timeline_frame) {
290  dist = timeline_frame - seq_frame;
291  }
292  break;
293  case SEQ_SIDE_RIGHT:
294  if (seq_frame > timeline_frame) {
295  dist = seq_frame - timeline_frame;
296  }
297  break;
298  case SEQ_SIDE_BOTH:
299  dist = abs(seq_frame - timeline_frame);
300  break;
301  }
302 
303  if (dist < best_dist) {
304  best_frame = seq_frame;
305  best_dist = dist;
306  }
307  }
308  }
309 
310  return best_frame;
311 }
312 
314 {
315  switch (seq->type) {
316  case SEQ_TYPE_MOVIE: {
317  seq_open_anim_file(scene, seq, true);
318  if (BLI_listbase_is_empty(&seq->anims)) {
319  return 0.0f;
320  }
321  StripAnim *strip_anim = seq->anims.first;
322  if (strip_anim->anim == NULL) {
323  return 0.0f;
324  }
325  short frs_sec;
326  float frs_sec_base;
327  if (IMB_anim_get_fps(strip_anim->anim, &frs_sec, &frs_sec_base, true)) {
328  return (float)frs_sec / frs_sec_base;
329  }
330  break;
331  }
332  case SEQ_TYPE_MOVIECLIP:
333  if (seq->clip != NULL) {
334  return BKE_movieclip_get_fps(seq->clip);
335  }
336  break;
337  case SEQ_TYPE_SCENE:
338  if (seq->scene != NULL) {
339  return (float)seq->scene->r.frs_sec / seq->scene->r.frs_sec_base;
340  }
341  break;
342  }
343  return 0.0f;
344 }
345 
347 {
348  rect->xmin = scene->r.sfra;
349  rect->xmax = scene->r.efra + 1;
350  rect->ymin = 0.0f;
351  rect->ymax = 8.0f;
352 }
353 
354 void SEQ_timeline_expand_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
355 {
356  if (seqbase == NULL) {
357  return;
358  }
359 
360  LISTBASE_FOREACH (Sequence *, seq, seqbase) {
361  if (rect->xmin > SEQ_time_left_handle_frame_get(scene, seq) - 1) {
362  rect->xmin = SEQ_time_left_handle_frame_get(scene, seq) - 1;
363  }
364  if (rect->xmax < SEQ_time_right_handle_frame_get(scene, seq) + 1) {
365  rect->xmax = SEQ_time_right_handle_frame_get(scene, seq) + 1;
366  }
367  if (rect->ymax < seq->machine) {
368  rect->ymax = seq->machine;
369  }
370  }
371 }
372 
373 void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
374 {
376  SEQ_timeline_expand_boundbox(scene, seqbase, rect);
377 }
378 
379 static bool strip_exists_at_frame(const Scene *scene,
380  SeqCollection *all_strips,
381  const int timeline_frame)
382 {
383  Sequence *seq;
384  SEQ_ITERATOR_FOREACH (seq, all_strips) {
385  if (SEQ_time_strip_intersects_frame(scene, seq, timeline_frame)) {
386  return true;
387  }
388  }
389  return false;
390 }
391 
393  ListBase *seqbase,
394  const int initial_frame,
395  GapInfo *r_gap_info)
396 {
397  rctf rectf;
398  /* Get first and last frame. */
399  SEQ_timeline_boundbox(scene, seqbase, &rectf);
400  const int sfra = (int)rectf.xmin;
401  const int efra = (int)rectf.xmax;
402  int timeline_frame = initial_frame;
403  r_gap_info->gap_exists = false;
404 
405  SeqCollection *collection = SEQ_query_all_strips(seqbase);
406 
407  if (!strip_exists_at_frame(scene, collection, initial_frame)) {
408  /* Search backward for gap_start_frame. */
409  for (; timeline_frame >= sfra; timeline_frame--) {
410  if (strip_exists_at_frame(scene, collection, timeline_frame)) {
411  break;
412  }
413  }
414  r_gap_info->gap_start_frame = timeline_frame + 1;
415  timeline_frame = initial_frame;
416  }
417  else {
418  /* Search forward for gap_start_frame. */
419  for (; timeline_frame <= efra; timeline_frame++) {
420  if (!strip_exists_at_frame(scene, collection, timeline_frame)) {
421  r_gap_info->gap_start_frame = timeline_frame;
422  break;
423  }
424  }
425  }
426  /* Search forward for gap_end_frame. */
427  for (; timeline_frame <= efra; timeline_frame++) {
428  if (strip_exists_at_frame(scene, collection, timeline_frame)) {
429  const int gap_end_frame = timeline_frame;
430  r_gap_info->gap_length = gap_end_frame - r_gap_info->gap_start_frame;
431  r_gap_info->gap_exists = true;
432  break;
433  }
434  }
435 }
436 
438  const Sequence *seq,
439  const int timeline_frame)
440 {
441  return (SEQ_time_left_handle_frame_get(scene, seq) <= timeline_frame) &&
442  (SEQ_time_right_handle_frame_get(scene, seq) > timeline_frame);
443 }
444 
445 void SEQ_time_speed_factor_set(const Scene *scene, Sequence *seq, const float speed_factor)
446 {
447 
448  if (seq->type == SEQ_TYPE_SOUND_RAM) {
449  seq->speed_factor = speed_factor;
450  }
451  else {
452  const float left_handle_frame = SEQ_time_left_handle_frame_get(scene, seq);
453  const float unity_start_offset = seq->startofs * seq->speed_factor;
454  const float unity_end_offset = seq->endofs * seq->speed_factor;
455  /* Left handle is pivot point for content scaling - it must always show same frame. */
456  seq->speed_factor = speed_factor;
457  seq->startofs = unity_start_offset / speed_factor;
458  seq->start = left_handle_frame - seq->startofs;
459  seq->endofs = unity_end_offset / speed_factor;
460  }
461 
464 }
465 
467 {
469 }
470 
472 {
475 }
476 
478 {
480 }
481 
482 /* Length of strip content in frames. This is number of original frames adjusted by playback rate
483  * factor */
485 {
486  if (seq->type == SEQ_TYPE_SOUND_RAM) {
487  return seq->len;
488  }
489 
490  return seq->len / seq_time_playback_rate_factor_get(scene, seq);
491 }
492 
493 /* Return timeline frame, where strip content starts. */
495 {
496  return seq->start;
497 }
498 
499 void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
500 {
501  seq->start = timeline_frame;
504 }
505 
507 {
508  if (seq->seq1 || seq->seq2) {
509  return seq->startdisp;
510  }
511 
512  return seq->start + seq->startofs;
513 }
514 
516 {
517  if (seq->seq1 || seq->seq2) {
518  return seq->enddisp;
519  }
520 
521  return seq->start + SEQ_time_strip_length_get(scene, seq) - seq->endofs;
522 }
523 
525 {
526  const float right_handle_orig_frame = SEQ_time_right_handle_frame_get(scene, seq);
527 
528  if (val >= right_handle_orig_frame) {
529  val = right_handle_orig_frame - 1;
530  }
531 
532  seq->startofs = val - seq->start;
533  seq->startdisp = val; /* Only to make files usable in older versions. */
534 
537 }
538 
540 {
541  const float strip_content_end_frame = seq->start + SEQ_time_strip_length_get(scene, seq);
542  const float left_handle_orig_frame = SEQ_time_left_handle_frame_get(scene, seq);
543 
544  if (val <= left_handle_orig_frame) {
545  val = left_handle_orig_frame + 1;
546  }
547 
548  seq->endofs = strip_content_end_frame - val;
549  seq->enddisp = val; /* Only to make files usable in older versions. */
550 
553 }
554 
555 void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int offset)
556 {
557  seq->startofs += offset;
558  seq->endofs -= offset;
559  seq->startdisp += offset; /* Only to make files usable in older versions. */
560  seq->enddisp -= offset; /* Only to make files usable in older versions. */
561 
564 }
typedef float(TangentPoint)[2]
float BKE_movieclip_get_fps(struct MovieClip *clip)
Definition: movieclip.c:1571
void BKE_sound_move_scene_sound(const struct Scene *scene, void *handle, int startframe, int endframe, int frameskip, double audio_offset)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE int min_ii(int a, int b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE int max_ii(int a, int b)
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
#define MAXFRAME
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_META
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_MOVIECLIP
@ SEQ_TYPE_EFFECT
@ SEQ_TYPE_MOVIE
@ SEQ_REVERSE_FRAMES
@ SEQ_AUTO_PLAYBACK_RATE
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base)
Definition: anim_movie.c:1678
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
#define SEQ_ITERATOR_FOREACH(var, collection)
Definition: SEQ_iterator.h:35
@ SEQ_SIDE_RIGHT
Definition: SEQ_sequencer.h:32
@ SEQ_SIDE_BOTH
Definition: SEQ_sequencer.h:33
@ SEQ_SIDE_LEFT
Definition: SEQ_sequencer.h:31
ListBase * SEQ_channels_displayed_get(Editing *ed)
Definition: channels.c:23
#define SELECT
Scene scene
SeqCollection * SEQ_query_all_strips(ListBase *seqbase)
Definition: iterator.c:206
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
#define fmodf(x, y)
Definition: metal/compat.h:230
T abs(const T &a)
bool SEQ_render_is_muted(const ListBase *channels, const Sequence *seq)
Definition: render.c:2199
SeqCollection * seq_sequence_lookup_effects_by_seq(const Scene *scene, const Sequence *key)
Sequence * seq_sequence_lookup_meta_by_seq(const Scene *scene, const Sequence *key)
Editing * SEQ_editing_get(const Scene *scene)
Definition: sequencer.c:241
#define min(a, b)
Definition: sort.c:35
void SEQ_time_start_frame_set(const Scene *scene, Sequence *seq, int timeline_frame)
Definition: strip_time.c:499
int SEQ_time_strip_length_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:484
static int metaseq_end(Sequence *metaseq)
Definition: strip_time.c:93
void SEQ_time_speed_factor_set(const Scene *scene, Sequence *seq, const float speed_factor)
Definition: strip_time.c:445
static float seq_time_media_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:34
void SEQ_time_right_handle_frame_set(const Scene *scene, Sequence *seq, int val)
Definition: strip_time.c:539
bool SEQ_time_has_right_still_frames(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:471
bool SEQ_time_has_left_still_frames(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:466
bool SEQ_time_has_still_frames(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:477
void SEQ_time_update_meta_strip_range(const Scene *scene, Sequence *seq_meta)
Definition: strip_time.c:147
void seq_update_sound_bounds_recursive(const Scene *scene, Sequence *metaseq)
Definition: strip_time.c:140
void SEQ_timeline_init_boundbox(const Scene *scene, rctf *rect)
Definition: strip_time.c:346
void seq_time_update_effects_strip_range(const Scene *scene, SeqCollection *effects)
Definition: strip_time.c:216
void SEQ_timeline_expand_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
Definition: strip_time.c:354
void seq_time_translate_handles(const Scene *scene, Sequence *seq, const int offset)
Definition: strip_time.c:555
int SEQ_time_left_handle_frame_get(const Scene *UNUSED(scene), const Sequence *seq)
Definition: strip_time.c:506
void SEQ_timeline_boundbox(const Scene *scene, const ListBase *seqbase, rctf *rect)
Definition: strip_time.c:373
void SEQ_time_left_handle_frame_set(const Scene *scene, Sequence *seq, int val)
Definition: strip_time.c:524
void seq_time_gap_info_get(const Scene *scene, ListBase *seqbase, const int initial_frame, GapInfo *r_gap_info)
Definition: strip_time.c:392
static int metaseq_start(Sequence *metaseq)
Definition: strip_time.c:88
void seq_time_effect_range_set(const Scene *scene, Sequence *seq)
Definition: strip_time.c:184
float SEQ_time_sequence_get_fps(Scene *scene, Sequence *seq)
Definition: strip_time.c:313
int SEQ_time_find_next_prev_edit(Scene *scene, int timeline_frame, const short side, const bool do_skip_mute, const bool do_center, const bool do_unselected)
Definition: strip_time.c:235
bool SEQ_time_strip_intersects_frame(const Scene *scene, const Sequence *seq, const int timeline_frame)
Definition: strip_time.c:437
float seq_give_frame_index(const Scene *scene, Sequence *seq, float timeline_frame)
Definition: strip_time.c:52
static bool strip_exists_at_frame(const Scene *scene, SeqCollection *all_strips, const int timeline_frame)
Definition: strip_time.c:379
static float seq_time_playback_rate_factor_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:47
float SEQ_time_start_frame_get(const Sequence *seq)
Definition: strip_time.c:494
static void seq_update_sound_bounds_recursive_impl(const Scene *scene, Sequence *metaseq, int start, int end)
Definition: strip_time.c:98
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
Definition: strip_time.c:515
ListBase * seqbasep
int gap_length
Definition: strip_time.h:25
int gap_start_frame
Definition: strip_time.h:24
bool gap_exists
Definition: strip_time.h:26
void * first
Definition: DNA_listBase.h:31
float frs_sec_base
struct RenderData r
float media_playback_rate
struct MovieClip * clip
struct Scene * scene
ListBase anims
void * scene_sound
ListBase seqbase
struct bSound * sound
struct Sequence * seq1
struct Sequence * seq2
struct Sequence * next
struct anim * anim
double offset_time
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
float max
void seq_open_anim_file(Scene *scene, Sequence *seq, bool openfile)
Definition: utils.c:209