Coverage Report

Created: 2026-03-10 07:34

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/data/motion.rs
Line
Count
Source
1
use std::{
2
    marker::PhantomData,
3
    ops,
4
    ops::{Index, IndexMut},
5
    slice,
6
    sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
7
};
8
9
use arrayvec::ArrayVec;
10
use v_frame::{frame::Frame, pixel::Pixel, plane::Plane};
11
12
const MV_IN_USE_BITS: usize = 14;
13
pub const MV_UPP: i32 = 1 << MV_IN_USE_BITS;
14
pub const MV_LOW: i32 = -(1 << MV_IN_USE_BITS);
15
16
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
17
pub struct MotionVector {
18
    pub row: i16,
19
    pub col: i16,
20
}
21
22
impl MotionVector {
23
0
    pub const fn quantize_to_fullpel(self) -> Self {
24
0
        Self {
25
0
            row: (self.row / 8) * 8,
26
0
            col: (self.col / 8) * 8,
27
0
        }
28
0
    }
29
}
30
31
impl ops::Mul<i16> for MotionVector {
32
    type Output = MotionVector;
33
34
0
    fn mul(self, rhs: i16) -> MotionVector {
35
0
        MotionVector {
36
0
            row: self.row * rhs,
37
0
            col: self.col * rhs,
38
0
        }
39
0
    }
40
}
41
42
impl ops::Mul<u16> for MotionVector {
43
    type Output = MotionVector;
44
45
0
    fn mul(self, rhs: u16) -> MotionVector {
46
0
        MotionVector {
47
0
            row: self.row * rhs as i16,
48
0
            col: self.col * rhs as i16,
49
0
        }
50
0
    }
51
}
52
53
impl ops::Shr<u8> for MotionVector {
54
    type Output = MotionVector;
55
56
0
    fn shr(self, rhs: u8) -> MotionVector {
57
0
        MotionVector {
58
0
            row: self.row >> rhs,
59
0
            col: self.col >> rhs,
60
0
        }
61
0
    }
62
}
63
64
impl ops::Shl<u8> for MotionVector {
65
    type Output = MotionVector;
66
67
0
    fn shl(self, rhs: u8) -> MotionVector {
68
0
        MotionVector {
69
0
            row: self.row << rhs,
70
0
            col: self.col << rhs,
71
0
        }
72
0
    }
73
}
74
75
impl ops::Add<MotionVector> for MotionVector {
76
    type Output = MotionVector;
77
78
0
    fn add(self, rhs: MotionVector) -> MotionVector {
79
0
        MotionVector {
80
0
            row: self.row + rhs.row,
81
0
            col: self.col + rhs.col,
82
0
        }
83
0
    }
84
}
85
86
#[derive(Debug, Copy, Clone, Default)]
87
pub struct MEStats {
88
    pub mv: MotionVector,
89
    /// SAD value on the scale of a 128x128 block
90
    pub normalized_sad: u32,
91
}
92
93
#[derive(Debug, Clone)]
94
pub struct FrameMEStats {
95
    stats: Box<[MEStats]>,
96
    pub cols: usize,
97
    pub rows: usize,
98
}
99
100
pub const REF_FRAMES_LOG2: usize = 3;
101
pub const REF_FRAMES: usize = 1 << REF_FRAMES_LOG2;
102
pub type RefMEStats = Arc<RwLock<[FrameMEStats; REF_FRAMES]>>;
103
pub type ReadGuardMEStats<'a> = RwLockReadGuard<'a, [FrameMEStats; REF_FRAMES]>;
104
pub type WriteGuardMEStats<'a> = RwLockWriteGuard<'a, [FrameMEStats; REF_FRAMES]>;
105
106
impl FrameMEStats {
107
0
    pub fn new(cols: usize, rows: usize) -> Self {
108
0
        Self {
109
0
            // dynamic allocation: once per frame
110
0
            stats: vec![MEStats::default(); cols * rows].into_boxed_slice(),
111
0
            cols,
112
0
            rows,
113
0
        }
114
0
    }
115
116
0
    pub fn new_arc_array(cols: usize, rows: usize) -> RefMEStats {
117
0
        Arc::new(RwLock::new([
118
0
            FrameMEStats::new(cols, rows),
119
0
            FrameMEStats::new(cols, rows),
120
0
            FrameMEStats::new(cols, rows),
121
0
            FrameMEStats::new(cols, rows),
122
0
            FrameMEStats::new(cols, rows),
123
0
            FrameMEStats::new(cols, rows),
124
0
            FrameMEStats::new(cols, rows),
125
0
            FrameMEStats::new(cols, rows),
126
0
        ]))
127
0
    }
128
}
129
130
impl Index<usize> for FrameMEStats {
131
    type Output = [MEStats];
132
133
0
    fn index(&self, index: usize) -> &Self::Output {
134
0
        &self.stats[index * self.cols..(index + 1) * self.cols]
135
0
    }
136
}
137
138
impl IndexMut<usize> for FrameMEStats {
139
0
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
140
0
        &mut self.stats[index * self.cols..(index + 1) * self.cols]
141
0
    }
