Coverage Report

Created: 2026-01-17 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/av-scenechange-0.14.1/src/analyze/standard.rs
Line
Count
Source
1
use std::sync::Arc;
2
3
use v_frame::{frame::Frame, math::Fixed, pixel::Pixel};
4
5
use super::{SceneChangeDetector, ScenecutResult};
6
use 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
15
impl<T: Pixel> SceneChangeDetector<T> {
16
    /// Run a comparison between two frames to determine if they qualify for a
17
    /// scenecut.
18
    ///
19
    /// We gather both intra and inter costs for the frames,
20
    /// as well as an importance-block-based difference,
21
    /// and use all three metrics.
22
0
    pub(super) fn cost_scenecut(
23
0
        &mut self,
24
0
        frame1: Arc<Frame<T>>,
25
0
        frame2: Arc<Frame<T>>,
26
0
        input_frameno: usize,
27
0
    ) -> ScenecutResult {
28
0
        let frame2_inter_ref = Arc::clone(&frame2);
29
0
        let frame1_imp_ref = Arc::clone(&frame1);
30
0
        let frame2_imp_ref = Arc::clone(&frame2);
31
32
0
        let mut intra_cost = 0.0;
33
0
        let mut mv_inter_cost = 0.0;
34
0
        let mut imp_block_cost = 0.0;
35
36
0
        let cols = 2 * self.resolution.0.align_power_of_two_and_shift(3);
37
0
        let rows = 2 * self.resolution.1.align_power_of_two_and_shift(3);
38
39
0
        let buffer = if let Some(buffer) = &self.frame_me_stats_buffer {
40
0
            Arc::clone(buffer)
41
        } else {
42
0
            let frame_me_stats = FrameMEStats::new_arc_array(cols, rows);
43
0
            let clone = Arc::clone(&frame_me_stats);
44
0
            self.frame_me_stats_buffer = Some(frame_me_stats);
45
0
            clone
46
        };
47
48
0
        rayon::scope(|s| {
49
0
            s.spawn(|_| {
50
0
                let temp_plane = self
51
0
                    .temp_plane
52
0
                    .get_or_insert_with(|| frame2.planes[0].clone());
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut::{closure#0}::{closure#0}::{closure#0}
53
54
0
                let intra_costs = estimate_intra_costs(
55
0
                    temp_plane,
56
0
                    &*frame2,
57
0
                    self.bit_depth,
58
0
                    self.cpu_feature_level,
59
                );
60
0
                if let Some(ref mut intra_cache) = self.intra_costs {
61
0
                    intra_cache.insert(input_frameno, intra_costs.clone());
62
0
                }
63
64
0
                intra_cost = intra_costs.iter().map(|&cost| cost as u64).sum::<u64>() as f64
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut::{closure#0}::{closure#0}::{closure#1}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut::{closure#0}::{closure#0}::{closure#1}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut::{closure#0}::{closure#0}::{closure#1}
65
0
                    / intra_costs.len() as f64;
66
0
            });
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut::{closure#0}::{closure#0}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut::{closure#0}::{closure#0}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut::{closure#0}::{closure#0}
67
0
            s.spawn(|_| {
68
0
                mv_inter_cost = estimate_inter_costs(
69
0
                    frame2_inter_ref,
70
0
                    frame1,
71
0
                    self.bit_depth,
72
0
                    self.frame_rate,
73
0
                    self.chroma_sampling,
74
0
                    buffer,
75
0
                    self.cpu_feature_level,
76
0
                );
77
0
            });
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut::{closure#0}::{closure#1}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut::{closure#0}::{closure#1}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut::{closure#0}::{closure#1}
78
0
            s.spawn(|_| {
79
0
                imp_block_cost =
80
0
                    estimate_importance_block_difference(frame2_imp_ref, frame1_imp_ref);
81
0
            });
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut::{closure#0}::{closure#2}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut::{closure#0}::{closure#2}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut::{closure#0}::{closure#2}
82
0
        });
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut::{closure#0}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut::{closure#0}
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut::{closure#0}
83
84
        // `BIAS` determines how likely we are
85
        // to choose a keyframe, between 0.0-1.0.
86
        // Higher values mean we are more likely to choose a keyframe.
87
        // This value was chosen based on trials using the new
88
        // adaptive scenecut code.
89
        const BIAS: f64 = 0.7;
90
0
        let threshold = intra_cost * (1.0 - BIAS);
91
92
0
        ScenecutResult {
93
0
            inter_cost: mv_inter_cost,
94
0
            imp_block_cost,
95
0
            threshold,
96
0
            backward_adjusted_cost: 0.0,
97
0
            forward_adjusted_cost: 0.0,
98
0
        }
99
0
    }
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u16>>::cost_scenecut
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<u8>>::cost_scenecut
Unexecuted instantiation: <av_scenechange::analyze::SceneChangeDetector<_>>::cost_scenecut
100
}