/rust/registry/src/index.crates.io-1949cf8c6b5b557f/av-scenechange-0.14.1/src/data/plane.rs
Line | Count | Source |
1 | | use std::{ |
2 | | iter::FusedIterator, |
3 | | marker::PhantomData, |
4 | | ops::{Index, IndexMut}, |
5 | | slice, |
6 | | }; |
7 | | |
8 | | use v_frame::{ |
9 | | pixel::Pixel, |
10 | | plane::{Plane, PlaneConfig, PlaneOffset}, |
11 | | }; |
12 | | |
13 | | use super::block::{BlockOffset, BLOCK_TO_PLANE_SHIFT}; |
14 | | |
15 | | /// Bounded region of a plane |
16 | | /// |
17 | | /// This allows giving access to a rectangular area of a plane without |
18 | | /// giving access to the whole plane. |
19 | | #[derive(Debug)] |
20 | | pub struct PlaneRegion<'a, T: Pixel> { |
21 | | data: *const T, // points to (plane_cfg.x, plane_cfg.y) |
22 | | pub plane_cfg: &'a PlaneConfig, |
23 | | // private to guarantee borrowing rules |
24 | | rect: Rect, |
25 | | phantom: PhantomData<&'a T>, |
26 | | } |
27 | | |
28 | | /// Mutable bounded region of a plane |
29 | | /// |
30 | | /// This allows to give mutable access to a rectangular area of the plane |
31 | | /// without giving access to the whole plane. |
32 | | #[derive(Debug)] |
33 | | pub struct PlaneRegionMut<'a, T: Pixel> { |
34 | | data: *mut T, // points to (plane_cfg.x, plane_cfg.y) |
35 | | pub plane_cfg: &'a PlaneConfig, |
36 | | rect: Rect, |
37 | | phantom: PhantomData<&'a mut T>, |
38 | | } |
39 | | |
40 | | // common impl for PlaneRegion and PlaneRegionMut |
41 | | macro_rules! plane_region_common { |
42 | | // $name: PlaneRegion or PlaneRegionMut |
43 | | // $as_ptr: as_ptr or as_mut_ptr |
44 | | // $opt_mut: nothing or mut |
45 | | ($name:ident, $as_ptr:ident $(,$opt_mut:tt)?) => { |
46 | | impl<'a, T: Pixel> $name<'a, T> { |
47 | | #[cold] |
48 | 0 | pub fn empty(plane_cfg : &'a PlaneConfig) -> Self { |
49 | 0 | return Self { |
50 | 0 | // SAFETY: This is actually pretty unsafe. |
51 | 0 | // This means we need to ensure that no other method on this struct |
52 | 0 | // can access data if the dimensions are 0. |
53 | 0 | data: std::ptr::null_mut::<T>(), |
54 | 0 | plane_cfg, |
55 | 0 | rect: Rect::default(), |
56 | 0 | phantom: PhantomData, |
57 | 0 | } |
58 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::empty Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::empty Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::empty Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::empty Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::empty Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::empty |
59 | | |
60 | | /// # Panics |
61 | | /// |
62 | | /// - If the configured dimensions are invalid |
63 | 0 | pub fn from_slice(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self { |
64 | 0 | if cfg.width == 0 || cfg.height == 0 { |
65 | 0 | return Self::empty(&cfg); |
66 | 0 | } |
67 | 0 | assert!(rect.x >= -(cfg.xorigin as isize)); |
68 | 0 | assert!(rect.y >= -(cfg.yorigin as isize)); |
69 | 0 | assert!(cfg.xorigin as isize + rect.x + rect.width as isize <= cfg.stride as isize); |
70 | 0 | assert!(cfg.yorigin as isize + rect.y + rect.height as isize <= cfg.alloc_height as isize); |
71 | | |
72 | | // SAFETY: The above asserts ensure we do not go OOB. |
73 | 0 | unsafe { Self::from_slice_unsafe(data, cfg, rect)} |
74 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::from_slice Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::from_slice Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::from_slice Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::from_slice Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::from_slice Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::from_slice |
75 | | |
76 | 0 | unsafe fn from_slice_unsafe(data: &'a $($opt_mut)? [T], cfg: &'a PlaneConfig, rect: Rect) -> Self { |
77 | 0 | let origin = (cfg.yorigin as isize + rect.y) * cfg.stride as isize + cfg.xorigin as isize + rect.x; |
78 | 0 | Self { |
79 | 0 | data: data.$as_ptr().offset(origin), |
80 | 0 | plane_cfg: cfg, |
81 | 0 | rect, |
82 | 0 | phantom: PhantomData, |
83 | 0 | } |
84 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::from_slice_unsafe Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::from_slice_unsafe Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::from_slice_unsafe Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::from_slice_unsafe Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::from_slice_unsafe Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::from_slice_unsafe |
85 | | |
86 | 0 | pub fn new(plane: &'a $($opt_mut)? Plane<T>, rect: Rect) -> Self { |
87 | 0 | Self::from_slice(& $($opt_mut)? plane.data, &plane.cfg, rect) |
88 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::new Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::new Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::new Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::new Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::new Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::new |
89 | | |
90 | | #[allow(dead_code)] |
91 | 0 | pub fn new_from_plane(plane: &'a $($opt_mut)? Plane<T>) -> Self { |
92 | 0 | let rect = Rect { |
93 | 0 | x: 0, |
94 | 0 | y: 0, |
95 | 0 | width: plane.cfg.stride - plane.cfg.xorigin, |
96 | 0 | height: plane.cfg.alloc_height - plane.cfg.yorigin, |
97 | 0 | }; |
98 | | |
99 | | // SAFETY: Area::StartingAt{}.to_rect is guaranteed to be the entire plane |
100 | 0 | unsafe { Self::from_slice_unsafe(& $($opt_mut)? plane.data, &plane.cfg, rect) } |
101 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::new_from_plane Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::new_from_plane Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::new_from_plane Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::new_from_plane |
102 | | |
103 | | #[allow(dead_code)] |
104 | 0 | pub fn data_ptr(&self) -> *const T { |
105 | 0 | self.data |
106 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::data_ptr Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::data_ptr |
107 | | |
108 | 0 | pub fn rect(&self) -> &Rect { |
109 | 0 | &self.rect |
110 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::rect Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::rect Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::rect Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::rect Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::rect Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::rect |
111 | | |
112 | | #[allow(dead_code)] |
113 | 0 | pub fn rows_iter(&self) -> PlaneRegionRowsIter<'_, T> { |
114 | 0 | PlaneRegionRowsIter { |
115 | 0 | data: self.data, |
116 | 0 | stride: self.plane_cfg.stride, |
117 | 0 | width: self.rect.width, |
118 | 0 | remaining: self.rect.height, |
119 | 0 | phantom: PhantomData, |
120 | 0 | } |
121 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::rows_iter Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::rows_iter Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::rows_iter Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::rows_iter |
122 | | |
123 | | #[allow(dead_code)] |
124 | 0 | pub fn vert_windows(&self, h: usize) -> VertWindows<'_, T> { |
125 | 0 | VertWindows { |
126 | 0 | data: self.data, |
127 | 0 | plane_cfg: self.plane_cfg, |
128 | 0 | remaining: (self.rect.height as isize - h as isize + 1).max(0) as usize, |
129 | 0 | output_rect: Rect { |
130 | 0 | x: self.rect.x, |
131 | 0 | y: self.rect.y, |
132 | 0 | width: self.rect.width, |
133 | 0 | height: h |
134 | 0 | } |
135 | 0 | } |
136 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::vert_windows Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::vert_windows Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::vert_windows Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::vert_windows |
137 | | |
138 | | #[allow(dead_code)] |
139 | 0 | pub fn horz_windows(&self, w: usize) -> HorzWindows<'_, T> { |
140 | 0 | HorzWindows { |
141 | 0 | data: self.data, |
142 | 0 | plane_cfg: self.plane_cfg, |
143 | 0 | remaining: (self.rect.width as isize - w as isize + 1).max(0) as usize, |
144 | 0 | output_rect: Rect { |
145 | 0 | x: self.rect.x, |
146 | 0 | y: self.rect.y, |
147 | 0 | width: w, |
148 | 0 | height: self.rect.height |
149 | 0 | } |
150 | 0 | } |
151 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::horz_windows Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::horz_windows Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::horz_windows Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::horz_windows |
152 | | |
153 | | /// Return a view to a subregion of the plane |
154 | | /// |
155 | | /// The subregion must be included in (i.e. must not exceed) this region. |
156 | | /// |
157 | | /// It is described by an `Area`, relative to this region. |
158 | | /// |
159 | | /// # Panics |
160 | | /// |
161 | | /// - If the requested dimensions are larger than the plane region size |
162 | | /// |
163 | | /// # Example |
164 | | /// |
165 | | /// ``` ignore |
166 | | /// # use rav1e::tiling::*; |
167 | | /// # fn f(region: &PlaneRegion<'_, u16>) { |
168 | | /// // a subregion from (10, 8) to the end of the region |
169 | | /// let subregion = region.subregion(Area::StartingAt { x: 10, y: 8 }); |
170 | | /// # } |
171 | | /// ``` |
172 | | /// |
173 | | /// ``` ignore |
174 | | /// # use rav1e::context::*; |
175 | | /// # use rav1e::tiling::*; |
176 | | /// # fn f(region: &PlaneRegion<'_, u16>) { |
177 | | /// // a subregion from the top-left of block (2, 3) having size (64, 64) |
178 | | /// let bo = BlockOffset { x: 2, y: 3 }; |
179 | | /// let subregion = region.subregion(Area::BlockRect { bo, width: 64, height: 64 }); |
180 | | /// # } |
181 | | /// ``` |
182 | | #[allow(dead_code)] |
183 | 0 | pub fn subregion(&self, area: Area) -> PlaneRegion<'_, T> { |
184 | 0 | if self.data.is_null() { |
185 | 0 | return PlaneRegion::empty(&self.plane_cfg); |
186 | 0 | } |
187 | 0 | let rect = area.to_rect( |
188 | 0 | self.plane_cfg.xdec, |
189 | 0 | self.plane_cfg.ydec, |
190 | 0 | self.rect.width, |
191 | 0 | self.rect.height, |
192 | | ); |
193 | 0 | assert!(rect.x >= 0 && rect.x as usize <= self.rect.width); |
194 | 0 | assert!(rect.y >= 0 && rect.y as usize <= self.rect.height); |
195 | | // SAFETY: The above asserts ensure we do not go outside the original rectangle. |
196 | 0 | let data = unsafe { |
197 | 0 | self.data.add(rect.y as usize * self.plane_cfg.stride + rect.x as usize) |
198 | | }; |
199 | 0 | let absolute_rect = Rect { |
200 | 0 | x: self.rect.x + rect.x, |
201 | 0 | y: self.rect.y + rect.y, |
202 | 0 | width: rect.width, |
203 | 0 | height: rect.height, |
204 | 0 | }; |
205 | 0 | PlaneRegion { |
206 | 0 | data, |
207 | 0 | plane_cfg: &self.plane_cfg, |
208 | 0 | rect: absolute_rect, |
209 | 0 | phantom: PhantomData, |
210 | 0 | } |
211 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16>>::subregion Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8>>::subregion Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_>>::subregion Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::subregion |
212 | | } |
213 | | |
214 | | unsafe impl<T: Pixel> Send for $name<'_, T> {} |
215 | | unsafe impl<T: Pixel> Sync for $name<'_, T> {} |
216 | | |
217 | | impl<T: Pixel> Index<usize> for $name<'_, T> { |
218 | | type Output = [T]; |
219 | | |
220 | 0 | fn index(&self, index: usize) -> &Self::Output { |
221 | 0 | assert!(index < self.rect.height); |
222 | | // SAFETY: The above assert ensures we do not access OOB data. |
223 | | unsafe { |
224 | 0 | let ptr = self.data.add(index * self.plane_cfg.stride); |
225 | 0 | slice::from_raw_parts(ptr, self.rect.width) |
226 | | } |
227 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u16> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<u8> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegion<_> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_> as core::ops::index::Index<usize>>::index |
228 | | } |
229 | | } |
230 | | } |
231 | | |
232 | | plane_region_common!(PlaneRegion, as_ptr); |
233 | | plane_region_common!(PlaneRegionMut, as_mut_ptr, mut); |
234 | | |
235 | | impl<T: Pixel> PlaneRegionMut<'_, T> { |
236 | 0 | pub fn data_ptr_mut(&mut self) -> *mut T { |
237 | 0 | self.data |
238 | 0 | } |
239 | | |
240 | 0 | pub fn rows_iter_mut(&mut self) -> PlaneRegionRowsIterMut<'_, T> { |
241 | 0 | PlaneRegionRowsIterMut { |
242 | 0 | data: self.data, |
243 | 0 | stride: self.plane_cfg.stride, |
244 | 0 | width: self.rect.width, |
245 | 0 | remaining: self.rect.height, |
246 | 0 | phantom: PhantomData, |
247 | 0 | } |
248 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::rows_iter_mut Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::rows_iter_mut Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::rows_iter_mut |
249 | | |
250 | 0 | pub fn as_const(&self) -> PlaneRegion<'_, T> { |
251 | 0 | PlaneRegion { |
252 | 0 | data: self.data, |
253 | 0 | plane_cfg: self.plane_cfg, |
254 | 0 | rect: self.rect, |
255 | 0 | phantom: PhantomData, |
256 | 0 | } |
257 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16>>::as_const Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8>>::as_const Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_>>::as_const |
258 | | } |
259 | | |
260 | | impl<T: Pixel> IndexMut<usize> for PlaneRegionMut<'_, T> { |
261 | 0 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { |
262 | 0 | assert!(index < self.rect.height); |
263 | | // SAFETY: The above assert ensures we do not access OOB data. |
264 | 0 | unsafe { |
265 | 0 | let ptr = self.data.add(index * self.plane_cfg.stride); |
266 | 0 | slice::from_raw_parts_mut(ptr, self.rect.width) |
267 | 0 | } |
268 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u16> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<u8> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionMut<_> as core::ops::index::IndexMut<usize>>::index_mut |
269 | | } |
270 | | |
271 | | /// Iterator over plane region rows |
272 | | pub struct PlaneRegionRowsIter<'a, T: Pixel> { |
273 | | data: *const T, |
274 | | stride: usize, |
275 | | width: usize, |
276 | | remaining: usize, |
277 | | phantom: PhantomData<&'a T>, |
278 | | } |
279 | | |
280 | | impl<'a, T: Pixel> Iterator for PlaneRegionRowsIter<'a, T> { |
281 | | type Item = &'a [T]; |
282 | | |
283 | 0 | fn next(&mut self) -> Option<Self::Item> { |
284 | 0 | if self.remaining > 0 { |
285 | | // SAFETY: We verified that we have enough data left to not go OOB, |
286 | | // assuming that `self.stride` and `self.width` are set correctly. |
287 | 0 | let row = unsafe { |
288 | 0 | let ptr = self.data; |
289 | 0 | self.data = self.data.add(self.stride); |
290 | 0 | slice::from_raw_parts(ptr, self.width) |
291 | | }; |
292 | 0 | self.remaining -= 1; |
293 | 0 | Some(row) |
294 | | } else { |
295 | 0 | None |
296 | | } |
297 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionRowsIter<u16> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionRowsIter<u8> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionRowsIter<_> as core::iter::traits::iterator::Iterator>::next |
298 | | |
299 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
300 | 0 | (self.remaining, Some(self.remaining)) |
301 | 0 | } |
302 | | } |
303 | | |
304 | | /// Mutable iterator over plane region rows |
305 | | pub struct PlaneRegionRowsIterMut<'a, T: Pixel> { |
306 | | data: *mut T, |
307 | | stride: usize, |
308 | | width: usize, |
309 | | remaining: usize, |
310 | | phantom: PhantomData<&'a mut T>, |
311 | | } |
312 | | |
313 | | impl<'a, T: Pixel> Iterator for PlaneRegionRowsIterMut<'a, T> { |
314 | | type Item = &'a mut [T]; |
315 | | |
316 | 0 | fn next(&mut self) -> Option<Self::Item> { |
317 | 0 | if self.remaining > 0 { |
318 | | // SAFETY: We verified that we have enough data left to not go OOB, |
319 | | // assuming that `self.stride` and `self.width` are set correctly. |
320 | 0 | let row = unsafe { |
321 | 0 | let ptr = self.data; |
322 | 0 | self.data = self.data.add(self.stride); |
323 | 0 | slice::from_raw_parts_mut(ptr, self.width) |
324 | | }; |
325 | 0 | self.remaining -= 1; |
326 | 0 | Some(row) |
327 | | } else { |
328 | 0 | None |
329 | | } |
330 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionRowsIterMut<u16> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionRowsIterMut<u8> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <av_scenechange::data::plane::PlaneRegionRowsIterMut<_> as core::iter::traits::iterator::Iterator>::next |
331 | | |
332 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
333 | 0 | (self.remaining, Some(self.remaining)) |
334 | 0 | } |
335 | | } |
336 | | |
337 | | impl<T: Pixel> ExactSizeIterator for PlaneRegionRowsIter<'_, T> { |
338 | | } |
339 | | impl<T: Pixel> FusedIterator for PlaneRegionRowsIter<'_, T> { |
340 | | } |
341 | | impl<T: Pixel> ExactSizeIterator for PlaneRegionRowsIterMut<'_, T> { |
342 | | } |
343 | | impl<T: Pixel> FusedIterator for PlaneRegionRowsIterMut<'_, T> { |
344 | | } |
345 | | |
346 | | pub struct VertWindows<'a, T: Pixel> { |
347 | | data: *const T, |
348 | | plane_cfg: &'a PlaneConfig, |
349 | | remaining: usize, |
350 | | output_rect: Rect, |
351 | | } |
352 | | |
353 | | pub struct HorzWindows<'a, T: Pixel> { |
354 | | data: *const T, |
355 | | plane_cfg: &'a PlaneConfig, |
356 | | remaining: usize, |
357 | | output_rect: Rect, |
358 | | } |
359 | | |
360 | | impl<'a, T: Pixel> Iterator for VertWindows<'a, T> { |
361 | | type Item = PlaneRegion<'a, T>; |
362 | | |
363 | 0 | fn next(&mut self) -> Option<Self::Item> { |
364 | 0 | self.nth(0) |
365 | 0 | } |
366 | | |
367 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
368 | 0 | (self.remaining, Some(self.remaining)) |
369 | 0 | } |
370 | | |
371 | 0 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
372 | 0 | if self.remaining > n { |
373 | | // SAFETY: We verified that we have enough data left to not go OOB. |
374 | 0 | self.data = unsafe { self.data.add(self.plane_cfg.stride * n) }; |
375 | 0 | self.output_rect.y += n as isize; |
376 | 0 | let output = PlaneRegion { |
377 | 0 | data: self.data, |
378 | 0 | plane_cfg: self.plane_cfg, |
379 | 0 | rect: self.output_rect, |
380 | 0 | phantom: PhantomData, |
381 | 0 | }; |
382 | | // SAFETY: We verified that we have enough data left to not go OOB. |
383 | 0 | self.data = unsafe { self.data.add(self.plane_cfg.stride) }; |
384 | 0 | self.output_rect.y += 1; |
385 | 0 | self.remaining -= n + 1; |
386 | 0 | Some(output) |
387 | | } else { |
388 | 0 | None |
389 | | } |
390 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::VertWindows<u16> as core::iter::traits::iterator::Iterator>::nth Unexecuted instantiation: <av_scenechange::data::plane::VertWindows<u8> as core::iter::traits::iterator::Iterator>::nth Unexecuted instantiation: <av_scenechange::data::plane::VertWindows<_> as core::iter::traits::iterator::Iterator>::nth |
391 | | } |
392 | | |
393 | | impl<'a, T: Pixel> Iterator for HorzWindows<'a, T> { |
394 | | type Item = PlaneRegion<'a, T>; |
395 | | |
396 | 0 | fn next(&mut self) -> Option<Self::Item> { |
397 | 0 | self.nth(0) |
398 | 0 | } |
399 | | |
400 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
401 | 0 | (self.remaining, Some(self.remaining)) |
402 | 0 | } |
403 | | |
404 | 0 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
405 | 0 | if self.remaining > n { |
406 | | // SAFETY: We verified that we have enough data left to not go OOB. |
407 | 0 | self.data = unsafe { self.data.add(n) }; |
408 | 0 | self.output_rect.x += n as isize; |
409 | 0 | let output = PlaneRegion { |
410 | 0 | data: self.data, |
411 | 0 | plane_cfg: self.plane_cfg, |
412 | 0 | rect: self.output_rect, |
413 | 0 | phantom: PhantomData, |
414 | 0 | }; |
415 | | // SAFETY: We verified that we have enough data left to not go OOB. |
416 | 0 | self.data = unsafe { self.data.add(1) }; |
417 | 0 | self.output_rect.x += 1; |
418 | 0 | self.remaining -= n + 1; |
419 | 0 | Some(output) |
420 | | } else { |
421 | 0 | None |
422 | | } |
423 | 0 | } Unexecuted instantiation: <av_scenechange::data::plane::HorzWindows<u16> as core::iter::traits::iterator::Iterator>::nth Unexecuted instantiation: <av_scenechange::data::plane::HorzWindows<u8> as core::iter::traits::iterator::Iterator>::nth Unexecuted instantiation: <av_scenechange::data::plane::HorzWindows<_> as core::iter::traits::iterator::Iterator>::nth |
424 | | } |
425 | | |
426 | | impl<T: Pixel> ExactSizeIterator for VertWindows<'_, T> { |
427 | | } |
428 | | impl<T: Pixel> FusedIterator for VertWindows<'_, T> { |
429 | | } |
430 | | impl<T: Pixel> ExactSizeIterator for HorzWindows<'_, T> { |
431 | | } |
432 | | impl<T: Pixel> FusedIterator for HorzWindows<'_, T> { |
433 | | } |
434 | | |
435 | | /// Rectangle of a plane region, in pixels |
436 | | #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] |
437 | | pub struct Rect { |
438 | | // coordinates relative to the plane origin (xorigin, yorigin) |
439 | | pub x: isize, |
440 | | pub y: isize, |
441 | | pub width: usize, |
442 | | pub height: usize, |
443 | | } |
444 | | |
445 | | // Structure to describe a rectangle area in several ways |
446 | | // |
447 | | // To retrieve a subregion from a region, we need to provide the subregion |
448 | | // bounds, relative to its parent region. The subregion must always be included |
449 | | // in its parent region. |
450 | | // |
451 | | // For that purpose, we could just use a rectangle (x, y, width, height), but |
452 | | // this would be too cumbersome to use in practice. For example, we often need |
453 | | // to pass a subregion from an offset, using the same bottom-right corner as |
454 | | // its parent, or to pass a subregion expressed in block offset instead of |
455 | | // pixel offset. |
456 | | // |
457 | | // Area provides a flexible way to describe a subregion. |
458 | | #[derive(Debug, Clone, Copy)] |
459 | | pub enum Area { |
460 | | /// A well-defined rectangle |
461 | | Rect(Rect), |
462 | | /// A rectangle starting at offset (x, y) and ending at the bottom-right |
463 | | /// corner of the parent |
464 | | StartingAt { x: isize, y: isize }, |
465 | | /// a rectangle starting at given block offset until the bottom-right corner |
466 | | /// of the parent |
467 | | BlockStartingAt { bo: BlockOffset }, |
468 | | } |
469 | | |
470 | | impl Area { |
471 | | /// Convert to a rectangle of pixels. |
472 | | /// For a `BlockRect` and `BlockStartingAt`, for subsampled chroma planes, |
473 | | /// the returned rect will be aligned to a 4x4 chroma block. |
474 | | /// This is necessary for `compute_distortion` and `rdo_cfl_alpha` as |
475 | | /// the subsampled chroma block covers multiple luma blocks. |
476 | 0 | pub const fn to_rect( |
477 | 0 | self, |
478 | 0 | xdec: usize, |
479 | 0 | ydec: usize, |
480 | 0 | parent_width: usize, |
481 | 0 | parent_height: usize, |
482 | 0 | ) -> Rect { |
483 | 0 | match self { |
484 | 0 | Area::Rect(rect) => rect, |
485 | 0 | Area::StartingAt { x, y } => Rect { |
486 | 0 | x, |
487 | 0 | y, |
488 | 0 | width: (parent_width as isize - x) as usize, |
489 | 0 | height: (parent_height as isize - y) as usize, |
490 | 0 | }, |
491 | 0 | Area::BlockStartingAt { bo } => { |
492 | 0 | let x = (bo.x >> xdec << BLOCK_TO_PLANE_SHIFT) as isize; |
493 | 0 | let y = (bo.y >> ydec << BLOCK_TO_PLANE_SHIFT) as isize; |
494 | 0 | Rect { |
495 | 0 | x, |
496 | 0 | y, |
497 | 0 | width: (parent_width as isize - x) as usize, |
498 | 0 | height: (parent_height as isize - y) as usize, |
499 | 0 | } |
500 | | } |
501 | | } |
502 | 0 | } |
503 | | } |
504 | | |
505 | | pub trait AsRegion<T: Pixel> { |
506 | | fn as_region(&self) -> PlaneRegion<'_, T>; |
507 | | fn region(&self, area: Area) -> PlaneRegion<'_, T>; |
508 | | fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T>; |
509 | | } |
510 | | |
511 | | impl<T: Pixel> AsRegion<T> for Plane<T> { |
512 | 0 | fn as_region(&self) -> PlaneRegion<'_, T> { |
513 | 0 | PlaneRegion::new_from_plane(self) |
514 | 0 | } Unexecuted instantiation: <v_frame::plane::Plane<u16> as av_scenechange::data::plane::AsRegion<u16>>::as_region Unexecuted instantiation: <v_frame::plane::Plane<u8> as av_scenechange::data::plane::AsRegion<u8>>::as_region Unexecuted instantiation: <v_frame::plane::Plane<_> as av_scenechange::data::plane::AsRegion<_>>::as_region |
515 | | |
516 | 0 | fn region(&self, area: Area) -> PlaneRegion<'_, T> { |
517 | 0 | let rect = area.to_rect( |
518 | 0 | self.cfg.xdec, |
519 | 0 | self.cfg.ydec, |
520 | 0 | self.cfg.stride - self.cfg.xorigin, |
521 | 0 | self.cfg.alloc_height - self.cfg.yorigin, |
522 | | ); |
523 | 0 | PlaneRegion::new(self, rect) |
524 | 0 | } Unexecuted instantiation: <v_frame::plane::Plane<u16> as av_scenechange::data::plane::AsRegion<u16>>::region Unexecuted instantiation: <v_frame::plane::Plane<u8> as av_scenechange::data::plane::AsRegion<u8>>::region Unexecuted instantiation: <v_frame::plane::Plane<_> as av_scenechange::data::plane::AsRegion<_>>::region |
525 | | |
526 | 0 | fn region_mut(&mut self, area: Area) -> PlaneRegionMut<'_, T> { |
527 | 0 | let rect = area.to_rect( |
528 | 0 | self.cfg.xdec, |
529 | 0 | self.cfg.ydec, |
530 | 0 | self.cfg.stride - self.cfg.xorigin, |
531 | 0 | self.cfg.alloc_height - self.cfg.yorigin, |
532 | | ); |
533 | 0 | PlaneRegionMut::new(self, rect) |
534 | 0 | } Unexecuted instantiation: <v_frame::plane::Plane<u16> as av_scenechange::data::plane::AsRegion<u16>>::region_mut Unexecuted instantiation: <v_frame::plane::Plane<u8> as av_scenechange::data::plane::AsRegion<u8>>::region_mut Unexecuted instantiation: <v_frame::plane::Plane<_> as av_scenechange::data::plane::AsRegion<_>>::region_mut |
535 | | } |
536 | | |
537 | | /// Absolute offset in blocks inside a plane, where a block is defined |
538 | | /// to be an `N*N` square where `N == (1 << BLOCK_TO_PLANE_SHIFT)`. |
539 | | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
540 | | pub struct PlaneBlockOffset(pub BlockOffset); |
541 | | |
542 | | impl PlaneBlockOffset { |
543 | | /// Convert to plane offset without decimation. |
544 | 0 | pub const fn to_luma_plane_offset(self) -> PlaneOffset { |
545 | 0 | self.0.to_luma_plane_offset() |
546 | 0 | } |
547 | | } |