VSE: Add frame interpolation option to speed effect

Do cross transition from current to next frame instead of displaying
one image for n frames.

Reviewed By: ISS, sergey, campbellbarton

Differential Revision: https://developer.blender.org/D7417
This commit is contained in:
Israel Medina 2020-04-30 20:45:41 +02:00 committed by Richard Antalik
parent 1d63db2044
commit 99cb6dbe65
6 changed files with 100 additions and 57 deletions

View File

@ -1139,6 +1139,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
col = layout.column(align=True)
if strip_type == 'SPEED':
col.prop(strip, "multiply_speed")
col.prop(strip, "frame_interpolation_mode")
elif strip_type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}:
col.prop(strip, "use_default_fade", text="Default fade")
if not strip.use_default_fade:

View File

@ -218,6 +218,15 @@ struct ImBuf *BKE_sequencer_give_ibuf_seqbase(const SeqRenderData *context,
float cfra,
int chan_shown,
struct ListBase *seqbasep);
struct ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh,
const SeqRenderData *context,
struct Sequence *seq,
float cfra,
float facf0,
float facf1,
struct ImBuf *ibuf1,
struct ImBuf *ibuf2,
struct ImBuf *ibuf3);
/* **********************************************************************
* sequencer.c
@ -374,6 +383,10 @@ struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *s
/* intern */
struct SeqEffectHandle BKE_sequence_get_blend(struct Sequence *seq);
void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force);
float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context,
struct Sequence *seq,
float cfra,
int input);
/* extern */
struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq);
@ -507,6 +520,7 @@ void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq);
void BKE_sequence_init_colorspace(struct Sequence *seq);
float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq);
float BKE_sequencer_give_stripelem_index(struct Sequence *seq, float cfra);
/* RNA enums, just to be more readable */
enum {

View File

@ -61,6 +61,8 @@
#include "BLF_api.h"
static struct SeqEffectHandle get_sequence_effect_impl(int seq_type);
static void slice_get_byte_buffers(const SeqRenderData *context,
const ImBuf *ibuf1,
const ImBuf *ibuf2,
@ -3118,7 +3120,7 @@ static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(fla
static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
{
return EARLY_USE_INPUT_1;
return EARLY_DO_EFFECT;
}
static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float *ymin, float *ymax)
@ -3248,36 +3250,60 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool for
}
}
/* Override cfra when rendering speed effect input. */
float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context,
Sequence *seq,
float cfra,
int input)
{
int nr = BKE_sequencer_give_stripelem_index(seq, cfra);
SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false);
/* No interpolation. */
if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) {
return seq->start + s->frameMap[nr];
}
/* We need to provide current and next image for interpolation. */
if (input == 0) { /* Current frame. */
return floor(seq->start + s->frameMap[nr]);
}
else { /* Next frame. */
return ceil(seq->start + s->frameMap[nr]);
}
}
static float speed_effect_interpolation_ratio_get(SpeedControlVars *s, Sequence *seq, float cfra)
{
int nr = BKE_sequencer_give_stripelem_index(seq, cfra);
return s->frameMap[nr] - floor(s->frameMap[nr]);
}
static ImBuf *do_speed_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
float UNUSED(cfra),
Sequence *seq,
float cfra,
float facf0,
float facf1,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
{
ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
struct SeqEffectHandle cross_effect = get_sequence_effect_impl(SEQ_TYPE_CROSS);
ImBuf *out;
if (out->rect_float) {
do_cross_effect_float(facf0,
facf1,
context->rectx,
context->recty,
ibuf1->rect_float,
ibuf2->rect_float,
out->rect_float);
if (s->flags & SEQ_SPEED_USE_INTERPOLATION) {
out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
facf0 = facf1 = speed_effect_interpolation_ratio_get(s, seq, cfra);
/* Current frame is ibuf1, next frame is ibuf2. */
out = BKE_sequencer_effect_execute_threaded(
&cross_effect, context, NULL, cfra, facf0, facf1, ibuf1, ibuf2, ibuf3);
return out;
}
else {
do_cross_effect_byte(facf0,
facf1,
context->rectx,
context->recty,
(unsigned char *)ibuf1->rect,
(unsigned char *)ibuf2->rect,
(unsigned char *)out->rect);
}
return out;
/* No interpolation. */
return IMB_dupImBuf(ibuf1);
}
/*********************** overdrop *************************/

View File

@ -1394,7 +1394,7 @@ static void multibuf(ImBuf *ibuf, const float fmul)
}
}
static float give_stripelem_index(Sequence *seq, float cfra)
float BKE_sequencer_give_stripelem_index(Sequence *seq, float cfra)
{
float nr;
int sta = seq->start;
@ -1452,7 +1452,7 @@ StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra)
* all other strips don't use this...
*/
int nr = (int)give_stripelem_index(seq, cfra);
int nr = (int)BKE_sequencer_give_stripelem_index(seq, cfra);
if (nr == -1 || se == NULL) {
return NULL;
@ -1889,7 +1889,7 @@ static bool seq_proxy_get_fname(Editing *ed,
frameno = 1;
}
else {
frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
frameno = (int)BKE_sequencer_give_stripelem_index(seq, cfra) + seq->anim_startofs;
BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, proxy_size_number, suffix);
}
@ -1922,7 +1922,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
}
if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) {
int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs;
int frameno = (int)BKE_sequencer_give_stripelem_index(seq, cfra) + seq->anim_startofs;
if (proxy->anim == NULL) {
if (seq_proxy_get_fname(ed, seq, cfra, psize, name, context->view_id) == 0) {
return NULL;
@ -2887,15 +2887,15 @@ static void *render_effect_execute_do_thread(void *thread_data_v)
return NULL;
}
static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh,
const SeqRenderData *context,
Sequence *seq,
float cfra,
float facf0,
float facf1,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh,
const SeqRenderData *context,
Sequence *seq,
float cfra,
float facf0,
float facf1,
ImBuf *ibuf1,
ImBuf *ibuf2,
ImBuf *ibuf3)
{
RenderEffectInitData init_data;
ImBuf *out = sh->init_execution(context, ibuf1, ibuf2, ibuf3);
@ -2969,14 +2969,21 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context,
break;
case EARLY_DO_EFFECT:
for (i = 0; i < 3; i++) {
if (input[i]) {
ibuf[i] = seq_render_strip(context, state, input[i], cfra);
/* Speed effect requires time remapping of cfra for input(s). */
if (input[1] && seq->type == SEQ_TYPE_SPEED) {
float target_frame = BKE_sequencer_speed_effect_target_frame_get(context, seq, cfra, i);
ibuf[i] = seq_render_strip(context, state, input[i], target_frame);
}
else { /* Other effects. */
if (input[i]) {
ibuf[i] = seq_render_strip(context, state, input[i], cfra);
}
}
}
if (ibuf[0] && ibuf[1]) {
if (sh.multithreaded) {
out = seq_render_effect_execute_threaded(
out = BKE_sequencer_effect_execute_threaded(
&sh, context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
}
else {
@ -3679,9 +3686,8 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context,
float cfra)
{
ImBuf *ibuf = NULL;
float nr = give_stripelem_index(seq, cfra);
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT :
seq->type;
float nr = BKE_sequencer_give_stripelem_index(seq, cfra);
int type = (seq->type & SEQ_TYPE_EFFECT) ? SEQ_TYPE_EFFECT : seq->type;
switch (type) {
case SEQ_TYPE_META: {
ibuf = do_render_strip_seqbase(context, state, seq, nr);
@ -3723,21 +3729,8 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context,
break;
}
case SEQ_TYPE_SPEED: {
float f_cfra;
SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false);
/* weeek! */
f_cfra = seq->start + s->frameMap[(int)nr];
ibuf = seq_render_strip(context, state, seq->seq1, f_cfra);
break;
}
case SEQ_TYPE_EFFECT: {
ibuf = seq_render_effect_strip_impl(context, state, seq, seq->start + nr);
ibuf = seq_render_effect_strip_impl(context, state, seq, cfra);
break;
}
@ -3931,7 +3924,7 @@ static ImBuf *seq_render_strip_stack_apply_effect(
if (swap_input) {
if (sh.multithreaded) {
out = seq_render_effect_execute_threaded(
out = BKE_sequencer_effect_execute_threaded(
&sh, context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL);
}
else {
@ -3940,7 +3933,7 @@ static ImBuf *seq_render_strip_stack_apply_effect(
}
else {
if (sh.multithreaded) {
out = seq_render_effect_execute_threaded(
out = BKE_sequencer_effect_execute_threaded(
&sh, context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL);
}
else {

View File

@ -468,6 +468,7 @@ typedef struct SequencerScopes {
#define SEQ_SPEED_INTEGRATE (1 << 0)
#define SEQ_SPEED_UNUSED_1 (1 << 1) /* cleared */
#define SEQ_SPEED_COMPRESS_IPO_Y (1 << 2)
#define SEQ_SPEED_USE_INTERPOLATION (1 << 3)
/* ***************** SEQUENCE ****************** */
#define SEQ_NAME_MAXSTR 64

View File

@ -2761,6 +2761,13 @@ static void rna_def_speed_control(StructRNA *srna)
prop, "Scale to Length", "Scale values from 0.0 to 1.0 to target sequence length");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_interpolation_mode", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_USE_INTERPOLATION);
RNA_def_property_ui_text(
prop, "Frame interpolation", "Do crossfade blending between current and next frame");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_gaussian_blur(StructRNA *srna)