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