rename register_all_codecs to register_all_decoders
[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 }
fa57381e 731 #[allow(clippy::cyclomatic_complexity)]
cd830591 732 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
733 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
734
735 let size = 1 << log_size;
736 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
737 self.cu_splits.push(split);
738 if split {
739 let hsize = size >> 1;
740 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
741 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
742 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
743 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
744 } else {
745 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
746 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
747 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
748 self.xpos = xpos;
749 self.ypos = ypos;
750 self.reconstruct_info(hdr, &cbh, size)?;
751
752 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
753 match cbh.cu_type {
754 CUType::Intra => {
755 let itype = self.blk_info[self.blk_pos].imode;
756 if !split_i4x4 {
cd830591 757 let dstride = buf.stride[0];
52aad9fe 758 let off = xpos + ypos * dstride;
cd830591 759 let dst = &mut buf.data;
52aad9fe
KS
760 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
761 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
762 }
763 for comp in 1..3 {
cd830591
KS
764 let dstride = buf.stride[comp];
765 let soff = buf.offset[comp];
52aad9fe 766 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 767 let mut dst = &mut buf.data;
52aad9fe
KS
768 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
769 self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false);
770 }
771 },
772 _ => {
773 let mut mv_x = xpos >> 2;
774 let mut mv_y = ypos >> 2;
775 let mut mv_pos = mv_x + mv_y * self.blk_stride;
776 for part_no in 0..cbh.pu_type.get_num_mvs() {
777 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
778 let mv = self.blk_info[mv_pos].mv;
779 let bw = mv_w << 2;
780 let bh = mv_h << 2;
781 let bx = mv_x << 2;
782 let by = mv_y << 2;
783 match mv.mvref {
784 MVRef::Ref0 => {
785 if hdr.ftype != FrameType::B {
786 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
787 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
788 }
789 } else {
790 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
791 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
792 }
793 }
794 },
795 MVRef::Ref1 => {
796 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
797 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
798 }
799 },
800 MVRef::BRef => {
801 validate!(hdr.ftype == FrameType::B);
802 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
803 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
804 }
805 },
806 MVRef::Ref0AndBRef => {
807 validate!(hdr.ftype == FrameType::B);
808 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
809 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
cd830591
KS
810 {
811 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
812 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
813 }
52aad9fe
KS
814 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
815 }
816 },
817 _ => unreachable!(),
818 };
819 if cbh.pu_type == PUType::Quarters {
820 if part_no != 1 {
821 mv_pos += mv_w;
822 mv_x += mv_w;
823 } else {
824 mv_pos += mv_h * self.blk_stride - mv_w;
825 mv_x -= mv_w;
826 mv_y += mv_h;
827 }
828 } else if cbh.pu_type.has_hor_split() {
829 mv_pos += mv_h * self.blk_stride;
830 mv_y += mv_h;
831 } else if cbh.pu_type.has_ver_split() {
832 mv_pos += mv_w;
833 mv_x += mv_w;
834 }
835 }
836 },
837 };
838 if cbh.ttype != TransformType::None {
839 self.y_coeffs = [0; 16 * 16];
840 self.u_coeffs = [0; 8 * 8];
841 self.v_coeffs = [0; 8 * 8];
842 }
843 let is_intra = cbh.cu_type == CUType::Intra;
844 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
845 match cbh.ttype {
846 TransformType::T4X4 => {
847 let subset = if is_intra { 0 } else { 2 };
848 if size == 16 {
849 let cbp16;
850 if br.read_bool()? {
851 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
852 } else {
853 cbp16 = 0;
854 }
855 if cbp16 != 0 {
856 self.coded_blk[cb_pos + 0] = true;
857 self.coded_blk[cb_pos + 1] = true;
858 self.coded_blk[cb_pos + 8] = true;
859 self.coded_blk[cb_pos + 9] = true;
860 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)?;
861 for y in 0..4 {
862 for x in 0..4 {
863 let i = x + y * 4;
864 if ((cbp16 >> i) & 1) != 0 {
865 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
cd830591 866 let dstride = buf.stride[0];
52aad9fe 867 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
cd830591 868 let mut dst = &mut buf.data;
52aad9fe
KS
869 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
870 }
871 }
872 }
873 for y in 0..2 {
874 for x in 0..2 {
875 let i = x + y * 2;
876 let xoff = (xpos >> 1) + x * 4;
877 let yoff = (ypos >> 1) + y * 4;
878 if ((cbp16 >> (16 + i)) & 1) != 0 {
879 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
cd830591
KS
880 let dstride = buf.stride[1];
881 let off = buf.offset[1] + xoff + yoff * dstride;
882 let mut dst = &mut buf.data;
52aad9fe
KS
883 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
884 }
885 if ((cbp16 >> (20 + i)) & 1) != 0 {
886 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
cd830591
KS
887 let dstride = buf.stride[2];
888 let off = buf.offset[2] + xoff + yoff * dstride;
889 let mut dst = &mut buf.data;
52aad9fe
KS
890 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
891 }
892 }
893 }
894 }
895 } else {
896 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
897 if cbp8 != 0 {
898 self.coded_blk[cb_pos] = true;
899 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)?;
900 }
901 for i in 0..4 {
902 let xoff = (i & 1) * 4;
903 let yoff = (i & 2) * 2;
904 if split_i4x4 {
cd830591 905 let dstride = buf.stride[0];
52aad9fe 906 let off = xpos + xoff + (ypos + yoff) * dstride;
cd830591 907 let mut dst = &mut buf.data;
52aad9fe
KS
908 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
909 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
910 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
911 }
912 if ((cbp8 >> i) & 1) != 0 {
913 let blk = &mut self.y_coeffs[i * 16..][..16];
914 self.dsp.transform4x4(blk);
cd830591
KS
915 let dstride = buf.stride[0];
916 let soff = buf.offset[0];
52aad9fe 917 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
cd830591 918 let mut dst = &mut buf.data;
52aad9fe
KS
919 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
920 }
921 }
922 if ((cbp8 >> 4) & 1) != 0 {
923 self.dsp.transform4x4(&mut self.u_coeffs);
cd830591
KS
924 let dstride = buf.stride[1];
925 let soff = buf.offset[1];
52aad9fe 926 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 927 let mut dst = &mut buf.data;
52aad9fe
KS
928 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
929 }
930 if ((cbp8 >> 5) & 1) != 0 {
931 self.dsp.transform4x4(&mut self.v_coeffs);
cd830591
KS
932 let dstride = buf.stride[2];
933 let soff = buf.offset[2];
52aad9fe 934 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 935 let mut dst = &mut buf.data;
52aad9fe
KS
936 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
937 }
938 }
939 },
940 TransformType::T8X8 => {
941 let subset = if is_intra { 1 } else { 3 };
942 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
943 if cbp8 != 0 {
944 self.coded_blk[cb_pos] = true;
945 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)?;
946 if (cbp8 & 0xF) != 0 {
947 self.dsp.transform8x8(&mut self.y_coeffs);
cd830591 948 let dstride = buf.stride[0];
52aad9fe 949 let off = xpos + ypos * dstride;
cd830591 950 let mut dst = &mut buf.data;
52aad9fe
KS
951 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
952 }
953 if ((cbp8 >> 4) & 1) != 0 {
954 self.dsp.transform4x4(&mut self.u_coeffs);
cd830591
KS
955 let dstride = buf.stride[1];
956 let soff = buf.offset[1];
52aad9fe 957 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 958 let mut dst = &mut buf.data;
52aad9fe
KS
959 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
960 }
961 if ((cbp8 >> 5) & 1) != 0 {
962 self.dsp.transform4x4(&mut self.v_coeffs);
cd830591
KS
963 let dstride = buf.stride[2];
964 let soff = buf.offset[2];
52aad9fe 965 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 966 let mut dst = &mut buf.data;
52aad9fe
KS
967 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
968 }
969 }
970 },
971 TransformType::T16X16 => {
972 let subset = if is_intra { 1 } else { 3 };
973 let num_clusters = size >> 4;
974 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
975 for y in 0..num_clusters {
976 for x in 0..num_clusters {
977 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
978 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
979 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
980 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
981 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
982 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
983 if super_cbp != 0 {
984 self.y_coeffs = [0; 16 * 16];
985 self.u_coeffs = [0; 8 * 8];
986 self.v_coeffs = [0; 8 * 8];
987 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)?;
988 if (super_cbp & 0xFFFF) != 0 {
989 self.dsp.transform16x16(&mut self.y_coeffs);
cd830591 990 let dstride = buf.stride[0];
52aad9fe 991 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
cd830591 992 let mut dst = &mut buf.data;
52aad9fe
KS
993 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
994 }
995 if ((super_cbp >> 16) & 0xF) != 0 {
996 self.dsp.transform8x8(&mut self.u_coeffs);
cd830591
KS
997 let dstride = buf.stride[1];
998 let soff = buf.offset[1];
52aad9fe 999 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
cd830591 1000 let mut dst = &mut buf.data;
52aad9fe
KS
1001 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
1002 }
1003 if ((super_cbp >> 20) & 0xF) != 0 {
1004 self.dsp.transform8x8(&mut self.v_coeffs);
cd830591
KS
1005 let dstride = buf.stride[2];
1006 let soff = buf.offset[2];
52aad9fe 1007 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
cd830591 1008 let mut dst = &mut buf.data;
52aad9fe
KS
1009 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
1010 }
1011 }
1012 }
1013 }
1014 },
1015 _ => {},
1016 };
1017 }
1018 Ok(())
1019 }
1020 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1021 let mut pui = PUInfo::default();
1022 let pu_size = size >> 3;
1023 pui.cu_type = cbh.cu_type;
1024 pui.ttype = cbh.ttype;
1025 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1026 self.pu_info[self.pu_pos] = pui;
1027 for y in 0..2 {
1028 for x in 0..2 {
1029 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1030 validate!(imode <= MAX_IMODE);
1031 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1032 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1033 }
1034 }
1035 return Ok(());
1036 }
1037 match cbh.cu_type {
1038 CUType::Intra => {
1039 self.pu_info[self.pu_pos] = pui;
1040 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1041 validate!(imode <= MAX_IMODE);
1042 for y in 0..(size >> 2) {
1043 for x in 0..(size >> 2) {
1044 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1045 }
1046 }
1047 },
1048 CUType::InterMV => {
1049 let mut mv_x = self.xpos >> 2;
1050 let mut mv_y = self.ypos >> 2;
1051 let mut mv_pos = self.blk_pos;
1052 let pu_type = cbh.pu_type;
1053 for part_no in 0..pu_type.get_num_mvs() {
1054 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1055 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1056 for y in 0..mv_h {
1057 for x in 0..mv_w {
1058 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1059 }
1060 }
1061 if pu_type == PUType::Quarters {
1062 if part_no != 1 {
1063 mv_pos += mv_w;
1064 mv_x += mv_w;
1065 } else {
1066 mv_pos += mv_h * self.blk_stride - mv_w;
1067 mv_x -= mv_w;
1068 mv_y += mv_h;
1069 }
1070 } else if pu_type.has_hor_split() {
1071 mv_pos += mv_h * self.blk_stride;
1072 mv_y += mv_h;
1073 } else if pu_type.has_ver_split() {
1074 mv_pos += mv_w;
1075 mv_x += mv_w;
1076 }
1077 }
1078 },
1079 _ => {
1080 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1081 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1082 self.fill_skip_cand(hdr, &mut skip_cand, size);
1083 let mv = skip_cand.list[skip_idx];
1084
1085 let mv_size = size >> 2;
1086 for y in 0..mv_size {
1087 for x in 0..mv_size {
1088 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1089 }
1090 }
1091 },
1092 };
1093 for y in 0..pu_size {
1094 for x in 0..pu_size {
1095 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1096 }
1097 }
1098 Ok(())
1099 }
1100 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1101 match cbh.imode[0] {
1102 IntraMode::DC64 => { return 1; },
1103 IntraMode::Plane64 => { return 0; },
1104 _ => {},
1105 };
1106 // form list of predictors
1107 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1108 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1109 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1110 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1111 if pu.is_intra() {
1112 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1113 }
1114 }
1115 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1116 let pu = &self.pu_info[self.pu_pos - 1];
1117 if pu.is_intra() {
1118 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1119 }
1120 }
1121 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1122 let tl_y = self.ypos + (sub & 2) * 4;
1123 if (tl_x > 0) && (tl_y > 0) {
1124 let pu = match sub {
1125 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1126 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1127 2 => &self.pu_info[self.pu_pos - 1],
1128 _ => &self.pu_info[self.pu_pos - 1],
1129 };
1130 if pu.is_intra() {
1131 if sub != 3 {
1132 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1133 } else {
1134 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1135 }
1136 }
1137 }
61d3e294 1138 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
52aad9fe
KS
1139 ipm_cand.add(*el);
1140 }
1141 // actually decode prediction mode
1142 match cbh.imode[sub] {
1143 IntraMode::Index(idx) => {
1144 ipm_cand.list[idx as usize]
1145 },
1146 IntraMode::Mode(mode) => {
1147 let mut imode = mode;
1148 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1149 ipm_cs.sort();
61d3e294 1150 for ic in ipm_cs.iter() {
52aad9fe
KS
1151 if imode >= *ic {
1152 imode += 1;
1153 }
1154 }
1155 imode
1156 },
1157 _ => unreachable!(),
1158 }
1159 }
1160 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1161 let src_off = if is_luma {
1162 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1163 } else {
1164 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1165 };
1166 self.ipred = IntraPredContext::new();
1167 if (self.ypos + yoff) > 0 {
1168 self.ipred.has_t = true;
1169 for x in 0..size {
1170 self.ipred.t[x + 1] = src[src_off - stride + x];
1171 }
1172 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1173 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1174 self.ipred.has_tr = true;
1175 for x in size..size*2 {
1176 self.ipred.t[x + 1] = src[src_off - stride + x];
1177 }
1178 } else {
1179 for i in 0..size {
1180 self.ipred.t[size + i + 1] = self.ipred.t[size];
1181 }
1182 }
1183 if (self.xpos + xoff) > 0 {
1184 self.ipred.t[0] = src[src_off - stride - 1];
1185 }
1186 }
1187 if (self.xpos + xoff) > 0 {
1188 self.ipred.has_l = true;
1189 for y in 0..size {
1190 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1191 }
1192 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1193 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1194 self.ipred.has_ld = true;
1195 for y in size..size*2 {
1196 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1197 }
1198 } else {
1199 for i in 0..size {
1200 self.ipred.l[size + i + 1] = self.ipred.l[size];
1201 }
1202 }
1203 if (self.ypos + yoff) > 0 {
1204 self.ipred.l[0] = src[src_off - stride - 1];
1205 }
1206 }
1207 }
1208 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1209 let mv_pos = mv_x + mv_y * self.blk_stride;
1210 let f_mv: MV;
1211 let b_mv: MV;
1212 if mvi.mvref.is_fwd() {
1213 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1214 let mut mv_cand_size: usize = 0;
1215 if mv_x > 0 {
1216 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1217 if ref_mv.matches_fwd(mvi.mvref) {
1218 mv_cand[mv_cand_size] = ref_mv.f_mv;
1219 mv_cand_size += 1;
1220 }
1221 }
1222 if mv_y > 0 {
1223 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1224 if ref_mv.matches_fwd(mvi.mvref) {
1225 mv_cand[mv_cand_size] = ref_mv.f_mv;
1226 mv_cand_size += 1;
1227 }
1228 }
1229 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1230 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1231 if ref_mv.matches_fwd(mvi.mvref) {
1232 mv_cand[mv_cand_size] = ref_mv.f_mv;
1233 mv_cand_size += 1;
1234 }
1235 }
1236 f_mv = match mv_cand_size {
1237 1 | 2 => {
1238 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1239 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1240 if mv_cand_size == 1 {
1241 MV { x, y }
1242 } else {
1243 MV { x: x >> 1, y: y >> 1 }
1244 }
1245 },
1246 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1247 _ => ZERO_MV,
1248 };
1249 } else {
1250 f_mv = ZERO_MV;
1251 }
1252 if mvi.mvref.is_bwd() {
1253 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1254 let mut mv_cand_size: usize = 0;
1255 if mv_x > 0 {
1256 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1257 if ref_mv.matches_bwd(mvi.mvref) {
1258 mv_cand[mv_cand_size] = ref_mv.b_mv;
1259 mv_cand_size += 1;
1260 }
1261 }
1262 if mv_y > 0 {
1263 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1264 if ref_mv.matches_bwd(mvi.mvref) {
1265 mv_cand[mv_cand_size] = ref_mv.b_mv;
1266 mv_cand_size += 1;
1267 }
1268 }
1269 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1270 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1271 if ref_mv.matches_bwd(mvi.mvref) {
1272 mv_cand[mv_cand_size] = ref_mv.b_mv;
1273 mv_cand_size += 1;
1274 }
1275 }
1276 b_mv = match mv_cand_size {
1277 1 | 2 => {
1278 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1279 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1280 if mv_cand_size == 1 {
1281 MV { x, y }
1282 } else {
1283 MV { x: x >> 1, y: y >> 1 }
1284 }
1285 },
1286 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1287 _ => ZERO_MV,
1288 };
1289 } else {
1290 b_mv = ZERO_MV;
1291 }
d24468d9 1292
52aad9fe
KS
1293 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1294 }
1295 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1296 let mv_size = size >> 2;
1297
1298 if self.xpos > 0 {
1299 let mv = &self.blk_info[self.blk_pos - 1].mv;
1300 if mv.is_some() {
1301 skip_cand.add(*mv);
1302 }
1303 }
1304 if self.ypos > 0 {
1305 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1306 if mv.is_some() {
1307 skip_cand.add(*mv);
1308 }
1309 }
1310 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1311 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1312 if mv.is_some() {
1313 skip_cand.add(*mv);
1314 }
1315 }
1316 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1317 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1318 if mv.is_some() {
1319 skip_cand.add(*mv);
1320 }
1321 }
1322 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1323 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1324 if mv.is_some() {
1325 skip_cand.add(*mv);
1326 }
1327 }
1328 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1329 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1330 if mv.is_some() {
1331 skip_cand.add(*mv);
1332 }
1333 }
1334 if (self.xpos > 0) && (self.ypos > 0) {
1335 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1336 if mv.is_some() {
1337 skip_cand.add(*mv);
1338 }
1339 }
1340 for i in skip_cand.fill..4 {
1341 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1342 }
1343 }
cd830591 1344 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
52aad9fe
KS
1345 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1346 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1347 if split {
1348 let hsize = 1 << (log_size - 1);
1349 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1350 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1351 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1352 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1353 } else {
1354 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1355 let cu_type = self.pu_info[pu_pos].cu_type;
1356 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1357 let ntiles = 1 << (log_size - tsize);
1358 let dparams = RV60DeblockParams {
1359 deblock_chroma: hdr.deblock_chroma,
1360 width: hdr.width,
1361 height: hdr.height,
1362 dblkstride: self.dblk.stride,
1363 };
1364 for ty in 0..ntiles {
1365 for tx in 0..ntiles {
1366 let x = xpos + (tx << tsize);
1367 let y = ypos + (ty << tsize);
1368 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1369 if cu_type == CUType::Intra {
1370 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1371 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1372 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1373 } else {
1374 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1375 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1376 }
1377 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1378 self.dblk.top_str.as_slice(),
1379 self.dblk.left_str.as_slice(),
1380 self.dblk.get_pos(x, y));
1381 }
1382 }
1383 }
1384 }
1385 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1386 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1387 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1388 if ypos > 0 {
1389 let top_blk_pos = blk_pos - self.blk_stride;
1390 for i in 0..size4 {
1391 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1392 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1393 self.dblk.set_top_strength(dblk_pos + i, 1);
1394 }
1395 }
1396 }
1397 }
1398 if xpos > 0 {
1399 for i in 0..size4 {
1400 if self.dblk.get_left_strength(dblk_pos) == 0 {
1401 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1402 self.dblk.set_left_strength(dblk_pos, 1);
1403 }
1404 }
1405 dblk_pos += self.dblk.stride;
1406 }
1407 }
1408 }
1409}
1410
1411impl NADecoder for RealVideo60Decoder {
3c69ce1b
KS
1412 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1413 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
52aad9fe
KS
1414 let fmt = YUV420_FORMAT;
1415 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
2422d969 1416 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
52aad9fe
KS
1417
1418 let edata = info.get_extradata().unwrap();
1419 let src: &[u8] = &edata;
1420
1421 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1422 let mut mr = MemoryReader::new_read(src);
1423 let mut br = ByteReader::new(&mut mr);
1424 let _flags = br.read_u32be()?;
1425 let version = br.read_u32be()?;
1426 let _unk = br.read_u16be()?;
1427 validate!((version >> 28) == 4);
1428 // then width and height again as 16be
1429
1430 //self.bd.width = vinfo.get_width();
1431 //self.bd.height = vinfo.get_height();
1432 //self.frmmgr.clear();
3c69ce1b
KS
1433
1434 supp.pool_u8.set_dec_bufs(3);
1435 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1436
52aad9fe
KS
1437 Ok(())
1438 } else {
1439println!("???");
1440 Err(DecoderError::InvalidData)
1441 }
1442 }
3c69ce1b 1443 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
52aad9fe
KS
1444 let src = pkt.get_buffer();
1445
1446 validate!(src.len() > 9);
1447 let hsize = (src[0] as usize) * 8 + 9;
fa90ccfb 1448 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
52aad9fe 1449 let hdr = FrameHeader::read(&mut br)?;
54d2b09a
KS
1450 match self.skip_mode {
1451 FrameSkipMode::None => {},
1452 FrameSkipMode::KeyframesOnly => {
1453 if hdr.ftype == FrameType::B {
1454 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1455 frm.set_frame_type(FrameType::Skip);
1456 return Ok(frm.into_ref());
1457 }
1458 },
1459 FrameSkipMode::IntraOnly => {
1460 if hdr.ftype != FrameType::I {
1461 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1462 frm.set_frame_type(FrameType::Skip);
1463 return Ok(frm.into_ref());
1464 }
1465 },
1466 };
1467
52aad9fe
KS
1468 let mut slices: Vec<usize> = Vec::new();
1469 hdr.parse_slice_sizes(&mut br, &mut slices)?;
6e24ec0b
KS
1470 match hdr.ftype {
1471 FrameType::P => {
1472 if self.ipbs.get_lastref().is_none() {
1473 return Err(DecoderError::MissingReference);
1474 }
1475 },
1476 FrameType::B => {
1477 if self.ipbs.get_lastref().is_none() {
1478 return Err(DecoderError::MissingReference);
1479 }
1480 if self.ipbs.get_nextref().is_none() {
1481 return Err(DecoderError::MissingReference);
1482 }
1483 },
1484 _ => {},
1485 };
52aad9fe
KS
1486
1487 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
3c69ce1b
KS
1488 let ret = supp.pool_u8.get_free();
1489 if ret.is_none() {
1490 return Err(DecoderError::AllocError);
1491 }
1492 let mut buf = ret.unwrap();
1493 if buf.get_info() != tmp_vinfo {
1494 self.ipbs.clear();
1495 supp.pool_u8.reset();
1496 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1497 let ret = supp.pool_u8.get_free();
1498 if ret.is_none() {
1499 return Err(DecoderError::AllocError);
1500 }
1501 buf = ret.unwrap();
1502 }
52aad9fe
KS
1503
1504 let cu_w = hdr.get_width_cu();
1505 let cu_h = hdr.get_height_cu();
1506 self.pu_stride = cu_w << 3;
1507 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1508 self.blk_stride = cu_w << 4;
1509 self.blk_info.truncate(0);
1510 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1511 if hdr.deblock {
1512 self.dblk.reinit(hdr.width, hdr.height);
1513 }
1514 let mut off = hsize + ((br.tell() >> 3) as usize);
cd830591 1515 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
52aad9fe 1516 for (cu_y, size) in slices.into_iter().enumerate() {
cd830591 1517 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
52aad9fe
KS
1518 off += size;
1519 }
1520 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
3c69ce1b 1521 self.ipbs.add_frame(buf.clone());
52aad9fe
KS
1522 }
1523
d32c444b
KS
1524 if hdr.ftype != FrameType::B {
1525 self.ref0_pts = self.ref1_pts;
1526 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1527 self.ref0_ts = self.ref1_ts;
1528 self.ref1_ts = hdr.ts as u64;
1529 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1530 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1531 }
1532 }
3c69ce1b 1533 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
52aad9fe 1534 frm.set_keyframe(hdr.ftype == FrameType::I);
d32c444b
KS
1535 if hdr.ftype == FrameType::B {
1536 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1537 frm.set_pts(Some(pts));
1538 }
52aad9fe 1539 frm.set_frame_type(hdr.ftype);
171860fc 1540 Ok(frm.into_ref())
52aad9fe 1541 }
f9be4e75
KS
1542 fn flush(&mut self) {
1543 self.ipbs.clear();
1544 }
52aad9fe
KS
1545}
1546
54d2b09a
KS
1547const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1548 NAOptionDefinition {
1549 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1550 opt_type: NAOptionDefinitionType::String(Some(&[
1551 FRAME_SKIP_OPTION_VAL_NONE,
1552 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1553 FRAME_SKIP_OPTION_VAL_INTRA
1554 ])) },
1555];
1556
7d57ae2f 1557impl NAOptionHandler for RealVideo60Decoder {
54d2b09a
KS
1558 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1559 fn set_options(&mut self, options: &[NAOption]) {
1560 for option in options.iter() {
1561 for opt_def in DECODER_OPTIONS.iter() {
1562 if opt_def.check(option).is_ok() {
1563 match (option.name, &option.value) {
1564 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1565 if let Ok(smode) = FrameSkipMode::from_str(str) {
1566 self.skip_mode = smode;
1567 }
1568 },
1569 _ => {},
1570 }
1571 }
1572 }
1573 }
1574 }
1575 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1576 match name {
1577 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1578 _ => None,
1579 }
1580 }
7d57ae2f
KS
1581}
1582
08a1fab7 1583pub fn get_decoder() -> Box<dyn NADecoder + Send> {
52aad9fe
KS
1584 Box::new(RealVideo60Decoder::new())
1585}
1586
1587#[cfg(test)]
1588mod test {
3167c45c
KS
1589 use nihav_core::codecs::RegisteredDecoders;
1590 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 1591 use nihav_codec_support::test::dec_video::*;
78fb6560 1592 use crate::realmedia_register_all_decoders;
e64739f8 1593 use crate::realmedia_register_all_demuxers;
52aad9fe
KS
1594 #[test]
1595 fn test_rv60() {
3167c45c
KS
1596 let mut dmx_reg = RegisteredDemuxers::new();
1597 realmedia_register_all_demuxers(&mut dmx_reg);
1598 let mut dec_reg = RegisteredDecoders::new();
78fb6560 1599 realmedia_register_all_decoders(&mut dec_reg);
3167c45c 1600
c5123998
KS
1601 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1602 ExpectedTestResult::MD5Frames(vec![
1603 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1604 [0xea406850, 0x400802b8, 0xac106fb6, 0xe1e2e766],
1605 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1606 [0xb04e2626, 0x976e16f5, 0xc41a7a78, 0x2d8765da],
1607 [0xf4f30d97, 0x7f2876eb, 0x265ffad4, 0x3542a7c4],
1608 [0xa5082524, 0x38a86952, 0x35bf1fee, 0xfc830d3f],
1609 [0x75eab1a2, 0x62e2222f, 0xe96a20d9, 0x652140b4],
1610 [0x7590fa49, 0x78c83490, 0x239eeff9, 0x64282ac7],
1611 [0x70b19e9f, 0x66c1f866, 0xb8d7142a, 0xf3e424b2],
1612 [0xc2934123, 0x3bf72fc4, 0x12d8d123, 0x1f39525b],
1613 [0x13344919, 0xecd01190, 0x2f69079b, 0xbf4d7026],
1614 [0xcefb3284, 0xa9b36d4d, 0xf1aa6752, 0xaae17d44],
1615 [0x57f01275, 0xf8e883ea, 0x4865752e, 0xc760a777]]));
52aad9fe
KS
1616 }
1617}