142
}
143
144
/// Tiled view of `FrameMEStats`
145
#[derive(Debug)]
146
pub struct TileMEStats<'a> {
147
    data: *const MEStats,
148
    // expressed in mi blocks
149
    // private to guarantee borrowing rules
150
    x: usize,
151
    y: usize,
152
    cols: usize,
153
    rows: usize,
154
    /// number of cols in the underlying `FrameMEStats`
155
    stride: usize,
156
    phantom: PhantomData<&'a MotionVector>,
157
}
158
159
/// Mutable tiled view of `FrameMEStats`
160
#[derive(Debug)]
161
pub struct TileMEStatsMut<'a> {
162
    data: *mut MEStats,
163
    // expressed in mi blocks
164
    // private to guarantee borrowing rules
165
    x: usize,
166
    y: usize,
167
    cols: usize,
168
    rows: usize,
169
    /// number of cols in the underlying `FrameMEStats`
170
    stride: usize,
171
    phantom: PhantomData<&'a mut MotionVector>,
172
}
173
174
// common impl for TileMotionVectors and TileMotionVectorsMut
175
macro_rules! tile_me_stats_common {
176
  // $name: TileMEStats or TileMEStatsMut
177
  // $opt_mut: nothing or mut
178
  ($name:ident $(,$opt_mut:tt)?) => {
179
    impl<'a> $name<'a> {
180
181
      /// # Panics
182
      ///
183
      /// - If the requested dimensions are larger than the frame MV size
184
      #[allow(dead_code)]
185
0
      pub fn new(
186
0
        frame_mvs: &'a $($opt_mut)? FrameMEStats,
187
0
        x: usize,
188
0
        y: usize,
189
0
        cols: usize,
190
0
        rows: usize,
191
0
      ) -> Self {
192
0
        assert!(x + cols <= frame_mvs.cols);
193
0
        assert!(y + rows <= frame_mvs.rows);
194
0
        Self {
195
0
          data: & $($opt_mut)? frame_mvs[y][x],
196
0
          x,
197
0
          y,
198
0
          cols,
199
0
          rows,
200
0
          stride: frame_mvs.cols,
201
0
          phantom: PhantomData,
202
0
        }
203
0
      }
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStatsMut>::new
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStats>::new
204
205
      #[allow(dead_code)]
206
0
      pub const fn x(&self) -> usize {
207
0
        self.x
208
0
      }
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStats>::x
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStatsMut>::x
209
210
      #[allow(dead_code)]
211
0
      pub const fn y(&self) -> usize {
212
0
        self.y
213
0
      }
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStats>::y
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStatsMut>::y
214
215
      #[allow(dead_code)]
216
0
      pub const fn cols(&self) -> usize {
217
0
        self.cols
218
0
      }
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStats>::cols
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStatsMut>::cols
219
220
      #[allow(dead_code)]
221
0
      pub const fn rows(&self) -> usize {
222
0
        self.rows
223
0
      }
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStats>::rows
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStatsMut>::rows
224
    }
225
226
    unsafe impl Send for $name<'_> {}
227
    unsafe impl Sync for $name<'_> {}
228
229
    impl Index<usize> for $name<'_> {
230
      type Output = [MEStats];
231
232
0
      fn index(&self, index: usize) -> &Self::Output {
233
0
        assert!(index < self.rows);
234
        // SAFETY: The above assert ensures we do not access OOB data.
235
        unsafe {
236
0
          let ptr = self.data.add(index * self.stride);
237
0
          slice::from_raw_parts(ptr, self.cols)
238
        }
239
0
      }
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStats as core::ops::index::Index<usize>>::index
Unexecuted instantiation: <av_scenechange::data::motion::TileMEStatsMut as core::ops::index::Index<usize>>::index
240
    }
241
  }
