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::*;
6 use nihav_core::data::GenericCache;
9 use super::rv34codes::*;
10 use super::rv34dsp::*;
13 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
16 const TR_SHIFT: u8 = 14;
17 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
19 impl RV34MVScale for MV {
20 fn scale(&self, trd: u16, trb: u16) -> (MV, MV) {
21 let ratio = ((trb as i32) << TR_SHIFT) / (trd as i32);
23 x: (((self.x as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16,
24 y: (((self.y as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16
26 let mv_b = mv_f - *self;
32 pub struct RV34SliceHeader {
44 impl RV34SliceHeader {
45 pub fn fits(&self, cmp: &RV34SliceHeader) -> bool {
46 (self.ftype == cmp.ftype) &&
47 (self.pts == cmp.pts) &&
48 (self.width == cmp.width) &&
49 (self.height == cmp.height)
54 #[derive(Debug,Clone,Copy,PartialEq)]
72 pub fn is_intra(self) -> bool {
73 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
75 pub fn is_16(self) -> bool {
76 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
78 pub fn is_intra_or_16(self) -> bool {
79 self.is_intra() || self.is_16()
81 pub fn get_num_mvs(self) -> usize {
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,
89 MBType::Invalid => unreachable!(),
92 pub fn is_fwd(self) -> bool {
94 MBType::MBP16x16 | MBType::MBP16x16Mix |
95 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
96 MBType::MBForward => true,
100 pub fn is_bwd(self) -> bool {
102 MBType::MBBidir | MBType::MBBackward => true,
106 pub fn has_mv_dir(self, fwd: bool) -> bool {
108 MBType::MBBidir => true,
109 MBType::MBForward if fwd => true,
110 MBType::MBBackward if !fwd => true,
114 pub fn is_nomv(self) -> bool {
116 MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
120 /*pub fn is_16x16(self) -> bool {
122 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
126 fn get_weight(self) -> usize {
128 MBType::MBIntra => 0,
129 MBType::MBIntra16 => 1,
130 MBType::MBSkip => unreachable!(),
131 MBType::MBP16x16 => 2,
132 MBType::MBP16x16Mix => 10,
133 MBType::MBP16x8 => 7,
134 MBType::MBP8x16 => 8,
136 MBType::MBDirect => 6,
137 MBType::MBBidir => 9,
138 MBType::MBForward => 4,
139 MBType::MBBackward => 5,
140 MBType::Invalid => unreachable!(),
145 const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
146 MBType::MBIntra, MBType::MBIntra16, MBType::MBP16x16, MBType::MBP8x8,
147 MBType::MBForward, MBType::MBBackward, MBType::MBDirect, MBType::MBP16x8,
148 MBType::MBP8x16, MBType::MBBidir, MBType::MBP16x16Mix,
151 #[derive(Clone,Copy)]
158 #[derive(Clone,Copy)]
159 pub struct RV34MBInfo {
163 pub cbp_c: u8, // for deblocking purposes
167 struct IntraModeState {
168 cache: GenericCache<i8>,
171 const RV34_INTRA_PRED4: [PredType4x4; 9] = [
172 PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
173 PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
174 PredType4x4::VerRight, PredType4x4::VerLeft,
175 PredType4x4::HorUp, PredType4x4::HorDown
178 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
179 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
182 impl IntraModeState {
183 fn new(mb_w: usize) -> Self {
184 let stride = 1 + mb_w * 4 + 1;
185 IntraModeState { cache: GenericCache::new(4, stride, -1) }
187 fn reset(&mut self) { self.cache.reset(); }
188 fn update(&mut self) { self.cache.update_row(); }
189 fn get_pos(&self, xpos: usize) -> usize {
190 self.cache.stride + 1 + xpos * 4
192 fn set_mb_x(&mut self, mb_x: usize) {
193 self.cache.xpos = self.get_pos(mb_x);
195 fn fill_block(&mut self, val: i8) {
196 let mut pos = self.cache.xpos;
199 self.cache.data[pos + j] = val;
201 pos += self.cache.stride;
204 fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
205 if !has_top && !has_left { return PredType8x8::DC128; }
206 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
209 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
210 PredType8x8::DC => PredType8x8::LeftDC,
213 } else if !has_left {
215 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
216 PredType8x8::DC => PredType8x8::TopDC,
222 fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
223 if !has_top && !has_left { return PredType8x8::DC128; }
224 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
225 im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
228 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
229 PredType8x8::DC => PredType8x8::LeftDC,
232 } else if !has_left {
234 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
235 PredType8x8::DC => PredType8x8::TopDC,
241 fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
242 let no_up = !has_top && (y == 0);
243 let no_left = !has_left && (x == 0);
244 if no_up && no_left { return PredType4x4::DC128; }
245 let no_down = !has_left || (x != 0) || (y == 3);
247 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
251 PredType4x4::Ver => PredType4x4::Hor,
252 PredType4x4::DC => PredType4x4::LeftDC,
257 PredType4x4::Hor => PredType4x4::Ver,
258 PredType4x4::DC => PredType4x4::TopDC,
259 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
265 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
266 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
267 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
274 fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
275 let no_up = !has_top && (y == 0);
276 let no_left = !has_left && (x == 0);
277 if no_up && no_left { return PredType4x4::DC128; }
278 let no_down = !has_left || (x != 0) || (y == 1);
280 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
284 PredType4x4::Ver => PredType4x4::Hor,
285 PredType4x4::DC => PredType4x4::LeftDC,
290 PredType4x4::Hor => PredType4x4::Ver,
291 PredType4x4::DC => PredType4x4::TopDC,
292 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
298 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
299 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
300 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
313 pub has_b: Vec<bool>,
314 pub has_f: Vec<bool>,
319 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
321 fn resize(&mut self, mb_w: usize, mb_h: usize) {
326 fn reset(&mut self) {
327 let size = self.w * self.h;
328 self.mv_f.truncate(0);
329 self.mv_f.resize(size, ZERO_MV);
330 self.mv_b.truncate(0);
331 self.mv_b.resize(size, ZERO_MV);
332 self.has_f.truncate(0);
333 self.has_f.resize(size >> 2, false);
334 self.has_b.truncate(0);
335 self.has_b.resize(size >> 2, false);
337 fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
338 let idx = mb_x * 2 + mb_y * 2 * self.w;
340 self.mv_f[idx + 0] = mv;
341 self.mv_f[idx + 1] = mv;
342 self.mv_f[idx + self.w + 0] = mv;
343 self.mv_f[idx + self.w + 1] = mv;
345 self.mv_b[idx + 0] = mv;
346 self.mv_b[idx + 1] = mv;
347 self.mv_b[idx + self.w + 0] = mv;
348 self.mv_b[idx + self.w + 1] = mv;
351 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
352 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
354 fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
355 if !has_top && !has_left { return ZERO_MV; }
356 let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
357 let top_mv = if has_top { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
358 let tr_add = if is16 { 2 } else { 1 };
361 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
363 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
367 MV::pred(left_mv, top_mv, tr_mv)
369 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 {
370 self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
372 fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
373 let mb_idx = mb_x + mb_y * (self.w >> 1);
374 self.has_f[mb_idx] = mbtype.is_fwd();
375 self.has_b[mb_idx] = mbtype.is_bwd();
376 if mbtype.is_nomv() {
377 self.fill(mb_x, mb_y, true, ZERO_MV);
378 self.fill(mb_x, mb_y, false, ZERO_MV);
382 self.fill(mb_x, mb_y, false, ZERO_MV);
383 } else if mbtype.is_bwd() {
384 self.fill(mb_x, mb_y, true, ZERO_MV);
386 let idx = mb_x * 2 + mb_y * 2 * self.w;
390 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
393 MBType::MBP16x16Mix => {
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.fill(mb_x, mb_y, true, new_mv);
399 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
400 let new_mv = mvs[0] + pred_mv;
401 self.mv_f[idx + 0] = new_mv;
402 self.mv_f[idx + 1] = new_mv;
404 let idx2 = idx + self.w;
405 let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
406 let new_mv = mvs[1] + pred_mv;
407 self.mv_f[idx2 + 0] = new_mv;
408 self.mv_f[idx2 + 1] = new_mv;
411 let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
412 let new_mv = mvs[0] + pred_mv;
413 self.mv_f[idx] = new_mv;
414 self.mv_f[idx + self.w] = new_mv;
416 let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
417 let new_mv = mvs[1] + pred_mv;
418 self.mv_f[idx + 1] = new_mv;
419 self.mv_f[idx + self.w + 1] = new_mv;
423 let mut has_top = sstate.has_top;
426 let has_left = (x > 0) || sstate.has_left;
427 let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
430 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
432 has_tl = if x == 0 { sstate.has_left } else { true };
434 let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
435 let new_mv = mvs[x + y * 2] + pred_mv;
436 self.mv_f[idx8 + x] = new_mv;
442 MBType::MBDirect => {
443 let mut cum_mv_f = ZERO_MV;
444 let mut cum_mv_b = ZERO_MV;
448 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
458 self.fill(mb_x, mb_y, true, cum_mv_f);
459 self.fill(mb_x, mb_y, false, cum_mv_b);
462 let pred_mv_f = ZERO_MV;
463 let new_mv = pred_mv_f + mvs[0];
464 self.fill(mb_x, mb_y, true, new_mv);
465 let pred_mv_b = ZERO_MV;
466 let new_mv = pred_mv_b + mvs[1];
467 self.fill(mb_x, mb_y, false, new_mv);
469 MBType::MBForward => {
470 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
471 let new_mv = mvs[0] + pred_mv;
472 self.fill(mb_x, mb_y, true, new_mv);
474 MBType::MBBackward => {
475 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
476 let new_mv = mvs[0] + pred_mv;
477 self.fill(mb_x, mb_y, false, new_mv);
482 pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
483 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
484 if fwd { self.mv_f[idx] }
485 else { self.mv_b[idx] }
487 fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
488 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
489 let off = if vert { self.w } else { 1 };
490 let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
491 let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
492 (diffx < -3) || (diffx > 3) || (diffy < -3) || (diffy > 3)
496 pub trait RV34BitstreamDecoder {
497 fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
498 fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
499 fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
500 fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
501 fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
505 fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize);
506 fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
507 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);
510 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
511 let num_slices = (src[0] as usize) + 1;
512 let ini_off = num_slices * 8 + 1;
515 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
517 let mut br = BitReader::new(&src[1..], ini_off - 1, BitReaderMode::BE);
519 for i in 0..num_slices {
521 let off = br.read(32)? as usize;
522 if (i == 0) && (off != 0) {
523 return Err(DecoderError::InvalidData);
525 if (i > 0) && (off <= offsets[i - 1]) {
526 return Err(DecoderError::InvalidData);
534 fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
535 validate!(slice_no < slice_offs.len());
536 br.seek((slice_offs[slice_no] * 8) as u32)?;
537 let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
538 if slice_no < slice_offs.len() - 1 {
539 let cur_pos = br.tell() as u32;
540 br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
541 let nhdr = bd.decode_slice_header(br, shdr.width, shdr.height)?;
543 validate!(nhdr.start > shdr.start);
544 shdr.end = nhdr.start;
546 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
551 const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
552 const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
554 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
555 let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
556 let mut idx: usize = 0;
557 while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
558 RV34_SLICE_START_BITS[idx]
561 const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
562 [ 0, 0 ], [ 2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
563 [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
564 [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
565 [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
568 const RV34_QUANT_TAB: [u16; 32] = [
569 60, 67, 76, 85, 96, 108, 121, 136,
570 152, 171, 192, 216, 242, 272, 305, 341,
571 383, 432, 481, 544, 606, 683, 767, 854,
572 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
575 const RV34_CHROMA_QUANT_DC: [u8; 32] = [
576 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
577 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
579 const RV34_CHROMA_QUANT_AC: [u8; 32] = [
580 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
581 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
584 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
586 let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
587 let qp = (q as i8) + diff;
588 validate!((qp > 0) && (qp < 32));
591 let qp = br.read(5)? as u8;
641 fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
642 fn add(&mut self, mbt: MBType) {
643 let mbt2 = match mbt {
644 MBType::MBSkip if self.is_p => MBType::MBP16x16,
645 MBType::MBSkip if !self.is_p => MBType::MBDirect,
648 self.hist[self.count] = mbt2;
651 fn get_mbtype(&self) -> MBType {
654 } else if self.count == 1 {
656 } else if self.count == 2 {
657 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
663 let mut w: [usize; 12] = [0; 12];
664 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
667 if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
668 if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
671 MBTYPE_FROM_WEIGHT[nz_idx]
676 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
677 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
678 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
682 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) {
683 dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
684 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
685 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
688 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) {
689 dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
690 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
691 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
694 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) {
696 let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
697 let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
698 let csize = if comp == 0 { size } else { size >> 1 };
699 let dstride = buf.get_stride(comp);
700 let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
701 let data = buf.get_data_mut().unwrap();
702 let dst: &mut [u8] = data.as_mut_slice();
704 let sstride = avg_buf.get_stride(comp);
705 let soffset = avg_buf.get_offset(comp);
706 let data = avg_buf.get_data();
707 let src: &[u8] = data.as_slice();
709 if ratio1 == ratio2 {
710 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
712 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
717 pub struct RV34Decoder {
720 dsp: Box<dyn RV34DSP>,
732 mbinfo: Vec<RV34MBInfo>,
733 avg_buf: NAVideoBufferRef<u8>,
738 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP>) -> Self {
739 let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
740 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
741 let vb = vt.get_vbuf();
742 let avg_buf = vb.unwrap();
745 coderead: RV34Codes::new(),
747 cdsp: RV34CommonDSP::new(),
748 ipbs: IPBShuffler::new(),
750 ref_mvi: MVInfo::new(),
753 last_ts: 0, next_ts: 0,
754 ratio1: 0, ratio2: 0,
760 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> {
762 let imode = br.read(2)? as i8;
763 im.fill_block(imode);
764 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
766 let dq = if !has_dq {
767 if !self.is_rv30 { !br.read_bool()? } else { false }
770 decode_dquant(br, q)?;
772 bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
773 Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
776 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> {
777 let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
778 validate!(hdr.mbtype != MBType::Invalid);
780 decode_dquant(br, q)?;
782 if hdr.mbtype.is_intra() {
783 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
788 fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
789 let mut cur_cbp = sstate.cbp;
791 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
792 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
793 let luma_set = if is_16 { 2 } else { 1 };
794 let mut coeffs16: [i16; 16] = [0; 16];
796 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
798 self.cdsp.transform16(&mut coeffs16);
800 self.cdsp.transform16_dc(&mut coeffs16);
803 let stride = buf.get_stride(0);
804 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
805 let data = buf.get_data_mut().unwrap();
806 let framebuf: &mut [u8] = data.as_mut_slice();
809 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
810 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
815 let mut coeffs: [i16; 16] = [0; 16];
817 if (cur_cbp & 1) != 0 {
818 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
823 coeffs[0] = coeffs16[x + y * 4];
825 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
826 let has_top = sstate.has_top || (y > 0);
827 let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
828 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
829 let i = offset + x * 4 - stride;
830 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
832 let i = offset + x * 4 - stride;
833 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
837 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
840 self.cdsp.transform(&mut coeffs);
842 self.cdsp.transform_dc(&mut coeffs);
844 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
847 offset += stride * 4;
850 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
851 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
854 let stride = buf.get_stride(comp);
855 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
856 let data = buf.get_data_mut().unwrap();
857 let framebuf: &mut [u8] = data.as_mut_slice();
859 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
860 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
864 let mut coeffs: [i16; 16] = [0; 16];
866 if (cur_cbp & 1) != 0 {
867 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
872 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
873 let has_top = sstate.has_top || (y > 0);
874 let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
875 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
876 let i = offset + x * 4 - stride;
877 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
879 let i = offset + x * 4 - stride;
880 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
884 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
887 self.cdsp.transform(&mut coeffs);
889 self.cdsp.transform_dc(&mut coeffs);
891 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
894 offset += stride * 4;
900 fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
901 let mb_x = sstate.mb_x;
902 let mb_y = sstate.mb_y;
904 MBType::MBP16x16 | MBType::MBP16x16Mix => {
905 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
906 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
907 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, mv, false);
910 MBType::MBForward => {
911 if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
912 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
913 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv, false);
916 MBType::MBBackward => {
917 if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
918 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
919 do_mc_16x16(&self.dsp, buf, bwdbuf, mb_x, mb_y, mv, false);
922 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
923 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
926 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
927 do_mc_8x8(&self.dsp, buf, prevbuf, mb_x, x, mb_y, y, mv, false);
932 MBType::MBSkip if !self.is_b => {
933 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
934 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
937 MBType::MBSkip | MBType::MBDirect => {
938 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
941 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
942 do_mc_8x8(&self.dsp, buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
943 do_mc_8x8(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
944 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
950 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
951 let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
952 let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
953 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv_f, false);
954 do_mc_16x16(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
955 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
961 fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
962 self.do_mc(buf, mbh, sstate);
964 let mut cur_cbp = sstate.cbp;
967 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
968 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
969 let luma_set = if is_16 { 2 } else { 0 };
970 let mut coeffs16: [i16; 16] = [0; 16];
972 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
974 self.cdsp.transform16(&mut coeffs16);
976 self.cdsp.transform16_dc(&mut coeffs16);
979 let stride = buf.get_stride(0);
980 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
981 let data = buf.get_data_mut().unwrap();
982 let framebuf: &mut [u8] = data.as_mut_slice();
986 let mut coeffs: [i16; 16] = [0; 16];
988 if (cur_cbp & 1) != 0 {
989 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
994 coeffs[0] = coeffs16[x + y * 4];
997 self.cdsp.transform(&mut coeffs);
999 self.cdsp.transform_dc(&mut coeffs);
1001 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1004 offset += stride * 4;
1008 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1010 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
1011 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
1014 let stride = buf.get_stride(comp);
1015 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
1016 let data = buf.get_data_mut().unwrap();
1017 let framebuf: &mut [u8] = data.as_mut_slice();
1020 let mut coeffs: [i16; 16] = [0; 16];
1022 if (cur_cbp & 1) != 0 {
1023 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
1028 self.cdsp.transform(&mut coeffs);
1030 self.cdsp.transform_dc(&mut coeffs);
1032 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1035 offset += stride * 4;
1040 fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut Vec<RV34MBInfo>) {
1041 let mbt = mbinfo[mb_pos].mbtype;
1042 let mut hmvmask = 0;
1043 let mut vmvmask = 0;
1047 let shift = x * 2 + y * 8;
1048 if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
1049 vmvmask |= 0x11 << shift;
1051 if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
1052 hmvmask |= 0x03 << shift;
1056 if !sstate.has_top { hmvmask &= !0x000F; }
1057 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1059 vmvmask |= (vmvmask & 0x4444) >> 1;
1060 hmvmask |= (hmvmask & 0x0F00) >> 4;
1061 if sstate.mb_x > 0 {
1062 mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
1066 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1069 if mbt.is_intra_or_16() {
1070 mbinfo[mb_pos].deblock = 0xFFFF;
1071 mbinfo[mb_pos].cbp_c = 0xFF;
1073 mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
1074 mbinfo[mb_pos].cbp_c = (mbinfo[mb_pos].cbp >> 16) as u8;
1078 pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
1079 let mut slice_offs: Vec<usize> = Vec::new();
1080 parse_slice_offsets(src, &mut slice_offs)?;
1081 let ini_off = slice_offs.len() * 8 + 1;
1083 let mut br = BitReader::new(&src[ini_off..], src.len() - ini_off, BitReaderMode::BE);
1084 let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
1085 validate!((hdr0.width != 0) && (hdr0.height != 0));
1086 self.width = hdr0.width;
1087 self.height = hdr0.height;
1088 let mb_w = (hdr0.width + 15) >> 4;
1089 let mb_h = (hdr0.height + 15) >> 4;
1090 let mut mb_pos: usize = 0;
1091 let mut slice = hdr0;
1092 let mut slice_no: usize = 1;
1093 let is_intra = hdr0.ftype == FrameType::I;
1094 let mut skip_run: usize = 0;
1095 let mut imode = IntraModeState::new(mb_w);
1096 let mut q = hdr0.quant;
1098 let mut sstate = SState::new();
1099 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1101 self.is_b = hdr0.ftype == FrameType::B;
1102 if hdr0.ftype != FrameType::B {
1103 self.last_ts = self.next_ts;
1104 self.next_ts = hdr0.pts;
1105 if self.last_ts > self.next_ts {
1106 self.base_ts += 1 << 13;
1109 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1110 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1111 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1112 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1113 if sstate.trb != 0 {
1114 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1115 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1117 self.ratio1 = 1 << 14 >> 1;
1118 self.ratio2 = 1 << 14 >> 1;
1120 //todo validate against ref frame
1122 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1123 let ret = supp.pool_u8.get_free();
1125 return Err(DecoderError::AllocError);
1127 let mut buf = ret.unwrap();
1128 if buf.get_info() != vinfo {
1130 supp.pool_u8.reset();
1131 supp.pool_u8.prealloc_video(vinfo, 4)?;
1132 let ret = supp.pool_u8.get_free();
1134 return Err(DecoderError::AllocError);
1140 sstate.has_top = false;
1143 sstate.set_idx = hdr0.set_idx;
1145 self.mvi.resize(mb_w, mb_h);
1146 for mb_y in 0..mb_h {
1148 sstate.has_left = false;
1149 for mb_x in 0..mb_w {
1151 if mb_pos == slice.end {
1152 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1153 validate!(slice.fits(&hdr0));
1158 sstate.has_top = false;
1159 sstate.has_left = false;
1160 sstate.set_idx = slice.set_idx;
1162 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1163 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1164 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1165 imode.set_mb_x(mb_x);
1166 let mbh = if is_intra {
1167 let is_i16 = br.read_bool()?;
1168 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1173 mbtype = MBType::Invalid;
1175 let mut hist = MBHist::new(hdr0.ftype);
1177 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1178 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1180 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1181 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1182 mbtype = hist.get_mbtype();
1184 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1187 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1190 if !mbh.mbtype.is_intra() {
1191 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1192 for i in 0..mbh.mbtype.get_num_mvs() {
1193 mvs[i] = decode_mv(&mut br)?;
1196 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1198 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1199 self.mvi.fill(mb_x, mb_y, true, mv_f);
1200 self.mvi.fill(mb_x, mb_y, false, mv_b);
1204 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1205 if mbh.mbtype == MBType::MBSkip {
1207 if mbh.skip_run > 0 {
1208 skip_run = mbh.skip_run;
1211 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1212 if mbh.mbtype == MBType::MBP16x16Mix {
1213 self.coderead.select_codes(true, q, slice.set_idx, true);
1215 cbp = self.coderead.decode_cbp(&mut br)?;
1218 if is_intra || mbh.mbtype.is_intra() {
1219 sstate.q_dc = bd.quant_dc(true, q);
1220 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1222 imode.fill_block(0);
1223 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1226 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1229 mbinfo[mb_pos].deblock = 0xFFFF;
1230 mbinfo[mb_pos].cbp_c = 0xFF;
1232 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1234 sstate.has_left = true;
1237 if hdr0.deblock && (mb_y >= 1) {
1238 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
1243 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
1246 self.ipbs.add_frame(buf.clone());
1247 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1248 mem::swap(&mut self.mbinfo, &mut mbinfo);
1251 Ok((NABufferType::Video(buf), hdr0.ftype, ts))