1use super::*;
11
12use crate::context::*;
13use crate::encoder::*;
14use crate::me::WriteGuardMEStats;
15use crate::util::*;
16
17use std::iter::FusedIterator;
18use std::marker::PhantomData;
19use std::ops::DerefMut;
20
21pub const MAX_TILE_WIDTH: usize = 4096;
22pub const MAX_TILE_AREA: usize = 4096 * 2304;
23pub const MAX_TILE_COLS: usize = 64;
24pub const MAX_TILE_ROWS: usize = 64;
25pub const MAX_TILE_RATE: f64 = 4096f64 * 2176f64 * 60f64 * 1.1;
26
27#[derive(Debug, Clone, Copy)]
35pub struct TilingInfo {
36 pub frame_width: usize,
37 pub frame_height: usize,
38 pub tile_width_sb: usize,
39 pub tile_height_sb: usize,
40 pub cols: usize, pub rows: usize, pub tile_cols_log2: usize,
43 pub tile_rows_log2: usize,
44 pub min_tile_cols_log2: usize,
45 pub max_tile_cols_log2: usize,
46 pub min_tile_rows_log2: usize,
47 pub max_tile_rows_log2: usize,
48 pub sb_size_log2: usize,
49 pub min_tiles_log2: usize,
50}
51
52impl TilingInfo {
53 pub fn from_target_tiles(
57 sb_size_log2: usize, frame_width: usize, frame_height: usize,
58 frame_rate: f64, tile_cols_log2: usize, tile_rows_log2: usize,
59 is_422_p: bool,
60 ) -> Self {
61 let frame_width = frame_width.align_power_of_two(3);
65 let frame_height = frame_height.align_power_of_two(3);
66 let frame_width_sb =
67 frame_width.align_power_of_two_and_shift(sb_size_log2);
68 let frame_height_sb =
69 frame_height.align_power_of_two_and_shift(sb_size_log2);
70 let sb_cols = frame_width.align_power_of_two_and_shift(sb_size_log2);
71 let sb_rows = frame_height.align_power_of_two_and_shift(sb_size_log2);
72
73 let max_tile_width_sb = MAX_TILE_WIDTH >> sb_size_log2;
75 let max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size_log2);
76 let min_tile_cols_log2 =
77 Self::tile_log2(max_tile_width_sb, sb_cols).unwrap();
78 let max_tile_cols_log2 =
79 Self::tile_log2(1, sb_cols.min(MAX_TILE_COLS)).unwrap();
80 let max_tile_rows_log2 =
81 Self::tile_log2(1, sb_rows.min(MAX_TILE_ROWS)).unwrap();
82 let min_tiles_log2 = min_tile_cols_log2
83 .max(Self::tile_log2(max_tile_area_sb, sb_cols * sb_rows).unwrap());
84
85 let min_tiles_ratelimit_log2 = min_tiles_log2.max(
89 ((frame_width * frame_height) as f64 * frame_rate / MAX_TILE_RATE)
90 .ceil()
91 .log2()
92 .ceil() as usize,
93 );
94
95 let tile_cols_log2 =
96 tile_cols_log2.clamp(min_tile_cols_log2, max_tile_cols_log2);
97 let tile_width_sb_pre =
98 sb_cols.align_power_of_two_and_shift(tile_cols_log2);
99
100 let tile_width_sb = if is_422_p {
113 (tile_width_sb_pre + 1) >> 1 << 1
114 } else {
115 tile_width_sb_pre
116 };
117
118 let cols = frame_width_sb.div_ceil(tile_width_sb);
119
120 let tile_cols_log2 = Self::tile_log2(1, cols).unwrap();
122 assert!(tile_cols_log2 >= min_tile_cols_log2);
123
124 let min_tile_rows_log2 = min_tiles_log2.saturating_sub(tile_cols_log2);
125 let min_tile_rows_ratelimit_log2 =
126 min_tiles_ratelimit_log2.saturating_sub(tile_cols_log2);
127 let tile_rows_log2 = tile_rows_log2
128 .max(min_tile_rows_log2)
129 .clamp(min_tile_rows_ratelimit_log2, max_tile_rows_log2);
130 let tile_height_sb = sb_rows.align_power_of_two_and_shift(tile_rows_log2);
131
132 let rows = frame_height_sb.div_ceil(tile_height_sb);
133
134 Self {
135 frame_width,
136 frame_height,
137 tile_width_sb,
138 tile_height_sb,
139 cols,
140 rows,
141 tile_cols_log2,
142 tile_rows_log2,
143 min_tile_cols_log2,
144 max_tile_cols_log2,
145 min_tile_rows_log2,
146 max_tile_rows_log2,
147 sb_size_log2,
148 min_tiles_log2,
149 }
150 }
151
152 pub fn tile_log2(blk_size: usize, target: usize) -> Option<usize> {
157 let mut k = 0;
158 while (blk_size.checked_shl(k)?) < target {
159 k += 1;
160 }
161 Some(k as usize)
162 }
163
164 #[inline(always)]
165 pub const fn tile_count(&self) -> usize {
166 self.cols * self.rows
167 }
168
169 pub fn tile_iter_mut<'a, T: Pixel>(
173 &self, fs: &'a mut FrameState<T>, fb: &'a mut FrameBlocks,
174 ) -> TileContextIterMut<'a, T> {
175 let afs = fs as *mut _;
176 let afb = fb as *mut _;
177 let frame_me_stats = fs.frame_me_stats.write().expect("poisoned lock");
178 TileContextIterMut { ti: *self, fs: afs, fb: afb, next: 0, frame_me_stats }
179 }
180}
181
182pub struct TileContextMut<'a, T: Pixel> {
184 pub ts: TileStateMut<'a, T>,
185 pub tb: TileBlocksMut<'a>,
186}
187
188pub struct TileContextIterMut<'a, T: Pixel> {
190 ti: TilingInfo,
191 fs: *mut FrameState<T>,
192 fb: *mut FrameBlocks,
193 frame_me_stats: WriteGuardMEStats<'a>,
194 next: usize,
195}
196
197impl<'a, T: Pixel> Iterator for TileContextIterMut<'a, T> {
198 type Item = TileContextMut<'a, T>;
199
200 fn next(&mut self) -> Option<Self::Item> {
201 if self.next < self.ti.rows * self.ti.cols {
202 let tile_col = self.next % self.ti.cols;
203 let tile_row = self.next / self.ti.cols;
204 let ctx = TileContextMut {
205 ts: {
206 let fs = unsafe { &mut *self.fs };
210 let frame_me_stats = unsafe {
212 let len = self.frame_me_stats.len();
213 let ptr = self.frame_me_stats.as_mut_ptr();
214 std::slice::from_raw_parts_mut(ptr, len)
215 };
216 let sbo = PlaneSuperBlockOffset(SuperBlockOffset {
217 x: tile_col * self.ti.tile_width_sb,
218 y: tile_row * self.ti.tile_height_sb,
219 });
220 let x = sbo.0.x << self.ti.sb_size_log2;
221 let y = sbo.0.y << self.ti.sb_size_log2;
222 let tile_width = self.ti.tile_width_sb << self.ti.sb_size_log2;
223 let tile_height = self.ti.tile_height_sb << self.ti.sb_size_log2;
224 let width = tile_width.min(self.ti.frame_width - x);
225 let height = tile_height.min(self.ti.frame_height - y);
226 TileStateMut::new(
227 fs,
228 sbo,
229 self.ti.sb_size_log2,
230 width,
231 height,
232 frame_me_stats,
233 )
234 },
235 tb: {
236 let fb = unsafe { &mut *self.fb };
240 let tile_width_mi =
241 self.ti.tile_width_sb << (self.ti.sb_size_log2 - MI_SIZE_LOG2);
242 let tile_height_mi =
243 self.ti.tile_height_sb << (self.ti.sb_size_log2 - MI_SIZE_LOG2);
244 let x = tile_col * tile_width_mi;
245 let y = tile_row * tile_height_mi;
246 let cols = tile_width_mi.min(fb.cols - x);
247 let rows = tile_height_mi.min(fb.rows - y);
248 TileBlocksMut::new(fb, x, y, cols, rows)
249 },
250 };
251 self.next += 1;
252 Some(ctx)
253 } else {
254 None
255 }
256 }
257
258 fn size_hint(&self) -> (usize, Option<usize>) {
259 let remaining = self.ti.cols * self.ti.rows - self.next;
260 (remaining, Some(remaining))
261 }
262}
263
264impl<T: Pixel> ExactSizeIterator for TileContextIterMut<'_, T> {}
265impl<T: Pixel> FusedIterator for TileContextIterMut<'_, T> {}
266
267#[cfg(test)]
268pub mod test {
269 use super::*;
270 use crate::api::*;
271 use crate::lrf::*;
272 use crate::mc::MotionVector;
273 use crate::predict::PredictionMode;
274 use std::sync::Arc;
275
276 #[test]
277 fn test_tiling_info_from_tile_count() {
278 let sb_size_log2 = 6;
279 let (width, height) = (160, 144);
280 let frame_rate = 25f64;
281
282 let ti = TilingInfo::from_target_tiles(
283 sb_size_log2,
284 width,
285 height,
286 frame_rate,
287 0,
288 0,
289 false,
290 );
291 assert_eq!(1, ti.cols);
292 assert_eq!(1, ti.rows);
293 assert_eq!(3, ti.tile_width_sb);
294 assert_eq!(3, ti.tile_height_sb);
295
296 let ti = TilingInfo::from_target_tiles(
297 sb_size_log2,
298 width,
299 height,
300 frame_rate,
301 1,
302 1,
303 false,
304 );
305 assert_eq!(2, ti.cols);
306 assert_eq!(2, ti.rows);
307 assert_eq!(2, ti.tile_width_sb);
308 assert_eq!(2, ti.tile_height_sb);
309
310 let ti = TilingInfo::from_target_tiles(
311 sb_size_log2,
312 width,
313 height,
314 frame_rate,
315 2,
316 2,
317 false,
318 );
319 assert_eq!(3, ti.cols);
320 assert_eq!(3, ti.rows);
321 assert_eq!(1, ti.tile_width_sb);
322 assert_eq!(1, ti.tile_height_sb);
323
324 let ti = TilingInfo::from_target_tiles(
326 sb_size_log2,
327 width,
328 height,
329 frame_rate,
330 10,
331 8,
332 false,
333 );
334 assert_eq!(3, ti.cols);
335 assert_eq!(3, ti.rows);
336 assert_eq!(1, ti.tile_width_sb);
337 assert_eq!(1, ti.tile_height_sb);
338
339 let ti = TilingInfo::from_target_tiles(
340 sb_size_log2,
341 1024,
342 1024,
343 frame_rate,
344 0,
345 0,
346 false,
347 );
348 assert_eq!(1, ti.cols);
349 assert_eq!(1, ti.rows);
350 assert_eq!(16, ti.tile_width_sb);
351 assert_eq!(16, ti.tile_height_sb);
352 }
353
354 fn setup(
355 width: usize, height: usize,
356 ) -> (FrameInvariants<u16>, FrameState<u16>, FrameBlocks, f64) {
357 assert!(width.trailing_zeros() >= 3);
359 assert!(height.trailing_zeros() >= 3);
360 let chroma_sampling = ChromaSampling::Cs420;
362 let config = Arc::new(EncoderConfig {
363 width,
364 height,
365 bit_depth: 8,
366 chroma_sampling,
367 ..Default::default()
368 });
369 let mut sequence = Sequence::new(&config);
370 sequence.enable_large_lru = false;
372 let frame_rate = config.frame_rate();
373 let fi = FrameInvariants::new(config, Arc::new(sequence));
374 let fs = FrameState::new(&fi);
375 let fb = FrameBlocks::new(fi.w_in_b, fi.h_in_b);
376
377 (fi, fs, fb, frame_rate)
378 }
379
380 #[test]
381 fn test_tile_iter_len() {
382 let (fi, mut fs, mut fb, frame_rate) = setup(160, 144);
384
385 {
386 let ti = TilingInfo::from_target_tiles(
388 fi.sb_size_log2(),
389 fi.width,
390 fi.height,
391 frame_rate,
392 1,
393 1,
394 false,
395 );
396 let mut iter = ti.tile_iter_mut(&mut fs, &mut fb);
397 assert_eq!(4, iter.len());
398 assert!(iter.next().is_some());
399 assert_eq!(3, iter.len());
400 assert!(iter.next().is_some());
401 assert_eq!(2, iter.len());
402 assert!(iter.next().is_some());
403 assert_eq!(1, iter.len());
404 assert!(iter.next().is_some());
405 assert_eq!(0, iter.len());
406 assert!(iter.next().is_none());
407 }
408
409 {
410 let ti = TilingInfo::from_target_tiles(
412 fi.sb_size_log2(),
413 fi.width,
414 fi.height,
415 frame_rate,
416 2,
417 2,
418 false,
419 );
420 let mut iter = ti.tile_iter_mut(&mut fs, &mut fb);
421 assert_eq!(9, iter.len());
422 assert!(iter.next().is_some());
423 assert_eq!(8, iter.len());
424 assert!(iter.next().is_some());
425 assert_eq!(7, iter.len());
426 assert!(iter.next().is_some());
427 assert_eq!(6, iter.len());
428 assert!(iter.next().is_some());
429 assert_eq!(5, iter.len());
430 assert!(iter.next().is_some());
431 assert_eq!(4, iter.len());
432 assert!(iter.next().is_some());
433 assert_eq!(3, iter.len());
434 assert!(iter.next().is_some());
435 assert_eq!(2, iter.len());
436 assert!(iter.next().is_some());
437 assert_eq!(1, iter.len());
438 assert!(iter.next().is_some());
439 assert_eq!(0, iter.len());
440 assert!(iter.next().is_none());
441 }
442 }
443
444 #[inline]
445 fn rect<T: Pixel>(
446 region: &PlaneRegionMut<'_, T>,
447 ) -> (isize, isize, usize, usize) {
448 let &Rect { x, y, width, height } = region.rect();
449 (x, y, width, height)
450 }
451
452 #[test]
453 fn test_tile_area() {
454 let (fi, mut fs, mut fb, frame_rate) = setup(160, 144);
455
456 let ti = TilingInfo::from_target_tiles(
458 fi.sb_size_log2(),
459 fi.width,
460 fi.height,
461 frame_rate,
462 2,
463 2,
464 false,
465 );
466 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
467 let tile_states = iter.map(|ctx| ctx.ts).collect::<Vec<_>>();
468
469 assert_eq!(9, tile_states.len());
477
478 let tile = &tile_states[0].rec; assert_eq!((0, 0, 64, 64), rect(&tile.planes[0]));
480 assert_eq!((0, 0, 32, 32), rect(&tile.planes[1]));
481 assert_eq!((0, 0, 32, 32), rect(&tile.planes[2]));
482
483 let tile = &tile_states[1].rec; assert_eq!((64, 0, 64, 64), rect(&tile.planes[0]));
485 assert_eq!((32, 0, 32, 32), rect(&tile.planes[1]));
486 assert_eq!((32, 0, 32, 32), rect(&tile.planes[2]));
487
488 let tile = &tile_states[2].rec; assert_eq!((128, 0, 64, 64), rect(&tile.planes[0]));
490 assert_eq!((64, 0, 32, 32), rect(&tile.planes[1]));
491 assert_eq!((64, 0, 32, 32), rect(&tile.planes[2]));
492
493 let tile = &tile_states[3].rec; assert_eq!((0, 64, 64, 64), rect(&tile.planes[0]));
495 assert_eq!((0, 32, 32, 32), rect(&tile.planes[1]));
496 assert_eq!((0, 32, 32, 32), rect(&tile.planes[2]));
497
498 let tile = &tile_states[4].rec; assert_eq!((64, 64, 64, 64), rect(&tile.planes[0]));
500 assert_eq!((32, 32, 32, 32), rect(&tile.planes[1]));
501 assert_eq!((32, 32, 32, 32), rect(&tile.planes[2]));
502
503 let tile = &tile_states[5].rec; assert_eq!((128, 64, 64, 64), rect(&tile.planes[0]));
505 assert_eq!((64, 32, 32, 32), rect(&tile.planes[1]));
506 assert_eq!((64, 32, 32, 32), rect(&tile.planes[2]));
507
508 let tile = &tile_states[6].rec; assert_eq!((0, 128, 64, 64), rect(&tile.planes[0]));
510 assert_eq!((0, 64, 32, 32), rect(&tile.planes[1]));
511 assert_eq!((0, 64, 32, 32), rect(&tile.planes[2]));
512
513 let tile = &tile_states[7].rec; assert_eq!((64, 128, 64, 64), rect(&tile.planes[0]));
515 assert_eq!((32, 64, 32, 32), rect(&tile.planes[1]));
516 assert_eq!((32, 64, 32, 32), rect(&tile.planes[2]));
517
518 let tile = &tile_states[8].rec; assert_eq!((128, 128, 64, 64), rect(&tile.planes[0]));
520 assert_eq!((64, 64, 32, 32), rect(&tile.planes[1]));
521 assert_eq!((64, 64, 32, 32), rect(&tile.planes[2]));
522 }
523
524 #[inline]
525 const fn b_area(region: &TileBlocksMut<'_>) -> (usize, usize, usize, usize) {
526 (region.x(), region.y(), region.cols(), region.rows())
527 }
528
529 #[test]
530 fn test_tile_blocks_area() {
531 let (fi, mut fs, mut fb, frame_rate) = setup(160, 144);
532
533 let ti = TilingInfo::from_target_tiles(
535 fi.sb_size_log2(),
536 fi.width,
537 fi.height,
538 frame_rate,
539 2,
540 2,
541 false,
542 );
543 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
544 let tbs = iter.map(|ctx| ctx.tb).collect::<Vec<_>>();
545
546 assert_eq!(9, tbs.len());
553
554 assert_eq!((0, 0, 16, 16), b_area(&tbs[0]));
555 assert_eq!((16, 0, 16, 16), b_area(&tbs[1]));
556 assert_eq!((32, 0, 8, 16), b_area(&tbs[2]));
557
558 assert_eq!((0, 16, 16, 16), b_area(&tbs[3]));
559 assert_eq!((16, 16, 16, 16), b_area(&tbs[4]));
560 assert_eq!((32, 16, 8, 16), b_area(&tbs[5]));
561
562 assert_eq!((0, 32, 16, 4), b_area(&tbs[6]));
563 assert_eq!((16, 32, 16, 4), b_area(&tbs[7]));
564 assert_eq!((32, 32, 8, 4), b_area(&tbs[8]));
565 }
566
567 #[test]
568 fn test_tile_write() {
569 let (fi, mut fs, mut fb, frame_rate) = setup(160, 144);
570
571 {
572 let ti = TilingInfo::from_target_tiles(
574 fi.sb_size_log2(),
575 fi.width,
576 fi.height,
577 frame_rate,
578 2,
579 2,
580 false,
581 );
582 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
583 let mut tile_states = iter.map(|ctx| ctx.ts).collect::<Vec<_>>();
584
585 {
586 let tile_plane = &mut tile_states[0].rec.planes[0];
588 let row = &mut tile_plane[12];
589 assert_eq!(64, row.len());
590 row[35..41].copy_from_slice(&[4, 42, 12, 18, 15, 31]);
591 }
592
593 {
594 let tile_plane = &mut tile_states[5].rec.planes[1];
596 let row = &mut tile_plane[8];
597 assert_eq!(32, row.len());
598 row[..4].copy_from_slice(&[14, 121, 1, 3]);
599 }
600
601 {
602 let tile_plane = &mut tile_states[7].rec.planes[2];
604 let row = &mut tile_plane[1];
605 assert_eq!(32, row.len());
606 row[11..16].copy_from_slice(&[6, 5, 2, 11, 8]);
607 }
608 }
609
610 let plane = &fs.rec.planes[0];
613 let y = plane.cfg.yorigin + 12;
614 let x = plane.cfg.xorigin + 35;
615 let idx = y * plane.cfg.stride + x;
616 assert_eq!(&[4, 42, 12, 18, 15, 31], &plane.data[idx..idx + 6]);
617
618 let plane = &fs.rec.planes[1];
619 let offset = (64, 32); let y = plane.cfg.yorigin + offset.1 + 8;
621 let x = plane.cfg.xorigin + offset.0;
622 let idx = y * plane.cfg.stride + x;
623 assert_eq!(&[14, 121, 1, 3], &plane.data[idx..idx + 4]);
624
625 let plane = &fs.rec.planes[2];
626 let offset = (32, 64); let y = plane.cfg.yorigin + offset.1 + 1;
628 let x = plane.cfg.xorigin + offset.0 + 11;
629 let idx = y * plane.cfg.stride + x;
630 assert_eq!(&[6, 5, 2, 11, 8], &plane.data[idx..idx + 5]);
631 }
632
633 #[test]
634 fn test_tile_restoration_edges() {
635 let (fi, mut fs, mut fb, frame_rate) = setup(64, 80);
636
637 let ti = TilingInfo::from_target_tiles(
638 fi.sb_size_log2(),
639 fi.width,
640 fi.height,
641 frame_rate,
642 2,
643 2,
644 false,
645 );
646 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
647 let mut tile_states = iter.map(|ctx| ctx.ts).collect::<Vec<_>>();
648
649 assert_eq!(tile_states.len(), 2);
650
651 {
652 let trs = &mut tile_states[0].restoration;
653 let units = &trs.planes[0].units;
654 assert_eq!(units.x(), 0);
655 assert_eq!(units.y(), 0);
656 assert_eq!(units.cols(), 1);
657 assert_eq!(units.rows(), 1);
658 }
659
660 {
661 let trs = &mut tile_states[1].restoration;
662 let units = &trs.planes[0].units;
663 assert_eq!(units.x(), 0);
664 assert_eq!(units.y(), 1);
665 assert_eq!(units.cols() * units.rows(), 0);
667 }
668 }
669
670 #[test]
671 fn test_tile_restoration_write() {
672 let (fi, mut fs, mut fb, frame_rate) = setup(256, 256);
673
674 {
675 let ti = TilingInfo::from_target_tiles(
677 fi.sb_size_log2(),
678 fi.width,
679 fi.height,
680 frame_rate,
681 1,
682 1,
683 false,
684 );
685 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
686 let mut tile_states = iter.map(|ctx| ctx.ts).collect::<Vec<_>>();
687
688 {
689 let units = &mut tile_states[0].restoration.planes[0].units;
691 units[0][1].filter =
692 RestorationFilter::Wiener { coeffs: [[1, 2, 3], [4, 5, 6]] };
693 }
694
695 {
696 let units = &mut tile_states[3].restoration.planes[1].units;
698 units[1][0].filter =
699 RestorationFilter::Sgrproj { set: 42, xqd: [10, 20] };
700 }
701
702 {
703 let units = &mut tile_states[2].restoration.planes[2].units;
705 units[1][1].filter =
706 RestorationFilter::Sgrproj { set: 5, xqd: [1, 2] };
707 }
708 }
709
710 let units = &mut fs.restoration.planes[0].units;
713 assert_eq!(
714 units[0][1].filter,
715 RestorationFilter::Wiener { coeffs: [[1, 2, 3], [4, 5, 6]] }
716 );
717
718 let units = &mut fs.restoration.planes[1].units;
719 assert_eq!(
720 units[3][2].filter,
721 RestorationFilter::Sgrproj { set: 42, xqd: [10, 20] }
722 );
723
724 let units = &mut fs.restoration.planes[2].units;
725 assert_eq!(
726 units[3][1].filter,
727 RestorationFilter::Sgrproj { set: 5, xqd: [1, 2] }
728 );
729 }
730
731 #[test]
732 fn test_tile_motion_vectors_write() {
733 let (fi, mut fs, mut fb, frame_rate) = setup(160, 144);
734
735 {
736 let ti = TilingInfo::from_target_tiles(
738 fi.sb_size_log2(),
739 fi.width,
740 fi.height,
741 frame_rate,
742 2,
743 2,
744 false,
745 );
746 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
747 let mut tile_states = iter.map(|ctx| ctx.ts).collect::<Vec<_>>();
748
749 {
750 let me_stats = &mut tile_states[0].me_stats[0];
752 me_stats[5][8].mv = MotionVector { col: 42, row: 38 };
753 println!("{:?}", me_stats[5][8].mv);
754 }
755
756 {
757 let me_stats = &mut tile_states[5].me_stats[2];
759 me_stats[2][3].mv = MotionVector { col: 2, row: 14 };
760 }
761 }
762
763 let me_stats = &fs.frame_me_stats.read().unwrap()[0];
766 assert_eq!(MotionVector { col: 42, row: 38 }, me_stats[5][8].mv);
767
768 let me_stats = &fs.frame_me_stats.read().unwrap()[2];
769 let mix = (128 >> MI_SIZE_LOG2) + 3;
770 let miy = (64 >> MI_SIZE_LOG2) + 2;
771 assert_eq!(MotionVector { col: 2, row: 14 }, me_stats[miy][mix].mv);
772 }
773
774 #[test]
775 fn test_tile_blocks_write() {
776 let (fi, mut fs, mut fb, frame_rate) = setup(160, 144);
777
778 {
779 let ti = TilingInfo::from_target_tiles(
781 fi.sb_size_log2(),
782 fi.width,
783 fi.height,
784 frame_rate,
785 2,
786 2,
787 false,
788 );
789 let iter = ti.tile_iter_mut(&mut fs, &mut fb);
790 let mut tbs = iter.map(|ctx| ctx.tb).collect::<Vec<_>>();
791
792 {
793 let tb = &mut tbs[0];
795 tb[3][4].n4_w = 42;
797 tb[5][8].segmentation_idx = 14;
799 }
800
801 {
802 let tb = &mut tbs[5];
804 tb[1][0].n4_h = 11;
806 tb[5][7].cdef_index = 3;
808 }
809
810 {
811 let tb = &mut tbs[7];
813 tb[2][3].mode = PredictionMode::PAETH_PRED;
815 tb[1][1].n4_w = 8;
817 }
818 }
819
820 assert_eq!(42, fb[3][4].n4_w);
823 assert_eq!(14, fb[5][8].segmentation_idx);
824
825 assert_eq!(11, fb[17][32].n4_h);
826 assert_eq!(3, fb[21][39].cdef_index);
827
828 assert_eq!(PredictionMode::PAETH_PRED, fb[34][19].mode);
829 assert_eq!(8, fb[33][17].n4_w);
830 }
831
832 #[test]
833 fn tile_log2_overflow() {
834 assert_eq!(TilingInfo::tile_log2(1, usize::MAX), None);
835 }
836
837 #[test]
838 fn from_target_tiles_422() {
839 let sb_size_log2 = 6;
840 let is_422_p = true;
841 let frame_rate = 60.;
842 let sb_size = 1 << sb_size_log2;
843
844 for frame_height in (sb_size..4352).step_by(sb_size) {
845 for tile_rows_log2 in
846 0..=TilingInfo::tile_log2(1, frame_height >> sb_size_log2).unwrap()
847 {
848 for frame_width in (sb_size..7680).step_by(sb_size) {
849 for tile_cols_log2 in
850 0..=TilingInfo::tile_log2(1, frame_width >> sb_size_log2).unwrap()
851 {
852 let ti = TilingInfo::from_target_tiles(
853 sb_size_log2,
854 frame_width,
855 frame_height,
856 frame_rate,
857 tile_cols_log2,
858 tile_rows_log2,
859 is_422_p,
860 );
861 assert_eq!(
862 ti.tile_cols_log2,
863 TilingInfo::tile_log2(1, ti.cols).unwrap()
864 );
865 assert_eq!(
866 ti.tile_rows_log2,
867 TilingInfo::tile_log2(1, ti.rows).unwrap()
868 );
869 }
870 }
871 }
872 }
873 }
874}