rename register_all_codecs to register_all_decoders
[nihav.git] / nihav-indeo / src / codecs / intel263.rs
CommitLineData
5641dccf
KS
1use nihav_core::io::bitreader::*;
2use nihav_core::io::codebook::*;
3use nihav_core::formats;
4use nihav_core::frame::*;
5use nihav_core::codecs::*;
b4d5b851 6use nihav_codec_support::codecs::{MV, ZIGZAG};
04bbfe10 7use nihav_codec_support::codecs::blockdsp;
b4d5b851 8use nihav_codec_support::codecs::h263::*;
04bbfe10 9use nihav_codec_support::codecs::h263::code::{H263_INTERP_FUNCS, H263_INTERP_AVG_FUNCS};
b4d5b851
KS
10use nihav_codec_support::codecs::h263::decoder::*;
11use nihav_codec_support::codecs::h263::data::*;
cf64af13
KS
12
13#[allow(dead_code)]
14struct Tables {
15 intra_mcbpc_cb: Codebook<u8>,
16 inter_mcbpc_cb: Codebook<u8>,
17 cbpy_cb: Codebook<u8>,
18 rl_cb: Codebook<H263RLSym>,
19 aic_rl_cb: Codebook<H263RLSym>,
20 mv_cb: Codebook<u8>,
21}
22
04bbfe10
KS
23#[derive(Default)]
24struct I263BlockDSP {}
25
cf64af13 26struct Intel263Decoder {
2422d969 27 info: NACodecInfoRef,
88c58b1b 28 dec: H263BaseDecoder,
cf64af13 29 tables: Tables,
04bbfe10 30 bdsp: I263BlockDSP,
2f67d8bb
KS
31 lastframe: Option<NABufferType>,
32 lastpts: Option<u64>,
cf64af13
KS
33}
34
35struct Intel263BR<'a> {
36 br: BitReader<'a>,
37 tables: &'a Tables,
38 gob_no: usize,
39 mb_w: usize,
40 is_pb: bool,
effbebce 41 is_ipb: bool,
cf64af13
KS
42}
43
04bbfe10
KS
44const W1: i32 = 2841;
45const W2: i32 = 2676;
46const W3: i32 = 2408;
47const W5: i32 = 1609;
48const W6: i32 = 1108;
49const W7: i32 = 565;
50const W8: i32 = 181;
51
52const ROW_SHIFT: u8 = 8;
53const COL_SHIFT: u8 = 14;
54
55#[allow(clippy::erasing_op)]
56fn idct_row(row: &mut [i16]) {
57 let in0 = ((i32::from(row[0])) << 11) + (1 << (ROW_SHIFT - 1));
58 let in1 = (i32::from(row[4])) << 11;
59 let in2 = i32::from(row[6]);
60 let in3 = i32::from(row[2]);
61 let in4 = i32::from(row[1]);
62 let in5 = i32::from(row[7]);
63 let in6 = i32::from(row[5]);
64 let in7 = i32::from(row[3]);
65
66 let tmp = W7 * (in4 + in5);
67 let a4 = tmp + (W1 - W7) * in4;
68 let a5 = tmp - (W1 + W7) * in5;
69
70 let tmp = W3 * (in6 + in7);
71 let a6 = tmp - (W3 - W5) * in6;
72 let a7 = tmp - (W3 + W5) * in7;
73
74 let tmp = in0 + in1;
75
76 let a0 = in0 - in1;
77 let t1 = W6 * (in2 + in3);
78 let a2 = t1 - (W2 + W6) * in2;
79 let a3 = t1 + (W2 - W6) * in3;
80 let b1 = a4 + a6;
81
82 let b4 = a4 - a6;
83 let t2 = a5 - a7;
84 let b6 = a5 + a7;
85 let b7 = tmp + a3;
86 let b5 = tmp - a3;
87 let b3 = a0 + a2;
88 let b0 = a0 - a2;
89 let b2 = (W8 * (b4 + t2) + 128) >> 8;
90 let b4 = (W8 * (b4 - t2) + 128) >> 8;
91
92 row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
93 row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
94 row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
95 row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
96 row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
97 row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
98 row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
99 row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
100}
101
102#[allow(clippy::erasing_op)]
103fn idct_col(blk: &mut [i16; 64], off: usize) {
104 let in0 = ((i32::from(blk[off + 0*8])) << 8) + (1 << (COL_SHIFT - 1));
105 let in1 = (i32::from(blk[off + 4*8])) << 8;
106 let in2 = i32::from(blk[off + 6*8]);
107 let in3 = i32::from(blk[off + 2*8]);
108 let in4 = i32::from(blk[off + 1*8]);
109 let in5 = i32::from(blk[off + 7*8]);
110 let in6 = i32::from(blk[off + 5*8]);
111 let in7 = i32::from(blk[off + 3*8]);
112
113 let tmp = W7 * (in4 + in5);
114 let a4 = (tmp + (W1 - W7) * in4) >> 3;
115 let a5 = (tmp - (W1 + W7) * in5) >> 3;
116
117 let tmp = W3 * (in6 + in7);
118 let a6 = (tmp - (W3 - W5) * in6) >> 3;
119 let a7 = (tmp - (W3 + W5) * in7) >> 3;
120
121 let tmp = in0 + in1;
122
123 let a0 = in0 - in1;
124 let t1 = W6 * (in2 + in3);
125 let a2 = (t1 - (W2 + W6) * in2) >> 3;
126 let a3 = (t1 + (W2 - W6) * in3) >> 3;
127 let b1 = a4 + a6;
128
129 let b4 = a4 - a6;
130 let t2 = a5 - a7;
131 let b6 = a5 + a7;
132 let b7 = tmp + a3;
133 let b5 = tmp - a3;
134 let b3 = a0 + a2;
135 let b0 = a0 - a2;
136 let b2 = (W8 * (b4 + t2) + 128) >> 8;
137 let b4 = (W8 * (b4 - t2) + 128) >> 8;
138
139 blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
140 blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
141 blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
142 blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
143 blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
144 blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
145 blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
146 blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
147}
148
149const FILTER_STRENGTH: [u8; 32] = [
150 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7,
151 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12
152];
153
154#[allow(clippy::erasing_op)]
155fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
156 let stride = buf.get_stride(comp);
157 let dptr = buf.get_data_mut().unwrap();
158 let buf = dptr.as_mut_slice();
159 for x in 0..8 {
5a6dec5f
KS
160 let a = i16::from(buf[off - 2 * stride + x]);
161 let b = i16::from(buf[off - 1 * stride + x]);
162 let c = i16::from(buf[off + 0 * stride + x]);
163 let d = i16::from(buf[off + 1 * stride + x]);
04bbfe10
KS
164 let diff = (3 * (a - d) + 8 * (c - b)) / 16;
165 if (diff != 0) && (diff > -24) && (diff < 24) {
5a6dec5f 166 let d1a = (diff.abs() - 2 * (diff.abs() - i16::from(strength)).max(0)).max(0);
04bbfe10
KS
167 let d1 = if diff < 0 { -d1a } else { d1a };
168
169 buf[off - 1 * stride + x] = (b + d1).max(0).min(255) as u8;
170 buf[off + 0 * stride + x] = (c - d1).max(0).min(255) as u8;
171 }
172 }
173}
174
175fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
176 let stride = buf.get_stride(comp);
177 let dptr = buf.get_data_mut().unwrap();
178 let buf = dptr.as_mut_slice();
179 for y in 0..8 {
5a6dec5f
KS
180 let a = i16::from(buf[off - 2 + y * stride]);
181 let b = i16::from(buf[off - 1 + y * stride]);
182 let c = i16::from(buf[off + 0 + y * stride]);
183 let d = i16::from(buf[off + 1 + y * stride]);
04bbfe10
KS
184 let diff = (3 * (a - d) + 8 * (c - b)) / 16;
185 if (diff != 0) && (diff > -24) && (diff < 24) {
5a6dec5f 186 let d1a = (diff.abs() - 2 * (diff.abs() - i16::from(strength)).max(0)).max(0);
04bbfe10
KS
187 let d1 = if diff < 0 { -d1a } else { d1a };
188
189 buf[off - 1 + y * stride] = (b + d1).max(0).min(255) as u8;
190 buf[off + y * stride] = (c - d1).max(0).min(255) as u8;
191 }
192 }
193}
194
195impl BlockDSP for I263BlockDSP {
196 fn idct(&self, blk: &mut [i16; 64]) {
197 for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
198 for i in 0..8 { idct_col(blk, i); }
199 }
200 fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
201 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
202 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
203
204 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
205
206 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_FUNCS);
207 blockdsp::copy_block(&mut dst, src.clone(), 1, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
208 blockdsp::copy_block(&mut dst, src.clone(), 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
209 }
210 fn copy_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
211 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
212
213 for i in 0..4 {
214 let xadd = (i & 1) * 8;
215 let yadd = (i & 2) * 4;
216 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
217
218 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
219 }
220
221 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
222 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
223 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
224 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
225 for plane in 1..3 {
226 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
227 }
228 }
229 fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
230 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
231 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
232
233 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
234
235 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_AVG_FUNCS);
236 blockdsp::copy_block(&mut dst, src.clone(), 1, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
237 blockdsp::copy_block(&mut dst, src.clone(), 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
238 }
239 fn avg_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
240 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
241
242 for i in 0..4 {
243 let xadd = (i & 1) * 8;
244 let yadd = (i & 2) * 4;
245 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
246
247 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
248 }
249
250 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
251 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
252 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
253 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
254 for plane in 1..3 {
255 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
256 }
257 }
258 fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
259 let stride = buf.get_stride(0);
260 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
261 for mb_x in 0..mb_w {
262 let coff = off;
263 let coded0 = cbpi.is_coded(mb_x, 0);
264 let coded1 = cbpi.is_coded(mb_x, 1);
265 let q = cbpi.get_q(mb_w + mb_x);
266 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
267 if mb_y != 0 {
268 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, str, coff); }
269 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, str, coff + 8); }
270 }
271 let coff = off + 8 * stride;
272 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
273 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
274 off += 16;
275 }
276 let mut leftt = false;
277 let mut leftc = false;
278 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
279 for mb_x in 0..mb_w {
280 let ctop0 = cbpi.is_coded_top(mb_x, 0);
281 let ctop1 = cbpi.is_coded_top(mb_x, 0);
282 let ccur0 = cbpi.is_coded(mb_x, 0);
283 let ccur1 = cbpi.is_coded(mb_x, 1);
284 let q = cbpi.get_q(mb_w + mb_x);
285 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
286 if mb_y != 0 {
287 let coff = off - 8 * stride;
288 let qtop = cbpi.get_q(mb_x);
289 let strtop = if qtop < 32 { FILTER_STRENGTH[qtop as usize] } else { 0 };
290 if leftt && ctop0 { deblock_ver(buf, 0, strtop, coff); }
291 if ctop0 && ctop1 { deblock_ver(buf, 0, strtop, coff + 8); }
292 }
293 if leftc && ccur0 { deblock_ver(buf, 0, str, off); }
294 if ccur0 && ccur1 { deblock_ver(buf, 0, str, off + 8); }
295 leftt = ctop1;
296 leftc = ccur1;
297 off += 16;
298 }
299 let strideu = buf.get_stride(1);
300 let stridev = buf.get_stride(2);
301 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
302 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
303 if mb_y != 0 {
304 for mb_x in 0..mb_w {
305 let ctu = cbpi.is_coded_top(mb_x, 4);
306 let ccu = cbpi.is_coded(mb_x, 4);
307 let ctv = cbpi.is_coded_top(mb_x, 5);
308 let ccv = cbpi.is_coded(mb_x, 5);
309 let q = cbpi.get_q(mb_w + mb_x);
310 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
311 if ctu && ccu { deblock_hor(buf, 1, str, offu + mb_x * 8); }
312 if ctv && ccv { deblock_hor(buf, 2, str, offv + mb_x * 8); }
313 }
314 let mut leftu = false;
315 let mut leftv = false;
316 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
317 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
318 for mb_x in 0..mb_w {
319 let ctu = cbpi.is_coded_top(mb_x, 4);
320 let ctv = cbpi.is_coded_top(mb_x, 5);
321 let qt = cbpi.get_q(mb_x);
322 let strt = if qt < 32 { FILTER_STRENGTH[qt as usize] } else { 0 };
323 if leftu && ctu { deblock_ver(buf, 1, strt, offu + mb_x * 8); }
324 if leftv && ctv { deblock_ver(buf, 2, strt, offv + mb_x * 8); }
325 leftu = ctu;
326 leftv = ctv;
327 }
328 }
329 }
330}
331
cf64af13
KS
332fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> {
333 let mark = br.read(1)?;
334 validate!(mark == 1);
335 Ok(())
336}
337
338impl<'a> Intel263BR<'a> {
339 fn new(src: &'a [u8], tables: &'a Tables) -> Self {
340 Intel263BR {
fa90ccfb 341 br: BitReader::new(src, BitReaderMode::BE),
f2af8eca 342 tables,
cf64af13
KS
343 gob_no: 0,
344 mb_w: 0,
345 is_pb: false,
effbebce 346 is_ipb: false,
cf64af13
KS
347 }
348 }
349
350 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
9037cf6b 351 let br = &mut self.br;
cf64af13
KS
352 let mut idx = 0;
353 if intra {
354 let mut dc = br.read(8)?;
355 if dc == 255 { dc = 128; }
356 blk[0] = (dc as i16) << 3;
357 idx = 1;
358 }
359 if !coded { return Ok(()); }
360
361 let rl_cb = &self.tables.rl_cb; // could be aic too
f2af8eca
KS
362 let q_add = if quant == 0 { 0i16 } else { i16::from((quant - 1) | 1) };
363 let q = i16::from(quant * 2);
cf64af13
KS
364 while idx < 64 {
365 let code = br.read_cb(rl_cb)?;
366 let run;
367 let mut level;
368 let last;
369 if !code.is_escape() {
370 run = code.get_run();
371 level = code.get_level();
372 last = code.is_last();
373 if br.read_bool()? { level = -level; }
1032dfe1
KS
374 if level > 0 {
375 level = (level * q) + q_add;
376 } else {
377 level = (level * q) - q_add;
378 }
cf64af13
KS
379 } else {
380 last = br.read_bool()?;
381 run = br.read(6)? as u8;
382 level = br.read_s(8)? as i16;
383 if level == -128 {
384 let low = br.read(5)? as i16;
385 let top = br.read_s(6)? as i16;
386 level = (top << 5) | low;
387 }
1032dfe1
KS
388 if level > 0 {
389 level = (level * q) + q_add;
390 } else {
391 level = (level * q) - q_add;
392 }
cf64af13
KS
393 if level < -2048 { level = -2048; }
394 if level > 2047 { level = 2047; }
395 }
396 idx += run;
397 validate!(idx < 64);
64e8b971 398 let oidx = ZIGZAG[idx as usize];
cf64af13
KS
399 blk[oidx] = level;
400 idx += 1;
401 if last { break; }
402 }
403 Ok(())
404 }
405}
406
407fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
f2af8eca 408 let code = i16::from(br.read_cb(mv_cb)?);
cf64af13
KS
409 if code == 0 { return Ok(0) }
410 if !br.read_bool()? {
411 Ok(code)
412 } else {
413 Ok(-code)
414 }
415}
416
417fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
418 let xval = decode_mv_component(br, mv_cb)?;
419 let yval = decode_mv_component(br, mv_cb)?;
420 Ok(MV::new(xval, yval))
421}
422
effbebce 423fn decode_b_info(br: &mut BitReader, is_pb: bool, is_ipb: bool, is_intra: bool) -> DecoderResult<BBlockInfo> {
21c16d5f 424 if is_pb { // as improved pb
effbebce
KS
425 if is_ipb {
426 let pb_mv_add = if is_intra { 1 } else { 0 };
427 if br.read_bool()?{
428 if br.read_bool()? {
429 let pb_mv_count = 1 - (br.read(1)? as usize);
430 let cbpb = br.read(6)? as u8;
431 Ok(BBlockInfo::new(true, cbpb, pb_mv_count + pb_mv_add, pb_mv_count == 1))
432 } else {
433 Ok(BBlockInfo::new(true, 0, 1 + pb_mv_add, true))
434 }
21c16d5f 435 } else {
effbebce 436 Ok(BBlockInfo::new(true, 0, pb_mv_add, false))
21c16d5f
KS
437 }
438 } else {
effbebce
KS
439 let mvdb = br.read_bool()?;
440 let cbpb = if mvdb && br.read_bool()? { br.read(6)? as u8 } else { 0 };
441 Ok(BBlockInfo::new(true, cbpb, if mvdb { 1 } else { 0 }, false))
21c16d5f
KS
442 }
443 } else {
444 Ok(BBlockInfo::new(false, 0, 0, false))
445 }
446}
447
cf64af13
KS
448impl<'a> BlockDecoder for Intel263BR<'a> {
449
450#[allow(unused_variables)]
5a6dec5f 451#[allow(clippy::unreadable_literal)]
cf64af13 452 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
9037cf6b 453 let br = &mut self.br;
cf64af13
KS
454 let syncw = br.read(22)?;
455 validate!(syncw == 0x000020);
32007ad9 456 let tr = (br.read(8)? << 8) as u16;
cf64af13
KS
457 check_marker(br)?;
458 let id = br.read(1)?;
459 validate!(id == 0);
460 br.read(1)?; // split screen indicator
461 br.read(1)?; // document camera indicator
462 br.read(1)?; // freeze picture release
463 let mut sfmt = br.read(3)?;
464 validate!((sfmt != 0b000) && (sfmt != 0b110));
465 let is_intra = !br.read_bool()?;
466 let umv = br.read_bool()?;
467 br.read(1)?; // syntax arithmetic coding
468 let apm = br.read_bool()?;
469 self.is_pb = br.read_bool()?;
f2f1afb2 470 let deblock;
effbebce 471 let pbplus;
cf64af13
KS
472 if sfmt == 0b111 {
473 sfmt = br.read(3)?;
474 validate!((sfmt != 0b000) && (sfmt != 0b111));
475 br.read(2)?; // unknown flags
f2f1afb2 476 deblock = br.read_bool()?;
cf64af13 477 br.read(1)?; // unknown flag
effbebce 478 pbplus = br.read_bool()?;
cf64af13
KS
479 br.read(5)?; // unknown flags
480 let marker = br.read(5)?;
481 validate!(marker == 1);
f2f1afb2
KS
482 } else {
483 deblock = false;
effbebce 484 pbplus = false;
cf64af13 485 }
effbebce 486 self.is_ipb = pbplus;
cf64af13
KS
487 let w; let h;
488 if sfmt == 0b110 {
489 let par = br.read(4)?;
490 w = ((br.read(9)? + 1) * 4) as usize;
491 check_marker(br)?;
492 h = ((br.read(9)? + 1) * 4) as usize;
493 if par == 0b1111 {
494 let pixw = br.read(8)?;
495 let pixh = br.read(8)?;
496 validate!((pixw != 0) && (pixh != 0));
497 }
498 } else {
499 let (w_, h_) = H263_SIZES[sfmt as usize];
500 w = w_;
501 h = h_;
502 }
503 let quant = br.read(5)?;
504 let cpm = br.read_bool()?;
505 validate!(!cpm);
21c16d5f
KS
506
507 let pbinfo;
cf64af13
KS
508 if self.is_pb {
509 let trb = br.read(3)?;
510 let dbquant = br.read(2)?;
effbebce 511 pbinfo = Some(PBInfo::new(trb as u8, dbquant as u8, pbplus));
21c16d5f
KS
512 } else {
513 pbinfo = None;
cf64af13
KS
514 }
515 while br.read_bool()? { // skip PEI
516 br.read(8)?;
517 }
21c16d5f 518//println!("frame {}x{} intra: {} q {} pb {} apm {} umv {} @{}", w, h, is_intra, quant, self.is_pb, apm, umv, br.tell());
cf64af13
KS
519 self.gob_no = 0;
520 self.mb_w = (w + 15) >> 4;
521
522 let ftype = if is_intra { Type::I } else { Type::P };
2a2aa421 523 let plusinfo = if deblock { Some(PlusInfo::new(false, deblock, false, false)) } else { None };
32007ad9
KS
524 let mvmode = if umv { MVMode::UMV } else { MVMode::Old };
525 let picinfo = PicInfo::new(w, h, ftype, mvmode, umv, apm, quant as u8, tr, pbinfo, plusinfo);
cf64af13
KS
526 Ok(picinfo)
527 }
528
529 #[allow(unused_variables)]
2a2aa421 530 fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<SliceInfo> {
9037cf6b 531 let br = &mut self.br;
cf64af13 532 let gbsc = br.read(17)?;
cf64af13
KS
533 validate!(gbsc == 1);
534 let gn = br.read(5)?;
535 let gfid = br.read(2)?;
536 let gquant = br.read(5)?;
21c16d5f 537//println!("GOB gn {:X} id {} q {}", gn, gfid, gquant);
2a2aa421 538 let ret = SliceInfo::new_gob(0, self.gob_no, gquant as u8);
cf64af13
KS
539 self.gob_no += 1;
540 Ok(ret)
541 }
542
2a2aa421
KS
543 #[allow(unused_variables)]
544 fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo> {
9037cf6b 545 let br = &mut self.br;
cf64af13
KS
546 let mut q = slice.get_quant();
547 match info.get_mode() {
548 Type::I => {
549 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?;
550 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; }
551 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
552 let cbp = (cbpy << 2) | (cbpc & 3);
553 let dquant = (cbpc & 4) != 0;
554 if dquant {
555 let idx = br.read(2)? as usize;
f2af8eca 556 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
cf64af13 557 }
cf64af13
KS
558 Ok(BlockInfo::new(Type::I, cbp, q))
559 },
560 Type::P => {
cf64af13
KS
561 if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); }
562 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
563 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; }
564 let is_intra = (cbpc & 0x04) != 0;
565 let dquant = (cbpc & 0x08) != 0;
566 let is_4x4 = (cbpc & 0x10) != 0;
567 if is_intra {
568 let mut mvec: Vec<MV> = Vec::new();
effbebce 569 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, true)?;
cf64af13
KS
570 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
571 let cbp = (cbpy << 2) | (cbpc & 3);
572 if dquant {
573 let idx = br.read(2)? as usize;
f2af8eca 574 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
cf64af13
KS
575 }
576 let mut binfo = BlockInfo::new(Type::I, cbp, q);
21c16d5f 577 binfo.set_bpart(bbinfo);
cf64af13 578 if self.is_pb {
21c16d5f 579 for _ in 0..bbinfo.get_num_mv() {
cf64af13
KS
580 mvec.push(decode_mv(br, &self.tables.mv_cb)?);
581 }
21c16d5f 582 binfo.set_b_mv(mvec.as_slice());
cf64af13 583 }
cf64af13
KS
584 return Ok(binfo);
585 }
586
effbebce 587 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, false)?;
cf64af13
KS
588 let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?;
589// if /* !aiv && */(cbpc & 3) != 3 {
590 cbpy ^= 0xF;
591// }
592 let cbp = (cbpy << 2) | (cbpc & 3);
593 if dquant {
594 let idx = br.read(2)? as usize;
f2af8eca 595 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
cf64af13
KS
596 }
597 let mut binfo = BlockInfo::new(Type::P, cbp, q);
21c16d5f 598 binfo.set_bpart(bbinfo);
cf64af13
KS
599 if !is_4x4 {
600 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
cf64af13
KS
601 binfo.set_mv(&mvec);
602 } else {
603 let mvec: [MV; 4] = [
604 decode_mv(br, &self.tables.mv_cb)?,
605 decode_mv(br, &self.tables.mv_cb)?,
606 decode_mv(br, &self.tables.mv_cb)?,
607 decode_mv(br, &self.tables.mv_cb)?
608 ];
609 binfo.set_mv(&mvec);
610 }
611 if self.is_pb {
21c16d5f
KS
612 let mut mvec: Vec<MV> = Vec::with_capacity(bbinfo.get_num_mv());
613 for _ in 0..bbinfo.get_num_mv() {
cf64af13
KS
614 let mv = decode_mv(br, &self.tables.mv_cb)?;
615 mvec.push(mv);
616 }
21c16d5f 617 binfo.set_b_mv(mvec.as_slice());
cf64af13 618 }
cf64af13
KS
619 Ok(binfo)
620 },
621 _ => { Err(DecoderError::InvalidData) },
622 }
623 }
624
625 #[allow(unused_variables)]
2a2aa421 626 fn decode_block_intra(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
21c16d5f 627 self.decode_block(quant, true, coded, blk)
cf64af13
KS
628 }
629
630 #[allow(unused_variables)]
2a2aa421 631 fn decode_block_inter(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
21c16d5f 632 self.decode_block(quant, false, coded, blk)
cf64af13
KS
633 }
634
cf64af13
KS
635 fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
636}
637
638impl Intel263Decoder {
639 fn new() -> Self {
640 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
641 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
642 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
643 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
644 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
645 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
646 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
647 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
648 let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
649 let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
650 let mut coderead = H263ShortCodeReader::new(H263_MV);
651 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
652 let tables = Tables {
f2af8eca
KS
653 intra_mcbpc_cb,
654 inter_mcbpc_cb,
655 cbpy_cb,
656 rl_cb,
657 aic_rl_cb,
658 mv_cb,
cf64af13
KS
659 };
660
661 Intel263Decoder{
2422d969 662 info: NACodecInfo::new_dummy(),
42a59352 663 dec: H263BaseDecoder::new(true),
f2af8eca 664 tables,
04bbfe10 665 bdsp: I263BlockDSP::default(),
2f67d8bb
KS
666 lastframe: None,
667 lastpts: None,
cf64af13
KS
668 }
669 }
670}
671
672impl NADecoder for Intel263Decoder {
01613464 673 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
cf64af13
KS
674 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
675 let w = vinfo.get_width();
676 let h = vinfo.get_height();
677 let fmt = formats::YUV420_FORMAT;
678 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
2422d969 679 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
cf64af13
KS
680 Ok(())
681 } else {
682 Err(DecoderError::InvalidData)
683 }
684 }
01613464 685 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
cf64af13
KS
686 let src = pkt.get_buffer();
687
688 if src.len() == 8 {
cf64af13 689 let buftype;
2f67d8bb
KS
690 let ftype;
691 if self.lastframe.is_none() {
cf64af13 692 buftype = NABufferType::None;
2f67d8bb
KS
693 ftype = FrameType::Skip;
694 } else {
695 let mut buf = None;
696 std::mem::swap(&mut self.lastframe, &mut buf);
697 buftype = buf.unwrap();
698 ftype = FrameType::B;
cf64af13
KS
699 }
700 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
701 frm.set_keyframe(false);
2f67d8bb
KS
702 frm.set_frame_type(ftype);
703 if self.lastpts.is_some() {
704 frm.set_pts(self.lastpts);
705 self.lastpts = None;
706 }
171860fc 707 return Ok(frm.into_ref());
cf64af13 708 }
cf64af13
KS
709 let mut ibr = Intel263BR::new(&src, &self.tables);
710
2a2aa421 711 let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
cf64af13 712
2f67d8bb
KS
713 let mut cur_pts = pkt.get_pts();
714 if !self.dec.is_intra() {
715 let bret = self.dec.get_bframe(&self.bdsp);
716 if let Ok(b_buf) = bret {
717 self.lastframe = Some(b_buf);
718 self.lastpts = pkt.get_pts();
719 if let Some(pts) = pkt.get_pts() {
720 cur_pts = Some(pts + 1);
721 }
722 }
723 }
724
cf64af13
KS
725 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
726 frm.set_keyframe(self.dec.is_intra());
727 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
2f67d8bb 728 frm.set_pts(cur_pts);
171860fc 729 Ok(frm.into_ref())
cf64af13 730 }
f9be4e75
KS
731 fn flush(&mut self) {
732 self.dec.flush();
733 }
cf64af13
KS
734}
735
7d57ae2f
KS
736impl NAOptionHandler for Intel263Decoder {
737 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
738 fn set_options(&mut self, _options: &[NAOption]) { }
739 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
740}
741
cf64af13 742
08a1fab7 743pub fn get_decoder() -> Box<dyn NADecoder + Send> {
cf64af13
KS
744 Box::new(Intel263Decoder::new())
745}
746
747#[cfg(test)]
748mod test {
3167c45c
KS
749 use nihav_core::codecs::RegisteredDecoders;
750 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 751 use nihav_codec_support::test::dec_video::*;
78fb6560 752 use crate::indeo_register_all_decoders;
e64739f8 753 use nihav_commonfmt::generic_register_all_demuxers;
cf64af13
KS
754 #[test]
755 fn test_intel263() {
3167c45c
KS
756 let mut dmx_reg = RegisteredDemuxers::new();
757 generic_register_all_demuxers(&mut dmx_reg);
758 let mut dec_reg = RegisteredDecoders::new();
78fb6560 759 indeo_register_all_decoders(&mut dec_reg);
3167c45c 760
10a6216f
KS
761 test_decoding("avi", "intel263", "assets/Indeo/neal73_saber.avi", Some(16),
762 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
763 [0x698c4f70, 0xf727bfc1, 0x96e687e9, 0xc9e37073],
764 [0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e],
765 [0x95dfe457, 0xaaeeaca9, 0x9764c111, 0xdf055b1f],
766 [0xac1d708c, 0x8e34aa47, 0x240b8f0e, 0x797b052b],
767 [0x965fe621, 0xebb049da, 0x18345724, 0x748ea32f],
768 [0x126c7492, 0x54d7457f, 0x9968a723, 0x89629378],
769 [0x8c690125, 0x3de8da89, 0x6030b702, 0xbd3f09ab],
770 [0xa9d3f7c7, 0xdfa1795c, 0x7ed34e86, 0x58b7cc26],
771 [0xe500e50e, 0x2312197d, 0xb8e93f41, 0xe6890cd8],
772 [0x2e8d8f15, 0xaf1c84fe, 0x05fec093, 0x3c383abb],
773 [0x6a1def4b, 0xc3549acc, 0x9ed127be, 0x2872f751],
774 [0x36599508, 0xe169caf9, 0xcdf6af6b, 0x29d167b8],
775 [0xfe98869d, 0x2b16b94b, 0x97caaf72, 0xbf7cc0c1],
776 [0x9fbfaf0a, 0xfa4ce8fc, 0xdc038ab8, 0x649c1eaa],
777 [0x141749be, 0xfba7acd4, 0xd0372e02, 0x6b191bc5],
778 [0x99252b73, 0x2ce009d9, 0xf6753c1d, 0x31892a08],
779 [0xefe81436, 0x4ab365db, 0x57a0b058, 0x26a6ca02]]));
cf64af13
KS
780 }
781}