Skip to main content

av_scenechange/data/
sad.rs

1#[cfg(asm_x86_64)]
2mod simd_x86;
3
4use rust::get_sad_internal;
5#[cfg(not(asm_x86_64))]
6use rust::*;
7#[cfg(asm_x86_64)]
8use simd_x86::*;
9use v_frame::{pixel::Pixel, plane::Plane};
10
11use super::plane::PlaneRegion;
12use crate::cpu::CpuFeatureLevel;
13
14mod rust {
15    use v_frame::{
16        pixel::{CastFromPrimitive, Pixel},
17        plane::Plane,
18    };
19
20    use crate::{
21        data::plane::{Area, PlaneRegion, Rect},
22        CpuFeatureLevel,
23    };
24
25    pub(super) fn sad_plane_internal<T: Pixel>(
26        src: &Plane<T>,
27        dst: &Plane<T>,
28        _cpu: CpuFeatureLevel,
29    ) -> u64 {
30        assert_eq!(src.cfg.width, dst.cfg.width);
31        assert_eq!(src.cfg.height, dst.cfg.height);
32
33        src.rows_iter()
34            .zip(dst.rows_iter())
35            .map(|(src, dst)| {
36                src.iter()
37                    .zip(dst.iter())
38                    .map(|(&p1, &p2)| i32::cast_from(p1).abs_diff(i32::cast_from(p2)))
39                    .sum::<u32>() as u64
40            })
41            .sum()
42    }
43
44    pub fn get_sad_internal<T: Pixel>(
45        plane_org: &PlaneRegion<'_, T>,
46        plane_ref: &PlaneRegion<'_, T>,
47        w: usize,
48        h: usize,
49        _bit_depth: usize,
50        _cpu: CpuFeatureLevel,
51    ) -> u32 {
52        debug_assert!(w <= 128 && h <= 128);
53        let plane_org = plane_org.subregion(Area::Rect(Rect {
54            x: 0,
55            y: 0,
56            width: w,
57            height: h,
58        }));
59        let plane_ref = plane_ref.subregion(Area::Rect(Rect {
60            x: 0,
61            y: 0,
62            width: w,
63            height: h,
64        }));
65
66        plane_org
67            .rows_iter()
68            .zip(plane_ref.rows_iter())
69            .map(|(src, dst)| {
70                src.iter()
71                    .zip(dst)
72                    .map(|(&p1, &p2)| i32::cast_from(p1).abs_diff(i32::cast_from(p2)))
73                    .sum::<u32>()
74            })
75            .sum()
76    }
77}
78
79/// Compute the sum of absolute differences (SADs) on 2 rows of pixels
80///
81/// This differs from other SAD functions in that it operates over a row
82/// (or line) of unknown length rather than a `PlaneRegion<T>`.
83pub(crate) fn sad_plane<T: Pixel>(src: &Plane<T>, dst: &Plane<T>, cpu: CpuFeatureLevel) -> u64 {
84    sad_plane_internal(src, dst, cpu)
85}
86
87pub(crate) fn get_sad<T: Pixel>(
88    plane_org: &PlaneRegion<'_, T>,
89    plane_ref: &PlaneRegion<'_, T>,
90    w: usize,
91    h: usize,
92    bit_depth: usize,
93    cpu: CpuFeatureLevel,
94) -> u32 {
95    get_sad_internal(plane_org, plane_ref, w, h, bit_depth, cpu)
96}