Footage: 8-bit levels are read while the render records its reads

footage_buf8 asked for a movie's 8-bit levels outside Renderer::read, so the media pool noted the movie in no recording: a layer buffer made of it listed no files and was still marked complete, and could be served stale after the movie changed on disk.
This commit is contained in:
nazar-gavrylyk committed 2026-11-10 15:04:01 +01:00
1 parent 396495dfa0
commit dd1aff17e5
2 files changed
+38 -1

No files matched your search

+1 -1
View File
@@ -1056,7 +1056,7 @@ impl<'a> Renderer<'a> {
if !plain {
return None;
}
let fr = self.footage.frame8(item, pf, t, self.pipe.float_curve(pf))?;
let fr = self.read(|| self.footage.frame8(item, pf, t, self.pipe.float_curve(pf)))?;
let n = (fr.width as usize).checked_mul(fr.height as usize)?;
let px = fr.rgba.as_chunks::<4>().0;
if px.len() != n {
+37
View File
@@ -157,3 +157,40 @@ fn footage_kept_as_8_bit_levels_renders_the_same_pixels() {
assert_eq!(q8.asked.into_inner() > 0, used, "{depth:?} {invert} {scale}");
}
}
/// The 8-bit levels are read while the render records its reads: the movie is in the files the
/// frame (and a cached layer buffer) was made of. (Read outside, a buffer of a movie listed no
/// files and was still marked complete: changed on disk, it was served stale.)
#[test]
fn footage_kept_as_8_bit_levels_is_noted_as_read() {
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
struct Noted {
clip: Clip8,
recording: AtomicBool,
outside: AtomicUsize,
}
impl FootageSource for Noted {
fn frame(&self, item: ItemId, f: &Footage, t: Tick) -> Option<Arc<Image>> {
self.clip.frame(item, f, t)
}
fn frame8(&self, item: ItemId, f: &Footage, t: Tick, float: crate::FloatCurve) -> Option<Arc<crate::disk_cache::Frame8>> {
if !self.recording.load(Ordering::SeqCst) {
self.outside.fetch_add(1, Ordering::SeqCst);
}
self.clip.frame8(item, f, t, float)
}
fn recording(&self, _: &crate::reads::ReadLog, f: &mut dyn FnMut()) {
self.recording.store(true, Ordering::SeqCst);
f();
self.recording.store(false, Ordering::SeqCst);
}
}
let (p, cid) = project(BitDepth::Bpc8, false);
let src = Noted { clip: Clip8 { asked: Default::default() }, recording: AtomicBool::new(false), outside: AtomicUsize::new(0) };
let log = crate::reads::ReadLog::new();
let mut r = Renderer::new(&p, &src, RenderOpts::default());
r.reads = Some(&log);
r.comp_frame(cid, Tick::ZERO);
assert!(src.clip.asked.load(Ordering::SeqCst) > 0, "the 8-bit levels were not asked for");
assert_eq!(src.outside.load(Ordering::SeqCst), 0, "8-bit levels read outside the render's recording");
}