1 use nihav_core::io::byteio::{ByteReader,MemoryReader};
2 use nihav_core::formats::YUV420_FORMAT;
3 use nihav_core::codecs::*;
4 use nihav_codec_support::codecs::HAMShuffler;
7 #[derive(Clone,Copy,PartialEq)]
15 struct CinepakDecoder {
18 cb_v1: [[u8; 6]; 256],
19 cb_v4: [[u8; 6]; 256],
23 fn put_block(block: &[u8; 24], x: usize, y: usize, frm: &mut NASimpleVideoFrame<u8>) {
24 let mut yoff = frm.offset[0] + x + y * frm.stride[0];
27 frm.data[yoff + j] = block[j + i * 4];
29 yoff += frm.stride[0];
31 let mut uoff = frm.offset[1] + x / 2 + y / 2 * frm.stride[1];
34 frm.data[uoff + j] = block[j + i * 2 + 16];
36 uoff += frm.stride[1];
38 let mut voff = frm.offset[2] + x / 2 + y / 2 * frm.stride[2];
41 frm.data[voff + j] = block[j + i * 2 + 20];
43 voff += frm.stride[2];
47 fn put_block_gray(block: &[u8; 24], x: usize, y: usize, frm: &mut NASimpleVideoFrame<u8>) {
48 let mut yoff = frm.offset[0] + x + y * frm.stride[0];
51 frm.data[yoff + j] = block[j + i * 4];
53 yoff += frm.stride[0];
60 info: NACodecInfo::new_dummy(),
61 frmmgr: HAMShuffler::new(),
64 mode: DecodeMode::Unknown,
67 fn read_cb(br: &mut ByteReader, size: usize, cb: &mut [[u8; 6]; 256], is_yuv: bool) -> DecoderResult<()> {
68 let cb_elem = if is_yuv { 6 } else { 4 };
69 let cb_size = (size - 4) / cb_elem;
70 validate!(size - 4 == cb_size * cb_elem);
71 validate!(cb_size <= 256);
73 br.read_buf(&mut cb[i][..cb_elem])?;
84 fn read_cb_upd(br: &mut ByteReader, size: usize, cb: &mut [[u8; 6]; 256], is_yuv: bool) -> DecoderResult<()> {
85 let cb_elem = if is_yuv { 6 } else { 4 };
86 let end = br.tell() + (size as u64) - 4;
87 for i in (0..256).step_by(32) {
91 let upd = br.read_u32be()?;
93 if ((upd >> (31 - j)) & 1) != 0 {
94 br.read_buf(&mut cb[i + j][..cb_elem])?;
100 cb[i + j][5] ^= 0x80;
105 validate!(br.tell() == end);
108 fn decode_strip(&mut self, src: &[u8], is_intra: bool, is_intra_strip: bool, xoff: usize, yoff: usize, xend: usize, yend: usize, frm: &mut NASimpleVideoFrame<u8>) -> DecoderResult<()> {
109 let mut mr = MemoryReader::new_read(src);
110 let mut br = ByteReader::new(&mut mr);
112 let mut idx_size = 0;
113 let mut v1_only = false;
114 while br.left() > 0 {
115 let id = br.read_byte()?;
116 if (id & 0xF0) == 0x20 {
117 validate!(((id & 1) != 0) ^ is_intra_strip);
119 let size = br.read_u24be()? as usize;
120 validate!(size >= 4 && (size - 4 <= (br.left() as usize)));
122 0x20 => Self::read_cb (&mut br, size, &mut self.cb_v4, true)?,
123 0x21 => Self::read_cb_upd(&mut br, size, &mut self.cb_v4, true)?,
124 0x22 => Self::read_cb (&mut br, size, &mut self.cb_v1, true)?,
125 0x23 => Self::read_cb_upd(&mut br, size, &mut self.cb_v1, true)?,
126 0x24 => Self::read_cb (&mut br, size, &mut self.cb_v4, false)?,
127 0x25 => Self::read_cb_upd(&mut br, size, &mut self.cb_v4, false)?,
128 0x26 => Self::read_cb (&mut br, size, &mut self.cb_v1, false)?,
129 0x27 => Self::read_cb_upd(&mut br, size, &mut self.cb_v1, false)?,
130 0x30 => { // intra indices
131 validate!(idx_pos == 0);
132 idx_pos = br.tell() as usize;
134 br.read_skip(idx_size)?;
136 0x31 => { // inter indices
137 validate!(!is_intra);
138 validate!(idx_pos == 0);
139 idx_pos = br.tell() as usize;
141 br.read_skip(idx_size)?;
143 0x32 => { // V1-only blocks
144 validate!(idx_pos == 0);
145 idx_pos = br.tell() as usize;
148 br.read_skip(idx_size)?;
150 _ => return Err(DecoderError::InvalidData),
153 validate!(idx_pos != 0);
154 let mut mr = MemoryReader::new_read(&src[idx_pos..][..idx_size]);
155 let mut br = ByteReader::new(&mut mr);
159 let mut block = [0u8; 24];
160 while br.left() > 0 {
161 let flags = if !v1_only { br.read_u32be()? } else { 0xFFFFFFFF };
162 let mut mask = 1 << 31;
165 let skip = (flags & mask) == 0;
179 if (flags & mask) == 0 {
180 let idx = br.read_byte()? as usize;
181 let cb = &self.cb_v1[idx];
182 block[ 0] = cb[0]; block[ 1] = cb[0]; block[ 2] = cb[1]; block[ 3] = cb[1];
183 block[ 4] = cb[0]; block[ 5] = cb[0]; block[ 6] = cb[1]; block[ 7] = cb[1];
184 block[ 8] = cb[2]; block[ 9] = cb[2]; block[10] = cb[3]; block[11] = cb[3];
185 block[12] = cb[2]; block[13] = cb[2]; block[14] = cb[3]; block[15] = cb[3];
186 block[16] = cb[4]; block[17] = cb[4];
187 block[18] = cb[4]; block[19] = cb[4];
188 block[20] = cb[5]; block[21] = cb[5];
189 block[22] = cb[5]; block[23] = cb[5];
191 let idx0 = br.read_byte()? as usize;
192 let cb0 = &self.cb_v4[idx0];
193 let idx1 = br.read_byte()? as usize;
194 let cb1 = &self.cb_v4[idx1];
195 let idx2 = br.read_byte()? as usize;
196 let cb2 = &self.cb_v4[idx2];
197 let idx3 = br.read_byte()? as usize;
198 let cb3 = &self.cb_v4[idx3];
199 block[ 0] = cb0[0]; block[ 1] = cb0[1]; block[ 2] = cb1[0]; block[ 3] = cb1[1];
200 block[ 4] = cb0[2]; block[ 5] = cb0[3]; block[ 6] = cb1[2]; block[ 7] = cb1[3];
201 block[ 8] = cb2[0]; block[ 9] = cb2[1]; block[10] = cb3[0]; block[11] = cb3[1];
202 block[12] = cb2[2]; block[13] = cb2[3]; block[14] = cb3[2]; block[15] = cb3[3];
203 block[16] = cb0[4]; block[17] = cb1[4];
204 block[18] = cb2[4]; block[19] = cb3[4];
205 block[20] = cb0[5]; block[21] = cb1[5];
206 block[22] = cb2[5]; block[23] = cb3[5];
209 if self.mode == DecodeMode::YUV {
210 put_block(&block, x, y, frm);
212 put_block_gray(&block, x, y, frm);
228 impl NADecoder for CinepakDecoder {
229 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
230 if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
231 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT));
232 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, None).into_ref();
236 Err(DecoderError::InvalidData)
239 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
240 let src = pkt.get_buffer();
241 if src.len() <= 10 { return Err(DecoderError::ShortData); }
243 let mut mr = MemoryReader::new_read(src.as_slice());
244 let mut br = ByteReader::new(&mut mr);
246 let flags = br.read_byte()?;
247 let size = br.read_u24be()? as usize;
248 validate!(src.len() >= size);
249 let width = br.read_u16be()? as usize;
250 let height = br.read_u16be()? as usize;
251 let nstrips = br.read_u16be()? as usize;
253 let is_intra = (flags & 1) == 0;
255 let mut mode = DecodeMode::Unknown;
257 let mut stripsize = br.read_u24be()?;
259 while stripsize > 0 {
260 let ctype = br.read_byte()?;
261 let csize = br.read_u24be()?;
263 0x20 | 0x21 | 0x22 | 0x23 => {
264 mode = DecodeMode::YUV;
267 0x24 | 0x25 | 0x26 | 0x27 => {
268 mode = DecodeMode::Gray;
272 br.read_skip(csize as usize)?;
273 validate!(stripsize >= csize);
278 validate!(mode != DecodeMode::Unknown);
279 br.seek(SeekFrom::Start(10))?;
280 for sd in pkt.side_data.iter() {
282 NASideData::Palette(_, _) => {
283 mode = DecodeMode::Palette;
290 if let Some(ref vinfo) = self.info.get_properties().get_video_info() {
291 if vinfo.width != width || vinfo.height != height || self.mode != mode {
293 let fmt = match mode {
294 DecodeMode::YUV => YUV420_FORMAT,
295 DecodeMode::Gray => NAPixelFormaton {
296 model: ColorModel::YUV(YUVSubmodel::YUVJ),
298 comp_info: [Some(NAPixelChromaton{h_ss: 0, v_ss: 0, packed: false, depth: 8, shift: 0, comp_offs: 0, next_elem: 1}), None, None, None, None],
304 DecodeMode::Palette => PAL8_FORMAT,
307 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(width, height, false, fmt));
308 self.info = NACodecInfo::new_ref(self.info.get_name(), myinfo, None).into_ref();
314 let vinfo = self.info.get_properties().get_video_info().unwrap();
315 let bufinfo = alloc_video_buffer(vinfo, 2)?;
316 buf = bufinfo.get_vbuf().unwrap();
319 validate!(self.mode == mode);
320 let bufret = self.frmmgr.clone_ref();
321 if let Some(vbuf) = bufret {
324 return Err(DecoderError::MissingReference);
327 if self.mode == DecodeMode::Palette {
328 let paloff = buf.get_offset(1);
329 let data = buf.get_data_mut().unwrap();
330 let dpal = &mut data[paloff..];
331 for sd in pkt.side_data.iter() {
333 NASideData::Palette(_, ref pal) => {
334 for (dst, src) in dpal.chunks_mut(3).zip(pal.chunks(4)) {
345 let mut frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
348 for i in 0..nstrips {
349 let flags = br.read_byte()?;
350 validate!(flags == 0x10 || flags == 0x11);
351 let is_intra_strip = (flags & 1) == 0;
352 let size = br.read_u24be()? as usize;
353 validate!(size > 12 && (size - 4) <= (br.left() as usize));
354 let yoff = br.read_u16be()? as usize;
355 let xoff = br.read_u16be()? as usize;
356 if xoff != 0 || yoff != 0 {
357 return Err(DecoderError::NotImplemented);
359 let yend = br.read_u16be()? as usize;
360 let xend = br.read_u16be()? as usize;
361 if i == 0 && is_intra && !is_intra_strip {
362 return Err(DecoderError::InvalidData);
364 let start = br.tell() as usize;
365 let end = start + size - 12;
366 let strip_data = &src[start..end];
367 self.decode_strip(strip_data, is_intra, is_intra_strip, 0, last_y, xend, last_y + yend, &mut frm)?;
368 br.read_skip(size - 12)?;
372 self.frmmgr.add_frame(buf.clone());
373 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
374 frm.set_keyframe(is_intra);
375 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
378 fn flush(&mut self) {
383 impl NAOptionHandler for CinepakDecoder {
384 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
385 fn set_options(&mut self, _options: &[NAOption]) { }
386 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
389 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
390 Box::new(CinepakDecoder::new())
395 use nihav_core::codecs::RegisteredDecoders;
396 use nihav_core::demuxers::RegisteredDemuxers;
397 use nihav_codec_support::test::dec_video::*;
398 use crate::generic_register_all_codecs;
399 use crate::generic_register_all_demuxers;
402 let mut dmx_reg = RegisteredDemuxers::new();
403 generic_register_all_demuxers(&mut dmx_reg);
404 let mut dec_reg = RegisteredDecoders::new();
405 generic_register_all_codecs(&mut dec_reg);
406 test_decoding("avi", "cinepak", "assets/Misc/ot171.avi", Some(10), &dmx_reg,
407 &dec_reg, ExpectedTestResult::MD5Frames(vec![
408 [0xd58326b0, 0xdbfc1dcc, 0x6d66a04c, 0x08a21bbb],
409 [0x9b2cb5c5, 0x69b5f261, 0xcaccaaaf, 0xff2a807d],
410 [0x55c322d5, 0xf76f81ce, 0x923ada8c, 0x4925a5c8],
411 [0x2d1a537a, 0x62233cb6, 0xc1d39c2f, 0xeec9ccf3],
412 [0xf3cc841d, 0x56603c01, 0x34f521cf, 0x61f8a0c9],
413 [0xd75c0802, 0x9e786186, 0xc7a05cdf, 0x52ddc59d],
414 [0xde19733b, 0x29633d17, 0x507e9f82, 0x94c09158],
415 [0x1ea11919, 0x133a282c, 0x8cee485c, 0x150cb3f4],
416 [0x55a6d8fb, 0x2ea287c0, 0x36b3083b, 0x954cfc64],
417 [0xfb8be1fb, 0x84ad10aa, 0xa00ee55c, 0x9e191e5b],
418 [0x9c090a08, 0x43071726, 0x26236b5a, 0x79595848]]));
421 fn test_cinepak_gray() {
422 let mut dmx_reg = RegisteredDemuxers::new();
423 generic_register_all_demuxers(&mut dmx_reg);
424 let mut dec_reg = RegisteredDecoders::new();
425 generic_register_all_codecs(&mut dec_reg);
426 test_decoding("mov", "cinepak", "assets/Misc/dday.mov", Some(10), &dmx_reg,
427 &dec_reg, ExpectedTestResult::MD5Frames(vec![
428 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
429 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
430 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
431 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
432 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
433 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
434 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
435 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
436 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
437 [0x2ab229bc, 0xb71308aa, 0x979511c6, 0xcef3ea92],
438 [0xb8411fa4, 0x3a35f646, 0x85e8e04a, 0xfff58785]]));
441 fn test_cinepak_pal() {
442 let mut dmx_reg = RegisteredDemuxers::new();
443 generic_register_all_demuxers(&mut dmx_reg);
444 let mut dec_reg = RegisteredDecoders::new();
445 generic_register_all_codecs(&mut dec_reg);
446 test_decoding("mov", "cinepak", "assets/Misc/catfight Tag team DT.mov", Some(10), &dmx_reg,
447 &dec_reg, ExpectedTestResult::MD5Frames(vec![
448 [0x3f7ec8ea, 0x873a2bc6, 0xcc58336e, 0xe88c4ffd],
449 [0x9665feab, 0xc035fb92, 0x5e4b8718, 0xd1c68877],
450 [0x804f8838, 0x7f4b126e, 0x9efab284, 0xee62d451],
451 [0xbb1930dd, 0x62d4a5d1, 0xca34d891, 0x31236269],
452 [0xc23ec739, 0xbe683ffd, 0xecbc337b, 0x73a96b63],
453 [0xa2fa75f2, 0x1dd937a8, 0x44e2074e, 0x1ac24467],
454 [0x9ba0f1e5, 0xadbe5357, 0x4cfa785b, 0x16181d41],
455 [0xe126c340, 0x6ceaac41, 0x64992bff, 0x8d4bc3c4],
456 [0xba6b2510, 0xc40c2b85, 0x1c7d0199, 0x333d4860],
457 [0x293fe1c2, 0x9f358a7e, 0x4fef6450, 0x8477a4ff],
458 [0x4509095a, 0x65575fdd, 0x3a17ecc4, 0x37821bf9]]));