1 // Somewhat simplified JPEG decoder
2 // TODO: move common JPEG decoding into codec-support
4 use nihav_core::io::byteio::{ByteReader,MemoryReader};
5 use nihav_core::io::bitreader::*;
6 use nihav_core::io::codebook::*;
7 use nihav_core::codecs::*;
8 use nihav_codec_support::codecs::ZIGZAG;
18 const ROW_SHIFT: u8 = 8;
19 const COL_SHIFT: u8 = 14;
21 #[allow(clippy::erasing_op)]
22 fn idct_row(row: &mut [i16]) {
23 let in0 = ((i32::from(row[0])) << 11) + (1 << (ROW_SHIFT - 1));
24 let in1 = (i32::from(row[4])) << 11;
25 let in2 = i32::from(row[6]);
26 let in3 = i32::from(row[2]);
27 let in4 = i32::from(row[1]);
28 let in5 = i32::from(row[7]);
29 let in6 = i32::from(row[5]);
30 let in7 = i32::from(row[3]);
32 let tmp = W7 * (in4 + in5);
33 let a4 = tmp + (W1 - W7) * in4;
34 let a5 = tmp - (W1 + W7) * in5;
36 let tmp = W3 * (in6 + in7);
37 let a6 = tmp - (W3 - W5) * in6;
38 let a7 = tmp - (W3 + W5) * in7;
43 let t1 = W6 * (in2 + in3);
44 let a2 = t1 - (W2 + W6) * in2;
45 let a3 = t1 + (W2 - W6) * in3;
55 let b2 = (W8 * (b4 + t2) + 128) >> 8;
56 let b4 = (W8 * (b4 - t2) + 128) >> 8;
58 row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
59 row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
60 row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
61 row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
62 row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
63 row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
64 row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
65 row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
68 #[allow(clippy::erasing_op)]
69 #[allow(clippy::identity_op)]
70 fn idct_col(blk: &mut [i16; 64], off: usize) {
71 let in0 = ((i32::from(blk[off + 0*8])) << 8) + (1 << (COL_SHIFT - 1));
72 let in1 = (i32::from(blk[off + 4*8])) << 8;
73 let in2 = i32::from(blk[off + 6*8]);
74 let in3 = i32::from(blk[off + 2*8]);
75 let in4 = i32::from(blk[off + 1*8]);
76 let in5 = i32::from(blk[off + 7*8]);
77 let in6 = i32::from(blk[off + 5*8]);
78 let in7 = i32::from(blk[off + 3*8]);
80 let tmp = W7 * (in4 + in5);
81 let a4 = (tmp + (W1 - W7) * in4) >> 3;
82 let a5 = (tmp - (W1 + W7) * in5) >> 3;
84 let tmp = W3 * (in6 + in7);
85 let a6 = (tmp - (W3 - W5) * in6) >> 3;
86 let a7 = (tmp - (W3 + W5) * in7) >> 3;
91 let t1 = W6 * (in2 + in3);
92 let a2 = (t1 - (W2 + W6) * in2) >> 3;
93 let a3 = (t1 + (W2 - W6) * in3) >> 3;
103 let b2 = (W8 * (b4 + t2) + 128) >> 8;
104 let b4 = (W8 * (b4 - t2) + 128) >> 8;
106 blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
107 blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
108 blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
109 blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
110 blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
111 blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
112 blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
113 blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
116 fn idct(blk: &mut [i16; 64]) {
117 for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
118 for i in 0..8 { idct_col(blk, i); }
121 fn put_block(blk: &[i16; 64], dst: &mut [u8], stride: usize) {
122 for (drow, srow) in dst.chunks_mut(stride).zip(blk.chunks(8)) {
123 for (del, &pix) in drow.iter_mut().zip(srow.iter()) {
124 *del = pix.max(0).min(255) as u8;
129 #[derive(Clone,Copy,Default)]
130 struct ComponentInfo {
136 struct RadiusStudioDecoder {
137 info: NACodecInfoRef,
138 quant: [[i16; 64]; 4],
139 qselect: [u8; MAX_CHROMATONS],
140 subsamp: [u8; MAX_CHROMATONS],
141 codebook: [[Option<Codebook<u8>>; 4]; 2],
146 fn read_dc(br: &mut BitReader, cb: &Codebook<u8>) -> DecoderResult<i16> {
147 let cat = br.read_cb(cb)?;
152 let add_bits = br.read(cat)? as i16;
153 let pivot = 1 << (cat - 1);
154 if add_bits < pivot {
155 Ok(add_bits + 1 - pivot * 2)
162 fn read_ac(br: &mut BitReader, cb: &Codebook<u8>) -> DecoderResult<(usize, i16)> {
163 let val = br.read_cb(cb)?;
164 let run = usize::from(val >> 4);
166 let level = if cat != 0 {
168 let add_bits = br.read(cat)? as i16;
169 let pivot = 1 << (cat - 1);
170 if add_bits < pivot {
171 add_bits + 1 - pivot * 2
176 validate!(run == 0 || run == 15);
182 fn read_block(br: &mut BitReader, blk: &mut [i16; 64], dc_cb: &Codebook<u8>, ac_cb: &Codebook<u8>, ss: usize, se: usize, qmat: &[i16; 64]) -> DecoderResult<()> {
184 blk[0] = read_dc(br, dc_cb)?;
189 let (run, level) = read_ac(br, ac_cb)?;
190 if run == 0 && level == 0 {
195 blk[ZIGZAG[idx]] = level * qmat[idx];
201 impl RadiusStudioDecoder {
203 let dummy_info = NACodecInfo::new_dummy();
208 qselect: [0, 1, 1, 0, 0],
209 subsamp: [0x21, 0x11, 0x11, 0, 0],
210 codebook: [[None, None, None, None], [None, None, None, None]],
216 #[allow(clippy::needless_range_loop)]
217 fn decode_scan(&mut self, src: &[u8], mut buf: NAVideoBufferRef<u8>, ci: &[ComponentInfo], ss: usize, se: usize) -> DecoderResult<usize> {
218 let num_components = ci.len();
219 let mut last_dc = [1024; MAX_CHROMATONS];
220 let mut dc_cbs = Vec::with_capacity(num_components);
221 let mut ac_cbs = Vec::with_capacity(num_components);
222 let mut qmats = [&self.quant[0]; MAX_CHROMATONS];
223 for (i, cinfo) in ci.iter().enumerate() {
224 dc_cbs.push(if let Some(ref cb) = self.codebook[0][cinfo.dc_table_id] {
226 } else { unreachable!(); });
227 ac_cbs.push(if let Some(ref cb) = self.codebook[1][cinfo.ac_table_id] {
229 } else { unreachable!(); });
230 qmats[i] = &self.quant[self.qselect[cinfo.component_id] as usize];
233 let frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
235 let mut br = BitReader::new(src, BitReaderMode::BE);
237 let mut offs = frm.offset;
238 let mut nblks = [0; MAX_CHROMATONS];
239 let mut xstep = [0; MAX_CHROMATONS];
240 let mut ystep = [0; MAX_CHROMATONS];
243 for i in 0..num_components {
244 let hs = (self.subsamp[i] >> 4) as usize;
245 let vs = (self.subsamp[i] & 0xF) as usize;
246 hstep = hstep.max(hs * 8);
247 vstep = vstep.max(vs * 8);
254 for _y in (0..self.height).step_by(vstep) {
255 for x in 0..(self.width + hstep - 1) / hstep {
256 for i in 0..num_components {
257 blocks = [[0; 64]; 4];
258 for blk in blocks[..nblks[i]].iter_mut() {
259 read_block(&mut br, blk, dc_cbs[i], ac_cbs[i], ss, se, qmats[i])?;
261 blk[0] += last_dc[i];
264 blk[0] += last_dc[1];
269 match self.subsamp[i] {
271 put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], frm.stride[i]);
274 put_block(&blocks[0], &mut frm.data[offs[i] + x * 16..], frm.stride[i]);
275 put_block(&blocks[1], &mut frm.data[offs[i] + x * 16 + 8..], frm.stride[i]);
278 put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], frm.stride[i]);
279 put_block(&blocks[1], &mut frm.data[offs[i] + x * 8 + frm.stride[i] * 8..], frm.stride[i]);
283 put_block(&blocks[j], &mut frm.data[offs[i] + x * 16 + (j & 1) * 8 + (j >> 1) * 8 * frm.stride[i]..], frm.stride[i]);
290 for i in 0..num_components {
291 offs[i] += frm.stride[i] * ystep[i];
295 Ok((br.tell() + 7) / 8)
299 struct HuffDescReader<'a> {
305 impl<'a> CodebookDescReader<u8> for HuffDescReader<'a> {
306 fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] }
307 fn code(&mut self, idx: usize) -> u32 { u32::from(self.codes[idx]) }
308 fn sym (&mut self, idx: usize) -> u8 { self.syms[idx] }
309 fn len(&mut self) -> usize { self.syms.len() }
312 fn generate_cb(lens: &[u8; 16], syms: &[u8]) -> DecoderResult<Codebook<u8>> {
313 let mut codes = [0; 256];
314 let mut bits = [0; 256];
316 let mut iter = bits.iter_mut();
317 for (i, &len) in lens.iter().enumerate() {
319 *iter.next().unwrap() = (i + 1) as u8;
323 let mut si = bits[0];
325 while idx < syms.len() {
326 while idx < syms.len() && bits[idx] == si {
331 while idx < syms.len() && bits[idx] != si {
337 let mut cbr = HuffDescReader { codes: &codes, bits: &bits, syms };
338 Ok(Codebook::new(&mut cbr, CodebookMode::MSB)?)
341 fn build_default_cb(dc: bool, idx: usize) -> DecoderResult<Codebook<u8>> {
343 generate_cb(&DC_LENS[idx], &DC_SYMS)
345 generate_cb(&AC_LENS[idx], AC_SYMS[idx])
349 impl NADecoder for RadiusStudioDecoder {
350 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
351 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
352 let w = vinfo.get_width();
353 let h = vinfo.get_height();
356 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, YUV420_FORMAT));
357 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
360 Err(DecoderError::InvalidData)
363 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
364 let src = pkt.get_buffer();
365 if src.len() < 2048 { return Err(DecoderError::ShortData); }
366 let mut mr = MemoryReader::new_read(&src);
367 let mut br = ByteReader::new(&mut mr);
368 let _size_v0 = br.read_u32be()? as usize;
369 let field2_size = br.read_u32be()? as usize;
370 if field2_size != 0 {
371 return Err(DecoderError::NotImplemented);
373 let version = br.read_u16be()?;
374 validate!(version < 2);
375 let hdr_size = if version == 0 { 16 } else { 32 };
377 let quant = br.read_byte()?;
379 let formaton = NAPixelFormaton {
380 model: ColorModel::YUV(YUVSubmodel::YUVJ),
383 Some(NAPixelChromaton {
391 Some(NAPixelChromaton {
399 Some(NAPixelChromaton {
415 let vinfo = NAVideoInfo::new(self.width, self.height, false, formaton);
416 let bufinfo = alloc_video_buffer(vinfo, 4)?;
418 for (dc_id, dc_cb) in self.codebook[0].iter_mut().enumerate().take(2) {
420 validate!(dc_id < 2);
421 *dc_cb = Some(build_default_cb(true, dc_id)?);
424 for (ac_id, ac_cb) in self.codebook[1].iter_mut().enumerate().take(2) {
426 validate!(ac_id < 2);
427 *ac_cb = Some(build_default_cb(false, ac_id)?);
431 const DEF_LUMA_QUANT: [u8; 64] = [
432 16, 11, 12, 14, 12, 10, 16, 14,
433 13, 14, 18, 17, 16, 19, 24, 40,
434 26, 24, 22, 22, 24, 49, 35, 37,
435 29, 40, 58, 51, 61, 60, 57, 51,
436 56, 55, 64, 72, 92, 78, 64, 68,
437 87, 69, 55, 56, 80, 109, 81, 87,
438 95, 98, 103, 104, 103, 62, 77, 113,
439 121, 112, 100, 120, 92, 101, 103, 99
441 const DEF_CHROMA_QUANT: [u8; 64] = [
442 17, 18, 18, 24, 21, 24, 47, 26,
443 26, 47, 99, 66, 56, 66, 99, 99,
444 99, 99, 99, 99, 99, 99, 99, 99,
445 99, 99, 99, 99, 99, 99, 99, 99,
446 99, 99, 99, 99, 99, 99, 99, 99,
447 99, 99, 99, 99, 99, 99, 99, 99,
448 99, 99, 99, 99, 99, 99, 99, 99,
449 99, 99, 99, 99, 99, 99, 99, 99
452 for (i, (&luma_q, &chroma_q)) in DEF_LUMA_QUANT.iter().zip(DEF_CHROMA_QUANT.iter()).enumerate() {
453 self.quant[0][ZIGZAG[i]] = ((i16::from(quant) * i16::from(luma_q) + 25) / 50).max(1).min(255);
454 self.quant[1][ZIGZAG[i]] = ((i16::from(quant) * i16::from(chroma_q) + 25) / 50).max(1).min(255);
457 if let Some(buf) = bufinfo.get_vbuf() {
459 ComponentInfo { component_id: 1, dc_table_id: 0, ac_table_id: 0 },
460 ComponentInfo { component_id: 2, dc_table_id: 1, ac_table_id: 1 },
461 ComponentInfo { component_id: 3, dc_table_id: 1, ac_table_id: 1 },
463 self.decode_scan(&src[hdr_size..], buf, &ci, 0, 63)?;
464 } else { unreachable!(); }
466 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
467 frm.set_keyframe(true);
468 frm.set_frame_type(FrameType::I);
471 fn flush(&mut self) {
475 impl NAOptionHandler for RadiusStudioDecoder {
476 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
477 fn set_options(&mut self, _options: &[NAOption]) { }
478 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
481 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
482 Box::new(RadiusStudioDecoder::new())
487 use nihav_core::codecs::RegisteredDecoders;
488 use nihav_core::demuxers::RegisteredDemuxers;
489 use nihav_codec_support::test::dec_video::*;
490 use crate::misc_register_all_decoders;
491 use nihav_commonfmt::generic_register_all_demuxers;
494 let mut dmx_reg = RegisteredDemuxers::new();
495 generic_register_all_demuxers(&mut dmx_reg);
496 let mut dec_reg = RegisteredDecoders::new();
497 misc_register_all_decoders(&mut dec_reg);
498 // sample: https://samples.mplayerhq.hu/V-codecs/PGVV-RadiusStudio/airfone.mov
499 test_decoding("mov", "pgvv", "assets/Misc/airfone.mov", Some(6), &dmx_reg,
500 &dec_reg, ExpectedTestResult::MD5Frames(vec![
501 [0x84c27180, 0x1ae0ab09, 0x8cb668b5, 0xeba06638],
502 [0x803eae91, 0x56618078, 0x95b8a98f, 0x7e718ad9],
503 [0xd9543391, 0x339d9cc5, 0x100e868c, 0xa467eda1],
504 [0x5f50f6a4, 0x20e88428, 0xb1f3a573, 0xd8ac5acf]]));
508 const DC_LENS: [[u8; 16]; 2] = [
509 [ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 ],
510 [ 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ]
512 const DC_SYMS: [u8; 12] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
513 const AC_LENS: [[u8; 16]; 2] = [
514 [ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 ],
515 [ 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 ]
517 const AC_SYMS: [&[u8]; 2] = [
519 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
520 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
521 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
522 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
523 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
524 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
525 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
526 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
527 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
528 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
529 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
530 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
531 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
532 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
533 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
534 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
535 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
536 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
537 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
538 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
542 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
543 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
544 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
545 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
546 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
547 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
548 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
549 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
550 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
551 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
552 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
553 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
554 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
555 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
556 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
557 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
558 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
559 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
560 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
561 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,