/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 | | } |