From 7b7b5a5fcd511feb3be8d0d00a4de6735c2f5e30 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 8 Oct 2025 08:53:26 +0200 Subject: [PATCH] Fix: Crash when prefetching scene strip Fix done in 7805a4bfe1 introduced another crash - null dereference when accessing `strip->scene`. Also the mentioned fix was not quite correct, because it used incorrect scene and timeline frame to get rendered strips. Pull Request: https://projects.blender.org/blender/blender/pulls/147595 --- source/blender/sequencer/intern/prefetch.cc | 35 ++++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/source/blender/sequencer/intern/prefetch.cc b/source/blender/sequencer/intern/prefetch.cc index a94a9a5f62d..c9027356933 100644 --- a/source/blender/sequencer/intern/prefetch.cc +++ b/source/blender/sequencer/intern/prefetch.cc @@ -43,6 +43,7 @@ #include "SEQ_render.hh" #include "SEQ_sequencer.hh" +#include "SEQ_time.hh" #include "cache/final_image_cache.hh" #include "cache/source_image_cache.hh" #include "prefetch.hh" @@ -419,35 +420,43 @@ static blender::VectorSet query_scene_strips(ListBase *seqbase) return strips; } -static bool seq_prefetch_scene_strip_is_rendered(PrefetchJob *pfjob, +static bool seq_prefetch_scene_strip_is_rendered(const Scene *scene, ListBase *channels, ListBase *seqbase, - blender::Span scene_strips) + blender::Span scene_strips, + int timeline_frame) { - int cfra = seq_prefetch_cfra(pfjob); - blender::Vector strips = seq_shown_strips_get( - pfjob->scene_eval, channels, seqbase, cfra, 0); + blender::Vector rendered_strips = seq_shown_strips_get( + scene, channels, seqbase, timeline_frame, 0); /* Iterate over rendered strips. */ - for (Strip *strip : strips) { + for (Strip *strip : rendered_strips) { if (strip->type == STRIP_TYPE_META && seq_prefetch_scene_strip_is_rendered( - pfjob, &strip->channels, &strip->seqbase, scene_strips)) + scene, &strip->channels, &strip->seqbase, scene_strips, timeline_frame)) { return true; } - if (strip->type == STRIP_TYPE_SCENE && (strip->flag & SEQ_SCENE_STRIPS) != 0) { + if (strip->type == STRIP_TYPE_SCENE && (strip->flag & SEQ_SCENE_STRIPS) != 0 && + strip->scene != nullptr) + { const Scene *target_scene = strip->scene; const Editing *target_ed = editing_get(target_scene); ListBase *target_seqbase = target_ed->current_strips(); blender::VectorSet target_scene_strips = query_scene_strips(target_seqbase); + int target_timeline_frame = give_frame_index(scene, strip, timeline_frame) + + target_scene->r.sfra; - return seq_prefetch_scene_strip_is_rendered( - pfjob, target_ed->current_channels(), target_ed->current_strips(), target_scene_strips); + return seq_prefetch_scene_strip_is_rendered(target_scene, + target_ed->current_channels(), + target_ed->current_strips(), + target_scene_strips, + target_timeline_frame); } - /* Check if strip is effect of scene strip or uses it as modifier. This is recursive check. */ + /* Check if strip is effect of scene strip or uses it as modifier. + * This also checks if `strip == seq_scene`. */ for (Strip *seq_scene : scene_strips) { if (relations_render_loop_check(strip, seq_scene)) { return true; @@ -462,7 +471,9 @@ static bool seq_prefetch_scene_strip_is_rendered(PrefetchJob *pfjob, static bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, ListBase *channels, ListBase *seqbase) { blender::VectorSet scene_strips = query_scene_strips(seqbase); - if (seq_prefetch_scene_strip_is_rendered(pfjob, channels, seqbase, scene_strips)) { + if (seq_prefetch_scene_strip_is_rendered( + pfjob->scene_eval, channels, seqbase, scene_strips, seq_prefetch_cfra(pfjob))) + { return true; } return false;