factor out decoder test
[nihav.git] / src / codecs / h263 / intel263.rs
1 use io::bitreader::*;
2 use io::codebook::*;
3 use formats;
4 use super::super::*;
5 use super::*;
6 use super::decoder::*;
7 use super::data::*;
8
9 #[allow(dead_code)]
10 struct 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 struct Intel263Decoder {
20 info: Rc<NACodecInfo>,
21 dec: H263BaseDecoder,
22 tables: Tables,
23 }
24
25 struct Intel263BR<'a> {
26 br: BitReader<'a>,
27 tables: &'a Tables,
28 gob_no: usize,
29 mb_w: usize,
30 is_pb: bool,
31 }
32
33 fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> {
34 let mark = br.read(1)?;
35 validate!(mark == 1);
36 Ok(())
37 }
38
39 impl<'a> Intel263BR<'a> {
40 fn new(src: &'a [u8], tables: &'a Tables) -> Self {
41 Intel263BR {
42 br: BitReader::new(src, src.len(), BitReaderMode::BE),
43 tables: tables,
44 gob_no: 0,
45 mb_w: 0,
46 is_pb: false,
47 }
48 }
49
50 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
51 let mut br = &mut self.br;
52 let mut idx = 0;
53 if intra {
54 let mut dc = br.read(8)?;
55 if dc == 255 { dc = 128; }
56 blk[0] = (dc as i16) << 3;
57 idx = 1;
58 }
59 if !coded { return Ok(()); }
60
61 let rl_cb = &self.tables.rl_cb; // could be aic too
62 let q_add = if quant == 0 { 0i16 } else { ((quant - 1) | 1) as i16 };
63 let q = (quant * 2) as i16;
64 while idx < 64 {
65 let code = br.read_cb(rl_cb)?;
66 let run;
67 let mut level;
68 let last;
69 if !code.is_escape() {
70 run = code.get_run();
71 level = code.get_level();
72 last = code.is_last();
73 if br.read_bool()? { level = -level; }
74 level = (level * q) + q_add;
75 } else {
76 last = br.read_bool()?;
77 run = br.read(6)? as u8;
78 level = br.read_s(8)? as i16;
79 if level == -128 {
80 let low = br.read(5)? as i16;
81 let top = br.read_s(6)? as i16;
82 level = (top << 5) | low;
83 }
84 level = (level * q) + q_add;
85 if level < -2048 { level = -2048; }
86 if level > 2047 { level = 2047; }
87 }
88 idx += run;
89 validate!(idx < 64);
90 let oidx = H263_ZIGZAG[idx as usize];
91 blk[oidx] = level;
92 idx += 1;
93 if last { break; }
94 }
95 Ok(())
96 }
97 }
98
99 fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
100 let code = br.read_cb(mv_cb)? as i16;
101 if code == 0 { return Ok(0) }
102 if !br.read_bool()? {
103 Ok(code)
104 } else {
105 Ok(-code)
106 }
107 }
108
109 fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
110 let xval = decode_mv_component(br, mv_cb)?;
111 let yval = decode_mv_component(br, mv_cb)?;
112 Ok(MV::new(xval, yval))
113 }
114
115 fn decode_b_info(br: &mut BitReader, is_pb: bool, is_intra: bool) -> DecoderResult<BBlockInfo> {
116 if is_pb { // as improved pb
117 let pb_mv_add = if is_intra { 1 } else { 0 };
118 if br.read_bool()?{
119 if br.read_bool()? {
120 let pb_mv_count = 1 - (br.read(1)? as usize);
121 let cbpb = br.read(6)? as u8;
122 Ok(BBlockInfo::new(true, cbpb, pb_mv_count + pb_mv_add, pb_mv_count == 1))
123 } else {
124 Ok(BBlockInfo::new(true, 0, 1 + pb_mv_add, true))
125 }
126 } else {
127 Ok(BBlockInfo::new(true, 0, pb_mv_add, false))
128 }
129 } else {
130 Ok(BBlockInfo::new(false, 0, 0, false))
131 }
132 }
133
134 impl<'a> BlockDecoder for Intel263BR<'a> {
135
136 #[allow(unused_variables)]
137 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
138 let mut br = &mut self.br;
139 let syncw = br.read(22)?;
140 validate!(syncw == 0x000020);
141 let tr = br.read(8)? as u8;
142 check_marker(br)?;
143 let id = br.read(1)?;
144 validate!(id == 0);
145 br.read(1)?; // split screen indicator
146 br.read(1)?; // document camera indicator
147 br.read(1)?; // freeze picture release
148 let mut sfmt = br.read(3)?;
149 validate!((sfmt != 0b000) && (sfmt != 0b110));
150 let is_intra = !br.read_bool()?;
151 let umv = br.read_bool()?;
152 br.read(1)?; // syntax arithmetic coding
153 let apm = br.read_bool()?;
154 self.is_pb = br.read_bool()?;
155 let deblock;
156 if sfmt == 0b111 {
157 sfmt = br.read(3)?;
158 validate!((sfmt != 0b000) && (sfmt != 0b111));
159 br.read(2)?; // unknown flags
160 deblock = br.read_bool()?;
161 br.read(1)?; // unknown flag
162 let pbplus = br.read_bool()?;
163 br.read(5)?; // unknown flags
164 let marker = br.read(5)?;
165 validate!(marker == 1);
166 } else {
167 deblock = false;
168 }
169 let w; let h;
170 if sfmt == 0b110 {
171 let par = br.read(4)?;
172 w = ((br.read(9)? + 1) * 4) as usize;
173 check_marker(br)?;
174 h = ((br.read(9)? + 1) * 4) as usize;
175 if par == 0b1111 {
176 let pixw = br.read(8)?;
177 let pixh = br.read(8)?;
178 validate!((pixw != 0) && (pixh != 0));
179 }
180 } else {
181 let (w_, h_) = H263_SIZES[sfmt as usize];
182 w = w_;
183 h = h_;
184 }
185 let quant = br.read(5)?;
186 let cpm = br.read_bool()?;
187 validate!(!cpm);
188
189 let pbinfo;
190 if self.is_pb {
191 let trb = br.read(3)?;
192 let dbquant = br.read(2)?;
193 pbinfo = Some(PBInfo::new(trb as u8, dbquant as u8));
194 } else {
195 pbinfo = None;
196 }
197 while br.read_bool()? { // skip PEI
198 br.read(8)?;
199 }
200 //println!("frame {}x{} intra: {} q {} pb {} apm {} umv {} @{}", w, h, is_intra, quant, self.is_pb, apm, umv, br.tell());
201 self.gob_no = 0;
202 self.mb_w = (w + 15) >> 4;
203
204 let ftype = if is_intra { Type::I } else { Type::P };
205 let picinfo = PicInfo::new(w, h, ftype, quant as u8, apm, umv, tr, pbinfo, deblock);
206 Ok(picinfo)
207 }
208
209 #[allow(unused_variables)]
210 fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
211 let mut br = &mut self.br;
212 let gbsc = br.read(17)?;
213 validate!(gbsc == 1);
214 let gn = br.read(5)?;
215 let gfid = br.read(2)?;
216 let gquant = br.read(5)?;
217 //println!("GOB gn {:X} id {} q {}", gn, gfid, gquant);
218 let ret = Slice::new(0, self.gob_no, gquant as u8);
219 self.gob_no += 1;
220 Ok(ret)
221 }
222
223 fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
224 let mut br = &mut self.br;
225 let mut q = slice.get_quant();
226 match info.get_mode() {
227 Type::I => {
228 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?;
229 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; }
230 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
231 let cbp = (cbpy << 2) | (cbpc & 3);
232 let dquant = (cbpc & 4) != 0;
233 if dquant {
234 let idx = br.read(2)? as usize;
235 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
236 }
237 Ok(BlockInfo::new(Type::I, cbp, q))
238 },
239 Type::P => {
240 if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); }
241 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
242 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; }
243 let is_intra = (cbpc & 0x04) != 0;
244 let dquant = (cbpc & 0x08) != 0;
245 let is_4x4 = (cbpc & 0x10) != 0;
246 if is_intra {
247 let mut mvec: Vec<MV> = Vec::new();
248 let bbinfo = decode_b_info(br, self.is_pb, true)?;
249 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
250 let cbp = (cbpy << 2) | (cbpc & 3);
251 if dquant {
252 let idx = br.read(2)? as usize;
253 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
254 }
255 let mut binfo = BlockInfo::new(Type::I, cbp, q);
256 binfo.set_bpart(bbinfo);
257 if self.is_pb {
258 for _ in 0..bbinfo.get_num_mv() {
259 mvec.push(decode_mv(br, &self.tables.mv_cb)?);
260 }
261 binfo.set_b_mv(mvec.as_slice());
262 }
263 return Ok(binfo);
264 }
265
266 let bbinfo = decode_b_info(br, self.is_pb, false)?;
267 let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?;
268 // if /* !aiv && */(cbpc & 3) != 3 {
269 cbpy ^= 0xF;
270 // }
271 let cbp = (cbpy << 2) | (cbpc & 3);
272 if dquant {
273 let idx = br.read(2)? as usize;
274 q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
275 }
276 let mut binfo = BlockInfo::new(Type::P, cbp, q);
277 binfo.set_bpart(bbinfo);
278 if !is_4x4 {
279 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
280 binfo.set_mv(&mvec);
281 } else {
282 let mvec: [MV; 4] = [
283 decode_mv(br, &self.tables.mv_cb)?,
284 decode_mv(br, &self.tables.mv_cb)?,
285 decode_mv(br, &self.tables.mv_cb)?,
286 decode_mv(br, &self.tables.mv_cb)?
287 ];
288 binfo.set_mv(&mvec);
289 }
290 if self.is_pb {
291 let mut mvec: Vec<MV> = Vec::with_capacity(bbinfo.get_num_mv());
292 for _ in 0..bbinfo.get_num_mv() {
293 let mv = decode_mv(br, &self.tables.mv_cb)?;
294 mvec.push(mv);
295 }
296 binfo.set_b_mv(mvec.as_slice());
297 }
298 Ok(binfo)
299 },
300 _ => { Err(DecoderError::InvalidData) },
301 }
302 }
303
304 #[allow(unused_variables)]
305 fn decode_block_intra(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
306 self.decode_block(quant, true, coded, blk)
307 }
308
309 #[allow(unused_variables)]
310 fn decode_block_inter(&mut self, info: &BlockInfo, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
311 self.decode_block(quant, false, coded, blk)
312 }
313
314 fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
315
316 fn filter_row(&mut self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
317 let stride = buf.get_stride(0);
318 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
319 for mb_x in 0..mb_w {
320 let coff = off;
321 let coded0 = cbpi.is_coded(mb_x, 0);
322 let coded1 = cbpi.is_coded(mb_x, 1);
323 let q = cbpi.get_q(mb_w + mb_x);
324 if mb_y != 0 {
325 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, q, coff); }
326 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, q, coff + 8); }
327 }
328 let coff = off + 8 * stride;
329 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
330 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
331 off += 16;
332 }
333 let mut leftt = false;
334 let mut leftc = false;
335 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
336 for mb_x in 0..mb_w {
337 let ctop0 = cbpi.is_coded_top(mb_x, 0);
338 let ctop1 = cbpi.is_coded_top(mb_x, 0);
339 let ccur0 = cbpi.is_coded(mb_x, 0);
340 let ccur1 = cbpi.is_coded(mb_x, 1);
341 let q = cbpi.get_q(mb_w + mb_x);
342 if mb_y != 0 {
343 let coff = off - 8 * stride;
344 let qtop = cbpi.get_q(mb_x);
345 if leftt && ctop0 { deblock_ver(buf, 0, qtop, coff); }
346 if ctop0 && ctop1 { deblock_ver(buf, 0, qtop, coff + 8); }
347 }
348 if leftc && ccur0 { deblock_ver(buf, 0, q, off); }
349 if ccur0 && ccur1 { deblock_ver(buf, 0, q, off + 8); }
350 leftt = ctop1;
351 leftc = ccur1;
352 off += 16;
353 }
354 let strideu = buf.get_stride(1);
355 let stridev = buf.get_stride(2);
356 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
357 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
358 if mb_y != 0 {
359 for mb_x in 0..mb_w {
360 let ctu = cbpi.is_coded_top(mb_x, 4);
361 let ccu = cbpi.is_coded(mb_x, 4);
362 let ctv = cbpi.is_coded_top(mb_x, 5);
363 let ccv = cbpi.is_coded(mb_x, 5);
364 let q = cbpi.get_q(mb_w + mb_x);
365 if ctu && ccu { deblock_hor(buf, 1, q, offu + mb_x * 8); }
366 if ctv && ccv { deblock_hor(buf, 2, q, offv + mb_x * 8); }
367 }
368 let mut leftu = false;
369 let mut leftv = false;
370 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
371 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
372 for mb_x in 0..mb_w {
373 let ctu = cbpi.is_coded_top(mb_x, 4);
374 let ctv = cbpi.is_coded_top(mb_x, 5);
375 let qt = cbpi.get_q(mb_x);
376 if leftu && ctu { deblock_ver(buf, 1, qt, offu + mb_x * 8); }
377 if leftv && ctv { deblock_ver(buf, 2, qt, offv + mb_x * 8); }
378 leftu = ctu;
379 leftv = ctv;
380 }
381 }
382 }
383 }
384
385 fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
386 let stride = buf.get_stride(comp);
387 let mut dptr = buf.get_data_mut();
388 let mut buf = dptr.as_mut_slice();
389 for x in 0..8 {
390 let a = buf[off - 2 * stride + x] as i16;
391 let b = buf[off - 1 * stride + x] as i16;
392 let c = buf[off + 0 * stride + x] as i16;
393 let d = buf[off + 1 * stride + x] as i16;
394 let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
395 if (diff != 0) && (diff >= -32) && (diff < 32) {
396 let d0 = diff.abs() * 2 - (q as i16);
397 let d1 = if d0 < 0 { 0 } else { d0 };
398 let d2 = diff.abs() - d1;
399 let d3 = if d2 < 0 { 0 } else { d2 };
400
401 let delta = if diff < 0 { -d3 } else { d3 };
402
403 let b1 = b + delta;
404 if b1 < 0 { buf[off - 1 * stride + x] = 0; }
405 else if b1 > 255 { buf[off - 1 * stride + x] = 0xFF; }
406 else { buf[off - 1 * stride + x] = b1 as u8; }
407 let c1 = c - delta;
408 if c1 < 0 { buf[off + x] = 0; }
409 else if c1 > 255 { buf[off + x] = 0xFF; }
410 else { buf[off + x] = c1 as u8; }
411 }
412 }
413 }
414
415 fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, q: u8, off: usize) {
416 let stride = buf.get_stride(comp);
417 let mut dptr = buf.get_data_mut();
418 let mut buf = dptr.as_mut_slice();
419 for y in 0..8 {
420 let a = buf[off - 2 + y * stride] as i16;
421 let b = buf[off - 1 + y * stride] as i16;
422 let c = buf[off + 0 + y * stride] as i16;
423 let d = buf[off + 1 + y * stride] as i16;
424 let diff = ((a - d) * 3 + (c - b) * 8) >> 4;
425 if (diff != 0) && (diff >= -32) && (diff < 32) {
426 let d0 = diff.abs() * 2 - (q as i16);
427 let d1 = if d0 < 0 { 0 } else { d0 };
428 let d2 = diff.abs() - d1;
429 let d3 = if d2 < 0 { 0 } else { d2 };
430
431 let delta = if diff < 0 { -d3 } else { d3 };
432
433 let b1 = b + delta;
434 if b1 < 0 { buf[off - 1 + y * stride] = 0; }
435 else if b1 > 255 { buf[off - 1 + y * stride] = 0xFF; }
436 else { buf[off - 1 + y * stride] = b1 as u8; }
437 let c1 = c - delta;
438 if c1 < 0 { buf[off + y * stride] = 0; }
439 else if c1 > 255 { buf[off + y * stride] = 0xFF; }
440 else { buf[off + y * stride] = c1 as u8; }
441 }
442 }
443 }
444
445 impl Intel263Decoder {
446 fn new() -> Self {
447 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
448 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
449 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
450 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
451 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
452 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
453 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
454 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
455 let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
456 let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
457 let mut coderead = H263ShortCodeReader::new(H263_MV);
458 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
459 let tables = Tables {
460 intra_mcbpc_cb: intra_mcbpc_cb,
461 inter_mcbpc_cb: inter_mcbpc_cb,
462 cbpy_cb: cbpy_cb,
463 rl_cb: rl_cb,
464 aic_rl_cb: aic_rl_cb,
465 mv_cb: mv_cb,
466 };
467
468 Intel263Decoder{
469 info: Rc::new(DUMMY_CODEC_INFO),
470 dec: H263BaseDecoder::new(),
471 tables: tables,
472 }
473 }
474 }
475
476 impl NADecoder for Intel263Decoder {
477 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
478 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
479 let w = vinfo.get_width();
480 let h = vinfo.get_height();
481 let fmt = formats::YUV420_FORMAT;
482 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
483 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
484 Ok(())
485 } else {
486 Err(DecoderError::InvalidData)
487 }
488 }
489 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
490 let src = pkt.get_buffer();
491
492 if src.len() == 8 {
493 let bret = self.dec.get_bframe();
494 let buftype;
495 let is_skip;
496 if let Ok(btype) = bret {
497 buftype = btype;
498 is_skip = false;
499 } else {
500 buftype = NABufferType::None;
501 is_skip = true;
502 }
503 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
504 frm.set_keyframe(false);
505 frm.set_frame_type(if is_skip { FrameType::Skip } else { FrameType::B });
506 return Ok(Rc::new(RefCell::new(frm)));
507 }
508 let mut ibr = Intel263BR::new(&src, &self.tables);
509
510 let bufinfo = self.dec.parse_frame(&mut ibr)?;
511
512 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
513 frm.set_keyframe(self.dec.is_intra());
514 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
515 Ok(Rc::new(RefCell::new(frm)))
516 }
517 }
518
519
520 pub fn get_decoder() -> Box<NADecoder> {
521 Box::new(Intel263Decoder::new())
522 }
523
524 #[cfg(test)]
525 mod test {
526 use test::dec_video::test_file_decoding;
527 #[test]
528 fn test_intel263() {
529 test_file_decoding("avi", "assets/neal73_saber.avi", Some(16), true, false, None);
530 }
531 }