aac: fix intensity stereo reconstruction for ms_mask_present=0 case
[nihav.git] / nihav-game / src / codecs / smush / v2.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 //use std::str::FromStr;
4
5 struct FrameData {
6 info: NACodecInfoRef,
7 width: usize,
8 height: usize,
9 frm0: Vec<u16>,
10 frm1: Vec<u16>,
11 frm2: Vec<u16>,
12 }
13
14 impl FrameData {
15 fn new() -> Self {
16 Self {
17 info: NACodecInfoRef::default(),
18 width: 0,
19 height: 0,
20 frm0: Vec::new(),
21 frm1: Vec::new(),
22 frm2: Vec::new(),
23 }
24 }
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();
31
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);
35 Ok(())
36 } else {
37 Err(DecoderError::InvalidData)
38 }
39 }
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);
47 }
48 } else {
49 return Err(DecoderError::Bug);
50 }
51
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 });
56 Ok(frm.into_ref())
57 }
58 }
59
60 fn decode_rle(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
61 let mut len = 0;
62 let mut clr = 0;
63 let mut run = false;
64
65 for el in dst.iter_mut() {
66 if len == 0 {
67 let op = br.read_byte()?;
68 run = (op & 1) != 0;
69 if run {
70 clr = br.read_byte()?;
71 }
72 len = ((op >> 1) + 1) as usize;
73 }
74 *el = if run { clr } else { br.read_byte()? };
75 len -= 1;
76 }
77 validate!(len == 0);
78
79 Ok(())
80 }
81
82 struct Smush2Decoder {
83 glyphs4: [[u8; 16]; 256],
84 glyphs8: [[u8; 64]; 256],
85 pic: FrameData,
86 rle_buf: Vec<u8>,
87 }
88
89 impl Smush2Decoder {
90 fn new() -> Self {
91 let mut glyphs4 = [[0; 16]; 256];
92 let mut glyphs8 = [[0; 64]; 256];
93 super::make_glyphs_47(&mut glyphs4, &mut glyphs8);
94 Self {
95 pic: FrameData::new(),
96 rle_buf: Vec::new(),
97 glyphs4, glyphs8,
98 }
99 }
100 }
101
102 struct BlockData<'a> {
103 glyphs4: &'a [[u8; 16]; 256],
104 glyphs8: &'a [[u8; 64]; 256],
105 frm1: &'a [u16],
106 frm2: &'a [u16],
107 cb: &'a [u16; 256],
108 clr4: [u16; 4],
109 stride: usize,
110 }
111
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];
116 }
117 }
118 }
119
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()?;
123 match op {
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)?;
130 },
131 0xFF => {
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()?;
136 },
137 0xFE => {
138 let pix = br.read_u16le()?;
139 for dst in dst.chunks_mut(stride).take(bsize) {
140 for el in dst[..bsize].iter_mut() {
141 *el = pix;
142 }
143 }
144 },
145 0xFD => {
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() {
150 *el = pix;
151 }
152 }
153 },
154 0xF9..=0xFC => {
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() {
158 *el = pix;
159 }
160 }
161 },
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);
169 },
170 0xF8 => {
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()?;
175 },
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);
183 },
184 0xF7 => {
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];
189 },
190 0xF6 => {
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]);
195 }
196 },
197 0xF5 => {
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);
202 validate!(off >= 0);
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]);
207 }
208 },
209 _ => {
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]);
217 }
218 },
219 };
220 Ok(())
221 }
222
223 impl NADecoder for Smush2Decoder {
224 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
225 self.pic.init(info)
226 }
227 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
228 let src = pkt.get_buffer();
229 validate!(src.len() > 8);
230
231 let mut mr = MemoryReader::new_read(&src);
232 let mut br = ByteReader::new(&mut mr);
233
234 let mut reorder = 0;
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());
240 match &tag {
241 b"Bl16" => {
242 validate!(size >= 8);
243 br.read_skip(2)?;
244 let _x = br.read_u16le()? as usize;
245 let _y = br.read_u16le()? as usize;
246 br.read_skip(2)?;
247 validate!(_x <= self.pic.width && _y <= self.pic.height);
248 if size > 8 {
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()?;
255 br.read_skip(4)?;
256 let mut clr4 = [0; 4];
257 for el in clr4.iter_mut() {
258 *el = br.read_u16le()?;
259 }
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()?;
266 }
267 if size > 0x230 {
268 br.read_skip(8)?;
269 }
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);
275
276 if seq == 0 {
277 for el in self.pic.frm1.iter_mut() {
278 *el = bg_clr;
279 }
280 for el in self.pic.frm2.iter_mut() {
281 *el = bg_clr;
282 }
283 }
284
285 match compr {
286 0 => {
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()?;
290 }
291 }
292 },
293 1 => { unimplemented!(); }, //decode half-res and interpolate
294 2 => {
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,
301 clr4,
302 cb: &cb,
303 };
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)?;
309 }
310 }
311 },
312 3 => {
313 self.pic.frm0.copy_from_slice(&self.pic.frm2);
314 },
315 4 => {
316 self.pic.frm0.copy_from_slice(&self.pic.frm1);
317 },
318 5 => {
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)?;
325 }
326 }
327 },
328 6 => {
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;
332 *el = cb[idx];
333 }
334 }
335 },
336 7 => { unimplemented!(); }, //decode half-res using codebook indices and interpolate
337 8 => {
338 let size = w * h;
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];
344 }
345 }
346 },
347 _ => return Err(DecoderError::NotImplemented),
348 };
349 }
350 },
351 _ => br.read_skip(size)?,
352 };
353 }
354
355 let ret = self.pic.get_frame(pkt);
356
357 if reorder == 2 {
358 std::mem::swap(&mut self.pic.frm1, &mut self.pic.frm2);
359 }
360 if reorder != 0 {
361 std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2);
362 }
363
364 ret
365 }
366 fn flush(&mut self) {
367 }
368 }
369
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 }
374 }
375
376
377 pub fn get_decoder_video_v2() -> Box<dyn NADecoder + Send> {
378 Box::new(Smush2Decoder::new())
379 }
380
381 #[cfg(test)]
382 mod test {
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
389 #[test]
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);
395
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]]));
404 }
405 }
406
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],
459 ];