av_scenechange/analyze/
fast.rs1use std::{cmp, sync::Arc};
2
3use log::debug;
4use v_frame::{frame::Frame, pixel::Pixel, plane::Plane};
5
6use super::{fast_idiv, ScaleFunction, SceneChangeDetector, ScenecutResult};
7use crate::{data::sad::sad_plane, SceneDetectionSpeed};
8
9pub(super) const FAST_THRESHOLD: f64 = 18.0;
11
12impl<T: Pixel> SceneChangeDetector<T> {
13 pub(super) fn fast_scenecut(
16 &mut self,
17 frame1: Arc<Frame<T>>,
18 frame2: Arc<Frame<T>>,
19 ) -> ScenecutResult {
20 if let Some(scale_func) = &self.scale_func {
21 if let Some(frame_buffer) = &mut self.downscaled_frame_buffer {
23 frame_buffer.swap(0, 1);
24 (scale_func.downscale_in_place)(&frame2.planes[0], &mut frame_buffer[1]);
25 } else {
26 self.downscaled_frame_buffer = Some([
27 (scale_func.downscale)(&frame1.planes[0]),
28 (scale_func.downscale)(&frame2.planes[0]),
29 ]);
30 }
31
32 if let Some(frame_buffer) = &self.downscaled_frame_buffer {
33 let &[first, second] = &frame_buffer;
34 let delta = self.delta_in_planes(first, second);
35
36 ScenecutResult {
37 threshold: self.threshold,
38 inter_cost: delta,
39 imp_block_cost: delta,
40 forward_adjusted_cost: delta,
41 backward_adjusted_cost: delta,
42 }
43 } else {
44 unreachable!()
45 }
46 } else {
47 let delta = self.delta_in_planes(&frame1.planes[0], &frame2.planes[0]);
48
49 ScenecutResult {
50 threshold: self.threshold,
51 inter_cost: delta,
52 imp_block_cost: delta,
53 backward_adjusted_cost: delta,
54 forward_adjusted_cost: delta,
55 }
56 }
57 }
58
59 fn delta_in_planes(&self, plane1: &Plane<T>, plane2: &Plane<T>) -> f64 {
62 let delta = sad_plane(plane1, plane2, self.cpu_feature_level);
63
64 delta as f64 / self.scaled_pixels as f64
65 }
66}
67
68pub(super) fn detect_scale_factor<T: Pixel>(
70 resolution: (usize, usize),
71 speed_mode: SceneDetectionSpeed,
72) -> Option<ScaleFunction<T>> {
73 let small_edge = cmp::min(resolution.0, resolution.1);
74 let scale_func = if speed_mode == SceneDetectionSpeed::Fast {
75 match small_edge {
76 0..=240 => None,
77 241..=480 => Some(ScaleFunction::from_scale::<2>()),
78 481..=720 => Some(ScaleFunction::from_scale::<4>()),
79 721..=1080 => Some(ScaleFunction::from_scale::<8>()),
80 1081..=1600 => Some(ScaleFunction::from_scale::<16>()),
81 1601..=usize::MAX => Some(ScaleFunction::from_scale::<32>()),
82 _ => None,
83 }
84 } else {
85 None
86 };
87
88 if let Some(scale_factor) = scale_func.as_ref().map(|x| x.factor) {
89 debug!(
90 "Scene detection scale factor {}, [{},{}] -> [{},{}]",
91 scale_factor,
92 resolution.0,
93 resolution.1,
94 fast_idiv(resolution.0, scale_factor),
95 fast_idiv(resolution.1, scale_factor)
96 );
97 }
98
99 scale_func
100}