]> git.nihav.org Git - nihav.git/blame - nihav-duck/src/codecs/truemotion2x.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-duck / src / codecs / truemotion2x.rs
CommitLineData
2994c841
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
3
4#[derive(Default)]
5struct Decryptor {
6 key: [u8; 4],
7}
8
9impl Decryptor {
10 fn decrypt(&mut self, buf: &mut [u8]) {
11 let mut pos: u8 = 0;
12 for el in buf.iter_mut() {
13 *el ^= self.key[(pos & 3) as usize];
14 pos = pos.wrapping_add(1);
15 }
16 }
17 fn set_state(&mut self, mut key: u32) {
18 for _ in 0..3 {
19 let bit31 = (key >> 31) & 1;
20 let bit21 = (key >> 21) & 1;
21 let bit01 = (key >> 1) & 1;
22 let nbit0 = !key & 1;
23 key = (key << 1) | (bit31 ^ bit21 ^ bit01 ^ nbit0);
24 }
25 for i in 0..4 {
26 self.key[i] = (key >> (8 * (i ^ 3))) as u8;
27 }
28 }
29}
30
31struct Deltas {
32 tabs: [[i16; 256]; 2],
33 codebook: [[u8; 8]; 256],
34 num_elems: [usize; 256],
35 num_vq: usize,
36 vq_idx: usize,
37 vq_pos: usize,
0cc2044a 38 vq_esc: u8,
2994c841
KS
39}
40
41impl Deltas {
42 fn reset(&mut self, br: &mut ByteReader) -> DecoderResult<()> {
43 let b = br.read_byte()? as usize;
44 self.vq_idx = b;
45 self.vq_pos = 0;
46 Ok(())
47 }
48 fn get_val(&mut self, br: &mut ByteReader) -> DecoderResult<u8> {
49 if self.vq_idx > self.codebook.len() { return Err(DecoderError::ShortData); }
50 let ret = self.codebook[self.vq_idx][self.vq_pos];
51 self.vq_pos += 1;
52 if self.vq_pos == self.num_elems[self.vq_idx] {
53 if br.left() > 0 {
54 self.reset(br)?;
55 } else {
56 self.vq_idx = self.codebook.len() + 1;
57 }
58 }
59 Ok(ret)
60 }
0cc2044a
KS
61 fn remap(val: u16) -> i16 {
62 let hval = (val >> 1) as i16;
63 if (val & 1) == 0 {
64 hval
65 } else {
66 -1 - hval
67 }
68 }
2994c841
KS
69 fn get_int(&mut self, br: &mut ByteReader) -> DecoderResult<i16> {
70 let b = self.get_val(br)?;
0cc2044a 71 if b != self.vq_esc - 1 {
8a7352c0 72 return Ok(Self::remap(u16::from(b)));
0cc2044a
KS
73 }
74 let mut run = 0;
75 let mut val;
8a7352c0 76 let mut pow = u16::from(self.vq_esc);
0cc2044a
KS
77 loop {
78 let b = self.get_val(br)?;
79 run += 1;
80 if b != self.vq_esc - 1 {
8a7352c0 81 val = u16::from(b) * pow;
0cc2044a
KS
82 break;
83 }
8a7352c0 84 pow *= u16::from(self.vq_esc);
0cc2044a
KS
85 }
86
87 for _ in 0..run {
8a7352c0
KS
88 pow /= u16::from(self.vq_esc);
89 let b = u16::from(self.get_val(br)?);
90 val += pow * b;
0cc2044a
KS
91 }
92 Ok(Self::remap(val))
2994c841
KS
93 }
94 fn get_dy(&mut self, br: &mut ByteReader) -> DecoderResult<i16> {
95 let b = self.get_val(br)?;
96 Ok(self.tabs[1][b as usize])
97 }
98 fn get_dc(&mut self, br: &mut ByteReader) -> DecoderResult<i16> {
99 let b = self.get_val(br)?;
100 Ok(self.tabs[0][b as usize])
101 }
102}
103
104impl Default for Deltas {
105 fn default() -> Self {
106 Self {
107 tabs: [[0; 256]; 2],
108 codebook: [[0; 8]; 256],
109 num_elems: [0; 256],
110 num_vq: 0,
111 vq_idx: 0,
112 vq_pos: 0,
0cc2044a 113 vq_esc: 0,
2994c841
KS
114 }
115 }
116}
117
118#[derive(Clone,Copy, Default)]
119struct BlkInfo {
120 btype: u8,
121 mode: u8,
122 mv_x: i16,
123 mv_y: i16,
124}
125
126const NUM_CPARAMS: usize = 25;
127const CPARAM_NONE: u8 = 42;
128const CPARAM_MISSING: u8 = 42 * 2;
0cc2044a 129const CPARAM_MV: u8 = 42 * 3;
2994c841
KS
130
131macro_rules! apply_delta {
132 ($buf:expr, $off:expr, $stride:expr, $hpred: expr, $delta:expr) => {
133 $hpred = $hpred.wrapping_add($delta);
134 $buf[$off] = $buf[$off - $stride].wrapping_add($hpred);
135 };
136}
137macro_rules! copy_line {
138 ($buf:expr, $off:expr, $stride:expr) => {
139 for i in 0..8 {
140 $buf[$off + i] = $buf[$off + i - $stride];
141 }
142 };
143}
144
0cc2044a
KS
145#[derive(Default)]
146struct Frame {
147 ydata: Vec<i16>,
148 udata: Vec<i16>,
149 vdata: Vec<i16>,
150 stride: usize,
151}
152
153impl Frame {
154 fn resize(&mut self, w: usize, h: usize) {
155 self.stride = w;
156 self.ydata.resize(self.stride * (h + 1), 0x80);
157 self.udata.resize(self.stride * (h + 1), 0x80);
158 self.vdata.resize(self.stride * (h + 1), 0x80);
159 }
160}
161
2994c841
KS
162#[derive(Default)]
163struct TM2XDecoder {
2422d969 164 info: NACodecInfoRef,
2994c841
KS
165 width: usize,
166 height: usize,
167 dec_buf: Vec<u8>,
168 version: u8,
0cc2044a 169 is_intra: bool,
2994c841
KS
170 deltas: Deltas,
171 blk_info: Vec<BlkInfo>,
172 tile_size: usize,
173 cparams: [[u8; 8]; NUM_CPARAMS],
0cc2044a
KS
174 cur_frame: Frame,
175 ref_frame: Frame,
2994c841
KS
176}
177
178impl TM2XDecoder {
179 fn new() -> Self { Self::default() }
180 fn output_frame(&mut self, buf: &mut NAVideoBuffer<u8>) {
0cc2044a
KS
181 let mut offs = [ buf.get_offset(0), buf.get_offset(1), buf.get_offset(2) ];
182 let strides = [ buf.get_stride(0), buf.get_stride(1), buf.get_stride(2) ];
1a967e6b 183 let data = buf.get_data_mut().unwrap();
2994c841
KS
184 let dst = data.as_mut_slice();
185
0cc2044a 186 let mut pos = self.cur_frame.stride;
2994c841 187 for _y in 0..self.height {
0cc2044a
KS
188 for x in 0..self.width {
189 let y = self.cur_frame.ydata[pos + x];
190 let u = self.cur_frame.udata[pos + x];
191 let v = self.cur_frame.vdata[pos + x];
192 dst[offs[0] + x] = y.max(0).min(255) as u8;
193 dst[offs[1] + x] = u.max(0).min(255) as u8;
194 dst[offs[2] + x] = v.max(0).min(255) as u8;
195 }
196 for c in 0..3 {
197 offs[c] += strides[c];
2994c841 198 }
0cc2044a 199 pos += self.cur_frame.stride;
2994c841
KS
200 }
201 }
202 fn parse_init(&mut self, version: u8) -> DecoderResult<()> {
203 self.version = version;
204
205 let mut mr = MemoryReader::new_read(&self.dec_buf);
206 let mut br = ByteReader::new(&mut mr);
207 if version > 4 {
208 let _smth = br.read_u32be()?;
209 }
210 let height = br.read_u16be()? as usize;
211 let width = br.read_u16be()? as usize;
212 validate!(width == self.width && height == self.height);
213 if version > 4 {
214 let _smth = br.read_u32be()?;
215 }
216 let _smth = br.read_byte()?;
217 let _nfuncs = br.read_byte()? as usize;
218 let _smth = br.read_u16be()? as usize;
219 let has_mv = br.read_byte()?;
0cc2044a 220 self.is_intra = has_mv == 0;
2994c841
KS
221 if version >= 4 {
222 let _flags = br.read_u16be()?;
223 let id_len = br.read_byte()? as usize;
224 br.read_skip(id_len)?;
225 let _smth1 = br.read_byte()?;
226 let len = br.read_byte()? as usize;
227 br.read_skip(len)?;
228 let _smth = br.read_u32be()?;
229 }
d24468d9 230
2994c841
KS
231 Ok(())
232 }
233 fn parse_tabs(&mut self) -> DecoderResult<()> {
234 let mut mr = MemoryReader::new_read(&self.dec_buf);
235 let mut br = ByteReader::new(&mut mr);
236
237 let idx = br.read_byte()? as usize;
238 validate!(idx < self.deltas.tabs.len());
239 let len = br.read_byte()? as usize;
240 validate!(((len * 2) as i64) == br.left());
241 for i in 0..len {
242 self.deltas.tabs[idx][i] = br.read_u16be()? as i16;
243 }
244
245 Ok(())
246 }
247 fn parse_cb_desc(&mut self, version: u8) -> DecoderResult<()> {
248 let mut mr = MemoryReader::new_read(&self.dec_buf);
249 let mut br = ByteReader::new(&mut mr);
250
251 if version == 0x0A {
0cc2044a
KS
252 self.deltas.vq_esc = br.read_byte()?;
253 validate!(self.deltas.vq_esc > 1);
2994c841
KS
254 let _tag = br.read_u16be()?;
255 }
256 let len = br.read_u16be()? as usize;
257 validate!(len + 3 == (br.left() as usize));
258 let num_entries = br.read_u16be()?;
259 validate!(num_entries == 256);
260 let max_elems = br.read_byte()?;
261 validate!(max_elems > 0 && max_elems <= 8);
262 let mut idx = 0;
263 while br.left() > 0 {
264 validate!(idx < self.deltas.codebook.len());
265 let num_elems = br.read_byte()? as usize;
266 validate!(num_elems <= 8);
267 self.deltas.num_elems[idx] = num_elems;
268 for i in 0..num_elems {
269 self.deltas.codebook[idx][i] = br.read_byte()?;
270 }
271 idx += 1;
272 }
273 validate!(idx == 256);
274 self.deltas.num_vq = idx;
275 Ok(())
276 }
277
b7c882c1 278 #[allow(clippy::cognitive_complexity)]
20b5a55f 279 #[allow(clippy::identity_op)]
2994c841
KS
280 fn decode_frame(&mut self, src: &[u8]) -> DecoderResult<()> {
281 let mut mr = MemoryReader::new_read(src);
282 let mut br = ByteReader::new(&mut mr);
283
284 self.deltas.reset(&mut br)?;
285 let bw = self.width / 8;
286 let bh = self.height / 8;
287 let ntiles = (bw + self.tile_size - 1) / self.tile_size;
0cc2044a
KS
288 let mut pos = self.cur_frame.stride;
289 let ydata = &mut self.cur_frame.ydata;
290 let udata = &mut self.cur_frame.udata;
291 let vdata = &mut self.cur_frame.vdata;
292 let stride = self.cur_frame.stride;
293 for by in 0..bh {
2994c841
KS
294 for tile in 0..ntiles {
295 let xpos = tile * self.tile_size;
296 let len = self.tile_size.min(bw - xpos);
0cc2044a
KS
297 let mut last_x = 0;
298 let mut last_y = 0;
2994c841
KS
299 for el in self.blk_info.iter_mut().take(len) {
300 let t1 = self.deltas.get_val(&mut br)?;
301 let t2 = self.deltas.get_val(&mut br)?;
2994c841
KS
302 validate!((t1 as usize) < NUM_CPARAMS);
303 validate!(self.cparams[t1 as usize][0] != CPARAM_MISSING);
304 el.btype = t1;
305 el.mode = t2;
306 if t2 > 0 {
307 el.mv_x = self.deltas.get_int(&mut br)?;
308 el.mv_y = self.deltas.get_int(&mut br)?;
0cc2044a
KS
309 last_x = el.mv_x;
310 last_y = el.mv_y;
2994c841 311 } else {
0cc2044a
KS
312 el.mv_x = last_x;
313 el.mv_y = last_y;
2994c841
KS
314 }
315 }
316 for line in 0..8 {
317 let mut ypred = 0i16;
318 let mut upred = 0i16;
319 let mut vpred = 0i16;
320 for x in 0..len {
321 let bx = xpos + x;
322 let op = self.cparams[self.blk_info[x].btype as usize][line];
0cc2044a 323 let cur_off = pos + bx * 8 + line * stride;
2994c841
KS
324 match op {
325 0 => { // y4|y4
326 for i in 0..8 {
327 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 328 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 329 }
0cc2044a
KS
330 copy_line!(udata, cur_off, stride);
331 copy_line!(vdata, cur_off, stride);
2994c841
KS
332 upred = 0;
333 vpred = 0;
334 },
335 1 => { // y2|y2
336 for i in 0..8 {
337 if (i & 1) == 0 {
338 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 339 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 340 } else {
0cc2044a 341 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
342 }
343 }
0cc2044a
KS
344 copy_line!(udata, cur_off, stride);
345 copy_line!(vdata, cur_off, stride);
2994c841
KS
346 upred = 0;
347 vpred = 0;
348 },
349 2 => { // y1|y1
350 for i in 0..8 {
351 if (i & 3) == 0 {
352 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 353 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 354 } else {
0cc2044a 355 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
356 }
357 }
0cc2044a
KS
358 copy_line!(udata, cur_off, stride);
359 copy_line!(vdata, cur_off, stride);
2994c841
KS
360 upred = 0;
361 vpred = 0;
362 },
363 3 => { // y1|0
364 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 365 apply_delta!(ydata, cur_off, stride, ypred, delta);
2994c841 366 for i in 1..8 {
0cc2044a 367 ydata[cur_off + i] = ydata[cur_off];
2994c841 368 }
0cc2044a
KS
369 copy_line!(udata, cur_off, stride);
370 copy_line!(vdata, cur_off, stride);
2994c841
KS
371 upred = 0;
372 vpred = 0;
373 },
374 4 => { // c2y2c2y2|c2y2c2y2
375 for i in (0..8).step_by(2) {
376 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a
KS
377 apply_delta!(udata, cur_off + i + 0, stride, upred, delta);
378 udata[cur_off + i + 1] = udata[cur_off + i];
2994c841 379 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a
KS
380 apply_delta!(vdata, cur_off + i + 0, stride, vpred, delta);
381 vdata[cur_off + i + 1] = vdata[cur_off + i];
2994c841 382 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 383 apply_delta!(ydata, cur_off + i + 0, stride, ypred, delta);
2994c841 384 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 385 apply_delta!(ydata, cur_off + i + 1, stride, ypred, delta);
2994c841
KS
386 }
387 },
388 5 => { // c2y1|c2y1
389 for i in 0..8 {
390 if (i & 3) == 0 {
391 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 392 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 393 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 394 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 395 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 396 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 397 } else {
0cc2044a
KS
398 udata[cur_off + i] = udata[cur_off + i - 1];
399 vdata[cur_off + i] = vdata[cur_off + i - 1];
400 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
401 }
402 }
403 },
404 6 | 7 => unreachable!(),
405 8 => { // c2y4|c2y4
406 for i in 0..8 {
407 if (i & 3) == 0 {
408 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 409 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 410 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 411 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 412 } else {
0cc2044a
KS
413 udata[cur_off + i] = udata[cur_off + i - 1];
414 vdata[cur_off + i] = vdata[cur_off + i - 1];
2994c841
KS
415 }
416 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 417 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841
KS
418 }
419 },
420 9 => { // c2y2|c2y2
421 for i in 0..8 {
422 if (i & 3) == 0 {
423 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 424 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 425 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 426 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 427 } else {
0cc2044a
KS
428 udata[cur_off + i] = udata[cur_off + i - 1];
429 vdata[cur_off + i] = vdata[cur_off + i - 1];
2994c841
KS
430 }
431 if (i & 1) == 0 {
432 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 433 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 434 } else {
0cc2044a 435 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
436 }
437 }
438 },
439 10 => { // c2y1|c2y1
440 for i in 0..8 {
441 if (i & 3) == 0 {
442 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 443 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 444 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 445 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 446 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 447 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 448 } else {
0cc2044a
KS
449 udata[cur_off + i] = udata[cur_off + i - 1];
450 vdata[cur_off + i] = vdata[cur_off + i - 1];
451 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
452 }
453 }
454 },
455 11 => unreachable!(),
456 12 => { // c2y8
457 for i in 0..8 {
458 if i == 0 {
459 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 460 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 461 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 462 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 463 } else {
0cc2044a
KS
464 udata[cur_off + i] = udata[cur_off + i - 1];
465 vdata[cur_off + i] = vdata[cur_off + i - 1];
2994c841
KS
466 }
467 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 468 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841
KS
469 }
470 },
471 13 => { // c2y4
472 for i in 0..8 {
473 if i == 0 {
474 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 475 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 476 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 477 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 478 } else {
0cc2044a
KS
479 udata[cur_off + i] = udata[cur_off + i - 1];
480 vdata[cur_off + i] = vdata[cur_off + i - 1];
2994c841
KS
481 }
482 if (i & 1) == 0 {
483 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 484 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 485 } else {
0cc2044a 486 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
487 }
488 }
489 },
490 14 => { // c2y2
491 for i in 0..8 {
492 if i == 0 {
493 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 494 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 495 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 496 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 497 } else {
0cc2044a
KS
498 udata[cur_off + i] = udata[cur_off + i - 1];
499 vdata[cur_off + i] = vdata[cur_off + i - 1];
2994c841
KS
500 }
501 if (i & 3) == 0 {
502 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 503 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 504 } else {
0cc2044a 505 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
506 }
507 }
508 },
509 15 => { // c2y1
510 for i in 0..8 {
511 if i == 0 {
512 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 513 apply_delta!(udata, cur_off + i, stride, upred, delta);
2994c841 514 let delta = self.deltas.get_dc(&mut br)?;
0cc2044a 515 apply_delta!(vdata, cur_off + i, stride, vpred, delta);
2994c841 516 let delta = self.deltas.get_dy(&mut br)?;
0cc2044a 517 apply_delta!(ydata, cur_off + i, stride, ypred, delta);
2994c841 518 } else {
0cc2044a
KS
519 udata[cur_off + i] = udata[cur_off + i - 1];
520 vdata[cur_off + i] = vdata[cur_off + i - 1];
521 ydata[cur_off + i] = ydata[cur_off + i - 1];
2994c841
KS
522 }
523 }
524 },
525 CPARAM_NONE => {
0cc2044a
KS
526 copy_line!(ydata, cur_off, stride);
527 copy_line!(udata, cur_off, stride);
528 copy_line!(vdata, cur_off, stride);
2994c841
KS
529 ypred = 0;
530 upred = 0;
531 vpred = 0;
532 },
20b5a55f 533 #[allow(clippy::int_plus_one)]
0cc2044a
KS
534 CPARAM_MV => {
535 let src_x = (bx as i16) * 8 + self.blk_info[x].mv_x;
536 let src_y = ((by * 8 + line) as i16) + self.blk_info[x].mv_y;
537 validate!(src_x >= 0 && (src_x as usize) + 8 <= self.width);
538 validate!(src_y >= 0 && (src_y as usize) + 1 <= self.height);
539 let ref_off = (src_x as usize) + ((src_y + 1) as usize) * stride;
20b5a55f
KS
540 ydata[cur_off..][..8].copy_from_slice(&self.ref_frame.ydata[ref_off..][..8]);
541 udata[cur_off..][..8].copy_from_slice(&self.ref_frame.udata[ref_off..][..8]);
542 vdata[cur_off..][..8].copy_from_slice(&self.ref_frame.vdata[ref_off..][..8]);
0cc2044a
KS
543 ypred = ydata[cur_off + 7] - ydata[cur_off + 7 - stride];
544 upred = udata[cur_off + 7] - udata[cur_off + 7 - stride];
545 vpred = vdata[cur_off + 7] - vdata[cur_off + 7 - stride];
546 },
2994c841
KS
547 _ => unreachable!(),
548 }
549 }
550 }
551 }
0cc2044a 552 pos += 8 * stride;
2994c841
KS
553 }
554
555 Ok(())
556 }
557}
558
559impl NADecoder for TM2XDecoder {
01613464 560 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
2994c841 561 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
0cc2044a
KS
562 let fmt = NAPixelFormaton::new(ColorModel::YUV(YUVSubmodel::YUVJ),
563 Some(NAPixelChromaton::new(0, 0, false, 8, 0, 0, 1)),
564 Some(NAPixelChromaton::new(0, 0, false, 8, 0, 1, 1)),
565 Some(NAPixelChromaton::new(0, 0, false, 8, 0, 2, 1)),
566 None, None, 0, 3);
567 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt));
2994c841
KS
568 self.width = vinfo.get_width();
569 self.height = vinfo.get_height();
0cc2044a
KS
570 self.cur_frame.resize(self.width, self.height);
571 self.ref_frame.resize(self.width, self.height);
2422d969 572 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
2994c841
KS
573 Ok(())
574 } else {
575 Err(DecoderError::InvalidData)
576 }
577 }
01613464 578 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
2994c841
KS
579 let src = pkt.get_buffer();
580 validate!(src.len() > 8);
581 let mut mr = MemoryReader::new_read(&src);
582 let mut br = ByteReader::new(&mut mr);
583 let mut dec = Decryptor::default();
584
585 let mut initialised = false;
586 let mut got_key = false;
587 let mut data_size = 0;
588 self.cparams = [[CPARAM_MISSING; 8]; NUM_CPARAMS];
0cc2044a 589 self.is_intra = false;
2994c841
KS
590 while br.left() >= 8 {
591 let magic = br.read_u24be()?;
592 let ctype = br.read_byte()?;
593 let size = br.read_u32be()? as usize;
594 validate!(magic == 0xA00001 && br.left() >= (size as i64));
595 if ctype == 0x06 {
596 validate!(size >= 4);
597 let key = br.read_u32be()?;
598 validate!((key as usize) == size - 4);
599 dec.set_state(key);
600 data_size = size - 4;
601 br.read_skip(size - 4)?;
602 got_key = true;
603 continue;
604 }
605 self.dec_buf.resize(size, 0);
606 br.read_buf(&mut self.dec_buf)?;
607 if ctype != 0x0A {
608 dec.decrypt(&mut self.dec_buf);
609 }
610 match ctype {
611 0x08 | 0x0C | 0x10 | 0x11 | 0x15 | 0x16 => {
612 if ctype < 0x15 { // old versions are not encrypted, roll back and zero key
613 dec.decrypt(&mut self.dec_buf);
614 dec.set_state(0);
615 got_key = true;
616 }
617 validate!(got_key && !initialised);
618 match ctype {
619 0x08 => self.parse_init(0)?,
620 0x0C => self.parse_init(1)?,
621 0x10 => self.parse_init(2)?,
622 0x11 => self.parse_init(3)?,
623 0x15 => self.parse_init(4)?,
624 0x16 => self.parse_init(5)?,
625 _ => unreachable!(),
626 };
627 initialised = true;
628 },
629 0x09 => {
630 validate!(initialised);
631 validate!(self.dec_buf.len() == 3);
632 validate!(self.dec_buf[0] == 8);
633 validate!(self.dec_buf[1] > 0);
634 validate!(self.dec_buf[2] == 1);
635 self.tile_size = self.dec_buf[1] as usize;
636 self.blk_info.resize(self.tile_size, BlkInfo::default());
637 },
638 0x0B => {
639 validate!(initialised);
640 validate!(self.dec_buf.len() == 4);
641 let idx = self.dec_buf[3] as usize;
642 validate!(idx < NUM_CPARAMS);
2994c841 643 validate!((self.dec_buf[0] as usize) < TM2X_CODING_PARAMS.len());
0cc2044a
KS
644 if self.dec_buf[0] != 0 {
645 let tab = &TM2X_CODING_PARAMS[self.dec_buf[0] as usize];
646 let m0 = tab[0] as usize;
647 let m1 = tab[1] as usize;
648 let m2 = tab[2] as usize;
649 let m3 = tab[3] as usize;
650 let full_mode = (m2 * 4 + m0) as u8;
651 let lores_mode = m0 as u8;
652 for i in 0..8 {
653 if (i % m1) == 0 && (i % m3) == 0 {
654 self.cparams[idx][i] = full_mode;
655 } else if (i % m1) == 0 {
656 self.cparams[idx][i] = lores_mode;
657 } else {
658 self.cparams[idx][i] = CPARAM_NONE;
659 }
2994c841 660 }
0cc2044a
KS
661 } else {
662 for i in 0..8 { self.cparams[idx][i] = CPARAM_MV; }
2994c841
KS
663 }
664 },
665 0x02 => {
666 validate!(initialised);
667 self.parse_tabs()?;
668 },
669 0x0A => {
670 validate!(initialised);
671 self.parse_cb_desc(0xA)?;
672 },
673 _ => { unimplemented!(); },
674 };
675 }
0cc2044a
KS
676 if !self.is_intra {
677 std::mem::swap(&mut self.cur_frame, &mut self.ref_frame);
678 }
2994c841
KS
679 self.decode_frame(&src[12..][..data_size])?;
680
0cc2044a 681 let myinfo = self.info.get_properties().get_video_info().unwrap();
8a7352c0 682 let bufinfo = alloc_video_buffer(myinfo, 2)?;
2994c841
KS
683 let mut buf = bufinfo.get_vbuf().unwrap();
684
2994c841
KS
685 self.output_frame(&mut buf);
686
687 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
0cc2044a
KS
688 frm.set_keyframe(self.is_intra);
689 frm.set_frame_type(if self.is_intra { FrameType::I } else { FrameType::P });
171860fc 690 Ok(frm.into_ref())
2994c841 691 }
f9be4e75
KS
692 fn flush(&mut self) {
693 }
2994c841
KS
694}
695
7d57ae2f
KS
696impl NAOptionHandler for TM2XDecoder {
697 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
698 fn set_options(&mut self, _options: &[NAOption]) { }
699 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
700}
701
08a1fab7 702pub fn get_decoder() -> Box<dyn NADecoder + Send> {
2994c841
KS
703 Box::new(TM2XDecoder::new())
704}
705
706#[cfg(test)]
707mod test {
708 use nihav_core::codecs::RegisteredDecoders;
709 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 710 use nihav_codec_support::test::dec_video::*;
78fb6560 711 use crate::duck_register_all_decoders;
e64739f8 712 use nihav_commonfmt::generic_register_all_demuxers;
2994c841
KS
713 #[test]
714 fn test_tm2x() {
715 let mut dmx_reg = RegisteredDemuxers::new();
716 generic_register_all_demuxers(&mut dmx_reg);
717 let mut dec_reg = RegisteredDecoders::new();
78fb6560 718 duck_register_all_decoders(&mut dec_reg);
2994c841 719
886cde48 720 // sample: https://samples.mplayerhq.hu/V-codecs/TM2x.avi
e12643e6
KS
721 test_decoding("avi", "truemotion2x", "assets/Duck/TM2x.avi", None,
722 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
723 [0x2854e7f3, 0x41e54fd3, 0xd9a16302, 0x580321b2],
724 [0x8e736f59, 0x57c58dc0, 0xe15bad3a, 0xf96e2c5b],
725 [0x12700e7c, 0xfa2d06e0, 0x05b758ba, 0xe79aabb6],
726 [0x29f935f2, 0x2ad0d6d1, 0x2fde19a2, 0x5aa3823b],
727 [0x7f1a787d, 0x77f3ab61, 0x0e584c66, 0x9d1842ea],
728 [0xb5607334, 0xdb149056, 0xe0e3ddb5, 0x19f8e254],
729 [0xb054e4d0, 0x1d241d4f, 0x75fdfe95, 0x9dde8024]]));
2994c841
KS
730 }
731}
732
733const TM2X_CODING_PARAMS: [[u8; 4]; 25] = [
734 [ 0, 0, 0, 0 ], [ 0, 1, 1, 1 ], [ 0, 1, 1, 2 ], [ 0, 1, 2, 4 ], [ 1, 1, 2, 4 ],
735 [ 0, 2, 2, 4 ], [ 1, 2, 2, 4 ], [ 2, 2, 2, 4 ], [ 1, 4, 2, 4 ], [ 2, 4, 2, 4 ],
736 [ 2, 8, 3, 8 ], [ 3, 4, 3, 8 ], [ 3, 8, 3, 8 ], [ 0, 1, 1, 4 ], [ 0, 1, 2, 2 ],
737 [ 0, 2, 1, 4 ], [ 1, 1, 2, 2 ], [ 1, 4, 2, 8 ], [ 2, 2, 3, 4 ], [ 2, 4, 3, 8 ],
738 [ 0, 1, 3, 8 ], [ 1, 2, 3, 8 ], [ 2, 4, 2, 4 ], [ 2, 4, 3, 8 ], [ 3, 8, 3, 8 ]
739];