/rust/registry/src/index.crates.io-1949cf8c6b5b557f/av-scenechange-0.14.1/src/data/prediction.rs
Line | Count | Source |
1 | | use v_frame::{ |
2 | | pixel::Pixel, |
3 | | plane::{Plane, PlaneConfig, PlaneOffset, PlaneSlice}, |
4 | | }; |
5 | | |
6 | | use crate::{ |
7 | | cpu::CpuFeatureLevel, |
8 | | data::{ |
9 | | frame::{FrameInvariants, RefType}, |
10 | | mc::put_8tap, |
11 | | motion::MotionVector, |
12 | | plane::PlaneRegionMut, |
13 | | tile::TileRect, |
14 | | }, |
15 | | }; |
16 | | |
17 | | // There are more modes than in the spec because every allowed |
18 | | // drl index for NEAR modes is considered its own mode. |
19 | | #[allow(non_camel_case_types)] |
20 | | #[allow(clippy::upper_case_acronyms)] |
21 | | #[allow(dead_code)] |
22 | | #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default)] |
23 | | pub enum PredictionMode { |
24 | | #[default] |
25 | | DC_PRED, // Average of above and left pixels |
26 | | V_PRED, // Vertical |
27 | | H_PRED, // Horizontal |
28 | | D45_PRED, // Directional 45 degree |
29 | | D135_PRED, // Directional 135 degree |
30 | | D113_PRED, // Directional 113 degree |
31 | | D157_PRED, // Directional 157 degree |
32 | | D203_PRED, // Directional 203 degree |
33 | | D67_PRED, // Directional 67 degree |
34 | | SMOOTH_PRED, // Combination of horizontal and vertical interpolation |
35 | | SMOOTH_V_PRED, |
36 | | SMOOTH_H_PRED, |
37 | | PAETH_PRED, |
38 | | UV_CFL_PRED, |
39 | | NEARESTMV, |
40 | | NEAR0MV, |
41 | | NEAR1MV, |
42 | | NEAR2MV, |
43 | | GLOBALMV, |
44 | | NEWMV, |
45 | | // Compound ref compound modes |
46 | | NEAREST_NEARESTMV, |
47 | | NEAR_NEAR0MV, |
48 | | NEAR_NEAR1MV, |
49 | | NEAR_NEAR2MV, |
50 | | NEAREST_NEWMV, |
51 | | NEW_NEARESTMV, |
52 | | NEAR_NEW0MV, |
53 | | NEAR_NEW1MV, |
54 | | NEAR_NEW2MV, |
55 | | NEW_NEAR0MV, |
56 | | NEW_NEAR1MV, |
57 | | NEW_NEAR2MV, |
58 | | GLOBAL_GLOBALMV, |
59 | | NEW_NEWMV, |
60 | | } |
61 | | |
62 | | impl PredictionMode { |
63 | 0 | pub fn is_intra(self) -> bool { |
64 | 0 | self < PredictionMode::NEARESTMV |
65 | 0 | } |
66 | | |
67 | | /// Inter prediction with a single reference (i.e. not compound mode) |
68 | | /// |
69 | | /// # Panics |
70 | | /// |
71 | | /// - If called on an intra `PredictionMode` |
72 | | #[allow(clippy::too_many_arguments)] |
73 | 0 | pub fn predict_inter_single<T: Pixel>( |
74 | 0 | self, |
75 | 0 | fi: &FrameInvariants<T>, |
76 | 0 | tile_rect: TileRect, |
77 | 0 | p: usize, |
78 | 0 | po: PlaneOffset, |
79 | 0 | dst: &mut PlaneRegionMut<'_, T>, |
80 | 0 | width: usize, |
81 | 0 | height: usize, |
82 | 0 | ref_frame: RefType, |
83 | 0 | mv: MotionVector, |
84 | 0 | bit_depth: usize, |
85 | 0 | cpu_feature_level: CpuFeatureLevel, |
86 | 0 | ) { |
87 | 0 | assert!(!self.is_intra()); |
88 | 0 | let frame_po = tile_rect.to_frame_plane_offset(po); |
89 | | |
90 | 0 | if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] { |
91 | 0 | let (row_frac, col_frac, src) = |
92 | 0 | PredictionMode::get_mv_params(&rec.frame.planes[p], frame_po, mv); |
93 | 0 | put_8tap( |
94 | 0 | dst, |
95 | 0 | src, |
96 | 0 | width, |
97 | 0 | height, |
98 | 0 | col_frac, |
99 | 0 | row_frac, |
100 | 0 | bit_depth, |
101 | 0 | cpu_feature_level, |
102 | 0 | ); |
103 | 0 | } |
104 | 0 | } Unexecuted instantiation: <av_scenechange::data::prediction::PredictionMode>::predict_inter_single::<u16> Unexecuted instantiation: <av_scenechange::data::prediction::PredictionMode>::predict_inter_single::<u8> Unexecuted instantiation: <av_scenechange::data::prediction::PredictionMode>::predict_inter_single::<_> |
105 | | |
106 | | // Used by inter prediction to extract the fractional component of a mv and |
107 | | // obtain the correct PlaneSlice to operate on. |
108 | 0 | fn get_mv_params<T: Pixel>( |
109 | 0 | rec_plane: &Plane<T>, |
110 | 0 | po: PlaneOffset, |
111 | 0 | mv: MotionVector, |
112 | 0 | ) -> (i32, i32, PlaneSlice<T>) { |
113 | 0 | let &PlaneConfig { xdec, ydec, .. } = &rec_plane.cfg; |
114 | 0 | let row_offset = mv.row as i32 >> (3 + ydec); |
115 | 0 | let col_offset = mv.col as i32 >> (3 + xdec); |
116 | 0 | let row_frac = ((mv.row as i32) << (1 - ydec)) & 0xf; |
117 | 0 | let col_frac = ((mv.col as i32) << (1 - xdec)) & 0xf; |
118 | 0 | let qo = PlaneOffset { |
119 | 0 | x: po.x + col_offset as isize - 3, |
120 | 0 | y: po.y + row_offset as isize - 3, |
121 | 0 | }; |
122 | 0 | ( |
123 | 0 | row_frac, |
124 | 0 | col_frac, |
125 | 0 | rec_plane.slice(qo).clamp().subslice(3, 3), |
126 | 0 | ) |
127 | 0 | } Unexecuted instantiation: <av_scenechange::data::prediction::PredictionMode>::get_mv_params::<u16> Unexecuted instantiation: <av_scenechange::data::prediction::PredictionMode>::get_mv_params::<u8> Unexecuted instantiation: <av_scenechange::data::prediction::PredictionMode>::get_mv_params::<_> |
128 | | } |
129 | | |
130 | | #[derive(Copy, Clone, Debug)] |
131 | | #[allow(clippy::upper_case_acronyms)] |
132 | | pub enum PredictionVariant { |
133 | | NONE, |
134 | | LEFT, |
135 | | TOP, |
136 | | BOTH, |
137 | | } |
138 | | |
139 | | impl PredictionVariant { |
140 | 0 | pub const fn new(x: usize, y: usize) -> Self { |
141 | 0 | match (x, y) { |
142 | 0 | (0, 0) => PredictionVariant::NONE, |
143 | 0 | (_, 0) => PredictionVariant::LEFT, |
144 | 0 | (0, _) => PredictionVariant::TOP, |
145 | 0 | _ => PredictionVariant::BOTH, |
146 | | } |
147 | 0 | } |
148 | | } |