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, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
4 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
5 use nihav_core::io::intcode::*;
8 use super::rv34codes::*;
11 pub struct GenericCache<T: Copy> {
19 impl<T:Copy> GenericCache<T> {
20 pub fn new(height: usize, stride: usize, default: T) -> Self {
25 data: Vec::with_capacity((height + 1) * stride),
31 fn full_size(&self) -> usize { self.stride * (self.height + 1) }
32 pub fn reset(&mut self) {
33 self.data.truncate(0);
34 let size = self.full_size();
35 self.data.resize(size, self.default);
36 self.xpos = self.stride + 1;
38 pub fn update_row(&mut self) {
39 for i in 0..self.stride {
40 self.data[i] = self.data[self.height * self.stride + i];
42 self.data.truncate(self.stride);
43 let size = self.full_size();
44 self.data.resize(size, self.default);
45 self.xpos = self.stride + 1;
50 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
53 const TR_SHIFT: u8 = 14;
54 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
56 impl RV34MVScale for MV {
57 fn scale(&self, trd: u16, trb: u16) -> (MV, MV) {
58 let ratio = ((trb as i32) << TR_SHIFT) / (trd as i32);
60 x: (((self.x as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16,
61 y: (((self.y as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16
63 let mv_b = mv_f - *self;
69 pub struct RV34SliceHeader {
81 impl RV34SliceHeader {
82 pub fn fits(&self, cmp: &RV34SliceHeader) -> bool {
83 (self.ftype == cmp.ftype) &&
84 (self.pts == cmp.pts) &&
85 (self.width == cmp.width) &&
86 (self.height == cmp.height)
91 #[derive(Debug,Clone,Copy,PartialEq)]
109 pub fn is_intra(self) -> bool {
110 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
112 pub fn is_16(self) -> bool {
113 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
115 pub fn is_intra_or_16(self) -> bool {
116 self.is_intra() || self.is_16()
118 pub fn get_num_mvs(self) -> usize {
120 MBType::MBIntra | MBType::MBIntra16 |
121 MBType::MBSkip | MBType::MBDirect => 0,
122 MBType::MBP16x16 | MBType::MBP16x16Mix |
123 MBType::MBForward | MBType::MBBackward => 1,
124 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBBidir => 2,
126 MBType::Invalid => unreachable!(),
129 pub fn is_fwd(self) -> bool {
131 MBType::MBP16x16 | MBType::MBP16x16Mix |
132 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
133 MBType::MBForward => true,
137 pub fn is_bwd(self) -> bool {
139 MBType::MBBidir | MBType::MBBackward => true,
143 pub fn has_mv_dir(self, fwd: bool) -> bool {
145 MBType::MBBidir => true,
146 MBType::MBForward if fwd => true,
147 MBType::MBBackward if !fwd => true,
151 pub fn is_nomv(self) -> bool {
153 MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
157 /*pub fn is_16x16(self) -> bool {
159 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
163 fn get_weight(self) -> usize {
165 MBType::MBIntra => 0,
166 MBType::MBIntra16 => 1,
167 MBType::MBSkip => unreachable!(),
168 MBType::MBP16x16 => 2,
169 MBType::MBP16x16Mix => 10,
170 MBType::MBP16x8 => 7,
171 MBType::MBP8x16 => 8,
173 MBType::MBDirect => 6,
174 MBType::MBBidir => 9,
175 MBType::MBForward => 4,
176 MBType::MBBackward => 5,
177 MBType::Invalid => unreachable!(),
182 const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
183 MBType::MBIntra, MBType::MBIntra16, MBType::MBP16x16, MBType::MBP8x8,
184 MBType::MBForward, MBType::MBBackward, MBType::MBDirect, MBType::MBP16x8,
185 MBType::MBP8x16, MBType::MBBidir, MBType::MBP16x16Mix,
188 #[derive(Clone,Copy)]
195 #[derive(Clone,Copy)]
196 pub struct RV34MBInfo {
200 pub cbp_c: u8, // for deblocking purposes
204 struct IntraModeState {
205 cache: GenericCache<i8>,
208 const RV34_INTRA_PRED4: [PredType4x4; 9] = [
209 PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
210 PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
211 PredType4x4::VerRight, PredType4x4::VerLeft,
212 PredType4x4::HorUp, PredType4x4::HorDown
215 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
216 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
219 impl IntraModeState {
220 fn new(mb_w: usize) -> Self {
221 let stride = 1 + mb_w * 4 + 1;
222 IntraModeState { cache: GenericCache::new(4, stride, -1) }
224 fn reset(&mut self) { self.cache.reset(); }
225 fn update(&mut self) { self.cache.update_row(); }
226 fn get_pos(&self, xpos: usize) -> usize {
227 self.cache.stride + 1 + xpos * 4
229 fn set_mb_x(&mut self, mb_x: usize) {
230 self.cache.xpos = self.get_pos(mb_x);
232 fn fill_block(&mut self, val: i8) {
233 let mut pos = self.cache.xpos;
236 self.cache.data[pos + j] = val;
238 pos += self.cache.stride;
241 fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
242 if !has_top && !has_left { return PredType8x8::DC128; }
243 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
246 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
247 PredType8x8::DC => PredType8x8::LeftDC,
250 } else if !has_left {
252 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
253 PredType8x8::DC => PredType8x8::TopDC,
259 fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
260 if !has_top && !has_left { return PredType8x8::DC128; }
261 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
262 im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
265 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
266 PredType8x8::DC => PredType8x8::LeftDC,
269 } else if !has_left {
271 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
272 PredType8x8::DC => PredType8x8::TopDC,
278 fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
279 let no_up = !has_top && (y == 0);
280 let no_left = !has_left && (x == 0);
281 if no_up && no_left { return PredType4x4::DC128; }
282 let no_down = !has_left || (x != 0) || (y == 3);
284 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
288 PredType4x4::Ver => PredType4x4::Hor,
289 PredType4x4::DC => PredType4x4::LeftDC,
294 PredType4x4::Hor => PredType4x4::Ver,
295 PredType4x4::DC => PredType4x4::TopDC,
296 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
302 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
303 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
304 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
311 fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
312 let no_up = !has_top && (y == 0);
313 let no_left = !has_left && (x == 0);
314 if no_up && no_left { return PredType4x4::DC128; }
315 let no_down = !has_left || (x != 0) || (y == 1);
317 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
321 PredType4x4::Ver => PredType4x4::Hor,
322 PredType4x4::DC => PredType4x4::LeftDC,
327 PredType4x4::Hor => PredType4x4::Ver,
328 PredType4x4::DC => PredType4x4::TopDC,
329 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
335 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
336 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
337 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
350 pub has_b: Vec<bool>,
351 pub has_f: Vec<bool>,
356 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
358 fn resize(&mut self, mb_w: usize, mb_h: usize) {
363 fn reset(&mut self) {
364 let size = self.w * self.h;
365 self.mv_f.truncate(0);
366 self.mv_f.resize(size, ZERO_MV);
367 self.mv_b.truncate(0);
368 self.mv_b.resize(size, ZERO_MV);
369 self.has_f.truncate(0);
370 self.has_f.resize(size >> 2, false);
371 self.has_b.truncate(0);
372 self.has_b.resize(size >> 2, false);
374 fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
375 let idx = mb_x * 2 + mb_y * 2 * self.w;
377 self.mv_f[idx + 0] = mv;
378 self.mv_f[idx + 1] = mv;
379 self.mv_f[idx + self.w + 0] = mv;
380 self.mv_f[idx + self.w + 1] = mv;
382 self.mv_b[idx + 0] = mv;
383 self.mv_b[idx + 1] = mv;
384 self.mv_b[idx + self.w + 0] = mv;
385 self.mv_b[idx + self.w + 1] = mv;
388 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
389 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
391 fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
392 if !has_top && !has_left { return ZERO_MV; }
393 let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
394 let top_mv = if has_top { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
395 let tr_add = if is16 { 2 } else { 1 };
398 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
400 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
404 MV::pred(left_mv, top_mv, tr_mv)
406 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 {
407 self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
409 fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
410 let mb_idx = mb_x + mb_y * (self.w >> 1);
411 self.has_f[mb_idx] = mbtype.is_fwd();
412 self.has_b[mb_idx] = mbtype.is_bwd();
413 if mbtype.is_nomv() {
414 self.fill(mb_x, mb_y, true, ZERO_MV);
415 self.fill(mb_x, mb_y, false, ZERO_MV);
419 self.fill(mb_x, mb_y, false, ZERO_MV);
420 } else if mbtype.is_bwd() {
421 self.fill(mb_x, mb_y, true, ZERO_MV);
423 let idx = mb_x * 2 + mb_y * 2 * self.w;
427 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
430 MBType::MBP16x16Mix => {
431 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
432 let new_mv = mvs[0] + pred_mv;
433 self.fill(mb_x, mb_y, true, new_mv);
436 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
437 let new_mv = mvs[0] + pred_mv;
438 self.mv_f[idx + 0] = new_mv;
439 self.mv_f[idx + 1] = new_mv;
441 let idx2 = idx + self.w;
442 let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
443 let new_mv = mvs[1] + pred_mv;
444 self.mv_f[idx2 + 0] = new_mv;
445 self.mv_f[idx2 + 1] = new_mv;
448 let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
449 let new_mv = mvs[0] + pred_mv;
450 self.mv_f[idx] = new_mv;
451 self.mv_f[idx + self.w] = new_mv;
453 let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
454 let new_mv = mvs[1] + pred_mv;
455 self.mv_f[idx + 1] = new_mv;
456 self.mv_f[idx + self.w + 1] = new_mv;
460 let mut has_top = sstate.has_top;
463 let has_left = (x > 0) || sstate.has_left;
464 let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
467 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
469 has_tl = if x == 0 { sstate.has_left } else { true };
471 let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
472 let new_mv = mvs[x + y * 2] + pred_mv;
473 self.mv_f[idx8 + x] = new_mv;
479 MBType::MBDirect => {
480 let mut cum_mv_f = ZERO_MV;
481 let mut cum_mv_b = ZERO_MV;
485 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
495 self.fill(mb_x, mb_y, true, cum_mv_f);
496 self.fill(mb_x, mb_y, false, cum_mv_b);
499 let pred_mv_f = ZERO_MV;
500 let new_mv = pred_mv_f + mvs[0];
501 self.fill(mb_x, mb_y, true, new_mv);
502 let pred_mv_b = ZERO_MV;
503 let new_mv = pred_mv_b + mvs[1];
504 self.fill(mb_x, mb_y, false, new_mv);
506 MBType::MBForward => {
507 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
508 let new_mv = mvs[0] + pred_mv;
509 self.fill(mb_x, mb_y, true, new_mv);
511 MBType::MBBackward => {
512 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
513 let new_mv = mvs[0] + pred_mv;
514 self.fill(mb_x, mb_y, false, new_mv);
519 pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
520 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
521 if fwd { self.mv_f[idx] }
522 else { self.mv_b[idx] }
524 fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
525 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
526 let off = if vert { self.w } else { 1 };
527 let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
528 let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
529 (diffx < -3) || (diffx > 3) || (diffy < -3) || (diffy > 3)
533 pub trait RV34BitstreamDecoder {
534 fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
535 fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
536 fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
537 fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
538 fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
542 fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize);
543 fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
544 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);
547 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
548 let num_slices = (src[0] as usize) + 1;
549 let ini_off = num_slices * 8 + 1;
552 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
554 let mut br = BitReader::new(&src[1..], ini_off - 1, BitReaderMode::BE);
556 for i in 0..num_slices {
558 let off = br.read(32)? as usize;
559 if (i == 0) && (off != 0) {
560 return Err(DecoderError::InvalidData);
562 if (i > 0) && (off <= offsets[i - 1]) {
563 return Err(DecoderError::InvalidData);
571 fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
572 validate!(slice_no < slice_offs.len());
573 br.seek((slice_offs[slice_no] * 8) as u32)?;
574 let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
575 if slice_no < slice_offs.len() - 1 {
576 let cur_pos = br.tell() as u32;
577 br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
578 let nhdr = bd.decode_slice_header(br, shdr.width, shdr.height)?;
580 validate!(nhdr.start > shdr.start);
581 shdr.end = nhdr.start;
583 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
588 const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
589 const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
591 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
592 let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
593 let mut idx: usize = 0;
594 while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
595 RV34_SLICE_START_BITS[idx]
598 const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
599 [ 0, 0 ], [ 2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
600 [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
601 [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
602 [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
605 const RV34_QUANT_TAB: [u16; 32] = [
606 60, 67, 76, 85, 96, 108, 121, 136,
607 152, 171, 192, 216, 242, 272, 305, 341,
608 383, 432, 481, 544, 606, 683, 767, 854,
609 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
612 const RV34_CHROMA_QUANT_DC: [u8; 32] = [
613 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
614 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
616 const RV34_CHROMA_QUANT_AC: [u8; 32] = [
617 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
618 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
621 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
623 let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
624 let qp = (q as i8) + diff;
625 validate!((qp > 0) && (qp < 32));
628 let qp = br.read(5)? as u8;
678 fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
679 fn add(&mut self, mbt: MBType) {
680 let mbt2 = match mbt {
681 MBType::MBSkip if self.is_p => MBType::MBP16x16,
682 MBType::MBSkip if !self.is_p => MBType::MBDirect,
685 self.hist[self.count] = mbt2;
688 fn get_mbtype(&self) -> MBType {
691 } else if self.count == 1 {
693 } else if self.count == 2 {
694 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
700 let mut w: [usize; 12] = [0; 12];
701 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
704 if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
705 if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
708 MBTYPE_FROM_WEIGHT[nz_idx]
713 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
714 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
715 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
719 fn do_mc_16x16(dsp: &Box<dyn RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
720 dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
721 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
722 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
725 fn do_mc_8x8(dsp: &Box<dyn RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
726 dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
727 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
728 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
731 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) {
733 let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
734 let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
735 let csize = if comp == 0 { size } else { size >> 1 };
736 let dstride = buf.get_stride(comp);
737 let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
738 let data = buf.get_data_mut().unwrap();
739 let dst: &mut [u8] = data.as_mut_slice();
741 let sstride = avg_buf.get_stride(comp);
742 let soffset = avg_buf.get_offset(comp);
743 let data = avg_buf.get_data();
744 let src: &[u8] = data.as_slice();
746 if ratio1 == ratio2 {
747 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
749 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
754 pub struct RV34Decoder {
757 dsp: Box<dyn RV34DSP>,
769 mbinfo: Vec<RV34MBInfo>,
770 avg_buf: NAVideoBufferRef<u8>,
775 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP>) -> Self {
776 let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
777 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
778 let vb = vt.get_vbuf();
779 let avg_buf = vb.unwrap();
782 coderead: RV34Codes::new(),
784 cdsp: RV34CommonDSP::new(),
785 ipbs: IPBShuffler::new(),
787 ref_mvi: MVInfo::new(),
790 last_ts: 0, next_ts: 0,
791 ratio1: 0, ratio2: 0,
797 fn decode_mb_header_intra(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
799 let imode = br.read(2)? as i8;
800 im.fill_block(imode);
801 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
803 let dq = if !has_dq {
804 if !self.is_rv30 { !br.read_bool()? } else { false }
807 decode_dquant(br, q)?;
809 bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
810 Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
813 fn decode_mb_header_inter(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
814 let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
815 validate!(hdr.mbtype != MBType::Invalid);
817 decode_dquant(br, q)?;
819 if hdr.mbtype.is_intra() {
820 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
825 fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
826 let mut cur_cbp = sstate.cbp;
828 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
829 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
830 let luma_set = if is_16 { 2 } else { 1 };
831 let mut coeffs16: [i16; 16] = [0; 16];
833 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
835 self.cdsp.transform16(&mut coeffs16);
837 self.cdsp.transform16_dc(&mut coeffs16);
840 let stride = buf.get_stride(0);
841 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
842 let data = buf.get_data_mut().unwrap();
843 let framebuf: &mut [u8] = data.as_mut_slice();
846 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
847 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
852 let mut coeffs: [i16; 16] = [0; 16];
854 if (cur_cbp & 1) != 0 {
855 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
860 coeffs[0] = coeffs16[x + y * 4];
862 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
863 let has_top = sstate.has_top || (y > 0);
864 let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
865 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
866 let i = offset + x * 4 - stride;
867 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
869 let i = offset + x * 4 - stride;
870 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
874 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
877 self.cdsp.transform(&mut coeffs);
879 self.cdsp.transform_dc(&mut coeffs);
881 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
884 offset += stride * 4;
887 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
888 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
891 let stride = buf.get_stride(comp);
892 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
893 let data = buf.get_data_mut().unwrap();
894 let framebuf: &mut [u8] = data.as_mut_slice();
896 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
897 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
901 let mut coeffs: [i16; 16] = [0; 16];
903 if (cur_cbp & 1) != 0 {
904 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
909 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
910 let has_top = sstate.has_top || (y > 0);
911 let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
912 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
913 let i = offset + x * 4 - stride;
914 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
916 let i = offset + x * 4 - stride;
917 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
921 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
924 self.cdsp.transform(&mut coeffs);
926 self.cdsp.transform_dc(&mut coeffs);
928 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
931 offset += stride * 4;
937 fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
938 let mb_x = sstate.mb_x;
939 let mb_y = sstate.mb_y;
941 MBType::MBP16x16 | MBType::MBP16x16Mix => {
942 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
943 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
944 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, mv, false);
947 MBType::MBForward => {
948 if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
949 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
950 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv, false);
953 MBType::MBBackward => {
954 if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
955 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
956 do_mc_16x16(&self.dsp, buf, bwdbuf, mb_x, mb_y, mv, false);
959 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
960 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
963 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
964 do_mc_8x8(&self.dsp, buf, prevbuf, mb_x, x, mb_y, y, mv, false);
969 MBType::MBSkip if !self.is_b => {
970 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
971 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
974 MBType::MBSkip | MBType::MBDirect => {
975 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
978 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
979 do_mc_8x8(&self.dsp, buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
980 do_mc_8x8(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
981 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
987 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
988 let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
989 let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
990 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv_f, false);
991 do_mc_16x16(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
992 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
998 fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
999 self.do_mc(buf, mbh, sstate);
1001 let mut cur_cbp = sstate.cbp;
1004 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
1005 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
1006 let luma_set = if is_16 { 2 } else { 0 };
1007 let mut coeffs16: [i16; 16] = [0; 16];
1009 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
1011 self.cdsp.transform16(&mut coeffs16);
1013 self.cdsp.transform16_dc(&mut coeffs16);
1016 let stride = buf.get_stride(0);
1017 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
1018 let data = buf.get_data_mut().unwrap();
1019 let framebuf: &mut [u8] = data.as_mut_slice();
1023 let mut coeffs: [i16; 16] = [0; 16];
1025 if (cur_cbp & 1) != 0 {
1026 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
1031 coeffs[0] = coeffs16[x + y * 4];
1034 self.cdsp.transform(&mut coeffs);
1036 self.cdsp.transform_dc(&mut coeffs);
1038 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1041 offset += stride * 4;
1045 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1047 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
1048 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
1051 let stride = buf.get_stride(comp);
1052 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
1053 let data = buf.get_data_mut().unwrap();
1054 let framebuf: &mut [u8] = data.as_mut_slice();
1057 let mut coeffs: [i16; 16] = [0; 16];
1059 if (cur_cbp & 1) != 0 {
1060 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
1065 self.cdsp.transform(&mut coeffs);
1067 self.cdsp.transform_dc(&mut coeffs);
1069 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1072 offset += stride * 4;
1077 fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut Vec<RV34MBInfo>) {
1078 let mbt = mbinfo[mb_pos].mbtype;
1079 let mut hmvmask = 0;
1080 let mut vmvmask = 0;
1084 let shift = x * 2 + y * 8;
1085 if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
1086 vmvmask |= 0x11 << shift;
1088 if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
1089 hmvmask |= 0x03 << shift;
1093 if !sstate.has_top { hmvmask &= !0x000F; }
1094 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1096 vmvmask |= (vmvmask & 0x4444) >> 1;
1097 hmvmask |= (hmvmask & 0x0F00) >> 4;
1098 if sstate.mb_x > 0 {
1099 mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
1103 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1106 if mbt.is_intra_or_16() {
1107 mbinfo[mb_pos].deblock = 0xFFFF;
1108 mbinfo[mb_pos].cbp_c = 0xFF;
1110 mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
1111 mbinfo[mb_pos].cbp_c = (mbinfo[mb_pos].cbp >> 16) as u8;
1115 pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
1116 let mut slice_offs: Vec<usize> = Vec::new();
1117 parse_slice_offsets(src, &mut slice_offs)?;
1118 let ini_off = slice_offs.len() * 8 + 1;
1120 let mut br = BitReader::new(&src[ini_off..], src.len() - ini_off, BitReaderMode::BE);
1121 let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
1122 validate!((hdr0.width != 0) && (hdr0.height != 0));
1123 self.width = hdr0.width;
1124 self.height = hdr0.height;
1125 let mb_w = (hdr0.width + 15) >> 4;
1126 let mb_h = (hdr0.height + 15) >> 4;
1127 let mut mb_pos: usize = 0;
1128 let mut slice = hdr0;
1129 let mut slice_no: usize = 1;
1130 let is_intra = hdr0.ftype == FrameType::I;
1131 let mut skip_run: usize = 0;
1132 let mut imode = IntraModeState::new(mb_w);
1133 let mut q = hdr0.quant;
1135 let mut sstate = SState::new();
1136 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1138 self.is_b = hdr0.ftype == FrameType::B;
1139 if hdr0.ftype != FrameType::B {
1140 self.last_ts = self.next_ts;
1141 self.next_ts = hdr0.pts;
1142 if self.last_ts > self.next_ts {
1143 self.base_ts += 1 << 13;
1146 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1147 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1148 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1149 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1150 if sstate.trb != 0 {
1151 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1152 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1154 self.ratio1 = 1 << 14 >> 1;
1155 self.ratio2 = 1 << 14 >> 1;
1157 //todo validate against ref frame
1159 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1160 let ret = supp.pool_u8.get_free();
1162 return Err(DecoderError::AllocError);
1164 let mut buf = ret.unwrap();
1165 if buf.get_info() != vinfo {
1167 supp.pool_u8.reset();
1168 supp.pool_u8.prealloc_video(vinfo, 4)?;
1169 let ret = supp.pool_u8.get_free();
1171 return Err(DecoderError::AllocError);
1177 sstate.has_top = false;
1180 sstate.set_idx = hdr0.set_idx;
1182 self.mvi.resize(mb_w, mb_h);
1183 for mb_y in 0..mb_h {
1185 sstate.has_left = false;
1186 for mb_x in 0..mb_w {
1188 if mb_pos == slice.end {
1189 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1190 validate!(slice.fits(&hdr0));
1195 sstate.has_top = false;
1196 sstate.has_left = false;
1197 sstate.set_idx = slice.set_idx;
1199 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1200 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1201 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1202 imode.set_mb_x(mb_x);
1203 let mbh = if is_intra {
1204 let is_i16 = br.read_bool()?;
1205 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1210 mbtype = MBType::Invalid;
1212 let mut hist = MBHist::new(hdr0.ftype);
1214 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1215 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1217 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1218 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1219 mbtype = hist.get_mbtype();
1221 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1224 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1227 if !mbh.mbtype.is_intra() {
1228 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1229 for i in 0..mbh.mbtype.get_num_mvs() {
1230 mvs[i] = decode_mv(&mut br)?;
1233 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1235 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1236 self.mvi.fill(mb_x, mb_y, true, mv_f);
1237 self.mvi.fill(mb_x, mb_y, false, mv_b);
1241 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1242 if mbh.mbtype == MBType::MBSkip {
1244 if mbh.skip_run > 0 {
1245 skip_run = mbh.skip_run;
1248 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1249 if mbh.mbtype == MBType::MBP16x16Mix {
1250 self.coderead.select_codes(true, q, slice.set_idx, true);
1252 cbp = self.coderead.decode_cbp(&mut br)?;
1255 if is_intra || mbh.mbtype.is_intra() {
1256 sstate.q_dc = bd.quant_dc(true, q);
1257 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1259 imode.fill_block(0);
1260 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1263 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1266 mbinfo[mb_pos].deblock = 0xFFFF;
1267 mbinfo[mb_pos].cbp_c = 0xFF;
1269 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1271 sstate.has_left = true;
1274 if hdr0.deblock && (mb_y >= 1) {
1275 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
1280 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
1283 self.ipbs.add_frame(buf.clone());
1284 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1285 mem::swap(&mut self.mbinfo, &mut mbinfo);
1288 Ok((NABufferType::Video(buf), hdr0.ftype, ts))