242
}
243
244
tile_me_stats_common!(TileMEStats);
245
tile_me_stats_common!(TileMEStatsMut, mut);
246
247
impl TileMEStatsMut<'_> {
248
0
    pub const fn as_const(&self) -> TileMEStats<'_> {
249
0
        TileMEStats {
250
0
            data: self.data,
251
0
            x: self.x,
252
0
            y: self.y,
253
0
            cols: self.cols,
254
0
            rows: self.rows,
255
0
            stride: self.stride,
256
0
            phantom: PhantomData,
257
0
        }
258
0
    }
259
}
260
261
impl IndexMut<usize> for TileMEStatsMut<'_> {
262
0
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
263
0
        assert!(index < self.rows);
264
        // SAFETY: The above assert ensures we do not access OOB data.
265
0
        unsafe {
266
0
            let ptr = self.data.add(index * self.stride);
267
0
            slice::from_raw_parts_mut(ptr, self.cols)
268
0
        }
269
0
    }
270
}
271
272
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
273
#[allow(clippy::upper_case_acronyms)]
274
pub enum MVSamplingMode {
275
    INIT,
276
    CORNER { right: bool, bottom: bool },
277
}
278
279
#[derive(Debug, Clone)]
280
pub struct ReferenceFrame<T: Pixel> {
281
    pub frame: Arc<Frame<T>>,
282
    pub input_hres: Arc<Plane<T>>,
283
    pub input_qres: Arc<Plane<T>>,
284
    pub frame_me_stats: RefMEStats,
285
}
286
287
#[derive(Debug, Clone, Default)]
288
pub struct ReferenceFramesSet<T: Pixel> {
289
    pub frames: [Option<Arc<ReferenceFrame<T>>>; REF_FRAMES],
290
}
291
292
impl<T: Pixel> ReferenceFramesSet<T> {
293
0
    pub fn new() -> Self {
294
0
        Self {
295
0
            frames: Default::default(),
296
0
            // deblock: Default::default()
297
0
        }
298
0
    }
Unexecuted instantiation: <av_scenechange::data::motion::ReferenceFramesSet<u16>>::new
Unexecuted instantiation: <av_scenechange::data::motion::ReferenceFramesSet<u8>>::new
Unexecuted instantiation: <av_scenechange::data::motion::ReferenceFramesSet<_>>::new
299
}
300
301
pub struct MotionEstimationSubsets {
302
    pub min_sad: u32,
303
    pub median: Option<MotionVector>,
304
    pub subset_b: ArrayVec<MotionVector, 5>,
305
    pub subset_c: ArrayVec<MotionVector, 5>,
306
}
307
308
impl MotionEstimationSubsets {
309
0
    pub fn all_mvs(&self) -> ArrayVec<MotionVector, 11> {
310
0
        let mut all = ArrayVec::new();
311
0
        if let Some(median) = self.median {
312
0
            all.push(median);
313
0
        }
314
315
0
        all.extend(self.subset_b.iter().copied());
316
0
        all.extend(self.subset_c.iter().copied());
317
318
0
        all
319
0
    }
320
}