1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 //use std::str::FromStr;
17 info: NACodecInfoRef::default(),
25 fn init(&mut self, info: NACodecInfoRef) -> DecoderResult<()> {
26 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
27 self.width = vinfo.get_width();
28 self.height = vinfo.get_height();
29 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, RGB565_FORMAT));
30 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
32 self.frm0.resize(self.width * self.height, 0);
33 self.frm1.resize(self.width * self.height, 0);
34 self.frm2.resize(self.width * self.height, 0);
37 Err(DecoderError::InvalidData)
40 fn get_frame(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
41 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
42 if let Some(ref mut vbuf) = bufinfo.get_vbuf16() {
43 let stride = vbuf.get_stride(0);
44 let data = vbuf.get_data_mut().unwrap();
45 for (dst, src) in data.chunks_mut(stride).zip(self.frm0.chunks(self.width).take(self.height)) {
46 dst[..self.width].copy_from_slice(src);
49 return Err(DecoderError::Bug);
52 let is_intra = pkt.keyframe;
53 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
54 frm.set_keyframe(is_intra);
55 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
60 fn decode_rle(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
65 for el in dst.iter_mut() {
67 let op = br.read_byte()?;
70 clr = br.read_byte()?;
72 len = ((op >> 1) + 1) as usize;
74 *el = if run { clr } else { br.read_byte()? };
82 struct Smush2Decoder {
83 glyphs4: [[u8; 16]; 256],
84 glyphs8: [[u8; 64]; 256],
91 let mut glyphs4 = [[0; 16]; 256];
92 let mut glyphs8 = [[0; 64]; 256];
93 super::make_glyphs_47(&mut glyphs4, &mut glyphs8);
95 pic: FrameData::new(),
102 struct BlockData<'a> {
103 glyphs4: &'a [[u8; 16]; 256],
104 glyphs8: &'a [[u8; 64]; 256],
112 fn draw_glyph(dst: &mut [u16], stride: usize, bsize: usize, glyph: &[u8], clr2: [u16; 2]) {
113 for (dst, src) in dst.chunks_mut(stride).zip(glyph.chunks_exact(bsize)) {
114 for (el, &bit) in dst[..bsize].iter_mut().zip(src.iter()) {
115 *el = clr2[bit as usize];
120 fn do_block2(br: &mut ByteReader, dst: &mut [u16], x: usize, y: usize, bsize: usize, bdata: &BlockData) -> DecoderResult<()> {
121 let stride = bdata.stride;
122 let op = br.read_byte()?;
124 0xFF if bsize > 2 => {
125 let hsize = bsize / 2;
126 do_block2(br, dst, x, y, hsize, bdata)?;
127 do_block2(br, &mut dst[hsize..], x + hsize, y, bsize / 2, bdata)?;
128 do_block2(br, &mut dst[hsize * stride..], x, y + hsize, hsize, bdata)?;
129 do_block2(br, &mut dst[hsize * (stride + 1)..], x + hsize, y + hsize, bsize / 2, bdata)?;
132 dst[0] = br.read_u16le()?;
133 dst[1] = br.read_u16le()?;
134 dst[stride] = br.read_u16le()?;
135 dst[stride + 1] = br.read_u16le()?;
138 let pix = br.read_u16le()?;
139 for dst in dst.chunks_mut(stride).take(bsize) {
140 for el in dst[..bsize].iter_mut() {
146 let idx = br.read_byte()? as usize;
147 let pix = bdata.cb[idx];
148 for dst in dst.chunks_mut(stride).take(bsize) {
149 for el in dst[..bsize].iter_mut() {
155 let pix = bdata.clr4[(op - 0xF9) as usize];
156 for dst in dst.chunks_mut(stride).take(bsize) {
157 for el in dst[..bsize].iter_mut() {
162 0xF8 if bsize > 2 => {
163 let idx = br.read_byte()? as usize;
164 let mut clr2 = [0; 2];
165 clr2[1] = br.read_u16le()?;
166 clr2[0] = br.read_u16le()?;
167 let glyph: &[u8] = if bsize == 8 { &bdata.glyphs8[idx] } else { &bdata.glyphs4[idx] };
168 draw_glyph(dst, stride, bsize, glyph, clr2);
171 dst[0] = br.read_u16le()?;
172 dst[1] = br.read_u16le()?;
173 dst[stride] = br.read_u16le()?;
174 dst[stride + 1] = br.read_u16le()?;
176 0xF7 if bsize > 2 => {
177 let idx = br.read_byte()? as usize;
178 let mut clr2 = [0; 2];
179 clr2[1] = bdata.cb[br.read_byte()? as usize];
180 clr2[0] = bdata.cb[br.read_byte()? as usize];
181 let glyph: &[u8] = if bsize == 8 { &bdata.glyphs8[idx] } else { &bdata.glyphs4[idx] };
182 draw_glyph(dst, stride, bsize, glyph, clr2);
185 dst[0] = bdata.cb[br.read_byte()? as usize];
186 dst[1] = bdata.cb[br.read_byte()? as usize];
187 dst[stride] = bdata.cb[br.read_byte()? as usize];
188 dst[stride + 1] = bdata.cb[br.read_byte()? as usize];
191 let off = x + y * stride;
192 let src = &bdata.frm1[off..];
193 for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) {
194 dst[..bsize].copy_from_slice(&src[..bsize]);
198 let off = br.read_u16le()? as i16 as isize;
199 let mx = off % (stride as isize);
200 let my = off / (stride as isize);
201 let off = (x as isize) + mx + ((y as isize) + my) * (stride as isize);
203 let src = &bdata.frm2[off as usize..];
204 for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) {
205 let size = dst.len().min(src.len()).min(bsize);
206 dst[..size].copy_from_slice(&src[..size]);
210 let mx = C47_MV[op as usize][0] as isize;
211 let my = C47_MV[op as usize][1] as isize;
212 let off = (x as isize) + mx + ((y as isize) + my) * (stride as isize);
213 let src = &bdata.frm2[off as usize..];
214 for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) {
215 let size = dst.len().min(src.len()).min(bsize);
216 dst[..size].copy_from_slice(&src[..size]);
223 impl NADecoder for Smush2Decoder {
224 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
227 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
228 let src = pkt.get_buffer();
229 validate!(src.len() > 8);
231 let mut mr = MemoryReader::new_read(&src);
232 let mut br = ByteReader::new(&mut mr);
235 while br.left() > 0 {
236 let tag = br.read_tag()?;
237 let size = br.read_u32be()? as usize;
238 let tend = br.tell() + (size as u64);
239 validate!((size as i64) <= br.left());
242 validate!(size >= 8);
244 let _x = br.read_u16le()? as usize;
245 let _y = br.read_u16le()? as usize;
247 validate!(_x <= self.pic.width && _y <= self.pic.height);
249 let w = br.read_u32le()? as usize;
250 let h = br.read_u32le()? as usize;
251 validate!(w == self.pic.width && h == self.pic.height);
252 let seq = br.read_u16le()?;
253 let compr = br.read_byte()?;
254 reorder = br.read_byte()?;
256 let mut clr4 = [0; 4];
257 for el in clr4.iter_mut() {
258 *el = br.read_u16le()?;
260 let bg_clr = br.read_u16le()?;
261 let _fg_clr = br.read_u16le()?;
262 let _unp_size = br.read_u32le()?;
263 let mut cb = [0; 256];
264 for el in cb.iter_mut() {
265 *el = br.read_u16le()?;
270 validate!(br.tell() < tend);
271 let start = br.tell() as usize;
272 br.seek(SeekFrom::Start(tend))?;
273 let mut mr = MemoryReader::new_read(&src[start..(tend as usize)]);
274 let mut br = ByteReader::new(&mut mr);
277 for el in self.pic.frm1.iter_mut() {
280 for el in self.pic.frm2.iter_mut() {
287 for row in self.pic.frm0.chunks_mut(self.pic.width).take(h) {
288 for el in row[..w].iter_mut() {
289 *el = br.read_u16le()?;
293 1 => { unimplemented!(); }, //decode half-res and interpolate
295 let bdata = BlockData {
296 glyphs4: &self.glyphs4,
297 glyphs8: &self.glyphs8,
298 frm1: &self.pic.frm1,
299 frm2: &self.pic.frm2,
300 stride: self.pic.width,
304 let dst = &mut self.pic.frm0;
305 let stride = self.pic.width;
306 for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() {
307 for col in (0..w).step_by(8) {
308 do_block2(&mut br, &mut row[col..], col, row_no * 8, 8, &bdata)?;
313 self.pic.frm0.copy_from_slice(&self.pic.frm2);
316 self.pic.frm0.copy_from_slice(&self.pic.frm1);
319 let size = w * h * 2;
320 self.rle_buf.resize(size, 0);
321 decode_rle(&mut br, &mut self.rle_buf)?;
322 for (drow, srow) in self.pic.frm0.chunks_mut(self.pic.width).zip(self.rle_buf.chunks(w * 2)) {
323 for (dst, src) in drow.iter_mut().zip(srow.chunks_exact(2)) {
324 *dst = read_u16le(src)?;
329 for row in self.pic.frm0.chunks_mut(self.pic.width).take(h) {
330 for el in row[..w].iter_mut() {
331 let idx = br.read_byte()? as usize;
336 7 => { unimplemented!(); }, //decode half-res using codebook indices and interpolate
339 self.rle_buf.resize(size, 0);
340 decode_rle(&mut br, &mut self.rle_buf)?;
341 for (row, src) in self.pic.frm0.chunks_mut(self.pic.width).zip(self.rle_buf.chunks(w)) {
342 for (el, &idx) in row.iter_mut().zip(src.iter()) {
343 *el = cb[idx as usize];
347 _ => return Err(DecoderError::NotImplemented),
351 _ => br.read_skip(size)?,
355 let ret = self.pic.get_frame(pkt);
358 std::mem::swap(&mut self.pic.frm1, &mut self.pic.frm2);
361 std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2);
366 fn flush(&mut self) {
370 impl NAOptionHandler for Smush2Decoder {
371 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
372 fn set_options(&mut self, _options: &[NAOption]) { }
373 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
377 pub fn get_decoder_video_v2() -> Box<dyn NADecoder + Send> {
378 Box::new(Smush2Decoder::new())
383 use nihav_core::codecs::RegisteredDecoders;
384 use nihav_core::demuxers::RegisteredDemuxers;
385 use nihav_codec_support::test::dec_video::*;
386 use crate::game_register_all_decoders;
387 use crate::game_register_all_demuxers;
388 // sample from Grim Fandango
390 fn test_smush_sanm() {
391 let mut dmx_reg = RegisteredDemuxers::new();
392 game_register_all_demuxers(&mut dmx_reg);
393 let mut dec_reg = RegisteredDecoders::new();
394 game_register_all_decoders(&mut dec_reg);
396 // sample from Grim Fandango
397 test_decoding("smush", "smushv2", "assets/Game/smush/lol.snm", Some(4), &dmx_reg, &dec_reg,
398 ExpectedTestResult::MD5Frames(vec![
399 [0x408e4dc9, 0x4483d7d8, 0xc9fae314, 0x3bb45ec9],
400 [0x83548952, 0x0b4a6ccb, 0x42609794, 0x59d3c7d4],
401 [0x5349f6ca, 0x56361199, 0x7194439f, 0x90df21b8],
402 [0x0c359bab, 0xed69f862, 0x9c899813, 0x3f6aac2a],
403 [0x58870617, 0x97c5f3a6, 0x1b2c761c, 0x6ec1cd0e]]));
407 const C47_MV: [[i8; 2]; 255] = [
408 [ 0, 0], [ -1, -43], [ 6, -43], [ -9, -42], [ 13, -41],
409 [-16, -40], [ 19, -39], [-23, -36], [ 26, -34], [ -2, -33],
410 [ 4, -33], [-29, -32], [ -9, -32], [ 11, -31], [-16, -29],
411 [ 32, -29], [ 18, -28], [-34, -26], [-22, -25], [ -1, -25],
412 [ 3, -25], [ -7, -24], [ 8, -24], [ 24, -23], [ 36, -23],
413 [-12, -22], [ 13, -21], [-38, -20], [ 0, -20], [-27, -19],
414 [ -4, -19], [ 4, -19], [-17, -18], [ -8, -17], [ 8, -17],
415 [ 18, -17], [ 28, -17], [ 39, -17], [-12, -15], [ 12, -15],
416 [-21, -14], [ -1, -14], [ 1, -14], [-41, -13], [ -5, -13],
417 [ 5, -13], [ 21, -13], [-31, -12], [-15, -11], [ -8, -11],
418 [ 8, -11], [ 15, -11], [ -2, -10], [ 1, -10], [ 31, -10],
419 [-23, -9], [-11, -9], [ -5, -9], [ 4, -9], [ 11, -9],
420 [ 42, -9], [ 6, -8], [ 24, -8], [-18, -7], [ -7, -7],
421 [ -3, -7], [ -1, -7], [ 2, -7], [ 18, -7], [-43, -6],
422 [-13, -6], [ -4, -6], [ 4, -6], [ 8, -6], [-33, -5],
423 [ -9, -5], [ -2, -5], [ 0, -5], [ 2, -5], [ 5, -5],
424 [ 13, -5], [-25, -4], [ -6, -4], [ -3, -4], [ 3, -4],
425 [ 9, -4], [-19, -3], [ -7, -3], [ -4, -3], [ -2, -3],
426 [ -1, -3], [ 0, -3], [ 1, -3], [ 2, -3], [ 4, -3],
427 [ 6, -3], [ 33, -3], [-14, -2], [-10, -2], [ -5, -2],
428 [ -3, -2], [ -2, -2], [ -1, -2], [ 0, -2], [ 1, -2],
429 [ 2, -2], [ 3, -2], [ 5, -2], [ 7, -2], [ 14, -2],
430 [ 19, -2], [ 25, -2], [ 43, -2], [ -7, -1], [ -3, -1],
431 [ -2, -1], [ -1, -1], [ 0, -1], [ 1, -1], [ 2, -1],
432 [ 3, -1], [ 10, -1], [ -5, 0], [ -3, 0], [ -2, 0],
433 [ -1, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0],
434 [ 7, 0], [-10, 1], [ -7, 1], [ -3, 1], [ -2, 1],
435 [ -1, 1], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1],
436 [-43, 2], [-25, 2], [-19, 2], [-14, 2], [ -5, 2],
437 [ -3, 2], [ -2, 2], [ -1, 2], [ 0, 2], [ 1, 2],
438 [ 2, 2], [ 3, 2], [ 5, 2], [ 7, 2], [ 10, 2],
439 [ 14, 2], [-33, 3], [ -6, 3], [ -4, 3], [ -2, 3],
440 [ -1, 3], [ 0, 3], [ 1, 3], [ 2, 3], [ 4, 3],
441 [ 19, 3], [ -9, 4], [ -3, 4], [ 3, 4], [ 7, 4],
442 [ 25, 4], [-13, 5], [ -5, 5], [ -2, 5], [ 0, 5],
443 [ 2, 5], [ 5, 5], [ 9, 5], [ 33, 5], [ -8, 6],
444 [ -4, 6], [ 4, 6], [ 13, 6], [ 43, 6], [-18, 7],
445 [ -2, 7], [ 0, 7], [ 2, 7], [ 7, 7], [ 18, 7],
446 [-24, 8], [ -6, 8], [-42, 9], [-11, 9], [ -4, 9],
447 [ 5, 9], [ 11, 9], [ 23, 9], [-31, 10], [ -1, 10],
448 [ 2, 10], [-15, 11], [ -8, 11], [ 8, 11], [ 15, 11],
449 [ 31, 12], [-21, 13], [ -5, 13], [ 5, 13], [ 41, 13],
450 [ -1, 14], [ 1, 14], [ 21, 14], [-12, 15], [ 12, 15],
451 [-39, 17], [-28, 17], [-18, 17], [ -8, 17], [ 8, 17],
452 [ 17, 18], [ -4, 19], [ 0, 19], [ 4, 19], [ 27, 19],
453 [ 38, 20], [-13, 21], [ 12, 22], [-36, 23], [-24, 23],
454 [ -8, 24], [ 7, 24], [ -3, 25], [ 1, 25], [ 22, 25],
455 [ 34, 26], [-18, 28], [-32, 29], [ 16, 29], [-11, 31],
456 [ 9, 32], [ 29, 32], [ -4, 33], [ 2, 33], [-26, 34],
457 [ 23, 36], [-19, 39], [ 16, 40], [-13, 41], [ 9, 42],
458 [ -6, 43], [ 1, 43], [ 0, 0], [ 0, 0], [ 0, 0],