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:
parent
1d63db2044
commit
99cb6dbe65
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 *************************/
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue