]> git.nihav.org Git - nihav.git/blob - nihav-realmedia/src/codecs/rv3040.rs
vp5: fix chroma MV
[nihav.git] / nihav-realmedia / src / codecs / rv3040.rs
1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::{NABufferType, NAVideoInfo, NAVideoBuffer, NAVideoBufferRef, FrameType, alloc_video_buffer};
3 use nihav_core::codecs::{NADecoderSupport, 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;
7 use std::mem;
8
9 use super::rv34codes::*;
10 use super::rv34dsp::*;
11
12 trait RV34MVScale {
13 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
14 }
15
16 const TR_SHIFT: u8 = 14;
17 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
18
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);
22 let mv_f = MV {
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
25 };
26 let mv_b = mv_f - *self;
27 (mv_f, mv_b)
28 }
29 }
30
31 #[derive(Clone,Copy)]
32 pub struct RV34SliceHeader {
33 pub ftype: FrameType,
34 pub quant: u8,
35 pub pts: u16,
36 pub width: usize,
37 pub height: usize,
38 pub start: usize,
39 pub end: usize,
40 pub set_idx: usize,
41 pub deblock: bool,
42 }
43
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)
50 }
51 }
52
53 #[allow(dead_code)]
54 #[derive(Debug,Clone,Copy,PartialEq)]
55 pub enum MBType {
56 MBIntra,
57 MBIntra16,
58 MBSkip,
59 MBP16x16,
60 MBP16x16Mix,
61 MBP16x8,
62 MBP8x16,
63 MBP8x8,
64 MBDirect,
65 MBBidir,
66 MBForward,
67 MBBackward,
68 Invalid,
69 }
70
71 impl MBType {
72 pub fn is_intra(self) -> bool {
73 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
74 }
75 pub fn is_16(self) -> bool {
76 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
77 }
78 pub fn is_intra_or_16(self) -> bool {
79 self.is_intra() || self.is_16()
80 }
81 pub fn get_num_mvs(self) -> usize {
82 match self {
83 MBType::MBIntra | MBType::MBIntra16 |
84 MBType::MBSkip | MBType::MBDirect => 0,
85 MBType::MBP16x16 | MBType::MBP16x16Mix |
86 MBType::MBForward | MBType::MBBackward => 1,
87 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBBidir => 2,
88 MBType::MBP8x8 => 4,
89 MBType::Invalid => unreachable!(),
90 }
91 }
92 pub fn is_fwd(self) -> bool {
93 match self {
94 MBType::MBP16x16 | MBType::MBP16x16Mix |
95 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
96 MBType::MBForward => true,
97 _ => false,
98 }
99 }
100 pub fn is_bwd(self) -> bool {
101 match self {
102 MBType::MBBidir | MBType::MBBackward => true,
103 _ => false,
104 }
105 }
106 pub fn has_mv_dir(self, fwd: bool) -> bool {
107 match self {
108 MBType::MBBidir => true,
109 MBType::MBForward if fwd => true,
110 MBType::MBBackward if !fwd => true,
111 _ => false,
112 }
113 }
114 pub fn is_nomv(self) -> bool {
115 match self {
116 MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
117 _ => false,
118 }
119 }
120 /*pub fn is_16x16(self) -> bool {
121 match self {
122 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
123 _ => true,
124 }
125 }*/
126 fn get_weight(self) -> usize {
127 match self {
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,
135 MBType::MBP8x8 => 3,
136 MBType::MBDirect => 6,
137 MBType::MBBidir => 9,
138 MBType::MBForward => 4,
139 MBType::MBBackward => 5,
140 MBType::Invalid => unreachable!(),
141 }
142 }
143 }
144
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,
149 ];
150
151 #[derive(Clone,Copy)]
152 pub struct MBInfo {
153 pub mbtype: MBType,
154 pub skip_run: usize,
155 pub dquant: bool,
156 }
157
158 #[derive(Clone,Copy)]
159 pub struct RV34MBInfo {
160 pub mbtype: MBType,
161 pub cbp: u32,
162 pub deblock:u16,
163 pub cbp_c: u8, // for deblocking purposes
164 pub q: u8,
165 }
166
167 struct IntraModeState {
168 cache: GenericCache<i8>,
169 }
170
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
176 ];
177
178 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
179 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
180 ];
181
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) }
186 }
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
191 }
192 fn set_mb_x(&mut self, mb_x: usize) {
193 self.cache.xpos = self.get_pos(mb_x);
194 }
195 fn fill_block(&mut self, val: i8) {
196 let mut pos = self.cache.xpos;
197 for _ in 0..4 {
198 for j in 0..4 {
199 self.cache.data[pos + j] = val;
200 }
201 pos += self.cache.stride;
202 }
203 }
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];
207 if !has_top {
208 im = match im {
209 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
210 PredType8x8::DC => PredType8x8::LeftDC,
211 _ => im,
212 };
213 } else if !has_left {
214 im = match im {
215 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
216 PredType8x8::DC => PredType8x8::TopDC,
217 _ => im,
218 };
219 }
220 im
221 }
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 };
226 if !has_top {
227 im = match im {
228 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
229 PredType8x8::DC => PredType8x8::LeftDC,
230 _ => im,
231 };
232 } else if !has_left {
233 im = match im {
234 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
235 PredType8x8::DC => PredType8x8::TopDC,
236 _ => im,
237 };
238 }
239 im
240 }
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);
246
247 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
248
249 if no_up {
250 im = match im {
251 PredType4x4::Ver => PredType4x4::Hor,
252 PredType4x4::DC => PredType4x4::LeftDC,
253 _ => im,
254 };
255 } else if no_left {
256 im = match im {
257 PredType4x4::Hor => PredType4x4::Ver,
258 PredType4x4::DC => PredType4x4::TopDC,
259 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
260 _ => im,
261 };
262 }
263 if no_down {
264 im = match im {
265 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
266 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
267 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
268 _ => im,
269 };
270 }
271 im
272 }
273 //todo merge
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);
279
280 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
281
282 if no_up {
283 im = match im {
284 PredType4x4::Ver => PredType4x4::Hor,
285 PredType4x4::DC => PredType4x4::LeftDC,
286 _ => im,
287 };
288 } else if no_left {
289 im = match im {
290 PredType4x4::Hor => PredType4x4::Ver,
291 PredType4x4::DC => PredType4x4::TopDC,
292 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
293 _ => im,
294 };
295 }
296 if no_down {
297 im = match im {
298 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
299 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
300 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
301 _ => im,
302 };
303 }
304 im
305 }
306 }
307
308 pub struct MVInfo {
309 pub mv_b: Vec<MV>,
310 pub mv_f: Vec<MV>,
311 pub w: usize,
312 pub h: usize,
313 pub has_b: Vec<bool>,
314 pub has_f: Vec<bool>,
315 }
316
317 impl MVInfo {
318 fn new() -> Self {
319 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
320 }
321 fn resize(&mut self, mb_w: usize, mb_h: usize) {
322 self.w = mb_w * 2;
323 self.h = mb_h * 2;
324 self.reset();
325 }
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);
336 }
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;
339 if fwd {
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;
344 } else {
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;
349 }
350 }
351 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
352 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
353 }
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 };
359 let tr_mv;
360 if has_tr {
361 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
362 } else if has_tl {
363 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
364 } else {
365 tr_mv = left_mv;
366 }
367 MV::pred(left_mv, top_mv, tr_mv)
368 }
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)
371 }
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);
379 return;
380 }
381 if mbtype.is_fwd() {
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);
385 }
386 let idx = mb_x * 2 + mb_y * 2 * self.w;
387
388 match mbtype {
389 MBType::MBSkip => {
390 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
391 },
392 MBType::MBP16x16 |
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);
397 },
398 MBType::MBP16x8 => {
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;
403
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;
409 },
410 MBType::MBP8x16 => {
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;
415
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;
420 },
421 MBType::MBP8x8 => {
422 let mut idx8 = idx;
423 let mut has_top = sstate.has_top;
424 for y in 0..2 {
425 for x in 0..2 {
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 };
428 let has_tl;
429 if y == 0 {
430 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
431 } else {
432 has_tl = if x == 0 { sstate.has_left } else { true };
433 }
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;
437 }
438 has_top = true;
439 idx8 += self.w;
440 }
441 },
442 MBType::MBDirect => {
443 let mut cum_mv_f = ZERO_MV;
444 let mut cum_mv_b = ZERO_MV;
445 let mut idx8 = idx;
446 for _ in 0..2 {
447 for x in 0..2 {
448 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
449 cum_mv_f += mv_f;
450 cum_mv_b += mv_b;
451 }
452 idx8 += self.w;
453 }
454 cum_mv_f.x >>= 2;
455 cum_mv_f.y >>= 2;
456 cum_mv_b.x >>= 2;
457 cum_mv_b.y >>= 2;
458 self.fill(mb_x, mb_y, true, cum_mv_f);
459 self.fill(mb_x, mb_y, false, cum_mv_b);
460 },
461 MBType::MBBidir => {
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);
468 },
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);
473 },
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);
478 },
479 _ => {},
480 }
481 }
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] }
486 }
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)
493 }
494 }
495
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);
502 }
503
504 pub trait RV34DSP {
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);
508 }
509
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;
513 offsets.truncate(0);
514
515 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
516
517 let mut br = BitReader::new(&src[1..], ini_off - 1, BitReaderMode::BE);
518
519 for i in 0..num_slices {
520 br.skip(32)?;
521 let off = br.read(32)? as usize;
522 if (i == 0) && (off != 0) {
523 return Err(DecoderError::InvalidData);
524 }
525 if (i > 0) && (off <= offsets[i - 1]) {
526 return Err(DecoderError::InvalidData);
527 }
528 offsets.push(off);
529 }
530
531 Ok(())
532 }
533
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)?;
542 br.seek(cur_pos)?;
543 validate!(nhdr.start > shdr.start);
544 shdr.end = nhdr.start;
545 } else {
546 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
547 }
548 Ok(shdr)
549 }
550
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 ];
553
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]
559 }
560
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 ]
566 ];
567
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
573 ];
574
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
578 ];
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
582 ];
583
584 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
585 if br.read_bool()? {
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));
589 Ok(qp as u8)
590 } else {
591 let qp = br.read(5)? as u8;
592 Ok(qp)
593 }
594 }
595
596 pub struct SState {
597 pub mb_x: usize,
598 pub mb_y: usize,
599 pub mb_w: usize,
600 pub mb_h: usize,
601 pub cbp: u32,
602 pub q: u8,
603 pub q_dc: u8,
604 pub set_idx: usize,
605 pub has_left: bool,
606 pub has_top: bool,
607 pub has_tl: bool,
608 pub has_tr: bool,
609 pub trd: u16,
610 pub trb: u16,
611 }
612
613 impl SState {
614 fn new() -> Self {
615 Self {
616 mb_x: 0,
617 mb_y: 0,
618 mb_w: 0,
619 mb_h: 0,
620 cbp: 0,
621 q: 0,
622 q_dc: 0,
623 set_idx: 0,
624 has_left: false,
625 has_top: false,
626 has_tl: false,
627 has_tr: false,
628 trd: 0,
629 trb: 0,
630 }
631 }
632 }
633
634 struct MBHist {
635 is_p: bool,
636 hist: [MBType; 4],
637 count: usize,
638 }
639
640 impl MBHist {
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,
646 _ => mbt,
647 };
648 self.hist[self.count] = mbt2;
649 self.count += 1;
650 }
651 fn get_mbtype(&self) -> MBType {
652 if self.count == 0 {
653 MBType::MBIntra
654 } else if self.count == 1 {
655 self.hist[0]
656 } else if self.count == 2 {
657 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
658 self.hist[0]
659 } else {
660 self.hist[1]
661 }
662 } else {
663 let mut w: [usize; 12] = [0; 12];
664 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
665 let mut nz_idx = 0;
666 for i in 0..12 {
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; }
669 }
670
671 MBTYPE_FROM_WEIGHT[nz_idx]
672 }
673 }
674 }
675
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;
679 Ok(MV{ x, y })
680 }
681
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);
686 }
687
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);
692 }
693
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) {
695 for comp in 0..3 {
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();
703
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();
708
709 if ratio1 == ratio2 {
710 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
711 } else {
712 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
713 }
714 }
715 }
716
717 pub struct RV34Decoder {
718 is_rv30: bool,
719 coderead: RV34Codes,
720 dsp: Box<dyn RV34DSP + Send>,
721 cdsp: RV34CommonDSP,
722 width: usize,
723 height: usize,
724 ipbs: IPBShuffler,
725 mvi: MVInfo,
726 ref_mvi: MVInfo,
727 last_ts: u16,
728 next_ts: u16,
729 ratio1: u32,
730 ratio2: u32,
731 is_b: bool,
732 mbinfo: Vec<RV34MBInfo>,
733 avg_buf: NAVideoBufferRef<u8>,
734 base_ts: u64,
735 }
736
737 impl RV34Decoder {
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();
743 RV34Decoder {
744 is_rv30,
745 coderead: RV34Codes::new(),
746 dsp,
747 cdsp: RV34CommonDSP::new(),
748 ipbs: IPBShuffler::new(),
749 mvi: MVInfo::new(),
750 ref_mvi: MVInfo::new(),
751 mbinfo: Vec::new(),
752 width: 0, height: 0,
753 last_ts: 0, next_ts: 0,
754 ratio1: 0, ratio2: 0,
755 is_b: false,
756 avg_buf,
757 base_ts: 0,
758 }
759 }
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> {
761 if is_i16 {
762 let imode = br.read(2)? as i8;
763 im.fill_block(imode);
764 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
765 } else {
766 let dq = if !has_dq {
767 if !self.is_rv30 { !br.read_bool()? } else { false }
768 } else { false };
769 if dq {
770 decode_dquant(br, q)?;
771 }
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 })
774 }
775 }
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);
779 if hdr.dquant {
780 decode_dquant(br, q)?;
781 }
782 if hdr.mbtype.is_intra() {
783 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
784 }
785 Ok(hdr)
786 }
787
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;
790 {
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];
795 if is_16 {
796 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
797 if has_ac {
798 self.cdsp.transform16(&mut coeffs16);
799 } else {
800 self.cdsp.transform16_dc(&mut coeffs16);
801 }
802 }
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();
807
808 if is_16 {
809 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
810 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
811 }
812
813 for y in 0..4 {
814 for x in 0..4 {
815 let mut coeffs: [i16; 16] = [0; 16];
816 let has_ac;
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)?;
819 } else {
820 has_ac = false;
821 }
822 if is_16 {
823 coeffs[0] = coeffs16[x + y * 4];
824 } else {
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]]
831 } else if has_top {
832 let i = offset + x * 4 - stride;
833 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
834 } else {
835 [0; 4]
836 };
837 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
838 }
839 if has_ac {
840 self.cdsp.transform(&mut coeffs);
841 } else {
842 self.cdsp.transform_dc(&mut coeffs);
843 }
844 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
845 cur_cbp >>= 1;
846 }
847 offset += stride * 4;
848 }
849 }
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];
852 let chroma_set = 0;
853 for comp in 1..3 {
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();
858 if is_16 {
859 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
860 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
861 }
862 for y in 0..2 {
863 for x in 0..2 {
864 let mut coeffs: [i16; 16] = [0; 16];
865 let has_ac;
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)?;
868 } else {
869 has_ac = false;
870 }
871 if !is_16 {
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]]
878 } else if has_top {
879 let i = offset + x * 4 - stride;
880 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
881 } else {
882 [0; 4]
883 };
884 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
885 }
886 if has_ac {
887 self.cdsp.transform(&mut coeffs);
888 } else {
889 self.cdsp.transform_dc(&mut coeffs);
890 }
891 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
892 cur_cbp >>= 1;
893 }
894 offset += stride * 4;
895 }
896 }
897 Ok(())
898 }
899
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;
903 match mbh.mbtype {
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);
908 }
909 },
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);
914 }
915 },
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);
920 }
921 },
922 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
923 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
924 for y in 0..2 {
925 for x in 0..2 {
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);
928 }
929 }
930 }
931 },
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);
935 }
936 },
937 MBType::MBSkip | MBType::MBDirect => {
938 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
939 for y in 0..2 {
940 for x in 0..2 {
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);
945 }
946 }
947 }
948 },
949 MBType::MBBidir => {
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);
956 }
957 },
958 _ => {},
959 };
960 }
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);
963
964 let mut cur_cbp = sstate.cbp;
965
966 {
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];
971 if is_16 {
972 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
973 if has_ac {
974 self.cdsp.transform16(&mut coeffs16);
975 } else {
976 self.cdsp.transform16_dc(&mut coeffs16);
977 }
978 }
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();
983
984 for y in 0..4 {
985 for x in 0..4 {
986 let mut coeffs: [i16; 16] = [0; 16];
987 let has_ac;
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)?;
990 } else {
991 has_ac = false;
992 }
993 if is_16 {
994 coeffs[0] = coeffs16[x + y * 4];
995 }
996 if has_ac {
997 self.cdsp.transform(&mut coeffs);
998 } else {
999 self.cdsp.transform_dc(&mut coeffs);
1000 }
1001 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1002 cur_cbp >>= 1;
1003 }
1004 offset += stride * 4;
1005 }
1006 }
1007 if is_16 {
1008 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1009 }
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];
1012 let chroma_set = 1;
1013 for comp in 1..3 {
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();
1018 for _ in 0..2 {
1019 for x in 0..2 {
1020 let mut coeffs: [i16; 16] = [0; 16];
1021 let has_ac;
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)?;
1024 } else {
1025 has_ac = false;
1026 }
1027 if has_ac {
1028 self.cdsp.transform(&mut coeffs);
1029 } else {
1030 self.cdsp.transform_dc(&mut coeffs);
1031 }
1032 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1033 cur_cbp >>= 1;
1034 }
1035 offset += stride * 4;
1036 }
1037 }
1038 Ok(())
1039 }
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;
1044
1045 for y in 0..2 {
1046 for x in 0..2 {
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;
1050 }
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;
1053 }
1054 }
1055 }
1056 if !sstate.has_top { hmvmask &= !0x000F; }
1057 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1058 if self.is_rv30 {
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;
1063 }
1064 if sstate.has_top {
1065
1066 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1067 }
1068 }
1069 if mbt.is_intra_or_16() {
1070 mbinfo[mb_pos].deblock = 0xFFFF;
1071 mbinfo[mb_pos].cbp_c = 0xFF;
1072 } else {
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;
1075 }
1076 }
1077
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;
1082
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;
1097
1098 let mut sstate = SState::new();
1099 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1100
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;
1107 }
1108 }
1109 match hdr0.ftype {
1110 FrameType::P => {
1111 if self.ipbs.get_lastref().is_none() {
1112 return Err(DecoderError::MissingReference);
1113 }
1114 },
1115 FrameType::B => {
1116 if self.ipbs.get_lastref().is_none() {
1117 return Err(DecoderError::MissingReference);
1118 }
1119 if self.ipbs.get_nextref().is_none() {
1120 return Err(DecoderError::MissingReference);
1121 }
1122 },
1123 _ => {},
1124 };
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);
1132 } else {
1133 self.ratio1 = 1 << 14 >> 1;
1134 self.ratio2 = 1 << 14 >> 1;
1135 }
1136 //todo validate against ref frame
1137
1138 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1139 let ret = supp.pool_u8.get_free();
1140 if ret.is_none() {
1141 return Err(DecoderError::AllocError);
1142 }
1143 let mut buf = ret.unwrap();
1144 if buf.get_info() != vinfo {
1145 self.ipbs.clear();
1146 supp.pool_u8.reset();
1147 supp.pool_u8.prealloc_video(vinfo, 4)?;
1148 let ret = supp.pool_u8.get_free();
1149 if ret.is_none() {
1150 return Err(DecoderError::AllocError);
1151 }
1152 buf = ret.unwrap();
1153 }
1154
1155 sstate.q = q;
1156 sstate.has_top = false;
1157 sstate.mb_w = mb_w;
1158 sstate.mb_h = mb_h;
1159 sstate.set_idx = hdr0.set_idx;
1160
1161 self.mvi.resize(mb_w, mb_h);
1162 for mb_y in 0..mb_h {
1163 sstate.mb_y = mb_y;
1164 sstate.has_left = false;
1165 for mb_x in 0..mb_w {
1166 sstate.mb_x = mb_x;
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));
1170 q = slice.quant;
1171 slice_no += 1;
1172 imode.reset();
1173 sstate.q = q;
1174 sstate.has_top = false;
1175 sstate.has_left = false;
1176 sstate.set_idx = slice.set_idx;
1177 }
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)?
1185 } else {
1186 if skip_run == 0 {
1187 let mbtype;
1188 if self.is_rv30 {
1189 mbtype = MBType::Invalid;
1190 } else {
1191 let mut hist = MBHist::new(hdr0.ftype);
1192 if sstate.has_top {
1193 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1194 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1195 }
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();
1199 }
1200 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1201 } else {
1202 skip_run -= 1;
1203 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1204 }
1205 };
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)?;
1210 }
1211 if !self.is_b {
1212 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1213 } else {
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);
1217 }
1218 }
1219 let cbp;
1220 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1221 if mbh.mbtype == MBType::MBSkip {
1222 cbp = 0;
1223 if mbh.skip_run > 0 {
1224 skip_run = mbh.skip_run;
1225 }
1226 } else {
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);
1230 }
1231 cbp = self.coderead.decode_cbp(&mut br)?;
1232 }
1233 sstate.cbp = cbp;
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)?;
1237 } else {
1238 imode.fill_block(0);
1239 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1240 }
1241
1242 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1243 mbinfo.push(mi);
1244 if is_intra {
1245 mbinfo[mb_pos].deblock = 0xFFFF;
1246 mbinfo[mb_pos].cbp_c = 0xFF;
1247 } else {
1248 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1249 }
1250 sstate.has_left = true;
1251 mb_pos += 1;
1252 }
1253 if hdr0.deblock && (mb_y >= 1) {
1254 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
1255 }
1256 imode.update();
1257 }
1258 if hdr0.deblock {
1259 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
1260 }
1261 if !self.is_b {
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);
1265 }
1266
1267 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1268 }
1269 pub fn flush(&mut self) {
1270 self.ipbs.clear();
1271 }
1272 }