bedebc9ac2161641ddb6b9f41692cc64c1a40267
[nihav.git] / nihav-realmedia / src / codecs / rv60.rs
1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::{NADecoder, NADecoderSupport, DecoderError, DecoderResult, FrameSkipMode};
4 use nihav_core::options::*;
5 use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
6 use nihav_core::io::byteio::{MemoryReader,ByteReader};
7 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
8 use nihav_core::io::intcode::*;
9 use std::str::FromStr;
10
11 use super::rv60codes::*;
12 use super::rv60dsp::*;
13
14 struct UniqueList<A> {
15 list: [A; 4],
16 fill: usize,
17 max_size: usize,
18 }
19
20 impl<A:Copy+Default+PartialEq> UniqueList<A> {
21 fn new(max_size: usize) -> Self {
22 Self { list: [A::default(); 4], fill: 0, max_size }
23 }
24 fn add(&mut self, cand: A) {
25 if self.fill == self.max_size { return; }
26 let mut unique = true;
27 for el in self.list.iter().take(self.fill) {
28 if *el == cand {
29 unique = false;
30 break;
31 }
32 }
33 if unique {
34 self.list[self.fill] = cand;
35 self.fill += 1;
36 }
37 }
38 }
39
40 const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
41 const MAX_IMODE: u8 = 34;
42
43 #[derive(Clone,Copy,Debug)]
44 #[allow(dead_code)]
45 struct FrameHeader {
46 profile: u8,
47 ftype: FrameType,
48 qp: u8,
49 osvquant: u8,
50 ts: u32,
51 width: usize,
52 height: usize,
53 two_f_refs: bool,
54 qp_off_type: u8,
55 deblock: bool,
56 deblock_chroma: bool,
57 }
58
59 const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
60 impl FrameHeader {
61 fn read(br: &mut BitReader) -> DecoderResult<Self> {
62 let marker = br.read(2)?;
63 validate!(marker == 3);
64 let profile = br.read(2)? as u8;
65 validate!(profile == 0);
66 let _someval = br.read(4)?;
67 let ftypeid = br.read(2)? as usize;
68 let ftype = RV60_FRAME_TYPES[ftypeid];
69 let qp = br.read(6)? as u8;
70 let marker = br.read(1)?;
71 validate!(marker == 0);
72 let toolset = br.read(2)?;
73 validate!(toolset == 0);
74 let osvquant = br.read(2)? as u8;
75 let _some_flag = br.read_bool()?;
76 let _some_val = br.read(2)?;
77 let ts = br.read(24)?;
78 let width = ((br.read(11)? as usize) + 1) * 4;
79 let height = ((br.read(11)? as usize) + 0) * 4;
80 validate!(height > 0);
81 let _some_flag = br.read_bool()?;
82 let two_f_refs;
83 if ftype == FrameType::I {
84 //byte17 = 0
85 two_f_refs = false;
86 } else {
87 let flag = br.read_bool()?;
88 if flag { // untested
89 br.skip(1)?;
90 br.skip(1)?;
91 br.skip(1)?;
92 }
93 //byte17 = flag?
94 two_f_refs = br.read_bool()?;
95 }
96 // if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
97 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
98 let chroma_qp_diff = br.read(1)?;
99 validate!(chroma_qp_diff == 0);
100 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
101 let deblock = br.read_bool()?;
102 let deblock_chroma = deblock && !br.read_bool()?;
103 if br.read_bool()? {
104 let custom_msg_hdr_len = br.read(2)? as usize;
105 if custom_msg_hdr_len != 0 {
106 for i in 0..custom_msg_hdr_len {
107 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
108 }
109 }
110 }
111
112 Ok(FrameHeader {
113 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
114 deblock, deblock_chroma,
115 })
116 }
117 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
118 let nslices = self.get_height_cu();
119 let nbits = (br.read(5)? as u8) + 1;
120 validate!(nbits < 32);
121 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
122 for _ in 0..nslices {
123 let sign = br.read_bool()?;
124 signs.push(sign);
125 }
126 validate!(signs[0]);
127 sizes.clear();
128 let mut sum = 0;
129 let first_size = br.read(nbits)? as usize;
130 validate!(first_size > 0);
131 sum += first_size;
132 let mut lastsize = first_size;
133 sizes.push(first_size);
134 for i in 1..nslices {
135 let diff = br.read(nbits)? as isize;
136 let size;
137 if signs[i] {
138 let sum = (lastsize as isize).checked_add(diff);
139 validate!(sum.is_some());
140 size = sum.unwrap() as usize;
141 } else {
142 let sum = (lastsize as isize).checked_sub(diff);
143 validate!(sum.is_some());
144 size = sum.unwrap() as usize;
145 }
146 sizes.push(size);
147 sum += size;
148 lastsize = size;
149 }
150 br.align();
151 if ((br.left() >> 3) as usize) != sum {
152 println!(" left {} / {}", br.left() >> 3, sum);
153 }
154 validate!((br.left() >> 3) >= (sum as isize));
155 Ok(())
156 }
157 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
158 match self.qp_off_type {
159 0 => Ok(0),
160 1 => {
161 let val = br.read_code(UintCodeType::Unary012)?;
162 if val != 2 {
163 Ok(val as i8)
164 } else {
165 Ok(-1)
166 }
167 },
168 _ => {
169 if br.read(1)? == 0 {
170 Ok(0)
171 } else {
172 let val = br.read(2)? as i8;
173 if (val & 2) == 0 {
174 Ok(val + 1)
175 } else {
176 Ok(-((val & 1) + 1))
177 }
178 }
179 },
180 }
181 }
182 fn get_width_cu(&self) -> usize {
183 (self.width + 63) >> 6
184 }
185 fn get_height_cu(&self) -> usize {
186 (self.height + 63) >> 6
187 }
188 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
189 if (ypos + dy) == 0 { return false; }
190 let xpos2 = xpos + dx;
191 if (xpos2 + size) > self.width { return false; }
192 true
193 }
194 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
195 if (ypos + dy) == 0 { return false; }
196 let xpos2 = xpos + dx;
197 if (xpos2 + size * 2) > self.width { return false; }
198 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
199 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
200 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
201 }
202 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
203 if (xpos + dx) == 0 { return false; }
204 let ypos2 = ypos + dy;
205 if (ypos2 + size) > self.height { return false; }
206 true
207 }
208 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
209 if (xpos + dx) == 0 { return false; }
210 let ypos2 = ypos + dy;
211 if (ypos2 + size * 2) > self.height { return false; }
212 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
213 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
214 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
215 }
216 }
217
218 const RV60_BLOCK_LOG2: [u8; 65] = [
219 0,
220 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
224 ];
225 const RV60_AVAIL_MASK: [u8; 64] = [
226 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0xF,
227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
230 ];
231
232 #[derive(Clone,Copy,PartialEq,Debug)]
233 enum CUType {
234 Intra,
235 InterMV,
236 Skip,
237 InterNoMV,
238 }
239
240 impl Default for CUType {
241 fn default() -> Self { CUType::Intra }
242 }
243
244 const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
245
246 #[derive(Clone,Copy,PartialEq,Debug)]
247 enum PUType {
248 Full,
249 N2Hor,
250 N2Ver,
251 Quarters,
252 N4Hor,
253 N34Hor,
254 N4Ver,
255 N34Ver,
256 }
257
258 const RV60_PU_TYPES: [PUType; 8] = [
259 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
260 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
261 ];
262
263 impl PUType {
264 fn get_num_mvs(self) -> usize {
265 match self {
266 PUType::Full => 1,
267 PUType::Quarters => 4,
268 _ => 2,
269 }
270 }
271 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
272 let mv_size = size >> 2;
273 match self {
274 PUType::Full => (mv_size, mv_size),
275 PUType::N2Hor => (mv_size, mv_size >> 1),
276 PUType::N2Ver => (mv_size >> 1, mv_size),
277 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
278 PUType::N4Hor => {
279 if part_no == 0 {
280 (mv_size, mv_size >> 2)
281 } else {
282 (mv_size, (3 * mv_size) >> 2)
283 }
284 },
285 PUType::N34Hor => {
286 if part_no == 0 {
287 (mv_size, (3 * mv_size) >> 2)
288 } else {
289 (mv_size, mv_size >> 2)
290 }
291 },
292 PUType::N4Ver => {
293 if part_no == 0 {
294 ( mv_size >> 2, mv_size)
295 } else {
296 ((3 * mv_size) >> 2, mv_size)
297 }
298 },
299 PUType::N34Ver => {
300 if part_no == 0 {
301 ((3 * mv_size) >> 2, mv_size)
302 } else {
303 ( mv_size >> 2, mv_size)
304 }
305 },
306 }
307 }
308 fn has_hor_split(self) -> bool {
309 matches!(self, PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters)
310 }
311 fn has_ver_split(self) -> bool {
312 matches!(self, PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters)
313 }
314 }
315
316 impl Default for PUType {
317 fn default() -> Self { PUType::Full }
318 }
319
320 #[derive(Clone,Copy,Debug)]
321 enum IntraMode {
322 Index(u8),
323 Mode(u8),
324 DC64,
325 Plane64,
326 }
327
328 #[derive(Clone,Copy,PartialEq,Debug)]
329 enum TransformType {
330 None,
331 T4X4,
332 T8X8,
333 T16X16,
334 }
335
336 impl Default for TransformType {
337 fn default() -> Self { TransformType::None }
338 }
339
340 #[derive(Clone,Copy,PartialEq,Debug)]
341 enum MVRef {
342 None,
343 Ref0,
344 Ref1,
345 BRef,
346 Ref0AndBRef,
347 Skip0,
348 Skip1,
349 Skip2,
350 Skip3,
351 }
352
353 const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
354
355 impl MVRef {
356 fn get_skip_mv_num(self) -> usize {
357 match self {
358 MVRef::Skip1 => 1,
359 MVRef::Skip2 => 2,
360 MVRef::Skip3 => 3,
361 _ => 0,
362 }
363 }
364 fn is_ref0(self) -> bool {
365 matches!(self, MVRef::Ref0 | MVRef::Ref0AndBRef)
366 }
367 fn is_fwd(self) -> bool {
368 matches!(self, MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef)
369 }
370 fn is_bwd(self) -> bool {
371 matches!(self, MVRef::BRef | MVRef::Ref0AndBRef)
372 }
373 }
374
375 #[derive(Clone,Copy,PartialEq,Debug)]
376 struct MVInfo {
377 f_mv: MV,
378 b_mv: MV,
379 mvref: MVRef,
380 }
381
382 impl MVInfo {
383 fn is_some(&self) -> bool { self.mvref != MVRef::None }
384 fn matches_fwd(&self, mvref: MVRef) -> bool {
385 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
386 }
387 fn matches_bwd(&self, mvref: MVRef) -> bool {
388 self.mvref.is_bwd() && mvref.is_bwd()
389 }
390 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
391 if self.mvref != other.mvref { return true; }
392 let mut mvdiff = 0;
393 if self.mvref.is_fwd() {
394 let diff = self.f_mv - other.f_mv;
395 mvdiff += diff.x.abs() + diff.y.abs();
396 }
397 if self.mvref.is_bwd() {
398 let diff = self.b_mv - other.b_mv;
399 mvdiff += diff.x.abs() + diff.y.abs();
400 }
401 mvdiff > 4
402 }
403 }
404
405 impl Default for MVInfo {
406 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
407 }
408
409 #[derive(Clone,Copy,Debug)]
410 struct CBHeader {
411 cu_type: CUType,
412 pu_type: PUType,
413 ttype: TransformType,
414 imode: [IntraMode; 4],
415 mv: [MVInfo; 4],
416 }
417
418 impl CBHeader {
419 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
420 let cu_type;
421 let pu_type;
422 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
423 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
424 if ftype == FrameType::I {
425 cu_type = CUType::Intra;
426 } else {
427 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
428 }
429 match cu_type {
430 CUType::Intra => {
431 if (size == 8) && br.read_bool()? {
432 pu_type = PUType::Quarters;
433 } else {
434 pu_type = PUType::Full;
435 }
436 if pu_type == PUType::Quarters {
437 for i in 0..4 {
438 imode[i] = CBHeader::read_intra_mode(br)?;
439 }
440 } else if size <= 32 {
441 imode[0] = CBHeader::read_intra_mode(br)?;
442 } else {
443 if !br.read_bool()? {
444 imode[0] = IntraMode::DC64;
445 } else {
446 imode[0] = IntraMode::Plane64;
447 }
448 }
449 },
450 CUType::InterMV => {
451 let bits = if size == 8 { 2 } else { 3 };
452 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
453 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
454 },
455 _ => {
456 pu_type = PUType::Full;
457 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
458 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
459 },
460 };
461 let ttype;
462 if cu_type == CUType::Skip {
463 ttype = TransformType::None;
464 } else if size >= 32 {
465 ttype = TransformType::T16X16;
466 } else if size == 16 {
467 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
468 ttype = TransformType::T16X16;
469 } else {
470 ttype = TransformType::T4X4;
471 }
472 } else {
473 if pu_type == PUType::Full {
474 ttype = TransformType::T8X8;
475 } else {
476 ttype = TransformType::T4X4;
477 }
478 }
479 Ok(Self {
480 cu_type, pu_type, ttype, imode, mv,
481 })
482 }
483 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
484 if br.read_bool()? {
485 let idx = br.read_code(UintCodeType::Unary012)? as u8;
486 Ok(IntraMode::Index(idx))
487 } else {
488 let mode = br.read(5)? as u8;
489 Ok(IntraMode::Mode(mode))
490 }
491 }
492 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
493 let mv_count = pu_type.get_num_mvs();
494 for i in 0..mv_count {
495 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
496 }
497 Ok(())
498 }
499 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
500 let mut f_mv = ZERO_MV;
501 let mut b_mv = ZERO_MV;
502 let mvref;
503 if ftype != FrameType::B {
504 if two_f_refs && br.read_bool()? {
505 mvref = MVRef::Ref1;
506 } else {
507 mvref = MVRef::Ref0;
508 }
509 f_mv = CBHeader::read_mv(br)?;
510 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
511 } else {
512 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
513 if !br.read_bool()? {
514 mvref = MVRef::Ref0;
515 f_mv = CBHeader::read_mv(br)?;
516 } else {
517 mvref = MVRef::BRef;
518 b_mv = CBHeader::read_mv(br)?;
519 }
520 } else {
521 mvref = MVRef::Ref0AndBRef;
522 f_mv = CBHeader::read_mv(br)?;
523 b_mv = CBHeader::read_mv(br)?;
524 }
525 Ok(MVInfo { f_mv, b_mv, mvref })
526 }
527 }
528 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
529 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
530 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
531 Ok(MV { x, y })
532 }
533 }
534
535 #[derive(Clone,Copy,Default)]
536 struct PUInfo {
537 cu_type: CUType,
538 ttype: TransformType,
539 }
540
541 impl PUInfo {
542 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
543 }
544
545 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
546
547 #[derive(Clone,Copy,Default)]
548 struct BlockInfo {
549 mv: MVInfo,
550 imode: u8,
551 }
552
553 struct DeblockInfo {
554 left_str: Vec<u8>,
555 top_str: Vec<u8>,
556 stride: usize,
557 }
558
559 impl DeblockInfo {
560 fn new() -> Self {
561 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
562 }
563 fn reinit(&mut self, w: usize, h: usize) {
564 self.left_str.clear();
565 self.top_str.clear();
566 self.stride = w >> 2;
567 let size = self.stride * (h >> 2);
568 self.left_str.resize(size, 0);
569 self.top_str.resize(size, 0);
570 }
571 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
572 let pos = self.get_pos(xpos, ypos);
573 let dsize = size >> 2;
574 let dval = (q << 2) | strength;
575 for x in 0..dsize {
576 self.top_str[pos + x] = dval;
577 }
578 for y in 0..dsize {
579 self.left_str[pos + y * self.stride] = dval;
580 }
581 }
582 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
583 (xpos >> 2) + (ypos >> 2) * self.stride
584 }
585 fn get_top_strength(&self, pos: usize) -> u8 {
586 self.top_str[pos] & 3
587 }
588 fn get_left_strength(&self, pos: usize) -> u8 {
589 self.left_str[pos] & 3
590 }
591 fn set_top_strength(&mut self, pos: usize, str: u8) {
592 self.top_str[pos] |= str;
593 }
594 fn set_left_strength(&mut self, pos: usize, str: u8) {
595 self.left_str[pos] |= str;
596 }
597 }
598
599 struct RealVideo60Decoder {
600 info: NACodecInfoRef,
601 cbs: RV60Codebooks,
602 ipbs: IPBShuffler,
603 dsp: RV60DSP,
604 ipred: IntraPredContext,
605 skip_mode: FrameSkipMode,
606
607 avg_buf: NAVideoBufferRef<u8>,
608
609 y_coeffs: [i16; 16 * 16],
610 u_coeffs: [i16; 8 * 8],
611 v_coeffs: [i16; 8 * 8],
612 qp: u8,
613 sel_qp: u8,
614
615 cu_splits: Vec<bool>,
616 coded_blk: [bool; 64],
617 dblk: DeblockInfo,
618
619 pu_info: Vec<PUInfo>,
620 pu_stride: usize,
621 pu_pos: usize,
622
623 blk_info: Vec<BlockInfo>,
624 blk_stride: usize,
625 blk_pos: usize,
626
627 xpos: usize,
628 ypos: usize,
629
630 ts_scale: u64,
631 ref0_pts: u64,
632 ref1_pts: u64,
633 ref0_ts: u64,
634 ref1_ts: u64,
635 }
636
637 impl RealVideo60Decoder {
638 fn new() -> Self {
639 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
640 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
641 let vb = vt.get_vbuf();
642 let avg_buf = vb.unwrap();
643 RealVideo60Decoder{
644 info: NACodecInfoRef::default(),
645 cbs: RV60Codebooks::init(),
646 ipbs: IPBShuffler::new(),
647 ipred: IntraPredContext::new(),
648 skip_mode: FrameSkipMode::default(),
649 dsp: RV60DSP::new(),
650 avg_buf,
651 y_coeffs: [0; 16 * 16],
652 u_coeffs: [0; 8 * 8],
653 v_coeffs: [0; 8 * 8],
654 qp: 0,
655 sel_qp: 0,
656 cu_splits: Vec::with_capacity(24),
657 coded_blk: [false; 64],
658 dblk: DeblockInfo::new(),
659 pu_info: Vec::new(),
660 pu_stride: 0,
661 pu_pos: 0,
662 blk_info: Vec::new(),
663 blk_stride: 0,
664 blk_pos: 0,
665 xpos: 0,
666 ypos: 0,
667
668 ts_scale: 1,
669 ref0_pts: 0,
670 ref1_pts: 0,
671 ref0_ts: 0,
672 ref1_ts: 0,
673 }
674 }
675 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
676 let mut br = BitReader::new(src, BitReaderMode::BE);
677 let cu_w = hdr.get_width_cu();
678 let dqp = hdr.read_line_qp_offset(&mut br)?;
679 let qps = (hdr.qp as i8) + dqp;
680 validate!((0..32).contains(&qps));
681 let qp = qps as u8;
682 self.qp = qp;
683 self.sel_qp = match hdr.osvquant {
684 0 => qp,
685 1 => {
686 if qp <= 25 {
687 qp + 5
688 } else {
689 qp
690 }
691 },
692 _ => {
693 if qp <= 18 {
694 qp + 10
695 } else if qp <= 25 {
696 qp + 5
697 } else {
698 qp
699 }
700 },
701 };
702
703 for cu_x in 0..cu_w {
704 self.cu_splits.clear();
705 self.coded_blk = [false; 64];
706 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
707 if hdr.deblock {
708 self.cu_splits.reverse();
709 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
710 }
711 }
712 if br.left() >= 8 {
713 println!(" left {} bits", br.left());
714 }
715 Ok(())
716 }
717 #[allow(clippy::cognitive_complexity)]
718 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
719 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
720
721 let size = 1 << log_size;
722 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
723 self.cu_splits.push(split);
724 if split {
725 let hsize = size >> 1;
726 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
727 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
728 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
729 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
730 } else {
731 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
732 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
733 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
734 self.xpos = xpos;
735 self.ypos = ypos;
736 self.reconstruct_info(hdr, &cbh, size)?;
737
738 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
739 match cbh.cu_type {
740 CUType::Intra => {
741 let itype = self.blk_info[self.blk_pos].imode;
742 if !split_i4x4 {
743 let dstride = buf.stride[0];
744 let off = xpos + ypos * dstride;
745 let dst = &mut buf.data;
746 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
747 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
748 }
749 for comp in 1..3 {
750 let dstride = buf.stride[comp];
751 let soff = buf.offset[comp];
752 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
753 let dst = &mut buf.data;
754 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
755 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
756 }
757 },
758 _ => {
759 let mut mv_x = xpos >> 2;
760 let mut mv_y = ypos >> 2;
761 let mut mv_pos = mv_x + mv_y * self.blk_stride;
762 for part_no in 0..cbh.pu_type.get_num_mvs() {
763 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
764 let mv = self.blk_info[mv_pos].mv;
765 let bw = mv_w << 2;
766 let bh = mv_h << 2;
767 let bx = mv_x << 2;
768 let by = mv_y << 2;
769 match mv.mvref {
770 MVRef::Ref0 => {
771 if hdr.ftype != FrameType::B {
772 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
773 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
774 }
775 } else {
776 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
777 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
778 }
779 }
780 },
781 MVRef::Ref1 => {
782 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
783 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
784 }
785 },
786 MVRef::BRef => {
787 validate!(hdr.ftype == FrameType::B);
788 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
789 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
790 }
791 },
792 MVRef::Ref0AndBRef => {
793 validate!(hdr.ftype == FrameType::B);
794 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
795 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
796 {
797 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
798 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
799 }
800 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
801 }
802 },
803 _ => unreachable!(),
804 };
805 if cbh.pu_type == PUType::Quarters {
806 if part_no != 1 {
807 mv_pos += mv_w;
808 mv_x += mv_w;
809 } else {
810 mv_pos += mv_h * self.blk_stride - mv_w;
811 mv_x -= mv_w;
812 mv_y += mv_h;
813 }
814 } else if cbh.pu_type.has_hor_split() {
815 mv_pos += mv_h * self.blk_stride;
816 mv_y += mv_h;
817 } else if cbh.pu_type.has_ver_split() {
818 mv_pos += mv_w;
819 mv_x += mv_w;
820 }
821 }
822 },
823 };
824 if cbh.ttype != TransformType::None {
825 self.y_coeffs = [0; 16 * 16];
826 self.u_coeffs = [0; 8 * 8];
827 self.v_coeffs = [0; 8 * 8];
828 }
829 let is_intra = cbh.cu_type == CUType::Intra;
830 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
831 match cbh.ttype {
832 TransformType::T4X4 => {
833 let subset = if is_intra { 0 } else { 2 };
834 if size == 16 {
835 let cbp16;
836 if br.read_bool()? {
837 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
838 } else {
839 cbp16 = 0;
840 }
841 if cbp16 != 0 {
842 self.coded_blk[cb_pos + 0] = true;
843 self.coded_blk[cb_pos + 1] = true;
844 self.coded_blk[cb_pos + 8] = true;
845 self.coded_blk[cb_pos + 9] = true;
846 rv6_decode_cu_4x4in16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp16)?;
847 for y in 0..4 {
848 for x in 0..4 {
849 let i = x + y * 4;
850 if ((cbp16 >> i) & 1) != 0 {
851 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
852 let dstride = buf.stride[0];
853 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
854 let dst = &mut buf.data;
855 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
856 }
857 }
858 }
859 for y in 0..2 {
860 for x in 0..2 {
861 let i = x + y * 2;
862 let xoff = (xpos >> 1) + x * 4;
863 let yoff = (ypos >> 1) + y * 4;
864 if ((cbp16 >> (16 + i)) & 1) != 0 {
865 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
866 let dstride = buf.stride[1];
867 let off = buf.offset[1] + xoff + yoff * dstride;
868 let dst = &mut buf.data;
869 self.dsp.add_block(dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
870 }
871 if ((cbp16 >> (20 + i)) & 1) != 0 {
872 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
873 let dstride = buf.stride[2];
874 let off = buf.offset[2] + xoff + yoff * dstride;
875 let dst = &mut buf.data;
876 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
877 }
878 }
879 }
880 }
881 } else {
882 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
883 if cbp8 != 0 {
884 self.coded_blk[cb_pos] = true;
885 rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, true)?;
886 }
887 for i in 0..4 {
888 let xoff = (i & 1) * 4;
889 let yoff = (i & 2) * 2;
890 if split_i4x4 {
891 let dstride = buf.stride[0];
892 let off = xpos + xoff + (ypos + yoff) * dstride;
893 let dst = &mut buf.data;
894 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
895 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
896 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, false);
897 }
898 if ((cbp8 >> i) & 1) != 0 {
899 let blk = &mut self.y_coeffs[i * 16..][..16];
900 self.dsp.transform4x4(blk);
901 let dstride = buf.stride[0];
902 let soff = buf.offset[0];
903 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
904 self.dsp.add_block(buf.data, off, dstride, blk, 4);
905 }
906 }
907 if ((cbp8 >> 4) & 1) != 0 {
908 self.dsp.transform4x4(&mut self.u_coeffs);
909 let dstride = buf.stride[1];
910 let soff = buf.offset[1];
911 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
912 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
913 }
914 if ((cbp8 >> 5) & 1) != 0 {
915 self.dsp.transform4x4(&mut self.v_coeffs);
916 let dstride = buf.stride[2];
917 let soff = buf.offset[2];
918 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
919 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
920 }
921 }
922 },
923 TransformType::T8X8 => {
924 let subset = if is_intra { 1 } else { 3 };
925 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
926 if cbp8 != 0 {
927 self.coded_blk[cb_pos] = true;
928 rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, false)?;
929 if (cbp8 & 0xF) != 0 {
930 self.dsp.transform8x8(&mut self.y_coeffs);
931 let dstride = buf.stride[0];
932 let off = xpos + ypos * dstride;
933 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
934 }
935 if ((cbp8 >> 4) & 1) != 0 {
936 self.dsp.transform4x4(&mut self.u_coeffs);
937 let dstride = buf.stride[1];
938 let soff = buf.offset[1];
939 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
940 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
941 }
942 if ((cbp8 >> 5) & 1) != 0 {
943 self.dsp.transform4x4(&mut self.v_coeffs);
944 let dstride = buf.stride[2];
945 let soff = buf.offset[2];
946 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
947 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
948 }
949 }
950 },
951 TransformType::T16X16 => {
952 let subset = if is_intra { 1 } else { 3 };
953 let num_clusters = size >> 4;
954 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
955 for y in 0..num_clusters {
956 for x in 0..num_clusters {
957 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
958 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
959 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
960 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
961 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
962 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
963 if super_cbp != 0 {
964 self.y_coeffs = [0; 16 * 16];
965 self.u_coeffs = [0; 8 * 8];
966 self.v_coeffs = [0; 8 * 8];
967 rv6_decode_cu_16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, super_cbp)?;
968 if (super_cbp & 0xFFFF) != 0 {
969 self.dsp.transform16x16(&mut self.y_coeffs);
970 let dstride = buf.stride[0];
971 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
972 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
973 }
974 if ((super_cbp >> 16) & 0xF) != 0 {
975 self.dsp.transform8x8(&mut self.u_coeffs);
976 let dstride = buf.stride[1];
977 let soff = buf.offset[1];
978 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
979 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
980 }
981 if ((super_cbp >> 20) & 0xF) != 0 {
982 self.dsp.transform8x8(&mut self.v_coeffs);
983 let dstride = buf.stride[2];
984 let soff = buf.offset[2];
985 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
986 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
987 }
988 }
989 }
990 }
991 },
992 _ => {},
993 };
994 }
995 Ok(())
996 }
997 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
998 let mut pui = PUInfo::default();
999 let pu_size = size >> 3;
1000 pui.cu_type = cbh.cu_type;
1001 pui.ttype = cbh.ttype;
1002 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1003 self.pu_info[self.pu_pos] = pui;
1004 for y in 0..2 {
1005 for x in 0..2 {
1006 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1007 validate!(imode <= MAX_IMODE);
1008 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1009 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1010 }
1011 }
1012 return Ok(());
1013 }
1014 match cbh.cu_type {
1015 CUType::Intra => {
1016 self.pu_info[self.pu_pos] = pui;
1017 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1018 validate!(imode <= MAX_IMODE);
1019 for y in 0..(size >> 2) {
1020 for x in 0..(size >> 2) {
1021 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1022 }
1023 }
1024 },
1025 CUType::InterMV => {
1026 let mut mv_x = self.xpos >> 2;
1027 let mut mv_y = self.ypos >> 2;
1028 let mut mv_pos = self.blk_pos;
1029 let pu_type = cbh.pu_type;
1030 for part_no in 0..pu_type.get_num_mvs() {
1031 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1032 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1033 for y in 0..mv_h {
1034 for x in 0..mv_w {
1035 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1036 }
1037 }
1038 if pu_type == PUType::Quarters {
1039 if part_no != 1 {
1040 mv_pos += mv_w;
1041 mv_x += mv_w;
1042 } else {
1043 mv_pos += mv_h * self.blk_stride - mv_w;
1044 mv_x -= mv_w;
1045 mv_y += mv_h;
1046 }
1047 } else if pu_type.has_hor_split() {
1048 mv_pos += mv_h * self.blk_stride;
1049 mv_y += mv_h;
1050 } else if pu_type.has_ver_split() {
1051 mv_pos += mv_w;
1052 mv_x += mv_w;
1053 }
1054 }
1055 },
1056 _ => {
1057 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1058 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1059 self.fill_skip_cand(hdr, &mut skip_cand, size);
1060 let mv = skip_cand.list[skip_idx];
1061
1062 let mv_size = size >> 2;
1063 for y in 0..mv_size {
1064 for x in 0..mv_size {
1065 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1066 }
1067 }
1068 },
1069 };
1070 for y in 0..pu_size {
1071 for x in 0..pu_size {
1072 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1073 }
1074 }
1075 Ok(())
1076 }
1077 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1078 match cbh.imode[0] {
1079 IntraMode::DC64 => { return 1; },
1080 IntraMode::Plane64 => { return 0; },
1081 _ => {},
1082 };
1083 // form list of predictors
1084 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1085 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1086 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1087 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1088 if pu.is_intra() {
1089 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1090 }
1091 }
1092 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1093 let pu = &self.pu_info[self.pu_pos - 1];
1094 if pu.is_intra() {
1095 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1096 }
1097 }
1098 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1099 let tl_y = self.ypos + (sub & 2) * 4;
1100 if (tl_x > 0) && (tl_y > 0) {
1101 let pu = match sub {
1102 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1103 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1104 2 => &self.pu_info[self.pu_pos - 1],
1105 _ => &self.pu_info[self.pu_pos - 1],
1106 };
1107 if pu.is_intra() {
1108 if sub != 3 {
1109 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1110 } else {
1111 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1112 }
1113 }
1114 }
1115 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1116 ipm_cand.add(*el);
1117 }
1118 // actually decode prediction mode
1119 match cbh.imode[sub] {
1120 IntraMode::Index(idx) => {
1121 ipm_cand.list[idx as usize]
1122 },
1123 IntraMode::Mode(mode) => {
1124 let mut imode = mode;
1125 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1126 ipm_cs.sort();
1127 for ic in ipm_cs.iter() {
1128 if imode >= *ic {
1129 imode += 1;
1130 }
1131 }
1132 imode
1133 },
1134 _ => unreachable!(),
1135 }
1136 }
1137 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1138 let src_off = if is_luma {
1139 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1140 } else {
1141 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1142 };
1143 self.ipred = IntraPredContext::new();
1144 if (self.ypos + yoff) > 0 {
1145 self.ipred.has_t = true;
1146 for x in 0..size {
1147 self.ipred.t[x + 1] = src[src_off - stride + x];
1148 }
1149 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1150 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1151 self.ipred.has_tr = true;
1152 for x in size..size*2 {
1153 self.ipred.t[x + 1] = src[src_off - stride + x];
1154 }
1155 } else {
1156 for i in 0..size {
1157 self.ipred.t[size + i + 1] = self.ipred.t[size];
1158 }
1159 }
1160 if (self.xpos + xoff) > 0 {
1161 self.ipred.t[0] = src[src_off - stride - 1];
1162 }
1163 }
1164 if (self.xpos + xoff) > 0 {
1165 self.ipred.has_l = true;
1166 for y in 0..size {
1167 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1168 }
1169 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1170 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1171 self.ipred.has_ld = true;
1172 for y in size..size*2 {
1173 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1174 }
1175 } else {
1176 for i in 0..size {
1177 self.ipred.l[size + i + 1] = self.ipred.l[size];
1178 }
1179 }
1180 if (self.ypos + yoff) > 0 {
1181 self.ipred.l[0] = src[src_off - stride - 1];
1182 }
1183 }
1184 }
1185 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1186 let mv_pos = mv_x + mv_y * self.blk_stride;
1187 let f_mv: MV;
1188 let b_mv: MV;
1189 if mvi.mvref.is_fwd() {
1190 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1191 let mut mv_cand_size: usize = 0;
1192 if mv_x > 0 {
1193 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1194 if ref_mv.matches_fwd(mvi.mvref) {
1195 mv_cand[mv_cand_size] = ref_mv.f_mv;
1196 mv_cand_size += 1;
1197 }
1198 }
1199 if mv_y > 0 {
1200 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1201 if ref_mv.matches_fwd(mvi.mvref) {
1202 mv_cand[mv_cand_size] = ref_mv.f_mv;
1203 mv_cand_size += 1;
1204 }
1205 }
1206 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1207 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1208 if ref_mv.matches_fwd(mvi.mvref) {
1209 mv_cand[mv_cand_size] = ref_mv.f_mv;
1210 mv_cand_size += 1;
1211 }
1212 }
1213 f_mv = match mv_cand_size {
1214 1 | 2 => {
1215 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1216 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1217 if mv_cand_size == 1 {
1218 MV { x, y }
1219 } else {
1220 MV { x: x >> 1, y: y >> 1 }
1221 }
1222 },
1223 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1224 _ => ZERO_MV,
1225 };
1226 } else {
1227 f_mv = ZERO_MV;
1228 }
1229 if mvi.mvref.is_bwd() {
1230 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1231 let mut mv_cand_size: usize = 0;
1232 if mv_x > 0 {
1233 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1234 if ref_mv.matches_bwd(mvi.mvref) {
1235 mv_cand[mv_cand_size] = ref_mv.b_mv;
1236 mv_cand_size += 1;
1237 }
1238 }
1239 if mv_y > 0 {
1240 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1241 if ref_mv.matches_bwd(mvi.mvref) {
1242 mv_cand[mv_cand_size] = ref_mv.b_mv;
1243 mv_cand_size += 1;
1244 }
1245 }
1246 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1247 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1248 if ref_mv.matches_bwd(mvi.mvref) {
1249 mv_cand[mv_cand_size] = ref_mv.b_mv;
1250 mv_cand_size += 1;
1251 }
1252 }
1253 b_mv = match mv_cand_size {
1254 1 | 2 => {
1255 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1256 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1257 if mv_cand_size == 1 {
1258 MV { x, y }
1259 } else {
1260 MV { x: x >> 1, y: y >> 1 }
1261 }
1262 },
1263 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1264 _ => ZERO_MV,
1265 };
1266 } else {
1267 b_mv = ZERO_MV;
1268 }
1269
1270 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1271 }
1272 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1273 let mv_size = size >> 2;
1274
1275 if self.xpos > 0 {
1276 let mv = &self.blk_info[self.blk_pos - 1].mv;
1277 if mv.is_some() {
1278 skip_cand.add(*mv);
1279 }
1280 }
1281 if self.ypos > 0 {
1282 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1283 if mv.is_some() {
1284 skip_cand.add(*mv);
1285 }
1286 }
1287 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1288 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1289 if mv.is_some() {
1290 skip_cand.add(*mv);
1291 }
1292 }
1293 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1294 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1295 if mv.is_some() {
1296 skip_cand.add(*mv);
1297 }
1298 }
1299 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1300 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1301 if mv.is_some() {
1302 skip_cand.add(*mv);
1303 }
1304 }
1305 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1306 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1307 if mv.is_some() {
1308 skip_cand.add(*mv);
1309 }
1310 }
1311 if (self.xpos > 0) && (self.ypos > 0) {
1312 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1313 if mv.is_some() {
1314 skip_cand.add(*mv);
1315 }
1316 }
1317 for i in skip_cand.fill..4 {
1318 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1319 }
1320 }
1321 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1322 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1323 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1324 if split {
1325 let hsize = 1 << (log_size - 1);
1326 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1327 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1328 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1329 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1330 } else {
1331 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1332 let cu_type = self.pu_info[pu_pos].cu_type;
1333 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1334 let ntiles = 1 << (log_size - tsize);
1335 let dparams = RV60DeblockParams {
1336 deblock_chroma: hdr.deblock_chroma,
1337 width: hdr.width,
1338 height: hdr.height,
1339 dblkstride: self.dblk.stride,
1340 };
1341 for ty in 0..ntiles {
1342 for tx in 0..ntiles {
1343 let x = xpos + (tx << tsize);
1344 let y = ypos + (ty << tsize);
1345 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1346 if cu_type == CUType::Intra {
1347 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1348 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1349 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1350 } else {
1351 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1352 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1353 }
1354 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1355 self.dblk.top_str.as_slice(),
1356 self.dblk.left_str.as_slice(),
1357 self.dblk.get_pos(x, y));
1358 }
1359 }
1360 }
1361 }
1362 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1363 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1364 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1365 if ypos > 0 {
1366 let top_blk_pos = blk_pos - self.blk_stride;
1367 for i in 0..size4 {
1368 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1369 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1370 self.dblk.set_top_strength(dblk_pos + i, 1);
1371 }
1372 }
1373 }
1374 }
1375 if xpos > 0 {
1376 for i in 0..size4 {
1377 if self.dblk.get_left_strength(dblk_pos) == 0 {
1378 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1379 self.dblk.set_left_strength(dblk_pos, 1);
1380 }
1381 }
1382 dblk_pos += self.dblk.stride;
1383 }
1384 }
1385 }
1386 }
1387
1388 impl NADecoder for RealVideo60Decoder {
1389 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1390 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1391 let fmt = YUV420_FORMAT;
1392 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1393 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1394
1395 let edata = info.get_extradata().unwrap();
1396 let src: &[u8] = &edata;
1397
1398 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1399 let mut mr = MemoryReader::new_read(src);
1400 let mut br = ByteReader::new(&mut mr);
1401 let _flags = br.read_u32be()?;
1402 let version = br.read_u32be()?;
1403 let _unk = br.read_u16be()?;
1404 validate!((version >> 28) == 4);
1405 // then width and height again as 16be
1406
1407 //self.bd.width = vinfo.get_width();
1408 //self.bd.height = vinfo.get_height();
1409 //self.frmmgr.clear();
1410
1411 supp.pool_u8.set_dec_bufs(3);
1412 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1413
1414 Ok(())
1415 } else {
1416 println!("???");
1417 Err(DecoderError::InvalidData)
1418 }
1419 }
1420 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1421 let src = pkt.get_buffer();
1422
1423 validate!(src.len() > 9);
1424 let hsize = (src[0] as usize) * 8 + 9;
1425 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1426 let hdr = FrameHeader::read(&mut br)?;
1427 match self.skip_mode {
1428 FrameSkipMode::None => {},
1429 FrameSkipMode::KeyframesOnly => {
1430 if hdr.ftype == FrameType::B {
1431 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1432 frm.set_frame_type(FrameType::Skip);
1433 return Ok(frm.into_ref());
1434 }
1435 },
1436 FrameSkipMode::IntraOnly => {
1437 if hdr.ftype != FrameType::I {
1438 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1439 frm.set_frame_type(FrameType::Skip);
1440 return Ok(frm.into_ref());
1441 }
1442 },
1443 };
1444
1445 let mut slices: Vec<usize> = Vec::new();
1446 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1447 match hdr.ftype {
1448 FrameType::P => {
1449 if self.ipbs.get_lastref().is_none() {
1450 return Err(DecoderError::MissingReference);
1451 }
1452 },
1453 FrameType::B => {
1454 if self.ipbs.get_lastref().is_none() {
1455 return Err(DecoderError::MissingReference);
1456 }
1457 if self.ipbs.get_nextref().is_none() {
1458 return Err(DecoderError::MissingReference);
1459 }
1460 },
1461 _ => {},
1462 };
1463
1464 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1465 let ret = supp.pool_u8.get_free();
1466 if ret.is_none() {
1467 return Err(DecoderError::AllocError);
1468 }
1469 let mut buf = ret.unwrap();
1470 if buf.get_info() != tmp_vinfo {
1471 self.ipbs.clear();
1472 supp.pool_u8.reset();
1473 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1474 let ret = supp.pool_u8.get_free();
1475 if ret.is_none() {
1476 return Err(DecoderError::AllocError);
1477 }
1478 buf = ret.unwrap();
1479 }
1480
1481 let cu_w = hdr.get_width_cu();
1482 let cu_h = hdr.get_height_cu();
1483 self.pu_stride = cu_w << 3;
1484 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1485 self.blk_stride = cu_w << 4;
1486 self.blk_info.clear();
1487 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1488 if hdr.deblock {
1489 self.dblk.reinit(hdr.width, hdr.height);
1490 }
1491 let mut off = hsize + ((br.tell() >> 3) as usize);
1492 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1493 for (cu_y, size) in slices.into_iter().enumerate() {
1494 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1495 off += size;
1496 }
1497 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1498 self.ipbs.add_frame(buf.clone());
1499 }
1500
1501 if hdr.ftype != FrameType::B {
1502 self.ref0_pts = self.ref1_pts;
1503 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1504 self.ref0_ts = self.ref1_ts;
1505 self.ref1_ts = hdr.ts as u64;
1506 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1507 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1508 }
1509 }
1510 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1511 frm.set_keyframe(hdr.ftype == FrameType::I);
1512 if hdr.ftype == FrameType::B {
1513 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1514 frm.set_pts(Some(pts));
1515 }
1516 frm.set_frame_type(hdr.ftype);
1517 Ok(frm.into_ref())
1518 }
1519 fn flush(&mut self) {
1520 self.ipbs.clear();
1521 }
1522 }
1523
1524 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1525 NAOptionDefinition {
1526 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1527 opt_type: NAOptionDefinitionType::String(Some(&[
1528 FRAME_SKIP_OPTION_VAL_NONE,
1529 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1530 FRAME_SKIP_OPTION_VAL_INTRA
1531 ])) },
1532 ];
1533
1534 impl NAOptionHandler for RealVideo60Decoder {
1535 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1536 fn set_options(&mut self, options: &[NAOption]) {
1537 for option in options.iter() {
1538 for opt_def in DECODER_OPTIONS.iter() {
1539 if opt_def.check(option).is_ok() {
1540 match (option.name, &option.value) {
1541 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1542 if let Ok(smode) = FrameSkipMode::from_str(str) {
1543 self.skip_mode = smode;
1544 }
1545 },
1546 _ => {},
1547 }
1548 }
1549 }
1550 }
1551 }
1552 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1553 match name {
1554 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1555 _ => None,
1556 }
1557 }
1558 }
1559
1560 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1561 Box::new(RealVideo60Decoder::new())
1562 }
1563
1564 #[cfg(test)]
1565 mod test {
1566 use nihav_core::codecs::RegisteredDecoders;
1567 use nihav_core::demuxers::RegisteredDemuxers;
1568 use nihav_codec_support::test::dec_video::*;
1569 use crate::realmedia_register_all_decoders;
1570 use crate::realmedia_register_all_demuxers;
1571 #[test]
1572 fn test_rv60() {
1573 let mut dmx_reg = RegisteredDemuxers::new();
1574 realmedia_register_all_demuxers(&mut dmx_reg);
1575 let mut dec_reg = RegisteredDecoders::new();
1576 realmedia_register_all_decoders(&mut dec_reg);
1577
1578 // sample from a private collection
1579 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1580 ExpectedTestResult::MD5Frames(vec![
1581 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1582 [0xea406850, 0x400802b8, 0xac106fb6, 0xe1e2e766],
1583 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1584 [0xb04e2626, 0x976e16f5, 0xc41a7a78, 0x2d8765da],
1585 [0xf4f30d97, 0x7f2876eb, 0x265ffad4, 0x3542a7c4],
1586 [0xa5082524, 0x38a86952, 0x35bf1fee, 0xfc830d3f],
1587 [0x75eab1a2, 0x62e2222f, 0xe96a20d9, 0x652140b4],
1588 [0x7590fa49, 0x78c83490, 0x239eeff9, 0x64282ac7],
1589 [0x70b19e9f, 0x66c1f866, 0xb8d7142a, 0xf3e424b2],
1590 [0xc2934123, 0x3bf72fc4, 0x12d8d123, 0x1f39525b],
1591 [0x13344919, 0xecd01190, 0x2f69079b, 0xbf4d7026],
1592 [0xcefb3284, 0xa9b36d4d, 0xf1aa6752, 0xaae17d44],
1593 [0x57f01275, 0xf8e883ea, 0x4865752e, 0xc760a777]]));
1594 }
1595 }