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 + Send>, 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 + Send>, 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 + Send>,
732 mbinfo: Vec<RV34MBInfo>,
733 avg_buf: NAVideoBufferRef<u8>,
738 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP + Send>) -> 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;
1111 if self.ipbs.get_lastref().is_none() {
1112 return Err(DecoderError::MissingReference);
1116 if self.ipbs.get_lastref().is_none() {
1117 return Err(DecoderError::MissingReference);
1119 if self.ipbs.get_nextref().is_none() {
1120 return Err(DecoderError::MissingReference);
1125 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1126 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1127 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1128 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1129 if sstate.trb != 0 {
1130 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1131 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1133 self.ratio1 = 1 << 14 >> 1;
1134 self.ratio2 = 1 << 14 >> 1;
1136 //todo validate against ref frame
1138 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1139 let ret = supp.pool_u8.get_free();
1141 return Err(DecoderError::AllocError);
1143 let mut buf = ret.unwrap();
1144 if buf.get_info() != vinfo {
1146 supp.pool_u8.reset();
1147 supp.pool_u8.prealloc_video(vinfo, 4)?;
1148 let ret = supp.pool_u8.get_free();
1150 return Err(DecoderError::AllocError);
1156 sstate.has_top = false;
1159 sstate.set_idx = hdr0.set_idx;
1161 self.mvi.resize(mb_w, mb_h);
1162 for mb_y in 0..mb_h {
1164 sstate.has_left = false;
1165 for mb_x in 0..mb_w {
1167 if mb_pos == slice.end {
1168 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1169 validate!(slice.fits(&hdr0));
1174 sstate.has_top = false;
1175 sstate.has_left = false;
1176 sstate.set_idx = slice.set_idx;
1178 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1179 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1180 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1181 imode.set_mb_x(mb_x);
1182 let mbh = if is_intra {
1183 let is_i16 = br.read_bool()?;
1184 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1189 mbtype = MBType::Invalid;
1191 let mut hist = MBHist::new(hdr0.ftype);
1193 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1194 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1196 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1197 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1198 mbtype = hist.get_mbtype();
1200 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1203 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1206 if !mbh.mbtype.is_intra() {
1207 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1208 for i in 0..mbh.mbtype.get_num_mvs() {
1209 mvs[i] = decode_mv(&mut br)?;
1212 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1214 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1215 self.mvi.fill(mb_x, mb_y, true, mv_f);
1216 self.mvi.fill(mb_x, mb_y, false, mv_b);
1220 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1221 if mbh.mbtype == MBType::MBSkip {
1223 if mbh.skip_run > 0 {
1224 skip_run = mbh.skip_run;
1227 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1228 if mbh.mbtype == MBType::MBP16x16Mix {
1229 self.coderead.select_codes(true, q, slice.set_idx, true);
1231 cbp = self.coderead.decode_cbp(&mut br)?;
1234 if is_intra || mbh.mbtype.is_intra() {
1235 sstate.q_dc = bd.quant_dc(true, q);
1236 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1238 imode.fill_block(0);
1239 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1242 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1245 mbinfo[mb_pos].deblock = 0xFFFF;
1246 mbinfo[mb_pos].cbp_c = 0xFF;
1248 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1250 sstate.has_left = true;
1253 if hdr0.deblock && (mb_y >= 1) {
1254 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
1259 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
1262 self.ipbs.add_frame(buf.clone());
1263 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1264 mem::swap(&mut self.mbinfo, &mut mbinfo);
1267 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1269 pub fn flush(&mut self) {