Coverage Report

Created: 2025-11-24 07:30

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