diff --git a/source/blender/sequencer/SEQ_effects.hh b/source/blender/sequencer/SEQ_effects.hh index 0aa63b2de6e..fc573ec0d26 100644 --- a/source/blender/sequencer/SEQ_effects.hh +++ b/source/blender/sequencer/SEQ_effects.hh @@ -20,6 +20,7 @@ struct TextVars; namespace blender::seq { +struct SeqRenderState; struct RenderData; enum class StripEarlyOut { @@ -58,6 +59,7 @@ struct EffectHandle { /* execute the effect */ ImBuf *(*execute)(const RenderData *context, + SeqRenderState *state, Strip *strip, float timeline_frame, float fac, diff --git a/source/blender/sequencer/intern/effects/vse_effect_add_sub_mul.cc b/source/blender/sequencer/intern/effects/vse_effect_add_sub_mul.cc index 54c23694e86..20c8f440c1d 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_add_sub_mul.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_add_sub_mul.cc @@ -47,6 +47,7 @@ struct AddEffectOp { }; static ImBuf *do_add_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*seq*/, float /*timeline_frame*/, float fac, @@ -91,6 +92,7 @@ struct SubEffectOp { }; static ImBuf *do_sub_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*seq*/, float /*timeline_frame*/, float fac, @@ -135,6 +137,7 @@ struct MulEffectOp { }; static ImBuf *do_mul_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*seq*/, float /*timeline_frame*/, float fac, diff --git a/source/blender/sequencer/intern/effects/vse_effect_adjustment.cc b/source/blender/sequencer/intern/effects/vse_effect_adjustment.cc index 162a78ccdb7..718d5876433 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_adjustment.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_adjustment.cc @@ -31,7 +31,10 @@ static StripEarlyOut early_out_adjustment(const Strip * /*strip*/, float /*fac*/ return StripEarlyOut::NoInput; } -static ImBuf *do_adjustment_impl(const RenderData *context, Strip *strip, float timeline_frame) +static ImBuf *do_adjustment_impl(const RenderData *context, + SeqRenderState *state, + Strip *strip, + float timeline_frame) { Editing *ed; ImBuf *i = nullptr; @@ -50,7 +53,7 @@ static ImBuf *do_adjustment_impl(const RenderData *context, Strip *strip, float if (strip->channel > 1) { i = seq_render_give_ibuf_seqbase( - context, timeline_frame, strip->channel - 1, channels, seqbasep); + context, state, timeline_frame, strip->channel - 1, channels, seqbasep); } /* Found nothing? so let's work the way up the meta-strip stack, so @@ -63,7 +66,7 @@ static ImBuf *do_adjustment_impl(const RenderData *context, Strip *strip, float meta = lookup_meta_by_strip(ed, strip); if (meta) { - i = do_adjustment_impl(context, meta, timeline_frame); + i = do_adjustment_impl(context, state, meta, timeline_frame); } } @@ -71,6 +74,7 @@ static ImBuf *do_adjustment_impl(const RenderData *context, Strip *strip, float } static ImBuf *do_adjustment(const RenderData *context, + SeqRenderState *state, Strip *strip, float timeline_frame, float /*fac*/, @@ -82,11 +86,12 @@ static ImBuf *do_adjustment(const RenderData *context, ed = context->scene->ed; - if (!ed) { + if (!ed || state->strips_rendering_seqbase.contains(strip)) { return nullptr; } - out = do_adjustment_impl(context, strip, timeline_frame); + state->strips_rendering_seqbase.add(strip); + out = do_adjustment_impl(context, state, strip, timeline_frame); return out; } diff --git a/source/blender/sequencer/intern/effects/vse_effect_blend.cc b/source/blender/sequencer/intern/effects/vse_effect_blend.cc index a05b4f1b191..9461025614d 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_blend.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_blend.cc @@ -76,6 +76,7 @@ struct AlphaOverEffectOp { }; static ImBuf *do_alphaover_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*strip*/, float /*timeline_frame*/, float fac, @@ -125,6 +126,7 @@ struct AlphaUnderEffectOp { }; static ImBuf *do_alphaunder_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*strip*/, float /*timeline_frame*/, float fac, @@ -325,6 +327,7 @@ struct BlendModeEffectOp { }; static ImBuf *do_blend_mode_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float fac, @@ -356,6 +359,7 @@ static void init_colormix_effect(Strip *strip) } static ImBuf *do_colormix_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float /*fac*/, diff --git a/source/blender/sequencer/intern/effects/vse_effect_cross.cc b/source/blender/sequencer/intern/effects/vse_effect_cross.cc index b44b12c63c5..22cb59b5364 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_cross.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_cross.cc @@ -45,6 +45,7 @@ struct CrossEffectOp { }; static ImBuf *do_cross_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*seq*/, float /*timeline_frame*/, float fac, @@ -98,6 +99,7 @@ struct GammaCrossEffectOp { }; static ImBuf *do_gammacross_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip * /*seq*/, float /*timeline_frame*/, float fac, diff --git a/source/blender/sequencer/intern/effects/vse_effect_gaussian_blur.cc b/source/blender/sequencer/intern/effects/vse_effect_gaussian_blur.cc index 98c4a6add94..029ddac66db 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_gaussian_blur.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_gaussian_blur.cc @@ -139,6 +139,7 @@ static void gaussian_blur_y(const Span gaussian, } static ImBuf *do_gaussian_blur_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float /*fac*/, diff --git a/source/blender/sequencer/intern/effects/vse_effect_glow.cc b/source/blender/sequencer/intern/effects/vse_effect_glow.cc index 45637775cc6..e9fd0aaa862 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_glow.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_glow.cc @@ -224,6 +224,7 @@ static void do_glow_effect_float(Strip *strip, } static ImBuf *do_glow_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float fac, diff --git a/source/blender/sequencer/intern/effects/vse_effect_multi_camera.cc b/source/blender/sequencer/intern/effects/vse_effect_multi_camera.cc index 7a2cb1b81ec..066fcae9467 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_multi_camera.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_multi_camera.cc @@ -30,6 +30,7 @@ static StripEarlyOut early_out_multicam(const Strip * /*strip*/, float /*fac*/) } static ImBuf *do_multicam(const RenderData *context, + SeqRenderState *state, Strip *strip, float timeline_frame, float /*fac*/, @@ -44,7 +45,7 @@ static ImBuf *do_multicam(const RenderData *context, } ed = context->scene->ed; - if (!ed) { + if (!ed || state->strips_rendering_seqbase.contains(strip)) { return nullptr; } ListBase *seqbasep = get_seqbase_by_strip(context->scene, strip); @@ -53,8 +54,9 @@ static ImBuf *do_multicam(const RenderData *context, return nullptr; } + state->strips_rendering_seqbase.add(strip); out = seq_render_give_ibuf_seqbase( - context, timeline_frame, strip->multicam_source, channels, seqbasep); + context, state, timeline_frame, strip->multicam_source, channels, seqbasep); return out; } diff --git a/source/blender/sequencer/intern/effects/vse_effect_solid_color.cc b/source/blender/sequencer/intern/effects/vse_effect_solid_color.cc index 75c672da9b4..845492c4542 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_solid_color.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_solid_color.cc @@ -50,6 +50,7 @@ static StripEarlyOut early_out_color(const Strip * /*strip*/, float /*fac*/) } static ImBuf *do_solid_color(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float /*fac*/, diff --git a/source/blender/sequencer/intern/effects/vse_effect_speed.cc b/source/blender/sequencer/intern/effects/vse_effect_speed.cc index 8a2a56becfc..e9c96fa7e4b 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_speed.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_speed.cc @@ -184,6 +184,7 @@ static float speed_effect_interpolation_ratio_get(Scene *scene, } static ImBuf *do_speed_effect(const RenderData *context, + SeqRenderState *state, Strip *strip, float timeline_frame, float fac, @@ -197,7 +198,7 @@ static ImBuf *do_speed_effect(const RenderData *context, if (s->flags & SEQ_SPEED_USE_INTERPOLATION) { fac = speed_effect_interpolation_ratio_get(context->scene, strip, timeline_frame); /* Current frame is ibuf1, next frame is ibuf2. */ - out = cross_effect.execute(context, nullptr, timeline_frame, fac, ibuf1, ibuf2); + out = cross_effect.execute(context, state, nullptr, timeline_frame, fac, ibuf1, ibuf2); return out; } diff --git a/source/blender/sequencer/intern/effects/vse_effect_text.cc b/source/blender/sequencer/intern/effects/vse_effect_text.cc index 27117ee80fc..57627144f7e 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_text.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_text.cc @@ -1021,6 +1021,7 @@ TextVarsRuntime *text_effect_calc_runtime(const Strip *strip, int font, const in } static ImBuf *do_text_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float /*fac*/, diff --git a/source/blender/sequencer/intern/effects/vse_effect_transform.cc b/source/blender/sequencer/intern/effects/vse_effect_transform.cc index 11c65ad01c4..d2c8295ef2d 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_transform.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_transform.cc @@ -130,6 +130,7 @@ static void transform_image(int x, } static ImBuf *do_transform_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float /*fac*/, diff --git a/source/blender/sequencer/intern/effects/vse_effect_wipe.cc b/source/blender/sequencer/intern/effects/vse_effect_wipe.cc index 016f7536901..c4083358265 100644 --- a/source/blender/sequencer/intern/effects/vse_effect_wipe.cc +++ b/source/blender/sequencer/intern/effects/vse_effect_wipe.cc @@ -354,6 +354,7 @@ static void do_wipe_effect( } static ImBuf *do_wipe_effect(const RenderData *context, + SeqRenderState * /*state*/, Strip *strip, float /*timeline_frame*/, float fac, diff --git a/source/blender/sequencer/intern/render.cc b/source/blender/sequencer/intern/render.cc index 66f9c496ab8..5b494a642f3 100644 --- a/source/blender/sequencer/intern/render.cc +++ b/source/blender/sequencer/intern/render.cc @@ -770,7 +770,7 @@ static ImBuf *seq_render_effect_strip_impl(const RenderData *context, switch (early_out) { case StripEarlyOut::NoInput: - out = sh.execute(context, strip, timeline_frame, fac, nullptr, nullptr); + out = sh.execute(context, state, strip, timeline_frame, fac, nullptr, nullptr); break; case StripEarlyOut::DoEffect: for (i = 0; i < 2; i++) { @@ -795,7 +795,7 @@ static ImBuf *seq_render_effect_strip_impl(const RenderData *context, } if (ibuf[0] && (ibuf[1] || effect_get_num_inputs(strip->type) == 1)) { - out = sh.execute(context, strip, timeline_frame, fac, ibuf[0], ibuf[1]); + out = sh.execute(context, state, strip, timeline_frame, fac, ibuf[0], ibuf[1]); } break; case StripEarlyOut::UseInput1: @@ -1789,7 +1789,13 @@ static StripEarlyOut strip_get_early_out_for_blend_mode(Strip *strip) } static ImBuf *seq_render_strip_stack_apply_effect( - const RenderData *context, Strip *strip, float timeline_frame, ImBuf *ibuf1, ImBuf *ibuf2) + + const RenderData *context, + SeqRenderState *state, + Strip *strip, + float timeline_frame, + ImBuf *ibuf1, + ImBuf *ibuf2) { ImBuf *out; EffectHandle sh = strip_blend_mode_handle_get(strip); @@ -1798,10 +1804,10 @@ static ImBuf *seq_render_strip_stack_apply_effect( int swap_input = seq_must_swap_input_in_blend_mode(strip); if (swap_input) { - out = sh.execute(context, strip, timeline_frame, fac, ibuf2, ibuf1); + out = sh.execute(context, state, strip, timeline_frame, fac, ibuf2, ibuf1); } else { - out = sh.execute(context, strip, timeline_frame, fac, ibuf1, ibuf2); + out = sh.execute(context, state, strip, timeline_frame, fac, ibuf1, ibuf2); } return out; @@ -1911,7 +1917,8 @@ static ImBuf *seq_render_strip_stack(const RenderData *context, context->rectx, context->recty, 32, use_float ? IB_float_data : IB_byte_data); seq_imbuf_assign_spaces(context->scene, ibuf1); - out = seq_render_strip_stack_apply_effect(context, strip, timeline_frame, ibuf1, ibuf2); + out = seq_render_strip_stack_apply_effect( + context, state, strip, timeline_frame, ibuf1, ibuf2); IMB_metadata_copy(out, ibuf2); intra_frame_cache_put_composite(context->scene, strip, out); @@ -1939,7 +1946,8 @@ static ImBuf *seq_render_strip_stack(const RenderData *context, ImBuf *ibuf1 = out; ImBuf *ibuf2 = seq_render_strip(context, state, strip, timeline_frame); - out = seq_render_strip_stack_apply_effect(context, strip, timeline_frame, ibuf1, ibuf2); + out = seq_render_strip_stack_apply_effect( + context, state, strip, timeline_frame, ibuf1, ibuf2); IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); @@ -2013,14 +2021,14 @@ ImBuf *render_give_ibuf(const RenderData *context, float timeline_frame, int cha } ImBuf *seq_render_give_ibuf_seqbase(const RenderData *context, + SeqRenderState *state, float timeline_frame, int chan_shown, ListBase *channels, ListBase *seqbasep) { - SeqRenderState state; - return seq_render_strip_stack(context, &state, channels, seqbasep, timeline_frame, chan_shown); + return seq_render_strip_stack(context, state, channels, seqbasep, timeline_frame, chan_shown); } ImBuf *render_give_ibuf_direct(const RenderData *context, float timeline_frame, Strip *strip) diff --git a/source/blender/sequencer/intern/render.hh b/source/blender/sequencer/intern/render.hh index 437377825eb..144fd51ebc6 100644 --- a/source/blender/sequencer/intern/render.hh +++ b/source/blender/sequencer/intern/render.hh @@ -9,6 +9,7 @@ */ #include "BLI_math_vector_types.hh" +#include "BLI_set.hh" #include "BLI_vector.hh" struct ImBuf; @@ -24,6 +25,7 @@ namespace blender::seq { /* Mutable state while rendering one sequencer frame. */ struct SeqRenderState { LinkNode *scene_parents = nullptr; + Set strips_rendering_seqbase; }; /* Strip corner coordinates in screen pixel space. Note that they might not be @@ -38,6 +40,7 @@ struct StripScreenQuad { }; ImBuf *seq_render_give_ibuf_seqbase(const RenderData *context, + SeqRenderState *state, float timeline_frame, int chan_shown, ListBase *channels, diff --git a/tests/files/sequence_editing/effects/recursive_render_crash_146484.blend b/tests/files/sequence_editing/effects/recursive_render_crash_146484.blend new file mode 100644 index 00000000000..05cda8b9913 --- /dev/null +++ b/tests/files/sequence_editing/effects/recursive_render_crash_146484.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ea97c8a65733cefe820f171d22d0bea91498401491eb0bb857c118554ff7d34 +size 278090 diff --git a/tests/files/sequence_editing/effects/reference/recursive_render_crash_146484.png b/tests/files/sequence_editing/effects/reference/recursive_render_crash_146484.png new file mode 100644 index 00000000000..208532a1a5c --- /dev/null +++ b/tests/files/sequence_editing/effects/reference/recursive_render_crash_146484.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a8575461ef5880eec3b52544c72f11b58b3462b1db029537fffd1db6ba26378 +size 1799