]> git.nihav.org Git - nihav.git/blame - nihav-indeo/src/codecs/intel263.rs
avimux: do not record palette change chunks in OpenDML index
[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 12
cf64af13
KS
13struct Tables {
14 intra_mcbpc_cb: Codebook<u8>,
15 inter_mcbpc_cb: Codebook<u8>,
16 cbpy_cb: Codebook<u8>,
17 rl_cb: Codebook<H263RLSym>,
cf64af13
KS
18 mv_cb: Codebook<u8>,
19}
20
04bbfe10
KS
21#[derive(Default)]
22struct I263BlockDSP {}
23
cf64af13 24struct Intel263Decoder {
2422d969 25 info: NACodecInfoRef,
88c58b1b 26 dec: H263BaseDecoder,
cf64af13 27 tables: Tables,
04bbfe10 28 bdsp: I263BlockDSP,
2f67d8bb
KS
29 lastframe: Option<NABufferType>,
30 lastpts: Option<u64>,
cf64af13
KS
31}
32
33struct Intel263BR<'a> {
34 br: BitReader<'a>,
35 tables: &'a Tables,
36 gob_no: usize,
37 mb_w: usize,
38 is_pb: bool,
effbebce 39 is_ipb: bool,
cf64af13
KS
40}
41
04bbfe10
KS
42const W1: i32 = 2841;
43const W2: i32 = 2676;
44const W3: i32 = 2408;
45const W5: i32 = 1609;
46const W6: i32 = 1108;
47const W7: i32 = 565;
48const W8: i32 = 181;
49
50const ROW_SHIFT: u8 = 8;
51const COL_SHIFT: u8 = 14;
52
04bbfe10
KS
53fn idct_row(row: &mut [i16]) {
54 let in0 = ((i32::from(row[0])) << 11) + (1 << (ROW_SHIFT - 1));
55 let in1 = (i32::from(row[4])) << 11;
56 let in2 = i32::from(row[6]);
57 let in3 = i32::from(row[2]);
58 let in4 = i32::from(row[1]);
59 let in5 = i32::from(row[7]);
60 let in6 = i32::from(row[5]);
61 let in7 = i32::from(row[3]);
62
63 let tmp = W7 * (in4 + in5);
64 let a4 = tmp + (W1 - W7) * in4;
65 let a5 = tmp - (W1 + W7) * in5;
66
67 let tmp = W3 * (in6 + in7);
68 let a6 = tmp - (W3 - W5) * in6;
69 let a7 = tmp - (W3 + W5) * in7;
70
71 let tmp = in0 + in1;
72
73 let a0 = in0 - in1;
74 let t1 = W6 * (in2 + in3);
75 let a2 = t1 - (W2 + W6) * in2;
76 let a3 = t1 + (W2 - W6) * in3;
77 let b1 = a4 + a6;
78
79 let b4 = a4 - a6;
80 let t2 = a5 - a7;
81 let b6 = a5 + a7;
82 let b7 = tmp + a3;
83 let b5 = tmp - a3;
84 let b3 = a0 + a2;
85 let b0 = a0 - a2;
86 let b2 = (W8 * (b4 + t2) + 128) >> 8;
87 let b4 = (W8 * (b4 - t2) + 128) >> 8;
88
89 row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
90 row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
91 row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
92 row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
93 row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
94 row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
95 row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
96 row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
97}
98
99#[allow(clippy::erasing_op)]
39cd2175 100#[allow(clippy::identity_op)]
04bbfe10
KS
101fn idct_col(blk: &mut [i16; 64], off: usize) {
102 let in0 = ((i32::from(blk[off + 0*8])) << 8) + (1 << (COL_SHIFT - 1));
103 let in1 = (i32::from(blk[off + 4*8])) << 8;
104 let in2 = i32::from(blk[off + 6*8]);
105 let in3 = i32::from(blk[off + 2*8]);
106 let in4 = i32::from(blk[off + 1*8]);
107 let in5 = i32::from(blk[off + 7*8]);
108 let in6 = i32::from(blk[off + 5*8]);
109 let in7 = i32::from(blk[off + 3*8]);
110
111 let tmp = W7 * (in4 + in5);
112 let a4 = (tmp + (W1 - W7) * in4) >> 3;
113 let a5 = (tmp - (W1 + W7) * in5) >> 3;
114
115 let tmp = W3 * (in6 + in7);
116 let a6 = (tmp - (W3 - W5) * in6) >> 3;
117 let a7 = (tmp - (W3 + W5) * in7) >> 3;
118
119 let tmp = in0 + in1;
120
121 let a0 = in0 - in1;
122 let t1 = W6 * (in2 + in3);
123 let a2 = (t1 - (W2 + W6) * in2) >> 3;
124 let a3 = (t1 + (W2 - W6) * in3) >> 3;
125 let b1 = a4 + a6;
126
127 let b4 = a4 - a6;
128 let t2 = a5 - a7;
129 let b6 = a5 + a7;
130 let b7 = tmp + a3;
131 let b5 = tmp - a3;
132 let b3 = a0 + a2;
133 let b0 = a0 - a2;
134 let b2 = (W8 * (b4 + t2) + 128) >> 8;
135 let b4 = (W8 * (b4 - t2) + 128) >> 8;
136
137 blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
138 blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
139 blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
140 blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
141 blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
142 blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
143 blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
144 blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
145}
146
147const FILTER_STRENGTH: [u8; 32] = [
148 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7,
149 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12
150];
151
152#[allow(clippy::erasing_op)]
39cd2175 153#[allow(clippy::identity_op)]
04bbfe10
KS
154fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
155 let stride = buf.get_stride(comp);
156 let dptr = buf.get_data_mut().unwrap();
157 let buf = dptr.as_mut_slice();
158 for x in 0..8 {
5a6dec5f
KS
159 let a = i16::from(buf[off - 2 * stride + x]);
160 let b = i16::from(buf[off - 1 * stride + x]);
161 let c = i16::from(buf[off + 0 * stride + x]);
162 let d = i16::from(buf[off + 1 * stride + x]);
04bbfe10
KS
163 let diff = (3 * (a - d) + 8 * (c - b)) / 16;
164 if (diff != 0) && (diff > -24) && (diff < 24) {
5a6dec5f 165 let d1a = (diff.abs() - 2 * (diff.abs() - i16::from(strength)).max(0)).max(0);
04bbfe10
KS
166 let d1 = if diff < 0 { -d1a } else { d1a };
167
168 buf[off - 1 * stride + x] = (b + d1).max(0).min(255) as u8;
169 buf[off + 0 * stride + x] = (c - d1).max(0).min(255) as u8;
170 }
171 }
172}
173
39cd2175 174#[allow(clippy::identity_op)]
04bbfe10
KS
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);
b7c882c1 208 blockdsp::copy_block(&mut dst, src, 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
04bbfe10
KS
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
39cd2175 213 for (i, mv) in mvs.iter().enumerate() {
04bbfe10
KS
214 let xadd = (i & 1) * 8;
215 let yadd = (i & 2) * 4;
39cd2175 216 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
04bbfe10 217
39cd2175 218 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mv.x >> 1, mv.y >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
04bbfe10
KS
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);
b7c882c1 237 blockdsp::copy_block(&mut dst, src, 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
04bbfe10
KS
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
39cd2175 242 for (i, mv) in mvs.iter().enumerate() {
04bbfe10
KS
243 let xadd = (i & 1) * 8;
244 let yadd = (i & 2) * 4;
39cd2175 245 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
04bbfe10 246
39cd2175 247 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mv.x >> 1, mv.y >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
04bbfe10
KS
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);
817e4872 266 let strength = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
04bbfe10 267 if mb_y != 0 {
817e4872
KS
268 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, strength, coff); }
269 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, strength, coff + 8); }
04bbfe10
KS
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);
817e4872 285 let strength = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
04bbfe10
KS
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 }
817e4872
KS
293 if leftc && ccur0 { deblock_ver(buf, 0, strength, off); }
294 if ccur0 && ccur1 { deblock_ver(buf, 0, strength, off + 8); }
04bbfe10
KS
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);
817e4872
KS
310 let strength = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
311 if ctu && ccu { deblock_hor(buf, 1, strength, offu + mb_x * 8); }
312 if ctv && ccv { deblock_hor(buf, 2, strength, offv + mb_x * 8); }
04bbfe10
KS
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
6f263099 332fn check_marker(br: &mut BitReader) -> DecoderResult<()> {
cf64af13
KS
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
cf64af13 450 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
9037cf6b 451 let br = &mut self.br;
cf64af13
KS
452 let syncw = br.read(22)?;
453 validate!(syncw == 0x000020);
32007ad9 454 let tr = (br.read(8)? << 8) as u16;
cf64af13
KS
455 check_marker(br)?;
456 let id = br.read(1)?;
457 validate!(id == 0);
458 br.read(1)?; // split screen indicator
459 br.read(1)?; // document camera indicator
460 br.read(1)?; // freeze picture release
461 let mut sfmt = br.read(3)?;
462 validate!((sfmt != 0b000) && (sfmt != 0b110));
463 let is_intra = !br.read_bool()?;
464 let umv = br.read_bool()?;
465 br.read(1)?; // syntax arithmetic coding
466 let apm = br.read_bool()?;
467 self.is_pb = br.read_bool()?;
f2f1afb2 468 let deblock;
effbebce 469 let pbplus;
cf64af13
KS
470 if sfmt == 0b111 {
471 sfmt = br.read(3)?;
472 validate!((sfmt != 0b000) && (sfmt != 0b111));
473 br.read(2)?; // unknown flags
f2f1afb2 474 deblock = br.read_bool()?;
cf64af13 475 br.read(1)?; // unknown flag
effbebce 476 pbplus = br.read_bool()?;
cf64af13
KS
477 br.read(5)?; // unknown flags
478 let marker = br.read(5)?;
479 validate!(marker == 1);
f2f1afb2
KS
480 } else {
481 deblock = false;
effbebce 482 pbplus = false;
cf64af13 483 }
effbebce 484 self.is_ipb = pbplus;
cf64af13
KS
485 let w; let h;
486 if sfmt == 0b110 {
487 let par = br.read(4)?;
488 w = ((br.read(9)? + 1) * 4) as usize;
489 check_marker(br)?;
490 h = ((br.read(9)? + 1) * 4) as usize;
491 if par == 0b1111 {
492 let pixw = br.read(8)?;
493 let pixh = br.read(8)?;
494 validate!((pixw != 0) && (pixh != 0));
495 }
496 } else {
497 let (w_, h_) = H263_SIZES[sfmt as usize];
498 w = w_;
499 h = h_;
500 }
501 let quant = br.read(5)?;
502 let cpm = br.read_bool()?;
503 validate!(!cpm);
21c16d5f 504
39cd2175
KS
505 let pbinfo = if self.is_pb {
506 let trb = br.read(3)?;
507 let dbquant = br.read(2)?;
508 Some(PBInfo::new(trb as u8, dbquant as u8, pbplus))
509 } else {
510 None
511 };
cf64af13
KS
512 while br.read_bool()? { // skip PEI
513 br.read(8)?;
514 }
21c16d5f 515//println!("frame {}x{} intra: {} q {} pb {} apm {} umv {} @{}", w, h, is_intra, quant, self.is_pb, apm, umv, br.tell());
cf64af13
KS
516 self.gob_no = 0;
517 self.mb_w = (w + 15) >> 4;
518
519 let ftype = if is_intra { Type::I } else { Type::P };
2a2aa421 520 let plusinfo = if deblock { Some(PlusInfo::new(false, deblock, false, false)) } else { None };
32007ad9
KS
521 let mvmode = if umv { MVMode::UMV } else { MVMode::Old };
522 let picinfo = PicInfo::new(w, h, ftype, mvmode, umv, apm, quant as u8, tr, pbinfo, plusinfo);
cf64af13
KS
523 Ok(picinfo)
524 }
525
39cd2175 526 fn decode_slice_header(&mut self, _info: &PicInfo) -> DecoderResult<SliceInfo> {
9037cf6b 527 let br = &mut self.br;
cf64af13 528 let gbsc = br.read(17)?;
cf64af13 529 validate!(gbsc == 1);
39cd2175
KS
530 let _gn = br.read(5)?;
531 let _gfid = br.read(2)?;
cf64af13 532 let gquant = br.read(5)?;
21c16d5f 533//println!("GOB gn {:X} id {} q {}", gn, gfid, gquant);
2a2aa421 534 let ret = SliceInfo::new_gob(0, self.gob_no, gquant as u8);
cf64af13
KS
535 self.gob_no += 1;
536 Ok(ret)
537 }
538
39cd2175 539 fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, _sstate: &SliceState) -> DecoderResult<BlockInfo> {
9037cf6b 540 let br = &mut self.br;
cf64af13
KS
541 let mut q = slice.get_quant();
542 match info.get_mode() {
543 Type::I => {
544 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?;
545 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; }
546 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
547 let cbp = (cbpy << 2) | (cbpc & 3);
548 let dquant = (cbpc & 4) != 0;
549 if dquant {
550 let idx = br.read(2)? as usize;
f2af8eca 551 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
cf64af13 552 }
cf64af13
KS
553 Ok(BlockInfo::new(Type::I, cbp, q))
554 },
555 Type::P => {
cf64af13
KS
556 if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); }
557 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
558 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; }
559 let is_intra = (cbpc & 0x04) != 0;
560 let dquant = (cbpc & 0x08) != 0;
561 let is_4x4 = (cbpc & 0x10) != 0;
562 if is_intra {
563 let mut mvec: Vec<MV> = Vec::new();
effbebce 564 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, true)?;
cf64af13
KS
565 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
566 let cbp = (cbpy << 2) | (cbpc & 3);
567 if dquant {
568 let idx = br.read(2)? as usize;
f2af8eca 569 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
cf64af13
KS
570 }
571 let mut binfo = BlockInfo::new(Type::I, cbp, q);
21c16d5f 572 binfo.set_bpart(bbinfo);
cf64af13 573 if self.is_pb {
21c16d5f 574 for _ in 0..bbinfo.get_num_mv() {
cf64af13
KS
575 mvec.push(decode_mv(br, &self.tables.mv_cb)?);
576 }
21c16d5f 577 binfo.set_b_mv(mvec.as_slice());
cf64af13 578 }
cf64af13
KS
579 return Ok(binfo);
580 }
581
effbebce 582 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, false)?;
cf64af13
KS
583 let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?;
584// if /* !aiv && */(cbpc & 3) != 3 {
585 cbpy ^= 0xF;
586// }
587 let cbp = (cbpy << 2) | (cbpc & 3);
588 if dquant {
589 let idx = br.read(2)? as usize;
f2af8eca 590 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
cf64af13
KS
591 }
592 let mut binfo = BlockInfo::new(Type::P, cbp, q);
21c16d5f 593 binfo.set_bpart(bbinfo);
cf64af13
KS
594 if !is_4x4 {
595 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
cf64af13
KS
596 binfo.set_mv(&mvec);
597 } else {
598 let mvec: [MV; 4] = [
599 decode_mv(br, &self.tables.mv_cb)?,
600 decode_mv(br, &self.tables.mv_cb)?,
601 decode_mv(br, &self.tables.mv_cb)?,
602 decode_mv(br, &self.tables.mv_cb)?
603 ];
604 binfo.set_mv(&mvec);
605 }
606 if self.is_pb {
21c16d5f
KS
607 let mut mvec: Vec<MV> = Vec::with_capacity(bbinfo.get_num_mv());
608 for _ in 0..bbinfo.get_num_mv() {
cf64af13
KS
609 let mv = decode_mv(br, &self.tables.mv_cb)?;
610 mvec.push(mv);
611 }
21c16d5f 612 binfo.set_b_mv(mvec.as_slice());
cf64af13 613 }
cf64af13
KS
614 Ok(binfo)
615 },
616 _ => { Err(DecoderError::InvalidData) },
617 }
618 }
619
39cd2175 620 fn decode_block_intra(&mut self, _info: &BlockInfo, _sstate: &SliceState, quant: u8, _no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
21c16d5f 621 self.decode_block(quant, true, coded, blk)
cf64af13
KS
622 }
623
39cd2175 624 fn decode_block_inter(&mut self, _info: &BlockInfo, _sstate: &SliceState, quant: u8, _no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
21c16d5f 625 self.decode_block(quant, false, coded, blk)
cf64af13
KS
626 }
627
cf64af13
KS
628 fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
629}
630
631impl Intel263Decoder {
632 fn new() -> Self {
633 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
634 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
635 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
636 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
637 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
638 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
639 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
640 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
cf64af13
KS
641 let mut coderead = H263ShortCodeReader::new(H263_MV);
642 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
643 let tables = Tables {
f2af8eca
KS
644 intra_mcbpc_cb,
645 inter_mcbpc_cb,
646 cbpy_cb,
647 rl_cb,
f2af8eca 648 mv_cb,
cf64af13
KS
649 };
650
651 Intel263Decoder{
2422d969 652 info: NACodecInfo::new_dummy(),
42a59352 653 dec: H263BaseDecoder::new(true),
f2af8eca 654 tables,
04bbfe10 655 bdsp: I263BlockDSP::default(),
2f67d8bb
KS
656 lastframe: None,
657 lastpts: None,
cf64af13
KS
658 }
659 }
660}
661
662impl NADecoder for Intel263Decoder {
01613464 663 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
cf64af13
KS
664 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
665 let w = vinfo.get_width();
666 let h = vinfo.get_height();
667 let fmt = formats::YUV420_FORMAT;
668 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
2422d969 669 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
cf64af13
KS
670 Ok(())
671 } else {
672 Err(DecoderError::InvalidData)
673 }
674 }
01613464 675 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
cf64af13
KS
676 let src = pkt.get_buffer();
677
678 if src.len() == 8 {
cf64af13 679 let buftype;
2f67d8bb
KS
680 let ftype;
681 if self.lastframe.is_none() {
cf64af13 682 buftype = NABufferType::None;
2f67d8bb
KS
683 ftype = FrameType::Skip;
684 } else {
685 let mut buf = None;
686 std::mem::swap(&mut self.lastframe, &mut buf);
687 buftype = buf.unwrap();
688 ftype = FrameType::B;
cf64af13
KS
689 }
690 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
691 frm.set_keyframe(false);
2f67d8bb
KS
692 frm.set_frame_type(ftype);
693 if self.lastpts.is_some() {
694 frm.set_pts(self.lastpts);
695 self.lastpts = None;
696 }
171860fc 697 return Ok(frm.into_ref());
cf64af13 698 }
cf64af13
KS
699 let mut ibr = Intel263BR::new(&src, &self.tables);
700
2a2aa421 701 let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
cf64af13 702
2f67d8bb
KS
703 let mut cur_pts = pkt.get_pts();
704 if !self.dec.is_intra() {
705 let bret = self.dec.get_bframe(&self.bdsp);
706 if let Ok(b_buf) = bret {
707 self.lastframe = Some(b_buf);
708 self.lastpts = pkt.get_pts();
709 if let Some(pts) = pkt.get_pts() {
710 cur_pts = Some(pts + 1);
711 }
712 }
713 }
714
cf64af13
KS
715 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
716 frm.set_keyframe(self.dec.is_intra());
717 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
2f67d8bb 718 frm.set_pts(cur_pts);
171860fc 719 Ok(frm.into_ref())
cf64af13 720 }
f9be4e75
KS
721 fn flush(&mut self) {
722 self.dec.flush();
723 }
cf64af13
KS
724}
725
7d57ae2f
KS
726impl NAOptionHandler for Intel263Decoder {
727 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
728 fn set_options(&mut self, _options: &[NAOption]) { }
729 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
730}
731
cf64af13 732
08a1fab7 733pub fn get_decoder() -> Box<dyn NADecoder + Send> {
cf64af13
KS
734 Box::new(Intel263Decoder::new())
735}
736
737#[cfg(test)]
738mod test {
3167c45c
KS
739 use nihav_core::codecs::RegisteredDecoders;
740 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 741 use nihav_codec_support::test::dec_video::*;
78fb6560 742 use crate::indeo_register_all_decoders;
e64739f8 743 use nihav_commonfmt::generic_register_all_demuxers;
cf64af13
KS
744 #[test]
745 fn test_intel263() {
3167c45c
KS
746 let mut dmx_reg = RegisteredDemuxers::new();
747 generic_register_all_demuxers(&mut dmx_reg);
748 let mut dec_reg = RegisteredDecoders::new();
78fb6560 749 indeo_register_all_decoders(&mut dec_reg);
3167c45c 750
886cde48 751 // sample: https://samples.mplayerhq.hu/A-codecs/IMC/neal73_saber.avi
10a6216f
KS
752 test_decoding("avi", "intel263", "assets/Indeo/neal73_saber.avi", Some(16),
753 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
754 [0x698c4f70, 0xf727bfc1, 0x96e687e9, 0xc9e37073],
755 [0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e],
756 [0x95dfe457, 0xaaeeaca9, 0x9764c111, 0xdf055b1f],
757 [0xac1d708c, 0x8e34aa47, 0x240b8f0e, 0x797b052b],
758 [0x965fe621, 0xebb049da, 0x18345724, 0x748ea32f],
759 [0x126c7492, 0x54d7457f, 0x9968a723, 0x89629378],
760 [0x8c690125, 0x3de8da89, 0x6030b702, 0xbd3f09ab],
761 [0xa9d3f7c7, 0xdfa1795c, 0x7ed34e86, 0x58b7cc26],
762 [0xe500e50e, 0x2312197d, 0xb8e93f41, 0xe6890cd8],
763 [0x2e8d8f15, 0xaf1c84fe, 0x05fec093, 0x3c383abb],
764 [0x6a1def4b, 0xc3549acc, 0x9ed127be, 0x2872f751],
765 [0x36599508, 0xe169caf9, 0xcdf6af6b, 0x29d167b8],
766 [0xfe98869d, 0x2b16b94b, 0x97caaf72, 0xbf7cc0c1],
767 [0x9fbfaf0a, 0xfa4ce8fc, 0xdc038ab8, 0x649c1eaa],
768 [0x141749be, 0xfba7acd4, 0xd0372e02, 0x6b191bc5],
769 [0x99252b73, 0x2ce009d9, 0xf6753c1d, 0x31892a08],
770 [0xefe81436, 0x4ab365db, 0x57a0b058, 0x26a6ca02]]));
cf64af13
KS
771 }
772}