]> git.nihav.org Git - nihav.git/blob - nihav-realmedia/src/codecs/rv3040.rs
62a258d20558a6659b3526611ad3f9ee2a32b20d
[nihav.git] / nihav-realmedia / src / codecs / rv3040.rs
1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::{NABufferType, NAVideoInfo, NAVideoBuffer, NAVideoBufferRef, FrameType, alloc_video_buffer};
3 use nihav_core::codecs::{NADecoderSupport, DecoderError, DecoderResult};
4 use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
5 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
6 use nihav_core::io::intcode::*;
7 use nihav_codec_support::data::GenericCache;
8 use std::mem;
9
10 use super::rv34codes::*;
11 use super::rv34dsp::*;
12
13 trait RV34MVScale {
14 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
15 }
16
17 const TR_SHIFT: u8 = 14;
18 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
19
20 impl RV34MVScale for MV {
21 fn scale(&self, trd: u16, trb: u16) -> (MV, MV) {
22 let ratio = ((trb as i32) << TR_SHIFT) / (trd as i32);
23 let mv_f = MV {
24 x: (((self.x as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16,
25 y: (((self.y as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16
26 };
27 let mv_b = mv_f - *self;
28 (mv_f, mv_b)
29 }
30 }
31
32 #[derive(Clone,Copy)]
33 pub struct RV34SliceHeader {
34 pub ftype: FrameType,
35 pub quant: u8,
36 pub pts: u16,
37 pub width: usize,
38 pub height: usize,
39 pub start: usize,
40 pub end: usize,
41 pub set_idx: usize,
42 pub deblock: bool,
43 }
44
45 impl RV34SliceHeader {
46 pub fn fits(&self, cmp: &RV34SliceHeader) -> bool {
47 (self.ftype == cmp.ftype) &&
48 (self.pts == cmp.pts) &&
49 (self.width == cmp.width) &&
50 (self.height == cmp.height)
51 }
52 }
53
54 #[derive(Debug,Clone,Copy,PartialEq)]
55 pub enum MBType {
56 MBIntra,
57 MBIntra16,
58 MBSkip,
59 MBP16x16,
60 MBP16x16Mix,
61 MBP16x8,
62 MBP8x16,
63 MBP8x8,
64 MBDirect,
65 MBBidir,
66 MBForward,
67 MBBackward,
68 Invalid,
69 }
70
71 impl MBType {
72 pub fn is_intra(self) -> bool {
73 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
74 }
75 pub fn is_16(self) -> bool {
76 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
77 }
78 pub fn is_intra_or_16(self) -> bool {
79 self.is_intra() || self.is_16()
80 }
81 pub fn get_num_mvs(self) -> usize {
82 match self {
83 MBType::MBIntra | MBType::MBIntra16 |
84 MBType::MBSkip | MBType::MBDirect => 0,
85 MBType::MBP16x16 | MBType::MBP16x16Mix |
86 MBType::MBForward | MBType::MBBackward => 1,
87 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBBidir => 2,
88 MBType::MBP8x8 => 4,
89 MBType::Invalid => unreachable!(),
90 }
91 }
92 pub fn is_fwd(self) -> bool {
93 matches!(self,
94 MBType::MBP16x16 | MBType::MBP16x16Mix |
95 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
96 MBType::MBForward)
97 }
98 pub fn is_bwd(self) -> bool {
99 matches!(self, MBType::MBBidir | MBType::MBBackward)
100 }
101 pub fn has_mv_dir(self, fwd: bool) -> bool {
102 match self {
103 MBType::MBBidir => true,
104 MBType::MBForward if fwd => true,
105 MBType::MBBackward if !fwd => true,
106 _ => false,
107 }
108 }
109 pub fn is_nomv(self) -> bool {
110 matches!(self, MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect)
111 }
112 /*pub fn is_16x16(self) -> bool {
113 match self {
114 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
115 _ => true,
116 }
117 }*/
118 fn get_weight(self) -> usize {
119 match self {
120 MBType::MBIntra => 0,
121 MBType::MBIntra16 => 1,
122 MBType::MBSkip => unreachable!(),
123 MBType::MBP16x16 => 2,
124 MBType::MBP16x16Mix => 10,
125 MBType::MBP16x8 => 7,
126 MBType::MBP8x16 => 8,
127 MBType::MBP8x8 => 3,
128 MBType::MBDirect => 6,
129 MBType::MBBidir => 9,
130 MBType::MBForward => 4,
131 MBType::MBBackward => 5,
132 MBType::Invalid => unreachable!(),
133 }
134 }
135 }
136
137 const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
138 MBType::MBIntra, MBType::MBIntra16, MBType::MBP16x16, MBType::MBP8x8,
139 MBType::MBForward, MBType::MBBackward, MBType::MBDirect, MBType::MBP16x8,
140 MBType::MBP8x16, MBType::MBBidir, MBType::MBP16x16Mix,
141 ];
142
143 #[derive(Clone,Copy)]
144 pub struct MBInfo {
145 pub mbtype: MBType,
146 pub skip_run: usize,
147 pub dquant: bool,
148 }
149
150 #[derive(Clone,Copy)]
151 pub struct RV34MBInfo {
152 pub mbtype: MBType,
153 pub cbp: u32,
154 pub deblock:u16,
155 pub cbp_c: u8, // for deblocking purposes
156 pub q: u8,
157 }
158
159 struct IntraModeState {
160 cache: GenericCache<i8>,
161 }
162
163 const RV34_INTRA_PRED4: [PredType4x4; 9] = [
164 PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
165 PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
166 PredType4x4::VerRight, PredType4x4::VerLeft,
167 PredType4x4::HorUp, PredType4x4::HorDown
168 ];
169
170 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
171 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
172 ];
173
174 impl IntraModeState {
175 fn new(mb_w: usize) -> Self {
176 let stride = 1 + mb_w * 4 + 1;
177 IntraModeState { cache: GenericCache::new(4, stride, -1) }
178 }
179 fn reset(&mut self) { self.cache.reset(); }
180 fn update(&mut self) { self.cache.update_row(); }
181 fn get_pos(&self, xpos: usize) -> usize {
182 self.cache.stride + 1 + xpos * 4
183 }
184 fn set_mb_x(&mut self, mb_x: usize) {
185 self.cache.xpos = self.get_pos(mb_x);
186 }
187 fn fill_block(&mut self, val: i8) {
188 let mut pos = self.cache.xpos;
189 for _ in 0..4 {
190 for j in 0..4 {
191 self.cache.data[pos + j] = val;
192 }
193 pos += self.cache.stride;
194 }
195 }
196 fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
197 if !has_top && !has_left { return PredType8x8::DC128; }
198 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
199 if !has_top {
200 im = match im {
201 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
202 PredType8x8::DC => PredType8x8::LeftDC,
203 _ => im,
204 };
205 } else if !has_left {
206 im = match im {
207 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
208 PredType8x8::DC => PredType8x8::TopDC,
209 _ => im,
210 };
211 }
212 im
213 }
214 fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
215 if !has_top && !has_left { return PredType8x8::DC128; }
216 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
217 im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
218 if !has_top {
219 im = match im {
220 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
221 PredType8x8::DC => PredType8x8::LeftDC,
222 _ => im,
223 };
224 } else if !has_left {
225 im = match im {
226 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
227 PredType8x8::DC => PredType8x8::TopDC,
228 _ => im,
229 };
230 }
231 im
232 }
233 fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
234 let no_up = !has_top && (y == 0);
235 let no_left = !has_left && (x == 0);
236 if no_up && no_left { return PredType4x4::DC128; }
237 let no_down = !has_left || (x != 0) || (y == 3);
238
239 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
240
241 if no_up {
242 im = match im {
243 PredType4x4::Ver => PredType4x4::Hor,
244 PredType4x4::DC => PredType4x4::LeftDC,
245 _ => im,
246 };
247 } else if no_left {
248 im = match im {
249 PredType4x4::Hor => PredType4x4::Ver,
250 PredType4x4::DC => PredType4x4::TopDC,
251 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
252 _ => im,
253 };
254 }
255 if no_down {
256 im = match im {
257 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
258 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
259 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
260 _ => im,
261 };
262 }
263 im
264 }
265 //todo merge
266 fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
267 let no_up = !has_top && (y == 0);
268 let no_left = !has_left && (x == 0);
269 if no_up && no_left { return PredType4x4::DC128; }
270 let no_down = !has_left || (x != 0) || (y == 1);
271
272 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
273
274 if no_up {
275 im = match im {
276 PredType4x4::Ver => PredType4x4::Hor,
277 PredType4x4::DC => PredType4x4::LeftDC,
278 _ => im,
279 };
280 } else if no_left {
281 im = match im {
282 PredType4x4::Hor => PredType4x4::Ver,
283 PredType4x4::DC => PredType4x4::TopDC,
284 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
285 _ => im,
286 };
287 }
288 if no_down {
289 im = match im {
290 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
291 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
292 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
293 _ => im,
294 };
295 }
296 im
297 }
298 }
299
300 pub struct MVInfo {
301 pub mv_b: Vec<MV>,
302 pub mv_f: Vec<MV>,
303 pub w: usize,
304 pub h: usize,
305 pub has_b: Vec<bool>,
306 pub has_f: Vec<bool>,
307 }
308
309 impl MVInfo {
310 fn new() -> Self {
311 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
312 }
313 fn resize(&mut self, mb_w: usize, mb_h: usize) {
314 self.w = mb_w * 2;
315 self.h = mb_h * 2;
316 self.reset();
317 }
318 fn reset(&mut self) {
319 let size = self.w * self.h;
320 self.mv_f.clear();
321 self.mv_f.resize(size, ZERO_MV);
322 self.mv_b.clear();
323 self.mv_b.resize(size, ZERO_MV);
324 self.has_f.clear();
325 self.has_f.resize(size >> 2, false);
326 self.has_b.clear();
327 self.has_b.resize(size >> 2, false);
328 }
329 #[allow(clippy::identity_op)]
330 fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
331 let idx = mb_x * 2 + mb_y * 2 * self.w;
332 if fwd {
333 self.mv_f[idx + 0] = mv;
334 self.mv_f[idx + 1] = mv;
335 self.mv_f[idx + self.w + 0] = mv;
336 self.mv_f[idx + self.w + 1] = mv;
337 } else {
338 self.mv_b[idx + 0] = mv;
339 self.mv_b[idx + 1] = mv;
340 self.mv_b[idx + self.w + 0] = mv;
341 self.mv_b[idx + self.w + 1] = mv;
342 }
343 }
344 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
345 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
346 }
347 fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
348 if !has_top && !has_left { return ZERO_MV; }
349 let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
350 let top_mv = if has_top { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
351 let tr_add = if is16 { 2 } else { 1 };
352 let tr_mv;
353 if has_tr {
354 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
355 } else if has_tl {
356 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
357 } else {
358 tr_mv = left_mv;
359 }
360 MV::pred(left_mv, top_mv, tr_mv)
361 }
362 pub fn pred_mb_mv(&self, mb_x: usize, mb_y: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool) -> MV {
363 self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
364 }
365 #[allow(clippy::collapsible_else_if)]
366 #[allow(clippy::identity_op)]
367 fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
368 let mb_idx = mb_x + mb_y * (self.w >> 1);
369 self.has_f[mb_idx] = mbtype.is_fwd();
370 self.has_b[mb_idx] = mbtype.is_bwd();
371 if mbtype.is_nomv() {
372 self.fill(mb_x, mb_y, true, ZERO_MV);
373 self.fill(mb_x, mb_y, false, ZERO_MV);
374 return;
375 }
376 if mbtype.is_fwd() {
377 self.fill(mb_x, mb_y, false, ZERO_MV);
378 } else if mbtype.is_bwd() {
379 self.fill(mb_x, mb_y, true, ZERO_MV);
380 }
381 let idx = mb_x * 2 + mb_y * 2 * self.w;
382
383 match mbtype {
384 MBType::MBSkip => {
385 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
386 },
387 MBType::MBP16x16 |
388 MBType::MBP16x16Mix => {
389 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
390 let new_mv = mvs[0] + pred_mv;
391 self.fill(mb_x, mb_y, true, new_mv);
392 },
393 MBType::MBP16x8 => {
394 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
395 let new_mv = mvs[0] + pred_mv;
396 self.mv_f[idx + 0] = new_mv;
397 self.mv_f[idx + 1] = new_mv;
398
399 let idx2 = idx + self.w;
400 let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
401 let new_mv = mvs[1] + pred_mv;
402 self.mv_f[idx2 + 0] = new_mv;
403 self.mv_f[idx2 + 1] = new_mv;
404 },
405 MBType::MBP8x16 => {
406 let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
407 let new_mv = mvs[0] + pred_mv;
408 self.mv_f[idx] = new_mv;
409 self.mv_f[idx + self.w] = new_mv;
410
411 let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
412 let new_mv = mvs[1] + pred_mv;
413 self.mv_f[idx + 1] = new_mv;
414 self.mv_f[idx + self.w + 1] = new_mv;
415 },
416 MBType::MBP8x8 => {
417 let mut idx8 = idx;
418 let mut has_top = sstate.has_top;
419 for y in 0..2 {
420 for x in 0..2 {
421 let has_left = (x > 0) || sstate.has_left;
422 let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
423 let has_tl = if y == 0 {
424 if x == 0 { sstate.has_tl } else { sstate.has_top }
425 } else {
426 if x == 0 { sstate.has_left } else { true }
427 };
428 let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
429 let new_mv = mvs[x + y * 2] + pred_mv;
430 self.mv_f[idx8 + x] = new_mv;
431 }
432 has_top = true;
433 idx8 += self.w;
434 }
435 },
436 MBType::MBDirect => {
437 let mut cum_mv_f = ZERO_MV;
438 let mut cum_mv_b = ZERO_MV;
439 let mut idx8 = idx;
440 for _ in 0..2 {
441 for x in 0..2 {
442 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
443 cum_mv_f += mv_f;
444 cum_mv_b += mv_b;
445 }
446 idx8 += self.w;
447 }
448 cum_mv_f.x >>= 2;
449 cum_mv_f.y >>= 2;
450 cum_mv_b.x >>= 2;
451 cum_mv_b.y >>= 2;
452 self.fill(mb_x, mb_y, true, cum_mv_f);
453 self.fill(mb_x, mb_y, false, cum_mv_b);
454 },
455 MBType::MBBidir => {
456 let pred_mv_f = ZERO_MV;
457 let new_mv = pred_mv_f + mvs[0];
458 self.fill(mb_x, mb_y, true, new_mv);
459 let pred_mv_b = ZERO_MV;
460 let new_mv = pred_mv_b + mvs[1];
461 self.fill(mb_x, mb_y, false, new_mv);
462 },
463 MBType::MBForward => {
464 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
465 let new_mv = mvs[0] + pred_mv;
466 self.fill(mb_x, mb_y, true, new_mv);
467 },
468 MBType::MBBackward => {
469 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
470 let new_mv = mvs[0] + pred_mv;
471 self.fill(mb_x, mb_y, false, new_mv);
472 },
473 _ => {},
474 }
475 }
476 pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
477 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
478 if fwd { self.mv_f[idx] }
479 else { self.mv_b[idx] }
480 }
481 fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
482 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
483 let off = if vert { self.w } else { 1 };
484 let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
485 let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
486 (diffx.abs() > 3) || (diffy.abs() > 3)
487 }
488 }
489
490 pub trait RV34BitstreamDecoder {
491 fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
492 fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
493 fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
494 fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
495 fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
496 }
497
498 pub trait RV34DSP {
499 fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, mb_h: usize, row: usize);
500 fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
501 fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool);
502 }
503
504 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
505 let num_slices = (src[0] as usize) + 1;
506 let ini_off = num_slices * 8 + 1;
507 offsets.clear();
508
509 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
510
511 let mut br = BitReader::new(&src[1..ini_off], BitReaderMode::BE);
512
513 for i in 0..num_slices {
514 br.skip(32)?;
515 let off = br.read(32)? as usize;
516 if (i == 0) && (off != 0) {
517 return Err(DecoderError::InvalidData);
518 }
519 if (i > 0) && (off <= offsets[i - 1]) {
520 return Err(DecoderError::InvalidData);
521 }
522 offsets.push(off);
523 }
524
525 Ok(())
526 }
527
528 fn decode_slice_header(br: &mut BitReader, bd: &mut dyn RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
529 validate!(slice_no < slice_offs.len());
530 br.seek((slice_offs[slice_no] * 8) as u32)?;
531 let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
532 if ((shdr.width == 0) || (shdr.height == 0)) && (shdr.ftype != FrameType::I) {
533 return Err(DecoderError::MissingReference);
534 }
535 if slice_no < slice_offs.len() - 1 {
536 let cur_pos = br.tell() as u32;
537 br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
538 if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
539 validate!(nhdr.start > shdr.start);
540 shdr.end = nhdr.start;
541 } else if slice_no + 2 < slice_offs.len() {
542 br.seek((slice_offs[slice_no + 2] * 8) as u32)?;
543 if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
544 validate!(nhdr.start > shdr.start);
545 shdr.end = nhdr.start;
546 } else {
547 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
548 }
549 } else {
550 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
551 }
552 br.seek(cur_pos)?;
553 } else {
554 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
555 }
556 Ok(shdr)
557 }
558
559 const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
560 const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
561
562 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
563 if (w == 0) || (h == 0) {
564 return 0;
565 }
566 let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
567 let mut idx: usize = 0;
568 while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
569 RV34_SLICE_START_BITS[idx]
570 }
571
572 const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
573 [ 0, 0 ], [ 2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
574 [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
575 [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
576 [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
577 ];
578
579 const RV34_QUANT_TAB: [u16; 32] = [
580 60, 67, 76, 85, 96, 108, 121, 136,
581 152, 171, 192, 216, 242, 272, 305, 341,
582 383, 432, 481, 544, 606, 683, 767, 854,
583 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
584 ];
585
586 const RV34_CHROMA_QUANT_DC: [u8; 32] = [
587 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
588 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
589 ];
590 const RV34_CHROMA_QUANT_AC: [u8; 32] = [
591 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
592 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
593 ];
594
595 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
596 if br.read_bool()? {
597 let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
598 let qp = (q as i8) + diff;
599 validate!((qp > 0) && (qp < 32));
600 Ok(qp as u8)
601 } else {
602 let qp = br.read(5)? as u8;
603 Ok(qp)
604 }
605 }
606
607 pub struct SState {
608 pub mb_x: usize,
609 pub mb_y: usize,
610 pub mb_w: usize,
611 pub mb_h: usize,
612 pub cbp: u32,
613 pub q: u8,
614 pub q_dc: u8,
615 pub set_idx: usize,
616 pub has_left: bool,
617 pub has_top: bool,
618 pub has_tl: bool,
619 pub has_tr: bool,
620 pub trd: u16,
621 pub trb: u16,
622 }
623
624 impl SState {
625 fn new() -> Self {
626 Self {
627 mb_x: 0,
628 mb_y: 0,
629 mb_w: 0,
630 mb_h: 0,
631 cbp: 0,
632 q: 0,
633 q_dc: 0,
634 set_idx: 0,
635 has_left: false,
636 has_top: false,
637 has_tl: false,
638 has_tr: false,
639 trd: 0,
640 trb: 0,
641 }
642 }
643 }
644
645 struct MBHist {
646 is_p: bool,
647 hist: [MBType; 4],
648 count: usize,
649 }
650
651 impl MBHist {
652 fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
653 fn add(&mut self, mbt: MBType) {
654 let mbt2 = match mbt {
655 MBType::MBSkip if self.is_p => MBType::MBP16x16,
656 MBType::MBSkip if !self.is_p => MBType::MBDirect,
657 _ => mbt,
658 };
659 self.hist[self.count] = mbt2;
660 self.count += 1;
661 }
662 fn get_mbtype(&self) -> MBType {
663 if self.count == 0 {
664 MBType::MBIntra
665 } else if self.count == 1 {
666 self.hist[0]
667 } else if self.count == 2 {
668 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
669 self.hist[0]
670 } else {
671 self.hist[1]
672 }
673 } else {
674 let mut w: [usize; 12] = [0; 12];
675 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
676 let mut nz_idx = 0;
677 for i in 0..12 {
678 if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
679 if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
680 }
681
682 MBTYPE_FROM_WEIGHT[nz_idx]
683 }
684 }
685 }
686
687 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
688 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
689 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
690 Ok(MV{ x, y })
691 }
692
693 fn do_mc_16x16(dsp: &mut dyn RV34DSP, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
694 dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
695 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
696 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
697 }
698
699 fn do_mc_8x8(dsp: &mut dyn RV34DSP, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
700 dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
701 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
702 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
703 }
704
705 fn do_avg(cdsp: &RV34CommonDSP, buf: &mut NAVideoBuffer<u8>, avg_buf: &NAVideoBuffer<u8>, mb_x: usize, xb: usize, mb_y: usize, yb: usize, size: usize, ratio1: u32, ratio2: u32) {
706 for comp in 0..3 {
707 let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
708 let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
709 let csize = if comp == 0 { size } else { size >> 1 };
710 let dstride = buf.get_stride(comp);
711 let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
712 let data = buf.get_data_mut().unwrap();
713 let dst: &mut [u8] = data.as_mut_slice();
714
715 let sstride = avg_buf.get_stride(comp);
716 let soffset = avg_buf.get_offset(comp);
717 let data = avg_buf.get_data();
718 let src: &[u8] = data.as_slice();
719
720 if ratio1 == ratio2 {
721 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
722 } else {
723 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
724 }
725 }
726 }
727
728 pub struct RV34Decoder {
729 is_rv30: bool,
730 coderead: RV34Codes,
731 dsp: Box<dyn RV34DSP + Send>,
732 cdsp: RV34CommonDSP,
733 width: usize,
734 height: usize,
735 ipbs: IPBShuffler,
736 mvi: MVInfo,
737 ref_mvi: MVInfo,
738 last_ts: u16,
739 next_ts: u16,
740 ratio1: u32,
741 ratio2: u32,
742 is_b: bool,
743 mbinfo: Vec<RV34MBInfo>,
744 avg_buf: NAVideoBufferRef<u8>,
745 base_ts: u64,
746 }
747
748 impl RV34Decoder {
749 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP + Send>) -> Self {
750 let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
751 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
752 let vb = vt.get_vbuf();
753 let avg_buf = vb.unwrap();
754 RV34Decoder {
755 is_rv30,
756 coderead: RV34Codes::new(),
757 dsp,
758 cdsp: RV34CommonDSP::new(),
759 ipbs: IPBShuffler::new(),
760 mvi: MVInfo::new(),
761 ref_mvi: MVInfo::new(),
762 mbinfo: Vec::new(),
763 width: 0, height: 0,
764 last_ts: 0, next_ts: 0,
765 ratio1: 0, ratio2: 0,
766 is_b: false,
767 avg_buf,
768 base_ts: 0,
769 }
770 }
771 fn decode_mb_header_intra(&mut self, bd: &mut dyn RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
772 if is_i16 {
773 let imode = br.read(2)? as i8;
774 im.fill_block(imode);
775 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
776 } else {
777 let dq = if !has_dq {
778 if !self.is_rv30 { !br.read_bool()? } else { false }
779 } else { false };
780 if dq {
781 decode_dquant(br, q)?;
782 }
783 bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
784 Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
785 }
786 }
787 fn decode_mb_header_inter(&mut self, bd: &mut dyn RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
788 let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
789 validate!(hdr.mbtype != MBType::Invalid);
790 if hdr.dquant {
791 decode_dquant(br, q)?;
792 }
793 if hdr.mbtype.is_intra() {
794 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
795 }
796 Ok(hdr)
797 }
798
799 fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
800 let mut cur_cbp = sstate.cbp;
801 {
802 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
803 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
804 let luma_set = if is_16 { 2 } else { 1 };
805 let mut coeffs16: [i16; 16] = [0; 16];
806 if is_16 {
807 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
808 if has_ac {
809 self.cdsp.transform16(&mut coeffs16);
810 } else {
811 self.cdsp.transform16_dc(&mut coeffs16);
812 }
813 }
814 let stride = buf.get_stride(0);
815 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
816 let data = buf.get_data_mut().unwrap();
817 let framebuf: &mut [u8] = data.as_mut_slice();
818
819 if is_16 {
820 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
821 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
822 }
823
824 for y in 0..4 {
825 for x in 0..4 {
826 let mut coeffs: [i16; 16] = [0; 16];
827 let has_ac = if (cur_cbp & 1) != 0 {
828 self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?
829 } else {
830 false
831 };
832 if is_16 {
833 coeffs[0] = coeffs16[x + y * 4];
834 } else {
835 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
836 let has_top = sstate.has_top || (y > 0);
837 let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
838 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
839 let i = offset + x * 4 - stride;
840 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
841 } else if has_top {
842 let i = offset + x * 4 - stride;
843 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
844 } else {
845 [0; 4]
846 };
847 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
848 }
849 if has_ac {
850 self.cdsp.transform(&mut coeffs);
851 } else {
852 self.cdsp.transform_dc(&mut coeffs);
853 }
854 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
855 cur_cbp >>= 1;
856 }
857 offset += stride * 4;
858 }
859 }
860 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
861 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
862 let chroma_set = 0;
863 for comp in 1..3 {
864 let stride = buf.get_stride(comp);
865 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
866 let data = buf.get_data_mut().unwrap();
867 let framebuf: &mut [u8] = data.as_mut_slice();
868 if is_16 {
869 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
870 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
871 }
872 for y in 0..2 {
873 for x in 0..2 {
874 let mut coeffs: [i16; 16] = [0; 16];
875 let has_ac = if (cur_cbp & 1) != 0 {
876 self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?
877 } else {
878 false
879 };
880 if !is_16 {
881 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
882 let has_top = sstate.has_top || (y > 0);
883 let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
884 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
885 let i = offset + x * 4 - stride;
886 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
887 } else if has_top {
888 let i = offset + x * 4 - stride;
889 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
890 } else {
891 [0; 4]
892 };
893 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
894 }
895 if has_ac {
896 self.cdsp.transform(&mut coeffs);
897 } else {
898 self.cdsp.transform_dc(&mut coeffs);
899 }
900 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
901 cur_cbp >>= 1;
902 }
903 offset += stride * 4;
904 }
905 }
906 Ok(())
907 }
908
909 fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
910 let mb_x = sstate.mb_x;
911 let mb_y = sstate.mb_y;
912 match mbh.mbtype {
913 MBType::MBP16x16 | MBType::MBP16x16Mix => {
914 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
915 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
916 do_mc_16x16(self.dsp.as_mut(), buf, prevbuf, mb_x, mb_y, mv, false);
917 }
918 },
919 MBType::MBForward => {
920 if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
921 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
922 do_mc_16x16(self.dsp.as_mut(), buf, fwdbuf, mb_x, mb_y, mv, false);
923 }
924 },
925 MBType::MBBackward => {
926 if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
927 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
928 do_mc_16x16(self.dsp.as_mut(), buf, bwdbuf, mb_x, mb_y, mv, false);
929 }
930 },
931 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
932 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
933 for y in 0..2 {
934 for x in 0..2 {
935 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
936 do_mc_8x8(self.dsp.as_mut(), buf, prevbuf, mb_x, x, mb_y, y, mv, false);
937 }
938 }
939 }
940 },
941 MBType::MBSkip if !self.is_b => {
942 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
943 do_mc_16x16(self.dsp.as_mut(), buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
944 }
945 },
946 MBType::MBSkip | MBType::MBDirect => {
947 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
948 for y in 0..2 {
949 for x in 0..2 {
950 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
951 do_mc_8x8(self.dsp.as_mut(), buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
952 do_mc_8x8(self.dsp.as_mut(), &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
953 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
954 }
955 }
956 }
957 },
958 MBType::MBBidir => {
959 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
960 let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
961 let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
962 do_mc_16x16(self.dsp.as_mut(), buf, fwdbuf, mb_x, mb_y, mv_f, false);
963 do_mc_16x16(self.dsp.as_mut(), &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
964 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
965 }
966 },
967 _ => {},
968 };
969 }
970 fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
971 self.do_mc(buf, mbh, sstate);
972
973 let mut cur_cbp = sstate.cbp;
974
975 {
976 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
977 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
978 let luma_set = if is_16 { 2 } else { 0 };
979 let mut coeffs16: [i16; 16] = [0; 16];
980 if is_16 {
981 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
982 if has_ac {
983 self.cdsp.transform16(&mut coeffs16);
984 } else {
985 self.cdsp.transform16_dc(&mut coeffs16);
986 }
987 }
988 let stride = buf.get_stride(0);
989 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
990 let data = buf.get_data_mut().unwrap();
991 let framebuf: &mut [u8] = data.as_mut_slice();
992
993 for y in 0..4 {
994 for x in 0..4 {
995 let mut coeffs: [i16; 16] = [0; 16];
996 let has_ac = if (cur_cbp & 1) != 0 {
997 self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?
998 } else {
999 false
1000 };
1001 if is_16 {
1002 coeffs[0] = coeffs16[x + y * 4];
1003 }
1004 if has_ac {
1005 self.cdsp.transform(&mut coeffs);
1006 } else {
1007 self.cdsp.transform_dc(&mut coeffs);
1008 }
1009 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1010 cur_cbp >>= 1;
1011 }
1012 offset += stride * 4;
1013 }
1014 }
1015 if is_16 {
1016 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1017 }
1018 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
1019 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
1020 let chroma_set = 1;
1021 for comp in 1..3 {
1022 let stride = buf.get_stride(comp);
1023 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
1024 let data = buf.get_data_mut().unwrap();
1025 let framebuf: &mut [u8] = data.as_mut_slice();
1026 for _ in 0..2 {
1027 for x in 0..2 {
1028 let mut coeffs: [i16; 16] = [0; 16];
1029 let has_ac = if (cur_cbp & 1) != 0 {
1030 self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?
1031 } else {
1032 false
1033 };
1034 if has_ac {
1035 self.cdsp.transform(&mut coeffs);
1036 } else {
1037 self.cdsp.transform_dc(&mut coeffs);
1038 }
1039 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1040 cur_cbp >>= 1;
1041 }
1042 offset += stride * 4;
1043 }
1044 }
1045 Ok(())
1046 }
1047 fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut [RV34MBInfo]) {
1048 let mbt = mbinfo[mb_pos].mbtype;
1049 let mut hmvmask = 0;
1050 let mut vmvmask = 0;
1051
1052 for y in 0..2 {
1053 for x in 0..2 {
1054 let shift = x * 2 + y * 8;
1055 if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
1056 vmvmask |= 0x11 << shift;
1057 }
1058 if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
1059 hmvmask |= 0x03 << shift;
1060 }
1061 }
1062 }
1063 if !sstate.has_top { hmvmask &= !0x000F; }
1064 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1065 if self.is_rv30 {
1066 vmvmask |= (vmvmask & 0x4444) >> 1;
1067 hmvmask |= (hmvmask & 0x0F00) >> 4;
1068 if sstate.mb_x > 0 {
1069 mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
1070 }
1071 if sstate.has_top {
1072
1073 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1074 }
1075 }
1076 if mbt.is_intra_or_16() {
1077 mbinfo[mb_pos].deblock = 0xFFFF;
1078 mbinfo[mb_pos].cbp_c = 0xFF;
1079 } else {
1080 mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
1081 mbinfo[mb_pos].cbp_c = (mbinfo[mb_pos].cbp >> 16) as u8;
1082 }
1083 }
1084
1085 #[allow(clippy::cognitive_complexity)]
1086 #[allow(clippy::collapsible_else_if)]
1087 pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut dyn RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
1088 let mut slice_offs: Vec<usize> = Vec::new();
1089 parse_slice_offsets(src, &mut slice_offs)?;
1090 let ini_off = slice_offs.len() * 8 + 1;
1091
1092 let mut br = BitReader::new(&src[ini_off..], BitReaderMode::BE);
1093 let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
1094 validate!((hdr0.width != 0) && (hdr0.height != 0));
1095 self.width = hdr0.width;
1096 self.height = hdr0.height;
1097 let mb_w = (hdr0.width + 15) >> 4;
1098 let mb_h = (hdr0.height + 15) >> 4;
1099 let mut mb_pos: usize = 0;
1100 let mut slice = hdr0;
1101 let mut slice_no: usize = 1;
1102 let is_intra = hdr0.ftype == FrameType::I;
1103 let mut skip_run: usize = 0;
1104 let mut imode = IntraModeState::new(mb_w);
1105 let mut q = hdr0.quant;
1106
1107 let mut sstate = SState::new();
1108 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1109
1110 self.is_b = hdr0.ftype == FrameType::B;
1111 if hdr0.ftype != FrameType::B {
1112 self.last_ts = self.next_ts;
1113 self.next_ts = hdr0.pts;
1114 if self.last_ts > self.next_ts {
1115 self.base_ts += 1 << 13;
1116 }
1117 }
1118 match hdr0.ftype {
1119 FrameType::P => {
1120 if self.ipbs.get_lastref().is_none() {
1121 return Err(DecoderError::MissingReference);
1122 }
1123 },
1124 FrameType::B => {
1125 if self.ipbs.get_lastref().is_none() {
1126 return Err(DecoderError::MissingReference);
1127 }
1128 if self.ipbs.get_nextref().is_none() {
1129 return Err(DecoderError::MissingReference);
1130 }
1131 },
1132 _ => {},
1133 };
1134 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1135 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1136 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1137 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1138 if sstate.trb != 0 {
1139 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1140 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1141 } else {
1142 self.ratio1 = 1 << 14 >> 1;
1143 self.ratio2 = 1 << 14 >> 1;
1144 }
1145 //todo validate against ref frame
1146
1147 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1148 let ret = supp.pool_u8.get_free();
1149 if ret.is_none() {
1150 return Err(DecoderError::AllocError);
1151 }
1152 let mut buf = ret.unwrap();
1153 if buf.get_info() != vinfo {
1154 self.ipbs.clear();
1155 supp.pool_u8.reset();
1156 supp.pool_u8.prealloc_video(vinfo, 4)?;
1157 let ret = supp.pool_u8.get_free();
1158 if ret.is_none() {
1159 return Err(DecoderError::AllocError);
1160 }
1161 buf = ret.unwrap();
1162 }
1163
1164 sstate.q = q;
1165 sstate.has_top = false;
1166 sstate.mb_w = mb_w;
1167 sstate.mb_h = mb_h;
1168 sstate.set_idx = hdr0.set_idx;
1169
1170 self.mvi.resize(mb_w, mb_h);
1171 for mb_y in 0..mb_h {
1172 sstate.mb_y = mb_y;
1173 sstate.has_left = false;
1174 for mb_x in 0..mb_w {
1175 sstate.mb_x = mb_x;
1176 if mb_pos == slice.end {
1177 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1178 validate!(slice.fits(&hdr0));
1179 q = slice.quant;
1180 slice_no += 1;
1181 imode.reset();
1182 sstate.q = q;
1183 sstate.has_top = false;
1184 sstate.has_left = false;
1185 sstate.set_idx = slice.set_idx;
1186 }
1187 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1188 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1189 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1190 imode.set_mb_x(mb_x);
1191 let mbh = if is_intra {
1192 let is_i16 = br.read_bool()?;
1193 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1194 } else {
1195 if skip_run == 0 {
1196 let mbtype = if self.is_rv30 {
1197 MBType::Invalid
1198 } else {
1199 let mut hist = MBHist::new(hdr0.ftype);
1200 if sstate.has_top {
1201 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1202 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1203 }
1204 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1205 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1206 hist.get_mbtype()
1207 };
1208 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1209 } else {
1210 skip_run -= 1;
1211 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1212 }
1213 };
1214 if !mbh.mbtype.is_intra() {
1215 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1216 for mv in mvs[..mbh.mbtype.get_num_mvs()].iter_mut() {
1217 *mv = decode_mv(&mut br)?;
1218 }
1219 if !self.is_b {
1220 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1221 } else {
1222 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1223 self.mvi.fill(mb_x, mb_y, true, mv_f);
1224 self.mvi.fill(mb_x, mb_y, false, mv_b);
1225 }
1226 }
1227 let cbp;
1228 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1229 if mbh.mbtype == MBType::MBSkip {
1230 cbp = 0;
1231 if mbh.skip_run > 0 {
1232 skip_run = mbh.skip_run;
1233 }
1234 } else {
1235 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1236 if mbh.mbtype == MBType::MBP16x16Mix {
1237 self.coderead.select_codes(true, q, slice.set_idx, true);
1238 }
1239 cbp = self.coderead.decode_cbp(&mut br)?;
1240 }
1241 sstate.cbp = cbp;
1242 if is_intra || mbh.mbtype.is_intra() {
1243 sstate.q_dc = bd.quant_dc(true, q);
1244 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1245 } else {
1246 sstate.q_dc = bd.quant_dc(false, q);
1247 imode.fill_block(0);
1248 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1249 }
1250
1251 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1252 mbinfo.push(mi);
1253 if is_intra {
1254 mbinfo[mb_pos].deblock = 0xFFFF;
1255 mbinfo[mb_pos].cbp_c = 0xFF;
1256 } else {
1257 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1258 }
1259 sstate.has_left = true;
1260 mb_pos += 1;
1261 }
1262 if hdr0.deblock && (mb_y >= 1) {
1263 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_y - 1);
1264 }
1265 imode.update();
1266 }
1267 if hdr0.deblock {
1268 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_h - 1);
1269 }
1270 if !self.is_b {
1271 self.ipbs.add_frame(buf.clone());
1272 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1273 mem::swap(&mut self.mbinfo, &mut mbinfo);
1274 }
1275
1276 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1277 }
1278 pub fn flush(&mut self) {
1279 self.ipbs.clear();
1280 }
1281 }