Skip to content

Commit f88cc27

Browse files
BoatsMcGeeBoats McGee
and
Boats McGee
authored
Fix Scene Detection frames mismatch causes invalid frame access crashes (#927)
* Fix frame count mismatch between FFmpeg and VapourSynth Fix Scene Detection uses incompatible decode method leading to accessing invalid frames * Fix race condition in Scene Detection causes End of File Error --------- Co-authored-by: Boats McGee <{ID}+{username}@users.noreply.github.com>
1 parent 1109675 commit f88cc27

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

av1an-core/src/context.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl Av1anContext {
120120

121121
// frames need to be recalculated in this case
122122
if self.frames == 0 {
123-
self.frames = self.args.input.frames()?;
123+
self.frames = self.args.input.frames(self.vs_script.clone())?;
124124
done.frames.store(self.frames, atomic::Ordering::Relaxed);
125125
}
126126

@@ -732,9 +732,19 @@ impl Av1anContext {
732732
fn calc_split_locations(&self) -> anyhow::Result<(Vec<Scene>, usize)> {
733733
let zones = self.parse_zones()?;
734734

735+
// Create a new input with the generated VapourSynth script for Scene Detection
736+
let input = if let Some(ref vs_script) = self.vs_script {
737+
Input::VapourSynth {
738+
path: vs_script.clone(),
739+
vspipe_args: Vec::new(),
740+
}
741+
} else {
742+
self.args.input.clone()
743+
};
744+
735745
Ok(match self.args.split_method {
736746
SplitMethod::AvScenechange => av_scenechange_detect(
737-
&self.args.input,
747+
&input,
738748
self.args.encoder,
739749
self.frames,
740750
self.args.min_scene_len,
@@ -770,8 +780,7 @@ impl Av1anContext {
770780
zone_overrides: None,
771781
});
772782
}
773-
774-
(scenes, self.args.input.frames()?)
783+
(scenes, self.args.input.frames(self.vs_script.clone())?)
775784
}
776785
})
777786
}
@@ -810,7 +819,7 @@ impl Av1anContext {
810819
crate::split::read_scenes_from_file(scene_file.as_ref())?
811820
} else {
812821
used_existing_cuts = false;
813-
self.frames = self.args.input.frames()?;
822+
self.frames = self.args.input.frames(self.vs_script.clone())?;
814823
self.calc_split_locations()?
815824
};
816825
self.frames = frames;

av1an-core/src/lib.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,20 @@ impl Input {
116116
matches!(&self, Input::VapourSynth { .. })
117117
}
118118

119-
pub fn frames(&self) -> anyhow::Result<usize> {
119+
pub fn frames(&self, vs_script_path: Option<PathBuf>) -> anyhow::Result<usize> {
120120
const FAIL_MSG: &str = "Failed to get number of frames for input video";
121121
Ok(match &self {
122-
Input::Video { path } => {
122+
Input::Video { path } if vs_script_path.is_none() => {
123123
ffmpeg::num_frames(path.as_path()).map_err(|_| anyhow::anyhow!(FAIL_MSG))?
124124
}
125-
Input::VapourSynth { path, .. } => {
126-
vapoursynth::num_frames(path.as_path(), self.as_vspipe_args_map()?)
127-
.map_err(|_| anyhow::anyhow!(FAIL_MSG))?
128-
}
125+
path => vapoursynth::num_frames(
126+
vs_script_path
127+
.as_ref()
128+
.map(|p| p.as_path())
129+
.unwrap_or(path.as_path()),
130+
self.as_vspipe_args_map()?,
131+
)
132+
.map_err(|_| anyhow::anyhow!(FAIL_MSG))?,
129133
})
130134
}
131135

av1an-core/src/scene_detect.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@ pub fn av_scenechange_detect(
3939

4040
let input2 = input.clone();
4141
let frame_thread = thread::spawn(move || {
42-
let frames = input2.frames().unwrap();
42+
let frames = input2.frames(None).unwrap();
4343
if verbosity != Verbosity::Quiet {
4444
progress_bar::convert_to_progress(0);
4545
progress_bar::set_len(frames as u64);
4646
}
4747
frames
4848
});
4949

50+
let frames = frame_thread.join().unwrap();
5051
let scenes = scene_detect(
5152
input,
5253
encoder,
@@ -66,8 +67,6 @@ pub fn av_scenechange_detect(
6667
zones,
6768
)?;
6869

69-
let frames = frame_thread.join().unwrap();
70-
7170
progress_bar::finish_progress_bar();
7271

7372
Ok((scenes, frames))

0 commit comments

Comments
 (0)