av_scenechange/data/
sad.rs1#[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
79pub(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}