av_scenechange/analyze/
standard.rs1use std::sync::Arc;
2
3use v_frame::{frame::Frame, math::Fixed, pixel::Pixel};
4
5use super::{SceneChangeDetector, ScenecutResult};
6use crate::{
7 analyze::{
8 importance::estimate_importance_block_difference,
9 inter::estimate_inter_costs,
10 intra::estimate_intra_costs,
11 },
12 data::motion::FrameMEStats,
13};
14
15impl<T: Pixel> SceneChangeDetector<T> {
16 pub(super) fn cost_scenecut(
23 &mut self,
24 frame1: Arc<Frame<T>>,
25 frame2: Arc<Frame<T>>,
26 input_frameno: usize,
27 ) -> ScenecutResult {
28 let frame2_inter_ref = Arc::clone(&frame2);
29 let frame1_imp_ref = Arc::clone(&frame1);
30 let frame2_imp_ref = Arc::clone(&frame2);
31
32 let mut intra_cost = 0.0;
33 let mut mv_inter_cost = 0.0;
34 let mut imp_block_cost = 0.0;
35
36 let cols = 2 * self.resolution.0.align_power_of_two_and_shift(3);
37 let rows = 2 * self.resolution.1.align_power_of_two_and_shift(3);
38
39 let buffer = if let Some(buffer) = &self.frame_me_stats_buffer {
40 Arc::clone(buffer)
41 } else {
42 let frame_me_stats = FrameMEStats::new_arc_array(cols, rows);
43 let clone = Arc::clone(&frame_me_stats);
44 self.frame_me_stats_buffer = Some(frame_me_stats);
45 clone
46 };
47
48 rayon::scope(|s| {
49 s.spawn(|_| {
50 let temp_plane = self
51 .temp_plane
52 .get_or_insert_with(|| frame2.planes[0].clone());
53
54 let intra_costs = estimate_intra_costs(
55 temp_plane,
56 &*frame2,
57 self.bit_depth,
58 self.cpu_feature_level,
59 );
60 if let Some(ref mut intra_cache) = self.intra_costs {
61 intra_cache.insert(input_frameno, intra_costs.clone());
62 }
63
64 intra_cost = intra_costs.iter().map(|&cost| cost as u64).sum::<u64>() as f64
65 / intra_costs.len() as f64;
66 });
67 s.spawn(|_| {
68 mv_inter_cost = estimate_inter_costs(
69 frame2_inter_ref,
70 frame1,
71 self.bit_depth,
72 self.frame_rate,
73 self.chroma_sampling,
74 buffer,
75 self.cpu_feature_level,
76 );
77 });
78 s.spawn(|_| {
79 imp_block_cost =
80 estimate_importance_block_difference(frame2_imp_ref, frame1_imp_ref);
81 });
82 });
83
84 const BIAS: f64 = 0.7;
90 let threshold = intra_cost * (1.0 - BIAS);
91
92 ScenecutResult {
93 inter_cost: mv_inter_cost,
94 imp_block_cost,
95 threshold,
96 backward_adjusted_cost: 0.0,
97 forward_adjusted_cost: 0.0,
98 }
99 }
100}