1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::{NABufferType, NAVideoInfo, NAVideoBuffer, NAVideoBufferRef, FrameType, alloc_video_buffer};
3 use nihav_core::codecs::{NADecoderSupport, DecoderError, DecoderResult};
4 use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
5 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
6 use nihav_core::io::intcode::*;
7 use nihav_codec_support::data::GenericCache;
10 use super::rv34codes::*;
11 use super::rv34dsp::*;
14 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
17 const TR_SHIFT: u8 = 14;
18 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
20 impl RV34MVScale for MV {
21 fn scale(&self, trd: u16, trb: u16) -> (MV, MV) {
22 let ratio = ((trb as i32) << TR_SHIFT) / (trd as i32);
24 x: (((self.x as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16,
25 y: (((self.y as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16
27 let mv_b = mv_f - *self;
33 pub struct RV34SliceHeader {
45 impl RV34SliceHeader {
46 pub fn fits(&self, cmp: &RV34SliceHeader) -> bool {
47 (self.ftype == cmp.ftype) &&
48 (self.pts == cmp.pts) &&
49 (self.width == cmp.width) &&
50 (self.height == cmp.height)
55 #[derive(Debug,Clone,Copy,PartialEq)]
73 pub fn is_intra(self) -> bool {
74 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
76 pub fn is_16(self) -> bool {
77 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
79 pub fn is_intra_or_16(self) -> bool {
80 self.is_intra() || self.is_16()
82 pub fn get_num_mvs(self) -> usize {
84 MBType::MBIntra | MBType::MBIntra16 |
85 MBType::MBSkip | MBType::MBDirect => 0,
86 MBType::MBP16x16 | MBType::MBP16x16Mix |
87 MBType::MBForward | MBType::MBBackward => 1,
88 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBBidir => 2,
90 MBType::Invalid => unreachable!(),
93 pub fn is_fwd(self) -> bool {
95 MBType::MBP16x16 | MBType::MBP16x16Mix |
96 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
97 MBType::MBForward => true,
101 pub fn is_bwd(self) -> bool {
103 MBType::MBBidir | MBType::MBBackward => true,
107 pub fn has_mv_dir(self, fwd: bool) -> bool {
109 MBType::MBBidir => true,
110 MBType::MBForward if fwd => true,
111 MBType::MBBackward if !fwd => true,
115 pub fn is_nomv(self) -> bool {
117 MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
121 /*pub fn is_16x16(self) -> bool {
123 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
127 fn get_weight(self) -> usize {
129 MBType::MBIntra => 0,
130 MBType::MBIntra16 => 1,
131 MBType::MBSkip => unreachable!(),
132 MBType::MBP16x16 => 2,
133 MBType::MBP16x16Mix => 10,
134 MBType::MBP16x8 => 7,
135 MBType::MBP8x16 => 8,
137 MBType::MBDirect => 6,
138 MBType::MBBidir => 9,
139 MBType::MBForward => 4,
140 MBType::MBBackward => 5,
141 MBType::Invalid => unreachable!(),
146 const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
147 MBType::MBIntra, MBType::MBIntra16, MBType::MBP16x16, MBType::MBP8x8,
148 MBType::MBForward, MBType::MBBackward, MBType::MBDirect, MBType::MBP16x8,
149 MBType::MBP8x16, MBType::MBBidir, MBType::MBP16x16Mix,
152 #[derive(Clone,Copy)]
159 #[derive(Clone,Copy)]
160 pub struct RV34MBInfo {
164 pub cbp_c: u8, // for deblocking purposes
168 struct IntraModeState {
169 cache: GenericCache<i8>,
172 const RV34_INTRA_PRED4: [PredType4x4; 9] = [
173 PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
174 PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
175 PredType4x4::VerRight, PredType4x4::VerLeft,
176 PredType4x4::HorUp, PredType4x4::HorDown
179 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
180 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
183 impl IntraModeState {
184 fn new(mb_w: usize) -> Self {
185 let stride = 1 + mb_w * 4 + 1;
186 IntraModeState { cache: GenericCache::new(4, stride, -1) }
188 fn reset(&mut self) { self.cache.reset(); }
189 fn update(&mut self) { self.cache.update_row(); }
190 fn get_pos(&self, xpos: usize) -> usize {
191 self.cache.stride + 1 + xpos * 4
193 fn set_mb_x(&mut self, mb_x: usize) {
194 self.cache.xpos = self.get_pos(mb_x);
196 fn fill_block(&mut self, val: i8) {
197 let mut pos = self.cache.xpos;
200 self.cache.data[pos + j] = val;
202 pos += self.cache.stride;
205 fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
206 if !has_top && !has_left { return PredType8x8::DC128; }
207 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
210 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
211 PredType8x8::DC => PredType8x8::LeftDC,
214 } else if !has_left {
216 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
217 PredType8x8::DC => PredType8x8::TopDC,
223 fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
224 if !has_top && !has_left { return PredType8x8::DC128; }
225 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
226 im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
229 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
230 PredType8x8::DC => PredType8x8::LeftDC,
233 } else if !has_left {
235 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
236 PredType8x8::DC => PredType8x8::TopDC,
242 fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
243 let no_up = !has_top && (y == 0);
244 let no_left = !has_left && (x == 0);
245 if no_up && no_left { return PredType4x4::DC128; }
246 let no_down = !has_left || (x != 0) || (y == 3);
248 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
252 PredType4x4::Ver => PredType4x4::Hor,
253 PredType4x4::DC => PredType4x4::LeftDC,
258 PredType4x4::Hor => PredType4x4::Ver,
259 PredType4x4::DC => PredType4x4::TopDC,
260 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
266 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
267 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
268 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
275 fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
276 let no_up = !has_top && (y == 0);
277 let no_left = !has_left && (x == 0);
278 if no_up && no_left { return PredType4x4::DC128; }
279 let no_down = !has_left || (x != 0) || (y == 1);
281 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
285 PredType4x4::Ver => PredType4x4::Hor,
286 PredType4x4::DC => PredType4x4::LeftDC,
291 PredType4x4::Hor => PredType4x4::Ver,
292 PredType4x4::DC => PredType4x4::TopDC,
293 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
299 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
300 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
301 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
314 pub has_b: Vec<bool>,
315 pub has_f: Vec<bool>,
320 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
322 fn resize(&mut self, mb_w: usize, mb_h: usize) {
327 fn reset(&mut self) {
328 let size = self.w * self.h;
329 self.mv_f.truncate(0);
330 self.mv_f.resize(size, ZERO_MV);
331 self.mv_b.truncate(0);
332 self.mv_b.resize(size, ZERO_MV);
333 self.has_f.truncate(0);
334 self.has_f.resize(size >> 2, false);
335 self.has_b.truncate(0);
336 self.has_b.resize(size >> 2, false);
338 fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
339 let idx = mb_x * 2 + mb_y * 2 * self.w;
341 self.mv_f[idx + 0] = mv;
342 self.mv_f[idx + 1] = mv;
343 self.mv_f[idx + self.w + 0] = mv;
344 self.mv_f[idx + self.w + 1] = mv;
346 self.mv_b[idx + 0] = mv;
347 self.mv_b[idx + 1] = mv;
348 self.mv_b[idx + self.w + 0] = mv;
349 self.mv_b[idx + self.w + 1] = mv;
352 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
353 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
355 fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
356 if !has_top && !has_left { return ZERO_MV; }
357 let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
358 let top_mv = if has_top { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
359 let tr_add = if is16 { 2 } else { 1 };
362 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
364 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
368 MV::pred(left_mv, top_mv, tr_mv)
370 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 {
371 self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
373 fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
374 let mb_idx = mb_x + mb_y * (self.w >> 1);
375 self.has_f[mb_idx] = mbtype.is_fwd();
376 self.has_b[mb_idx] = mbtype.is_bwd();
377 if mbtype.is_nomv() {
378 self.fill(mb_x, mb_y, true, ZERO_MV);
379 self.fill(mb_x, mb_y, false, ZERO_MV);
383 self.fill(mb_x, mb_y, false, ZERO_MV);
384 } else if mbtype.is_bwd() {
385 self.fill(mb_x, mb_y, true, ZERO_MV);
387 let idx = mb_x * 2 + mb_y * 2 * self.w;
391 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
394 MBType::MBP16x16Mix => {
395 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
396 let new_mv = mvs[0] + pred_mv;
397 self.fill(mb_x, mb_y, true, new_mv);
400 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
401 let new_mv = mvs[0] + pred_mv;
402 self.mv_f[idx + 0] = new_mv;
403 self.mv_f[idx + 1] = new_mv;
405 let idx2 = idx + self.w;
406 let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
407 let new_mv = mvs[1] + pred_mv;
408 self.mv_f[idx2 + 0] = new_mv;
409 self.mv_f[idx2 + 1] = new_mv;
412 let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
413 let new_mv = mvs[0] + pred_mv;
414 self.mv_f[idx] = new_mv;
415 self.mv_f[idx + self.w] = new_mv;
417 let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
418 let new_mv = mvs[1] + pred_mv;
419 self.mv_f[idx + 1] = new_mv;
420 self.mv_f[idx + self.w + 1] = new_mv;
424 let mut has_top = sstate.has_top;
427 let has_left = (x > 0) || sstate.has_left;
428 let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
431 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
433 has_tl = if x == 0 { sstate.has_left } else { true };
435 let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
436 let new_mv = mvs[x + y * 2] + pred_mv;
437 self.mv_f[idx8 + x] = new_mv;
443 MBType::MBDirect => {
444 let mut cum_mv_f = ZERO_MV;
445 let mut cum_mv_b = ZERO_MV;
449 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
459 self.fill(mb_x, mb_y, true, cum_mv_f);
460 self.fill(mb_x, mb_y, false, cum_mv_b);
463 let pred_mv_f = ZERO_MV;
464 let new_mv = pred_mv_f + mvs[0];
465 self.fill(mb_x, mb_y, true, new_mv);
466 let pred_mv_b = ZERO_MV;
467 let new_mv = pred_mv_b + mvs[1];
468 self.fill(mb_x, mb_y, false, new_mv);
470 MBType::MBForward => {
471 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
472 let new_mv = mvs[0] + pred_mv;
473 self.fill(mb_x, mb_y, true, new_mv);
475 MBType::MBBackward => {
476 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
477 let new_mv = mvs[0] + pred_mv;
478 self.fill(mb_x, mb_y, false, new_mv);
483 pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
484 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
485 if fwd { self.mv_f[idx] }
486 else { self.mv_b[idx] }
488 fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
489 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
490 let off = if vert { self.w } else { 1 };
491 let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
492 let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
493 (diffx < -3) || (diffx > 3) || (diffy < -3) || (diffy > 3)
497 pub trait RV34BitstreamDecoder {
498 fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
499 fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
500 fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
501 fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
502 fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
506 fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize);
507 fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
508 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);
511 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
512 let num_slices = (src[0] as usize) + 1;
513 let ini_off = num_slices * 8 + 1;
516 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
518 let mut br = BitReader::new(&src[1..ini_off], BitReaderMode::BE);
520 for i in 0..num_slices {
522 let off = br.read(32)? as usize;
523 if (i == 0) && (off != 0) {
524 return Err(DecoderError::InvalidData);
526 if (i > 0) && (off <= offsets[i - 1]) {
527 return Err(DecoderError::InvalidData);
535 fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
536 validate!(slice_no < slice_offs.len());
537 br.seek((slice_offs[slice_no] * 8) as u32)?;
538 let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
539 if slice_no < slice_offs.len() - 1 {
540 let cur_pos = br.tell() as u32;
541 br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
542 let nhdr = bd.decode_slice_header(br, shdr.width, shdr.height)?;
544 validate!(nhdr.start > shdr.start);
545 shdr.end = nhdr.start;
547 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
552 const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
553 const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
555 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
556 let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
557 let mut idx: usize = 0;
558 while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
559 RV34_SLICE_START_BITS[idx]
562 const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
563 [ 0, 0 ], [ 2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
564 [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
565 [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
566 [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
569 const RV34_QUANT_TAB: [u16; 32] = [
570 60, 67, 76, 85, 96, 108, 121, 136,
571 152, 171, 192, 216, 242, 272, 305, 341,
572 383, 432, 481, 544, 606, 683, 767, 854,
573 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
576 const RV34_CHROMA_QUANT_DC: [u8; 32] = [
577 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
578 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
580 const RV34_CHROMA_QUANT_AC: [u8; 32] = [
581 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
582 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
585 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
587 let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
588 let qp = (q as i8) + diff;
589 validate!((qp > 0) && (qp < 32));
592 let qp = br.read(5)? as u8;
642 fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
643 fn add(&mut self, mbt: MBType) {
644 let mbt2 = match mbt {
645 MBType::MBSkip if self.is_p => MBType::MBP16x16,
646 MBType::MBSkip if !self.is_p => MBType::MBDirect,
649 self.hist[self.count] = mbt2;
652 fn get_mbtype(&self) -> MBType {
655 } else if self.count == 1 {
657 } else if self.count == 2 {
658 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
664 let mut w: [usize; 12] = [0; 12];
665 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
668 if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
669 if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
672 MBTYPE_FROM_WEIGHT[nz_idx]
677 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
678 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
679 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
683 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) {
684 dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
685 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
686 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
689 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) {
690 dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
691 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
692 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
695 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) {
697 let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
698 let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
699 let csize = if comp == 0 { size } else { size >> 1 };
700 let dstride = buf.get_stride(comp);
701 let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
702 let data = buf.get_data_mut().unwrap();
703 let dst: &mut [u8] = data.as_mut_slice();
705 let sstride = avg_buf.get_stride(comp);
706 let soffset = avg_buf.get_offset(comp);
707 let data = avg_buf.get_data();
708 let src: &[u8] = data.as_slice();
710 if ratio1 == ratio2 {
711 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
713 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
718 pub struct RV34Decoder {
721 dsp: Box<dyn RV34DSP + Send>,
733 mbinfo: Vec<RV34MBInfo>,
734 avg_buf: NAVideoBufferRef<u8>,
739 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP + Send>) -> Self {
740 let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
741 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
742 let vb = vt.get_vbuf();
743 let avg_buf = vb.unwrap();
746 coderead: RV34Codes::new(),
748 cdsp: RV34CommonDSP::new(),
749 ipbs: IPBShuffler::new(),
751 ref_mvi: MVInfo::new(),
754 last_ts: 0, next_ts: 0,
755 ratio1: 0, ratio2: 0,
761 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> {
763 let imode = br.read(2)? as i8;
764 im.fill_block(imode);
765 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
767 let dq = if !has_dq {
768 if !self.is_rv30 { !br.read_bool()? } else { false }
771 decode_dquant(br, q)?;
773 bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
774 Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
777 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> {
778 let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
779 validate!(hdr.mbtype != MBType::Invalid);
781 decode_dquant(br, q)?;
783 if hdr.mbtype.is_intra() {
784 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
789 fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
790 let mut cur_cbp = sstate.cbp;
792 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
793 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
794 let luma_set = if is_16 { 2 } else { 1 };
795 let mut coeffs16: [i16; 16] = [0; 16];
797 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
799 self.cdsp.transform16(&mut coeffs16);
801 self.cdsp.transform16_dc(&mut coeffs16);
804 let stride = buf.get_stride(0);
805 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
806 let data = buf.get_data_mut().unwrap();
807 let framebuf: &mut [u8] = data.as_mut_slice();
810 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
811 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
816 let mut coeffs: [i16; 16] = [0; 16];
818 if (cur_cbp & 1) != 0 {
819 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
824 coeffs[0] = coeffs16[x + y * 4];
826 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
827 let has_top = sstate.has_top || (y > 0);
828 let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
829 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
830 let i = offset + x * 4 - stride;
831 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
833 let i = offset + x * 4 - stride;
834 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
838 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
841 self.cdsp.transform(&mut coeffs);
843 self.cdsp.transform_dc(&mut coeffs);
845 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
848 offset += stride * 4;
851 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
852 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
855 let stride = buf.get_stride(comp);
856 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
857 let data = buf.get_data_mut().unwrap();
858 let framebuf: &mut [u8] = data.as_mut_slice();
860 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
861 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
865 let mut coeffs: [i16; 16] = [0; 16];
867 if (cur_cbp & 1) != 0 {
868 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
873 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
874 let has_top = sstate.has_top || (y > 0);
875 let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
876 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
877 let i = offset + x * 4 - stride;
878 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
880 let i = offset + x * 4 - stride;
881 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
885 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
888 self.cdsp.transform(&mut coeffs);
890 self.cdsp.transform_dc(&mut coeffs);
892 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
895 offset += stride * 4;
901 fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
902 let mb_x = sstate.mb_x;
903 let mb_y = sstate.mb_y;
905 MBType::MBP16x16 | MBType::MBP16x16Mix => {
906 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
907 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
908 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, mv, false);
911 MBType::MBForward => {
912 if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
913 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
914 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv, false);
917 MBType::MBBackward => {
918 if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
919 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
920 do_mc_16x16(&self.dsp, buf, bwdbuf, mb_x, mb_y, mv, false);
923 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
924 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
927 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
928 do_mc_8x8(&self.dsp, buf, prevbuf, mb_x, x, mb_y, y, mv, false);
933 MBType::MBSkip if !self.is_b => {
934 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
935 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
938 MBType::MBSkip | MBType::MBDirect => {
939 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
942 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
943 do_mc_8x8(&self.dsp, buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
944 do_mc_8x8(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
945 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
951 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
952 let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
953 let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
954 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv_f, false);
955 do_mc_16x16(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
956 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
962 fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
963 self.do_mc(buf, mbh, sstate);
965 let mut cur_cbp = sstate.cbp;
968 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
969 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
970 let luma_set = if is_16 { 2 } else { 0 };
971 let mut coeffs16: [i16; 16] = [0; 16];
973 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
975 self.cdsp.transform16(&mut coeffs16);
977 self.cdsp.transform16_dc(&mut coeffs16);
980 let stride = buf.get_stride(0);
981 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
982 let data = buf.get_data_mut().unwrap();
983 let framebuf: &mut [u8] = data.as_mut_slice();
987 let mut coeffs: [i16; 16] = [0; 16];
989 if (cur_cbp & 1) != 0 {
990 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
995 coeffs[0] = coeffs16[x + y * 4];
998 self.cdsp.transform(&mut coeffs);
1000 self.cdsp.transform_dc(&mut coeffs);
1002 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1005 offset += stride * 4;
1009 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1011 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
1012 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
1015 let stride = buf.get_stride(comp);
1016 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
1017 let data = buf.get_data_mut().unwrap();
1018 let framebuf: &mut [u8] = data.as_mut_slice();
1021 let mut coeffs: [i16; 16] = [0; 16];
1023 if (cur_cbp & 1) != 0 {
1024 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
1029 self.cdsp.transform(&mut coeffs);
1031 self.cdsp.transform_dc(&mut coeffs);
1033 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1036 offset += stride * 4;
1041 fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut Vec<RV34MBInfo>) {
1042 let mbt = mbinfo[mb_pos].mbtype;
1043 let mut hmvmask = 0;
1044 let mut vmvmask = 0;
1048 let shift = x * 2 + y * 8;
1049 if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
1050 vmvmask |= 0x11 << shift;
1052 if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
1053 hmvmask |= 0x03 << shift;
1057 if !sstate.has_top { hmvmask &= !0x000F; }
1058 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1060 vmvmask |= (vmvmask & 0x4444) >> 1;
1061 hmvmask |= (hmvmask & 0x0F00) >> 4;
1062 if sstate.mb_x > 0 {
1063 mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
1067 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1070 if mbt.is_intra_or_16() {
1071 mbinfo[mb_pos].deblock = 0xFFFF;
1072 mbinfo[mb_pos].cbp_c = 0xFF;
1074 mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
1075 mbinfo[mb_pos].cbp_c = (mbinfo[mb_pos].cbp >> 16) as u8;
1079 pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
1080 let mut slice_offs: Vec<usize> = Vec::new();
1081 parse_slice_offsets(src, &mut slice_offs)?;
1082 let ini_off = slice_offs.len() * 8 + 1;
1084 let mut br = BitReader::new(&src[ini_off..], BitReaderMode::BE);
1085 let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
1086 validate!((hdr0.width != 0) && (hdr0.height != 0));
1087 self.width = hdr0.width;
1088 self.height = hdr0.height;
1089 let mb_w = (hdr0.width + 15) >> 4;
1090 let mb_h = (hdr0.height + 15) >> 4;
1091 let mut mb_pos: usize = 0;
1092 let mut slice = hdr0;
1093 let mut slice_no: usize = 1;
1094 let is_intra = hdr0.ftype == FrameType::I;
1095 let mut skip_run: usize = 0;
1096 let mut imode = IntraModeState::new(mb_w);
1097 let mut q = hdr0.quant;
1099 let mut sstate = SState::new();
1100 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1102 self.is_b = hdr0.ftype == FrameType::B;
1103 if hdr0.ftype != FrameType::B {
1104 self.last_ts = self.next_ts;
1105 self.next_ts = hdr0.pts;
1106 if self.last_ts > self.next_ts {
1107 self.base_ts += 1 << 13;
1112 if self.ipbs.get_lastref().is_none() {
1113 return Err(DecoderError::MissingReference);
1117 if self.ipbs.get_lastref().is_none() {
1118 return Err(DecoderError::MissingReference);
1120 if self.ipbs.get_nextref().is_none() {
1121 return Err(DecoderError::MissingReference);
1126 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1127 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1128 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1129 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1130 if sstate.trb != 0 {
1131 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1132 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1134 self.ratio1 = 1 << 14 >> 1;
1135 self.ratio2 = 1 << 14 >> 1;
1137 //todo validate against ref frame
1139 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1140 let ret = supp.pool_u8.get_free();
1142 return Err(DecoderError::AllocError);
1144 let mut buf = ret.unwrap();
1145 if buf.get_info() != vinfo {
1147 supp.pool_u8.reset();
1148 supp.pool_u8.prealloc_video(vinfo, 4)?;
1149 let ret = supp.pool_u8.get_free();
1151 return Err(DecoderError::AllocError);
1157 sstate.has_top = false;
1160 sstate.set_idx = hdr0.set_idx;
1162 self.mvi.resize(mb_w, mb_h);
1163 for mb_y in 0..mb_h {
1165 sstate.has_left = false;
1166 for mb_x in 0..mb_w {
1168 if mb_pos == slice.end {
1169 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1170 validate!(slice.fits(&hdr0));
1175 sstate.has_top = false;
1176 sstate.has_left = false;
1177 sstate.set_idx = slice.set_idx;
1179 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1180 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1181 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1182 imode.set_mb_x(mb_x);
1183 let mbh = if is_intra {
1184 let is_i16 = br.read_bool()?;
1185 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1190 mbtype = MBType::Invalid;
1192 let mut hist = MBHist::new(hdr0.ftype);
1194 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1195 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1197 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1198 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1199 mbtype = hist.get_mbtype();
1201 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1204 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1207 if !mbh.mbtype.is_intra() {
1208 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1209 for i in 0..mbh.mbtype.get_num_mvs() {
1210 mvs[i] = decode_mv(&mut br)?;
1213 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1215 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1216 self.mvi.fill(mb_x, mb_y, true, mv_f);
1217 self.mvi.fill(mb_x, mb_y, false, mv_b);
1221 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1222 if mbh.mbtype == MBType::MBSkip {
1224 if mbh.skip_run > 0 {
1225 skip_run = mbh.skip_run;
1228 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1229 if mbh.mbtype == MBType::MBP16x16Mix {
1230 self.coderead.select_codes(true, q, slice.set_idx, true);
1232 cbp = self.coderead.decode_cbp(&mut br)?;
1235 if is_intra || mbh.mbtype.is_intra() {
1236 sstate.q_dc = bd.quant_dc(true, q);
1237 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1239 imode.fill_block(0);
1240 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1243 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1246 mbinfo[mb_pos].deblock = 0xFFFF;
1247 mbinfo[mb_pos].cbp_c = 0xFF;
1249 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1251 sstate.has_left = true;
1254 if hdr0.deblock && (mb_y >= 1) {
1255 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
1260 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
1263 self.ipbs.add_frame(buf.clone());
1264 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1265 mem::swap(&mut self.mbinfo, &mut mbinfo);
1268 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1270 pub fn flush(&mut self) {