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
This commit is contained in:
Richard Antalik
2025-10-08 08:53:26 +02:00
committed by Richard Antalik
parent bd8fc0807c
commit 7b7b5a5fcd

View File

@@ -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<Strip *> 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<Strip *> scene_strips)
blender::Span<Strip *> scene_strips,
int timeline_frame)
{
int cfra = seq_prefetch_cfra(pfjob);
blender::Vector<Strip *> strips = seq_shown_strips_get(
pfjob->scene_eval, channels, seqbase, cfra, 0);
blender::Vector<Strip *> 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<Strip *> 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<Strip *> 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;