/rust/registry/src/index.crates.io-1949cf8c6b5b557f/av-scenechange-0.14.1/src/analyze/fast.rs
Line | Count | Source |
1 | | use std::{cmp, sync::Arc}; |
2 | | |
3 | | use log::debug; |
4 | | use v_frame::{frame::Frame, pixel::Pixel, plane::Plane}; |
5 | | |
6 | | use super::{fast_idiv, ScaleFunction, SceneChangeDetector, ScenecutResult}; |
7 | | use crate::{data::sad::sad_plane, SceneDetectionSpeed}; |
8 | | |
9 | | /// Experiments have determined this to be an optimal threshold |
10 | | pub(super) const FAST_THRESHOLD: f64 = 18.0; |
11 | | |
12 | | impl<T: Pixel> SceneChangeDetector<T> { |
13 | | /// The fast algorithm detects fast cuts using a raw difference |
14 | | /// in pixel values between the scaled frames. |
15 | 0 | pub(super) fn fast_scenecut( |
16 | 0 | &mut self, |
17 | 0 | frame1: Arc<Frame<T>>, |
18 | 0 | frame2: Arc<Frame<T>>, |
19 | 0 | ) -> ScenecutResult { |
20 | 0 | if let Some(scale_func) = &self.scale_func { |
21 | | // downscale both frames for faster comparison |
22 | 0 | if let Some(frame_buffer) = &mut self.downscaled_frame_buffer { |
23 | 0 | frame_buffer.swap(0, 1); |
24 | 0 | (scale_func.downscale_in_place)(&frame2.planes[0], &mut frame_buffer[1]); |
25 | 0 | } else { |
26 | 0 | self.downscaled_frame_buffer = Some([ |
27 | 0 | (scale_func.downscale)(&frame1.planes[0]), |
28 | 0 | (scale_func.downscale)(&frame2.planes[0]), |
29 | 0 | ]); |
30 | 0 | } |
31 | | |
32 | 0 | if let Some(frame_buffer) = &self.downscaled_frame_buffer { |
33 | 0 | let &[first, second] = &frame_buffer; |
34 | 0 | let delta = self.delta_in_planes(first, second); |
35 | | |
36 | 0 | ScenecutResult { |
37 | 0 | threshold: self.threshold, |
38 | 0 | inter_cost: delta, |
39 | 0 | imp_block_cost: delta, |
40 | 0 | forward_adjusted_cost: delta, |
41 | 0 | backward_adjusted_cost: delta, |
42 | 0 | } |
43 | | } else { |
44 | 0 | unreachable!() |
45 | | } |
46 | | } else { |
47 | 0 | let delta = self.delta_in_planes(&frame1.planes[0], &frame2.planes[0]); |
48 | | |
49 | 0 | ScenecutResult { |
50 | 0 | threshold: self.threshold, |
51 | 0 | inter_cost: delta, |
52 | 0 | imp_block_cost: delta, |
53 | 0 | backward_adjusted_cost: delta, |
54 | 0 | forward_adjusted_cost: delta, |
55 | 0 | } |
56 | | } |
57 | 0 | } Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::fast_scenecut Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::fast_scenecut Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::fast_scenecut |
58 | | |
59 | | /// Calculates the average sum of absolute difference (SAD) per pixel |
60 | | /// between 2 planes |
61 | 0 | fn delta_in_planes(&self, plane1: &Plane<T>, plane2: &Plane<T>) -> f64 { |
62 | 0 | let delta = sad_plane(plane1, plane2, self.cpu_feature_level); |
63 | | |
64 | 0 | delta as f64 / self.scaled_pixels as f64 |
65 | 0 | } Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::delta_in_planes Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::delta_in_planes Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::delta_in_planes |
66 | | } |
67 | | |
68 | | /// Scaling factor for frame in scene detection |
69 | 0 | pub(super) fn detect_scale_factor<T: Pixel>( |
70 | 0 | resolution: (usize, usize), |
71 | 0 | speed_mode: SceneDetectionSpeed, |
72 | 0 | ) -> Option<ScaleFunction<T>> { |
73 | 0 | let small_edge = cmp::min(resolution.0, resolution.1); |
74 | 0 | let scale_func = if speed_mode == SceneDetectionSpeed::Fast { |
75 | 0 | match small_edge { |
76 | 0 | 0..=240 => None, |
77 | 0 | 241..=480 => Some(ScaleFunction::from_scale::<2>()), |
78 | 0 | 481..=720 => Some(ScaleFunction::from_scale::<4>()), |
79 | 0 | 721..=1080 => Some(ScaleFunction::from_scale::<8>()), |
80 | 0 | 1081..=1600 => Some(ScaleFunction::from_scale::<16>()), |
81 | 0 | 1601..=usize::MAX => Some(ScaleFunction::from_scale::<32>()), |
82 | 0 | _ => None, |
83 | | } |
84 | | } else { |
85 | 0 | None |
86 | | }; |
87 | | |
88 | 0 | if let Some(scale_factor) = scale_func.as_ref().map(|x| x.factor) { |
89 | 0 | debug!( |
90 | 0 | "Scene detection scale factor {}, [{},{}] -> [{},{}]", |
91 | | scale_factor, |
92 | | resolution.0, |
93 | | resolution.1, |
94 | 0 | fast_idiv(resolution.0, scale_factor), |
95 | 0 | fast_idiv(resolution.1, scale_factor) |
96 | | ); |
97 | 0 | } |
98 | | |
99 | 0 | scale_func |
100 | 0 | } Unexecuted instantiation: av_scenechange::analyze::fast::detect_scale_factor::<u8> Unexecuted instantiation: av_scenechange::analyze::fast::detect_scale_factor::<u16> Unexecuted instantiation: av_scenechange::analyze::fast::detect_scale_factor::<_> |