1use super::*;
11
12use crate::context::*;
13use crate::encoder::*;
14use crate::frame::*;
15use crate::lrf::{IntegralImageBuffer, SOLVE_IMAGE_SIZE};
16use crate::mc::MotionVector;
17use crate::me::FrameMEStats;
18use crate::me::WriteGuardMEStats;
19use crate::partition::{RefType, REF_FRAMES};
20use crate::predict::{InterCompoundBuffers, PredictionMode};
21use crate::quantize::*;
22use crate::rdo::*;
23use crate::stats::EncoderStats;
24use crate::util::*;
25use std::ops::{Index, IndexMut};
26use std::sync::Arc;
27
28#[derive(Debug)]
49pub struct TileStateMut<'a, T: Pixel> {
50 pub sbo: PlaneSuperBlockOffset,
51 pub sb_size_log2: usize,
52 pub sb_width: usize,
53 pub sb_height: usize,
54 pub mi_width: usize,
55 pub mi_height: usize,
56 pub width: usize,
57 pub height: usize,
58 pub input: &'a Frame<T>, pub input_tile: Tile<'a, T>, pub input_hres: &'a Plane<T>,
61 pub input_qres: &'a Plane<T>,
62 pub deblock: &'a DeblockState,
63 pub rec: TileMut<'a, T>,
64 pub qc: QuantizationContext,
65 pub segmentation: &'a SegmentationState,
66 pub restoration: TileRestorationStateMut<'a>,
67 pub me_stats: Vec<TileMEStatsMut<'a>>,
68 pub coded_block_info: MiTileState,
69 pub integral_buffer: IntegralImageBuffer,
70 pub inter_compound_buffers: InterCompoundBuffers,
71}
72
73#[derive(Debug, Clone, Copy)]
77pub struct CodedBlockInfo {
78 pub luma_mode: PredictionMode,
79 pub chroma_mode: PredictionMode,
80 pub reference_types: [RefType; 2],
81}
82
83impl Default for CodedBlockInfo {
84 fn default() -> Self {
85 CodedBlockInfo {
86 luma_mode: PredictionMode::DC_PRED,
87 chroma_mode: PredictionMode::DC_PRED,
88 reference_types: [RefType::INTRA_FRAME, RefType::NONE_FRAME],
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
94pub struct MiTileState {
95 mi_width: usize,
96 mi_height: usize,
97 mi_block_info: Vec<CodedBlockInfo>,
98}
99
100impl MiTileState {
101 pub fn new(mi_width: usize, mi_height: usize) -> Self {
102 MiTileState {
103 mi_width,
104 mi_height,
105 mi_block_info: vec![CodedBlockInfo::default(); mi_width * mi_height],
106 }
107 }
108}
109
110impl Index<usize> for MiTileState {
111 type Output = [CodedBlockInfo];
112
113 #[inline(always)]
114 fn index(&self, index: usize) -> &Self::Output {
115 &self.mi_block_info[index * self.mi_width..(index + 1) * self.mi_width]
116 }
117}
118
119impl IndexMut<usize> for MiTileState {
120 #[inline(always)]
121 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
122 &mut self.mi_block_info[index * self.mi_width..(index + 1) * self.mi_width]
123 }
124}
125
126impl<'a, T: Pixel> TileStateMut<'a, T> {
127 pub fn new(
128 fs: &'a mut FrameState<T>, sbo: PlaneSuperBlockOffset,
129 sb_size_log2: usize, width: usize, height: usize,
130 frame_me_stats: &'a mut [FrameMEStats],
131 ) -> Self {
132 debug_assert!(
133 width % MI_SIZE == 0,
134 "Tile width must be a multiple of MI_SIZE"
135 );
136 debug_assert!(
137 height % MI_SIZE == 0,
138 "Tile width must be a multiple of MI_SIZE"
139 );
140
141 let sb_rounded_width = width.align_power_of_two(sb_size_log2);
142 let sb_rounded_height = height.align_power_of_two(sb_size_log2);
143
144 let luma_rect = TileRect {
145 x: sbo.0.x << sb_size_log2,
146 y: sbo.0.y << sb_size_log2,
147 width: sb_rounded_width,
148 height: sb_rounded_height,
149 };
150 let sb_width = width.align_power_of_two_and_shift(sb_size_log2);
151 let sb_height = height.align_power_of_two_and_shift(sb_size_log2);
152
153 Self {
154 sbo,
155 sb_size_log2,
156 sb_width,
157 sb_height,
158 mi_width: width >> MI_SIZE_LOG2,
159 mi_height: height >> MI_SIZE_LOG2,
160 width,
161 height,
162 input: &fs.input,
163 input_tile: Tile::new(&fs.input, luma_rect),
164 input_hres: &fs.input_hres,
165 input_qres: &fs.input_qres,
166 deblock: &fs.deblock,
167 rec: TileMut::new(Arc::make_mut(&mut fs.rec), luma_rect),
168 qc: Default::default(),
169 segmentation: &fs.segmentation,
170 restoration: TileRestorationStateMut::new(
171 &mut fs.restoration,
172 sbo,
173 sb_width,
174 sb_height,
175 ),
176 me_stats: frame_me_stats
177 .iter_mut()
178 .map(|fmvs| {
179 TileMEStatsMut::new(
180 fmvs,
181 sbo.0.x << (sb_size_log2 - MI_SIZE_LOG2),
182 sbo.0.y << (sb_size_log2 - MI_SIZE_LOG2),
183 width >> MI_SIZE_LOG2,
184 height >> MI_SIZE_LOG2,
185 )
186 })
187 .collect(),
188 coded_block_info: MiTileState::new(
189 width >> MI_SIZE_LOG2,
190 height >> MI_SIZE_LOG2,
191 ),
192 integral_buffer: IntegralImageBuffer::zeroed(SOLVE_IMAGE_SIZE),
193 inter_compound_buffers: InterCompoundBuffers::default(),
194 }
195 }
196
197 #[inline(always)]
198 pub fn tile_rect(&self) -> TileRect {
199 TileRect {
200 x: self.sbo.0.x << self.sb_size_log2,
201 y: self.sbo.0.y << self.sb_size_log2,
202 width: self.width,
203 height: self.height,
204 }
205 }
206
207 #[inline(always)]
208 pub fn to_frame_block_offset(
209 &self, tile_bo: TileBlockOffset,
210 ) -> PlaneBlockOffset {
211 let bx = self.sbo.0.x << (self.sb_size_log2 - MI_SIZE_LOG2);
212 let by = self.sbo.0.y << (self.sb_size_log2 - MI_SIZE_LOG2);
213 PlaneBlockOffset(BlockOffset { x: bx + tile_bo.0.x, y: by + tile_bo.0.y })
214 }
215
216 #[inline(always)]
217 pub fn to_frame_super_block_offset(
218 &self, tile_sbo: TileSuperBlockOffset,
219 ) -> PlaneSuperBlockOffset {
220 PlaneSuperBlockOffset(SuperBlockOffset {
221 x: self.sbo.0.x + tile_sbo.0.x,
222 y: self.sbo.0.y + tile_sbo.0.y,
223 })
224 }
225
226 pub fn above_block_info(
230 &self, bo: TileBlockOffset, xdec: usize, ydec: usize,
231 ) -> Option<CodedBlockInfo> {
232 let (mut bo_x, mut bo_y) = (bo.0.x, bo.0.y);
233 if bo_x & 1 == 0 {
234 bo_x += xdec
235 };
236 if bo_y & 1 == 1 {
237 bo_y -= ydec
238 };
239 if bo_y == 0 {
240 None
241 } else {
242 Some(self.coded_block_info[bo_y - 1][bo_x])
243 }
244 }
245
246 pub fn left_block_info(
250 &self, bo: TileBlockOffset, xdec: usize, ydec: usize,
251 ) -> Option<CodedBlockInfo> {
252 let (mut bo_x, mut bo_y) = (bo.0.x, bo.0.y);
253 if bo_x & 1 == 1 {
254 bo_x -= xdec
255 };
256 if bo_y & 1 == 0 {
257 bo_y += ydec
258 };
259 if bo_x == 0 {
260 None
261 } else {
262 Some(self.coded_block_info[bo_y][bo_x - 1])
263 }
264 }
265}