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