diff options
Diffstat (limited to 'source/blender/sequencer/intern/effects.c')
-rw-r--r-- | source/blender/sequencer/intern/effects.c | 209 |
1 files changed, 76 insertions, 133 deletions
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index 3ca0555d9a5..93ff6b4bf9c 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -3069,8 +3069,6 @@ static void init_speed_effect(Sequence *seq) seq->effectdata = MEM_callocN(sizeof(SpeedControlVars), "speedcontrolvars"); v = (SpeedControlVars *)seq->effectdata; - v->frameMap = NULL; - v->length = 0; v->speed_control_type = SEQ_SPEED_STRETCH; v->speed_fader = 1.0f; v->speed_fader_length = 0.0f; @@ -3080,9 +3078,7 @@ static void init_speed_effect(Sequence *seq) static void load_speed_effect(Sequence *seq) { SpeedControlVars *v = (SpeedControlVars *)seq->effectdata; - v->frameMap = NULL; - v->length = 0; } static int num_inputs_speed(void) @@ -3105,7 +3101,6 @@ static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(fla dst->effectdata = MEM_dupallocN(src->effectdata); v = (SpeedControlVars *)dst->effectdata; v->frameMap = NULL; - v->length = 0; } static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1)) @@ -3127,164 +3122,112 @@ static int seq_effect_speed_get_strip_content_length(const Sequence *seq) return seq->len; } -void seq_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force) +static FCurve *seq_effect_speed_speed_factor_curve_get(Scene *scene, Sequence *seq) { - int timeline_frame; - float fallback_fac = 1.0f; - SpeedControlVars *v = (SpeedControlVars *)seq->effectdata; - FCurve *fcu = NULL; - - /* if not already done, load / initialize data */ - SEQ_effect_handle_get(seq); + return id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL); +} - if ((force == false) && (seq->len == v->length) && (v->frameMap != NULL)) { - return; - } +/* 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)) { - /* make coverity happy and check for (CID 598) input strip ... */ - return; + return; /* Make coverity happy and check for (CID 598) input strip... */ } - /* XXX(campbell): new in 2.5x. should we use the animation system this way? - * The fcurve is needed because many frames need evaluating at once. */ - switch (v->speed_control_type) { - case SEQ_SPEED_MULTIPLY: { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL); - break; - } - case SEQ_SPEED_FRAME_NUMBER: { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_frame_number", 0, NULL); - break; - } - case SEQ_SPEED_LENGTH: { - fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_length", 0, NULL); - break; - } + FCurve *fcu = seq_effect_speed_speed_factor_curve_get(scene, seq); + if (fcu == NULL) { + return; } - if (!v->frameMap || v->length != seq->len) { - if (v->frameMap) { - MEM_freeN(v->frameMap); - } - - v->length = seq->len; - v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap"); + SpeedControlVars *v = (SpeedControlVars *)seq->effectdata; + if (v->frameMap) { + MEM_freeN(v->frameMap); } - fallback_fac = 1.0; + const int effect_strip_length = seq->enddisp - seq->startdisp; + v->frameMap = MEM_mallocN(sizeof(float) * effect_strip_length, __func__); + v->frameMap[0] = 0.0f; - const int target_strip_length = seq_effect_speed_get_strip_content_length(seq->seq1); - - if (v->speed_control_type == SEQ_SPEED_STRETCH) { - if ((seq->seq1->enddisp != seq->seq1->start) && (target_strip_length != 0)) { - fallback_fac = (float)target_strip_length / (float)(seq->seq1->enddisp - seq->seq1->start); - fcu = NULL; - } - } - else { - /* if there is no fcurve, use value as simple multiplier */ - if (!fcu) { - switch (v->speed_control_type) { - case SEQ_SPEED_MULTIPLY: { - fallback_fac = v->speed_fader; - break; - } - case SEQ_SPEED_FRAME_NUMBER: { - fallback_fac = v->speed_fader_frame_number; - break; - } - case SEQ_SPEED_LENGTH: { - fallback_fac = v->speed_fader_length; - break; - } - } - } + float target_frame = 0; + for (int frame_index = 1; frame_index < effect_strip_length; frame_index++) { + target_frame += evaluate_fcurve(fcu, seq->startdisp + frame_index); + v->frameMap[frame_index] = target_frame; } +} - if (ELEM(v->speed_control_type, SEQ_SPEED_MULTIPLY, SEQ_SPEED_STRETCH)) { - float cursor = 0; - float facf; - - v->frameMap[0] = 0; - v->lastValidFrame = 0; - - for (timeline_frame = 1; timeline_frame < v->length; timeline_frame++) { - if (fcu) { - facf = evaluate_fcurve(fcu, seq->startdisp + timeline_frame); - } - else { - facf = fallback_fac; - } - - cursor += facf; - - if (cursor >= target_strip_length) { - v->frameMap[timeline_frame] = target_strip_length - 1; - } - else { - v->frameMap[timeline_frame] = cursor; - v->lastValidFrame = timeline_frame; - } - } +static void seq_effect_speed_frame_map_ensure(Scene *scene, Sequence *seq, FCurve *fcu) +{ + SpeedControlVars *v = (SpeedControlVars *)seq->effectdata; + if (v->frameMap != NULL) { + return; } - else { - float facf; - v->lastValidFrame = 0; - for (timeline_frame = 0; timeline_frame < v->length; timeline_frame++) { + seq_effect_speed_rebuild_map(scene, seq); +} - if (fcu) { - facf = evaluate_fcurve(fcu, seq->startdisp + timeline_frame); - } - else { - facf = fallback_fac; - } +/* Override timeline_frame when rendering speed effect input. */ +float seq_speed_effect_target_frame_get(Scene *scene, + Sequence *seq_speed, + float timeline_frame, + int input) +{ + if (seq_speed->seq1 == NULL) { + return 0.0f; + } - if (v->speed_control_type == SEQ_SPEED_LENGTH) { - facf *= target_strip_length; - facf /= 100.0f; - } + SEQ_effect_handle_get(seq_speed); /* Ensure, that data are initialized. */ + int frame_index = seq_give_frame_index(seq_speed, timeline_frame); + SpeedControlVars *s = (SpeedControlVars *)seq_speed->effectdata; + const Sequence *source = seq_speed->seq1; - if (facf >= target_strip_length) { - facf = target_strip_length - 1; + float target_frame = 0.0f; + switch (s->speed_control_type) { + case SEQ_SPEED_STRETCH: + const float target_content_length = seq_effect_speed_get_strip_content_length(source); + const float target_strip_length = source->enddisp - source->startdisp; + const float ratio = target_content_length / target_strip_length; + target_frame = frame_index * ratio; + break; + case SEQ_SPEED_MULTIPLY: + FCurve *fcu = seq_effect_speed_speed_factor_curve_get(scene, seq_speed); + if (fcu != NULL) { + seq_effect_speed_frame_map_ensure(scene, seq_speed, fcu); + target_frame = s->frameMap[frame_index]; } else { - v->lastValidFrame = timeline_frame; + target_frame = frame_index * s->speed_fader; } - v->frameMap[timeline_frame] = facf; - } + break; + case SEQ_SPEED_LENGTH: + target_frame = seq_effect_speed_get_strip_content_length(source) * + (s->speed_fader_length / 100.0f); + break; + case SEQ_SPEED_FRAME_NUMBER: + target_frame = s->speed_fader_frame_number; + break; } -} -/* Override timeline_frame when rendering speed effect input. */ -float seq_speed_effect_target_frame_get(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int input) -{ - int frame_index = seq_give_frame_index(seq, timeline_frame); - SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; - seq_effect_speed_rebuild_map(context->scene, seq, false); + CLAMP(target_frame, 0, seq_effect_speed_get_strip_content_length(source)); + target_frame += seq_speed->start; /* No interpolation. */ if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) { - return seq->start + s->frameMap[frame_index]; + return target_frame; } - /* We need to provide current and next image for interpolation. */ - if (input == 0) { /* Current frame. */ - return floor(seq->start + s->frameMap[frame_index]); - } - /* Next frame. */ - return ceil(seq->start + s->frameMap[frame_index]); + /* Interpolation is used, switch between current and next frame based on which input is + * requested. */ + return input == 0 ? target_frame : ceil(target_frame); } -static float speed_effect_interpolation_ratio_get(SpeedControlVars *s, - Sequence *seq, +static float speed_effect_interpolation_ratio_get(Scene *scene, + Sequence *seq_speed, float timeline_frame) { - int frame_index = seq_give_frame_index(seq, timeline_frame); - return s->frameMap[frame_index] - floor(s->frameMap[frame_index]); + const float target_frame = seq_speed_effect_target_frame_get( + scene, seq_speed, timeline_frame, 0); + return target_frame - floor(target_frame); } static ImBuf *do_speed_effect(const SeqRenderData *context, @@ -3302,7 +3245,7 @@ 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(s, seq, timeline_frame); + facf0 = facf1 = 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); |