RealVideo 1 decoder and RealVideo 2 bitstream parser
[nihav.git] / src / codecs / h263 / rv20.rs
CommitLineData
be91b1c3
KS
1use io::bitreader::*;
2use io::codebook::*;
3use formats;
4use super::super::*;
5use super::*;
6use super::decoder::*;
7use super::data::*;
8
9#[allow(dead_code)]
10struct Tables {
11 intra_mcbpc_cb: Codebook<u8>,
12 inter_mcbpc_cb: Codebook<u8>,
13 cbpy_cb: Codebook<u8>,
14 rl_cb: Codebook<H263RLSym>,
15 aic_rl_cb: Codebook<H263RLSym>,
16 mv_cb: Codebook<u8>,
17}
18
19#[derive(Clone,Copy)]
20struct RPRInfo {
21 present: bool,
22 bits: u8,
23 widths: [usize; 8],
24 heights: [usize; 8],
25}
26
27struct RealVideo20Decoder {
28 info: Rc<NACodecInfo>,
29 dec: H263BaseDecoder,
30 tables: Tables,
31 w: usize,
32 h: usize,
33 minor_ver: u8,
34 rpr: RPRInfo,
35}
36
37struct RealVideo20BR<'a> {
38 br: BitReader<'a>,
39 tables: &'a Tables,
40 num_slices: usize,
41 slice_no: usize,
42 slice_off: Vec<u32>,
43 w: usize,
44 h: usize,
45 mb_w: usize,
46 mb_h: usize,
47 mb_x: usize,
48 mb_y: usize,
49 mb_pos_bits: u8,
50 mb_count: usize,
51 mb_end: usize,
52 minor_ver: u8,
53 rpr: RPRInfo,
54 is_intra: bool,
55}
56
57struct RV20SliceInfo {
58 ftype: Type,
59 qscale: u8,
60 mb_x: usize,
61 mb_y: usize,
62 mb_pos: usize,
63 w: usize,
64 h: usize,
65}
66
67impl RV20SliceInfo {
68 fn new(ftype: Type, qscale: u8, mb_x: usize, mb_y: usize, mb_pos: usize, w: usize, h: usize) -> Self {
69 RV20SliceInfo { ftype: ftype, qscale: qscale, mb_x: mb_x, mb_y: mb_y, mb_pos: mb_pos, w: w, h: h }
70 }
71}
72
73impl<'a> RealVideo20BR<'a> {
74 fn new(src: &'a [u8], tables: &'a Tables, width: usize, height: usize, minor_ver: u8, rpr: RPRInfo) -> Self {
75 let nslices = (src[0] as usize) + 1;
76 let mut slice_offs = Vec::with_capacity(nslices);
77 {
78 let offs = &src[1..][..nslices * 8];
79 let mut br = BitReader::new(offs, offs.len(), BitReaderMode::BE);
80 for _ in 0..nslices {
81 br.skip(32).unwrap();
82 let off = br.read(32).unwrap();
83 slice_offs.push(off);
84 }
85 }
86 let soff = nslices * 8 + 1;
87 let mb_w = (width + 15) >> 4;
88 let mb_h = (height + 15) >> 4;
89 let max_pos = mb_w * mb_h - 1;
90 let mut mbpb = 0;
91 for i in 0..H263_MBB.len() {
92 if max_pos <= H263_MBB[i].blocks {
93 mbpb = H263_MBB[i].bits;
94 break;
95 }
96 }
97 RealVideo20BR {
98 br: BitReader::new(&src[soff..], src.len() - soff, BitReaderMode::BE),
99 tables: tables,
100 num_slices: nslices,
101 slice_no: 0,
102 slice_off: slice_offs,
103 w: width,
104 h: height,
105 mb_w: mb_w,
106 mb_h: mb_h,
107 mb_pos_bits: mbpb,
108 mb_x: 0,
109 mb_y: 0,
110 mb_count: 0,
111 mb_end: 0,
112 minor_ver: minor_ver,
113 rpr: rpr,
114 is_intra: false,
115 }
116 }
117
118 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize) -> DecoderResult<()> {
119 let mut br = &mut self.br;
120 let mut idx = 0;
121 if !self.is_intra && intra {
122 let mut dc = br.read(8).unwrap() as i16;
123 if dc == 255 { dc = 128; }
124 blk[0] = dc << 3;
125 idx = 1;
126 }
127 if !coded { return Ok(()); }
128
129 let rl_cb = if self.is_intra { &self.tables.aic_rl_cb } else { &self.tables.rl_cb };
130 let q_add = if quant == 0 { 0i16 } else { ((quant - 1) | 1) as i16 };
131 let q = (quant * 2) as i16;
132 while idx < 64 {
133 let code = br.read_cb(rl_cb).unwrap();
134 let run;
135 let mut level;
136 let last;
137 if !code.is_escape() {
138 run = code.get_run();
139 level = code.get_level();
140 last = code.is_last();
141 if br.read_bool().unwrap() { level = -level; }
142 level = (level * q) + q_add;
143 } else {
144 last = br.read_bool().unwrap();
145 run = br.read(6).unwrap() as u8;
146 level = br.read_s(8).unwrap() as i16;
147 if level == -128 {
148 let low = br.read(5).unwrap() as i16;
149 let top = br.read_s(6).unwrap() as i16;
150 level = (top << 5) | low;
151 }
152 level = (level * q) + q_add;
153 if level < -2048 { level = -2048; }
154 if level > 2047 { level = 2047; }
155 }
156 idx += run;
157 validate!(idx < 64);
158 let oidx = H263_ZIGZAG[idx as usize];
159 blk[oidx] = level;
160 idx += 1;
161 if last { break; }
162 }
163 Ok(())
164 }
165}
166
167fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
168 let code = br.read_cb(mv_cb).unwrap() as i16;
169 if code == 0 { return Ok(0) }
170 if !br.read_bool().unwrap() {
171 Ok(code)
172 } else {
173 Ok(-code)
174 }
175}
176
177fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
178 let xval = decode_mv_component(br, mv_cb).unwrap();
179 let yval = decode_mv_component(br, mv_cb).unwrap();
180//println!(" MV {},{} @ {}", xval, yval, br.tell());
181 Ok(MV::new(xval, yval))
182}
183
184impl<'a> BlockDecoder for RealVideo20BR<'a> {
185
186#[allow(unused_variables)]
187 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
188 self.slice_no = 0;
189println!("decoding picture header size {}", if self.num_slices > 1 { self.slice_off[1] } else { ((self.br.tell() as u32) + (self.br.left() as u32))/8 });
190 self.mb_x = 0;
191 self.mb_y = 0;
192 self.mb_count = self.mb_w * self.mb_h;
193 let shdr = self.read_slice_header().unwrap();
194println!("slice ends @ {}\n", self.br.tell());
195 self.slice_no += 1;
196 validate!((shdr.mb_x == 0) && (shdr.mb_y == 0));
197 let mb_count;
198 if self.slice_no < self.num_slices {
199 let pos = self.br.tell();
200 let shdr2 = self.read_slice_header().unwrap();
201 self.br.seek(pos as u32)?;
202 mb_count = shdr2.mb_pos - shdr.mb_pos;
203 } else {
204 mb_count = self.mb_w * self.mb_h;
205 }
206
207 self.mb_x = shdr.mb_x;
208 self.mb_y = shdr.mb_y;
209 self.mb_count = mb_count;
210 self.mb_end = shdr.mb_pos + mb_count;
211 self.is_intra = shdr.ftype == Type::I;
212
213 let picinfo = PicInfo::new(shdr.w, shdr.h, shdr.ftype, shdr.qscale, false, MVMode::Old, 0, None, true);
214 Ok(picinfo)
215 }
216
217 #[allow(unused_variables)]
218 fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
219//println!("read slice {} header", self.slice_no);
220 let shdr = self.read_slice_header().unwrap();
221 self.slice_no += 1;
222 let mb_count;
223 if self.slice_no < self.num_slices {
224 let shdr2 = self.read_slice_header().unwrap();
225 mb_count = shdr2.mb_pos - shdr.mb_pos;
226 } else {
227 mb_count = self.mb_w * self.mb_h - shdr.mb_pos;
228 }
229 let ret = Slice::new(shdr.mb_x, shdr.mb_y, shdr.qscale);
230 self.mb_x = shdr.mb_x;
231 self.mb_y = shdr.mb_y;
232 self.mb_count = mb_count;
233 self.mb_end = shdr.mb_pos + mb_count;
234
235 Ok(ret)
236 }
237
238 fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
239 let mut br = &mut self.br;
240 let mut q = slice.get_quant();
241 match info.get_mode() {
242 Type::I => {
243 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb).unwrap();
244 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb).unwrap(); }
245if self.is_intra {
246let acpred = br.read_bool()?;
247println!(" acp {} @ {}", acpred, br.tell());
248if acpred {
249 br.skip(1)?;//pred direction
250}
251}
252 let cbpy = br.read_cb(&self.tables.cbpy_cb).unwrap();
253 let cbp = (cbpy << 2) | (cbpc & 3);
254 let dquant = (cbpc & 4) != 0;
255 if dquant {
256 let idx = br.read(2).unwrap() as usize;
257 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
258 }
259println!(" MB {},{} CBP {:X} @ {}", self.mb_x, self.mb_y, cbp, br.tell());
260 self.mb_x += 1;
261 if self.mb_x == self.mb_w {
262 self.mb_x = 0;
263 self.mb_y += 1;
264 }
265 Ok(BlockInfo::new(Type::I, cbp, q))
266 },
267 Type::P => {
268 if br.read_bool().unwrap() {
269self.mb_x += 1;
270if self.mb_x == self.mb_w {
271 self.mb_x = 0;
272 self.mb_y += 1;
273}
274 return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant()));
275 }
276 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb).unwrap();
277 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb).unwrap(); }
278 let is_intra = (cbpc & 0x04) != 0;
279 let dquant = (cbpc & 0x08) != 0;
280 let is_4x4 = (cbpc & 0x10) != 0;
281 if is_intra {
282 let cbpy = br.read_cb(&self.tables.cbpy_cb).unwrap();
283 let cbp = (cbpy << 2) | (cbpc & 3);
284 if dquant {
285 let idx = br.read(2).unwrap() as usize;
286 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
287 }
288 let binfo = BlockInfo::new(Type::I, cbp, q);
289 self.mb_x += 1;
290 if self.mb_x == self.mb_w {
291 self.mb_x = 0;
292 self.mb_y += 1;
293 }
294 return Ok(binfo);
295 }
296
297 let mut cbpy = br.read_cb(&self.tables.cbpy_cb).unwrap();
298// if /* !aiv && */(cbpc & 3) != 3 {
299 cbpy ^= 0xF;
300// }
301 let cbp = (cbpy << 2) | (cbpc & 3);
302 if dquant {
303 let idx = br.read(2).unwrap() as usize;
304 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
305 }
306println!(" MB {}.{} cbp = {:X}", self.mb_x, self.mb_y, cbp);
307 let mut binfo = BlockInfo::new(Type::P, cbp, q);
308 if !is_4x4 {
309 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb).unwrap()];
310 binfo.set_mv(&mvec);
311 } else {
312 let mvec: [MV; 4] = [
313 decode_mv(br, &self.tables.mv_cb).unwrap(),
314 decode_mv(br, &self.tables.mv_cb).unwrap(),
315 decode_mv(br, &self.tables.mv_cb).unwrap(),
316 decode_mv(br, &self.tables.mv_cb).unwrap()
317 ];
318 binfo.set_mv(&mvec);
319 }
320 self.mb_x += 1;
321 if self.mb_x == self.mb_w {
322 self.mb_x = 0;
323 self.mb_y += 1;
324 }
325 Ok(binfo)
326 },
327 _ => { println!("wrong info mode"); Err(DecoderError::InvalidData) },
328 }
329 }
330
331 #[allow(unused_variables)]
332 fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
333 self.decode_block(quant, true, coded, blk, if no < 4 { 0 } else { no - 3 })
334 }
335
336 #[allow(unused_variables)]
337 fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
338 self.decode_block(quant, false, coded, blk, if no < 4 { 0 } else { no - 3 })
339 }
340
341 fn is_slice_end(&mut self) -> bool { self.mb_x + self.mb_y * self.mb_w >= self.mb_end }
342
343 fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
344 let stride = buf.get_stride(0);
345 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
346 for mb_x in 0..mb_w {
347 let coff = off;
348 let coded0 = cbpi.is_coded(mb_x, 0);
349 let coded1 = cbpi.is_coded(mb_x, 1);
350 let q = cbpi.get_q(mb_w + mb_x);
351 if mb_y != 0 {
352 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
353 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
354 }
355 let coff = off + 8 * stride;
356 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
357 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
358 off += 16;
359 }
360 let mut leftt = false;
361 let mut leftc = false;
362 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
363 for mb_x in 0..mb_w {
364 let ctop0 = cbpi.is_coded_top(mb_x, 0);
365 let ctop1 = cbpi.is_coded_top(mb_x, 0);
366 let ccur0 = cbpi.is_coded(mb_x, 0);
367 let ccur1 = cbpi.is_coded(mb_x, 1);
368 let q = cbpi.get_q(mb_w + mb_x);
369 if mb_y != 0 {
370 let coff = off - 8 * stride;
371 let qtop = cbpi.get_q(mb_x);
372 if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
373 if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
374 }
375 if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
376 if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
377 leftt = ctop1;
378 leftc = ccur1;
379 off += 16;
380 }
381 let strideu = buf.get_stride(1);
382 let stridev = buf.get_stride(2);
383 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
384 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
385 if mb_y != 0 {
386 for mb_x in 0..mb_w {
387 let ctu = cbpi.is_coded_top(mb_x, 4);
388 let ccu = cbpi.is_coded(mb_x, 4);
389 let ctv = cbpi.is_coded_top(mb_x, 5);
390 let ccv = cbpi.is_coded(mb_x, 5);
391 let q = cbpi.get_q(mb_w + mb_x);
392 if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
393 if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
394 }
395 let mut leftu = false;
396 let mut leftv = false;
397 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
398 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
399 for mb_x in 0..mb_w {
400 let ctu = cbpi.is_coded_top(mb_x, 4);
401 let ctv = cbpi.is_coded_top(mb_x, 5);
402 let qt = cbpi.get_q(mb_x);
403 if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
404 if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
405 leftu = ctu;
406 leftv = ctv;
407 }
408 }
409 }
410}
411
412fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
413 let stride = buf.get_stride(comp);
414 let mut dptr = buf.get_data_mut();
415 let mut buf = dptr.as_mut_slice();
416 for x in 0..8 {
417 let a = buf[off - 2 * stride + x] as i16;
418 let b = buf[off - 1 * stride + x] as i16;
419 let c = buf[off + 0 * stride + x] as i16;
420 let d = buf[off + 1 * stride + x] as i16;
421 let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
422 if (diff != 0) && (diff >= -32) && (diff < 32) {
423 let d0 = diff.abs() * 2 - (q as i16);
424 let d1 = if d0 < 0 { 0 } else { d0 };
425 let d2 = diff.abs() - d1;
426 let d3 = if d2 < 0 { 0 } else { d2 };
427
428 let delta = if diff < 0 { -d3 } else { d3 };
429
430 let b1 = b + delta;
431 if b1 < 0 { buf[off - 1 * stride + x] = 0; }
432 else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
433 else { buf[off - 1 * stride + x] = b1 as u8; }
434 let c1 = c - delta;
435 if c1 < 0 { buf[off + x] = 0; }
436 else if c1 > 255 { buf[off + x] = 0xFF; }
437 else { buf[off + x] = c1 as u8; }
438 }
439 }
440}
441
442impl<'a> RealVideo20BR<'a> {
443 fn read_slice_header(&mut self) -> DecoderResult<RV20SliceInfo> {
444 validate!(self.slice_no < self.num_slices);
445
446 let mut br = &mut self.br;
447 br.seek(self.slice_off[self.slice_no] * 8).unwrap();
448//println!(" slice at off {}", br.tell());
449
450 let frm_type = br.read(2).unwrap();
451 let ftype = match frm_type {
452 0 | 1 => { Type::I },
453 2 => { Type::P },
454 _ => { Type::Skip },
455 };
456
457 let marker = br.read(1).unwrap();
458 validate!(marker == 0);
459 let qscale = br.read(5).unwrap() as u8;
460 validate!(qscale > 0);
461 if self.minor_ver >= 2 {
462 br.skip(1).unwrap(); // loop filter
463 }
464 let seq = if self.minor_ver <= 1 {
465 br.read(8).unwrap() << 7
466 } else {
467 br.read(13).unwrap() << 2
468 };
469 let w;
470 let h;
471 if self.rpr.present {
472 let rpr = br.read(self.rpr.bits).unwrap() as usize;
473 if rpr == 0 {
474 w = self.w;
475 h = self.h;
476 } else {
477 w = self.rpr.widths[rpr];
478 h = self.rpr.heights[rpr];
479 validate!((w != 0) && (h != 0));
480 }
481 } else {
482 w = self.w;
483 h = self.h;
484 }
485
486 let mb_pos = br.read(self.mb_pos_bits).unwrap() as usize;
487 let mb_x = mb_pos % self.mb_w;
488 let mb_y = mb_pos / self.mb_w;
489
490 br.skip(1).unwrap(); // no rounding
491
492 if (self.minor_ver <= 1) && (frm_type == 3) {
493 br.skip(5).unwrap();
494 }
495println!("slice q {} mb {},{}", qscale, mb_x, mb_y);
496
497 Ok(RV20SliceInfo::new(ftype, qscale, mb_x, mb_y, mb_pos, w, h))
498 }
499}
500
501fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
502 let stride = buf.get_stride(comp);
503 let mut dptr = buf.get_data_mut();
504 let mut buf = dptr.as_mut_slice();
505 for y in 0..8 {
506 let a = buf[off - 2 + y * stride] as i16;
507 let b = buf[off - 1 + y * stride] as i16;
508 let c = buf[off + 0 + y * stride] as i16;
509 let d = buf[off + 1 + y * stride] as i16;
510 let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
511 if (diff != 0) && (diff >= -32) && (diff < 32) {
512 let d0 = diff.abs() * 2 - (q as i16);
513 let d1 = if d0 < 0 { 0 } else { d0 };
514 let d2 = diff.abs() - d1;
515 let d3 = if d2 < 0 { 0 } else { d2 };
516
517 let delta = if diff < 0 { -d3 } else { d3 };
518
519 let b1 = b + delta;
520 if b1 < 0 { buf[off - 1 + y * stride] = 0; }
521 else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
522 else { buf[off - 1 + y * stride] = b1 as u8; }
523 let c1 = c - delta;
524 if c1 < 0 { buf[off + y * stride] = 0; }
525 else if c1 > 255 { buf[off + y * stride] = 0xFF; }
526 else { buf[off + y * stride] = c1 as u8; }
527 }
528 }
529}
530
531impl RealVideo20Decoder {
532 fn new() -> Self {
533 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
534 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
535 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
536 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
537 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
538 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
539 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
540 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
541 let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
542 let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
543 let mut coderead = H263ShortCodeReader::new(H263_MV);
544 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
545
546 let tables = Tables {
547 intra_mcbpc_cb: intra_mcbpc_cb,
548 inter_mcbpc_cb: inter_mcbpc_cb,
549 cbpy_cb: cbpy_cb,
550 rl_cb: rl_cb,
551 aic_rl_cb: aic_rl_cb,
552 mv_cb: mv_cb,
553 };
554
555 RealVideo20Decoder{
556 info: Rc::new(DUMMY_CODEC_INFO),
557 dec: H263BaseDecoder::new(),
558 tables: tables,
559 w: 0,
560 h: 0,
561 minor_ver: 0,
562 rpr: RPRInfo { present: false, bits: 0, widths: [0; 8], heights: [0; 8] },
563 }
564 }
565}
566
567impl NADecoder for RealVideo20Decoder {
568 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
569 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
570 let w = vinfo.get_width();
571 let h = vinfo.get_height();
572 let fmt = formats::YUV420_FORMAT;
573 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
574 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
575 self.w = w;
576 self.h = h;
577
578 let edata = info.get_extradata().unwrap();
579 let src: &[u8] = &edata;
580 let ver = ((src[4] as u32) << 12) | ((src[5] as u32) << 4) | ((src[6] as u32) >> 4);
581 let maj_ver = ver >> 16;
582 let min_ver = (ver >> 8) & 0xFF;
583 let mic_ver = ver & 0xFF;
584println!("ver {:06X}", ver);
585 validate!(maj_ver == 2);
586 self.minor_ver = min_ver as u8;
587 let rprb = src[1] & 7;
588 if rprb == 0 {
589 self.rpr.present = false;
590 } else {
591 self.rpr.present = true;
592 self.rpr.bits = rprb as u8;
593 for i in 4..(src.len()/2) {
594 self.rpr.widths [i - 4] = (src[i * 2] as usize) * 4;
595 self.rpr.heights[i - 4] = (src[i * 2 + 1] as usize) * 4;
596 }
597 }
598 Ok(())
599 } else {
600println!(".unwrap().unwrap().unwrap()");
601 Err(DecoderError::InvalidData)
602 }
603 }
604 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
605 let src = pkt.get_buffer();
606
607println!(" decode frame size {}, {} slices", src.len(), src[0]+1);
608 let mut ibr = RealVideo20BR::new(&src, &self.tables, self.w, self.h, self.minor_ver, self.rpr);
609
610 let bufinfo = self.dec.parse_frame(&mut ibr).unwrap();
611
612 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
613 frm.set_keyframe(self.dec.is_intra());
614 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
615 Ok(Rc::new(RefCell::new(frm)))
616 }
617}
618
619struct MBB { blocks: usize, bits: u8 }
620const H263_MBB: &[MBB; 7] = &[
621 MBB{ blocks: 47, bits: 6 },
622 MBB{ blocks: 98, bits: 7 },
623 MBB{ blocks: 395, bits: 9 },
624 MBB{ blocks: 1583, bits: 11 },
625 MBB{ blocks: 6335, bits: 13 },
626 MBB{ blocks: 9215, bits: 14 },
627 MBB{ blocks: 65536, bits: 14 },
628];
629
630pub fn get_decoder() -> Box<NADecoder> {
631 Box::new(RealVideo20Decoder::new())
632}
633
634#[cfg(test)]
635mod test {
636 use test::dec_video::test_file_decoding;
637 #[test]
638 fn test_rv20() {
639 test_file_decoding("realmedia", "assets/RV/rv20_cook_640x352_realproducer_plus_8.51.rm", None/*Some(160)*/, true, false, Some("rv20"));
640 }
641}