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