Skip to content

Commit

Permalink
Do not downscale if self.scale_factor == 1
Browse files Browse the repository at this point in the history
  • Loading branch information
redzic committed Sep 17, 2021
1 parent 0c066cb commit a9fed90
Showing 1 changed file with 70 additions and 40 deletions.
110 changes: 70 additions & 40 deletions src/scenechange/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ pub struct SceneChangeDetector<T: Pixel> {
/// scaling factor for fast scene detection
scale_factor: usize,
/// Frame buffer for scaled frames
frame_buffer: Option<(
downscaled_frame_buffer: Option<(
Box<[Plane<T>; 2]>,
// `true` if the data is valid and initialized, or `false`
// if it should be assumed that the data is uninitialized.
bool,
)>,
/// Frame buffer for holding references to source frames. Useful for not copying data
/// into the downscaled frame buffer when using a downscale factor of 1.
frame_ref_buffer: Option<Box<[Arc<Frame<T>>; 2]>>,
/// Deque offset for current
lookahead_offset: usize,
/// Start deque offset based on lookahead
Expand Down Expand Up @@ -105,7 +108,8 @@ impl<T: Pixel> SceneChangeDetector<T> {
threshold,
speed_mode,
scale_factor,
frame_buffer: None,
downscaled_frame_buffer: None,
frame_ref_buffer: None,
lookahead_offset,
deque_offset,
score_deque,
Expand Down Expand Up @@ -146,7 +150,7 @@ impl<T: Pixel> SceneChangeDetector<T> {
}
if distance >= self.encoder_config.max_key_frame_interval {
// Clear buffers and `score_deque`
if let Some((_, is_initialized)) = &mut self.frame_buffer {
if let Some((_, is_initialized)) = &mut self.downscaled_frame_buffer {
*is_initialized = false;
}
debug!("[SC-score-deque]{:.0?}", self.score_deque);
Expand Down Expand Up @@ -206,7 +210,7 @@ impl<T: Pixel> SceneChangeDetector<T> {

if scenecut {
// Clear buffers and `score_deque`
if let Some((_, is_initialized)) = &mut self.frame_buffer {
if let Some((_, is_initialized)) = &mut self.downscaled_frame_buffer {
*is_initialized = false;
}
debug!("[SC-score-deque]{:.0?}", self.score_deque);
Expand Down Expand Up @@ -307,43 +311,69 @@ impl<T: Pixel> SceneChangeDetector<T> {
fn fast_scenecut(
&mut self, frame1: Arc<Frame<T>>, frame2: Arc<Frame<T>>,
) -> ScenecutResult {
// downscale both frames for faster comparison
if let Some((frame_buffer, is_initialized)) = &mut self.frame_buffer {
let frame_buffer = &mut **frame_buffer;
if *is_initialized {
if self.scale_factor == 1 {
if let Some(frame_buffer) = self.frame_ref_buffer.as_deref_mut() {
frame_buffer.swap(0, 1);
frame2.planes[0]
.downscale_in_place(self.scale_factor, &mut frame_buffer[1]);
frame_buffer[1] = frame2;
} else {
// both frames are in an irrelevant and invalid state, so we have to reinitialize
// them, but we can reuse their allocations
frame1.planes[0]
.downscale_in_place(self.scale_factor, &mut frame_buffer[0]);
frame2.planes[0]
.downscale_in_place(self.scale_factor, &mut frame_buffer[1]);
*is_initialized = true;
self.frame_ref_buffer = Some(Box::new([frame1, frame2]));
}
} else {
self.frame_buffer = Some((
Box::new([
frame1.planes[0].downscale(self.scale_factor),
frame2.planes[0].downscale(self.scale_factor),
]),
true, // the frame buffer is initialized and in a valid state
));
}

if let Some((frame_buffer, _)) = &self.frame_buffer {
let frame_buffer = &**frame_buffer;
let delta = self.delta_in_planes(&frame_buffer[0], &frame_buffer[1]);
if let Some(frame_buffer) = self.frame_ref_buffer.as_deref() {
let delta = self.delta_in_planes(
&frame_buffer[0].planes[0],
&frame_buffer[1].planes[0],
);

ScenecutResult {
intra_cost: self.threshold as f64,
threshold: self.threshold as f64,
inter_cost: delta as f64,
ScenecutResult {
intra_cost: self.threshold as f64,
threshold: self.threshold as f64,
inter_cost: delta as f64,
}
} else {
unreachable!()
}
} else {
unreachable!()
// downscale both frames for faster comparison
if let Some((frame_buffer, is_initialized)) =
&mut self.downscaled_frame_buffer
{
let frame_buffer = &mut **frame_buffer;
if *is_initialized {
frame_buffer.swap(0, 1);
frame2.planes[0]
.downscale_in_place(self.scale_factor, &mut frame_buffer[1]);
} else {
// both frames are in an irrelevant and invalid state, so we have to reinitialize
// them, but we can reuse their allocations
frame1.planes[0]
.downscale_in_place(self.scale_factor, &mut frame_buffer[0]);
frame2.planes[0]
.downscale_in_place(self.scale_factor, &mut frame_buffer[1]);
*is_initialized = true;
}
} else {
self.downscaled_frame_buffer = Some((
Box::new([
frame1.planes[0].downscale(self.scale_factor),
frame2.planes[0].downscale(self.scale_factor),
]),
true, // the frame buffer is initialized and in a valid state
));
}

if let Some((frame_buffer, _)) = &self.downscaled_frame_buffer {
let frame_buffer = &**frame_buffer;
let delta = self.delta_in_planes(&frame_buffer[0], &frame_buffer[1]);

ScenecutResult {
intra_cost: self.threshold as f64,
threshold: self.threshold as f64,
inter_cost: delta as f64,
}
} else {
unreachable!()
}
}
}

Expand Down Expand Up @@ -450,12 +480,12 @@ fn detect_scale_factor(
let scale_factor;
if speed_mode == SceneDetectionSpeed::Fast {
scale_factor = match small_edge {
0..=240 => 1,
241..=480 => 2,
481..=720 => 4,
721..=1080 => 8,
1081..=1600 => 16,
1601..=usize::MAX => 32,
// 0..=240 => 1,
// 241..=480 => 2,
// 481..=720 => 4,
// 721..=1080 => 8,
// 1081..=1600 => 16,
// 1601..=usize::MAX => 32,
_ => 1,
} as usize
} else {
Expand Down

0 comments on commit a9fed90

Please sign in to comment.