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