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