]> git.nihav.org Git - nihav.git/blame_incremental - nihav-duck/src/codecs/truemotion1.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-duck / src / codecs / truemotion1.rs
... / ...
CommitLineData
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
3use super::truemotion1data::*;
4
5struct MaskState<'a> {
6 is_intra: bool,
7 pos: usize,
8 row_pos: usize,
9 row_size: usize,
10 mask: u8,
11 src: &'a [u8],
12}
13
14impl<'a> MaskState<'a> {
15 fn new(is_intra: bool, src: &'a [u8], row_size: usize) -> Self {
16 Self { is_intra, src, pos: 0, row_pos: 0, row_size, mask: 0x01 }
17 }
18 fn get_next(&mut self) -> bool {
19 if self.is_intra {
20 true
21 } else {
22 let res = (self.src[self.pos] & self.mask) == 0;
23 self.mask <<= 1;
24 if self.mask == 0 {
25 self.pos += 1;
26 self.mask = 0x01;
27 }
28 res
29 }
30 }
31 fn reset_row(&mut self) {
32 self.pos = self.row_pos;
33 self.mask = 0x01;
34 }
35 fn next_row(&mut self) {
36 self.row_pos += self.row_size;
37 self.reset_row();
38 }
39}
40
41struct IndexState<'a> {
42 src: &'a [u8],
43 pos: usize,
44 vec_idx: usize,
45 vec_subidx: usize,
46 tbl0: bool,
47}
48
49impl<'a> IndexState<'a> {
50 fn new(src: &'a [u8]) -> Self {
51 Self { src, pos: 0, vec_idx: 0, vec_subidx: 0, tbl0: false }
52 }
53 fn get_next(&mut self) -> DecoderResult<()> {
54 validate!(self.pos < self.src.len());
55 self.vec_idx = self.src[self.pos] as usize;
56 self.vec_subidx = 0;
57 self.pos += 1;
58 Ok(())
59 }
60 fn get_pred(&self, dtab: &[[u32; 4]; 256]) -> u32 { dtab[self.vec_idx][self.vec_subidx] }
61 fn get_diff16(&mut self, dtab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
62 if self.tbl0 {
63 return self.get_diff16_noesc(dtab);
64 }
65 let pred1 = self.get_pred(dtab);
66 let mut pred = pred1 >> 1;
67 if (pred1 & 1) != 0 {
68 self.get_next()?;
69 if self.vec_idx == 0 {
70 self.get_next()?;
71 let pred2 = self.get_pred(dtab);
72 pred = pred.wrapping_add((pred2 >> 1).wrapping_mul(5));
73 if (pred2 & 1) != 0 {
74 self.get_next()?;
75 } else {
76 self.vec_subidx += 1;
77 }
78 }
79 } else {
80 self.vec_subidx += 1;
81 }
82 Ok(pred)
83 }
84 fn get_diff16_noesc(&mut self, dtab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
85 let pred1 = self.get_pred(dtab);
86 let pred = pred1 >> 1;
87 if (pred1 & 1) != 0 {
88 self.get_next()?;
89 } else {
90 self.vec_subidx += 1;
91 }
92 Ok(pred)
93 }
94 fn get_diff24(&mut self, dtab: &[[u32; 4]; 256], esctab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
95 let pred1 = self.get_pred(dtab);
96 let mut pred = pred1 >> 1;
97 if (pred1 & 1) != 0 {
98 self.get_next()?;
99 if self.vec_idx == 0 {
100 self.get_next()?;
101 let pred2 = self.get_pred(esctab);
102 pred = pred.wrapping_add(pred2 >> 1);
103 if (pred2 & 1) != 0 {
104 self.get_next()?;
105 } else {
106 self.vec_subidx += 1;
107 }
108 }
109 } else {
110 self.vec_subidx += 1;
111 }
112 Ok(pred)
113 }
114}
115
116struct DeltaTables {
117 ydt: [[u32; 4]; 256],
118 cdt: [[u32; 4]; 256],
119 fat_ydt: [[u32; 4]; 256],
120 fat_cdt: [[u32; 4]; 256],
121 adt: [[u32; 4]; 256],
122}
123
124impl Default for DeltaTables {
125 fn default() -> Self {
126 Self {
127 ydt: [[0; 4]; 256],
128 cdt: [[0; 4]; 256],
129 fat_ydt: [[0; 4]; 256],
130 fat_cdt: [[0; 4]; 256],
131 adt: [[0; 4]; 256],
132 }
133 }
134}
135
136#[derive(Default)]
137struct FrameBuf {
138 last16: Option<NAVideoBufferRef<u16>>,
139 last24: Option<NAVideoBufferRef<u8>>,
140}
141
142impl FrameBuf {
143 fn set16(&mut self, buf: NAVideoBufferRef<u16>) { self.last16 = Some(buf); }
144 fn set24(&mut self, buf: NAVideoBufferRef<u8>) { self.last24 = Some(buf); }
145 fn get16(&mut self) -> Option<NAVideoBufferRef<u16>> {
146 if let Some(ref mut frm) = self.last16 {
147 let newfrm = frm.copy_buffer();
148 *frm = newfrm.clone().into_ref();
149 Some(newfrm.into_ref())
150 } else {
151 None
152 }
153 }
154 fn get24(&mut self) -> Option<NAVideoBufferRef<u8>> {
155 if let Some(ref mut frm) = self.last24 {
156 let newfrm = frm.copy_buffer();
157 *frm = newfrm.clone().into_ref();
158 Some(newfrm.into_ref())
159 } else {
160 None
161 }
162 }
163 fn reset(&mut self) {
164 self.last16 = None;
165 self.last24 = None;
166 }
167}
168
169#[derive(Default)]
170struct TM1Decoder {
171 info: NACodecInfoRef,
172 last_delta_set: usize,
173 last_table_idx: usize,
174 delta_tables: DeltaTables,
175 blk_w: usize,
176 blk_h: usize,
177 vert_pred: Vec<u32>,
178 lastframe: FrameBuf,
179}
180
181#[allow(clippy::identity_op)]
182impl TM1Decoder {
183 fn new() -> Self { Self { last_table_idx: 42, ..Default::default() } }
184 fn set_delta_tables(&mut self, delta_set: usize, table_idx: usize, is_24bit: bool) {
185 if (self.last_delta_set == delta_set) && (self.last_table_idx == table_idx) { return; }
186 let ydt = &DUCK_Y_DELTAS[delta_set];
187 let yfdt = DUCK_Y_FAT_DELTAS[delta_set];
188 let cdt = &DUCK_C_DELTAS[delta_set];
189 let cfdt = DUCK_C_FAT_DELTAS[delta_set];
190 let vec = DUCK_VECTABLES[table_idx];
191
192 let mut vec_iter = vec.iter();
193 for i in 0..256 {
194 let len = (*vec_iter.next().unwrap() as usize) >> 1;
195 for j in 0..len {
196 let pair = vec_iter.next().unwrap();
197 let lo = (pair >> 4) as usize;
198 let hi = (pair & 0xF) as usize;
199 if !is_24bit {
200 let d_lo = ydt[lo] + (ydt[lo] << 5) + (ydt[lo] << 10);
201 let d_hi = ydt[hi] + (ydt[hi] << 5) + (ydt[hi] << 10);
202 self.delta_tables.ydt[i][j] = ((d_lo + (d_hi << 16)) << 1) as u32;
203 let d_c = cdt[hi] + (cdt[lo] << 10);
204 self.delta_tables.cdt[i][j] = ((d_c + (d_c << 16)) << 1) as u32;
205 let d_a = lo + hi * 5;
206 self.delta_tables.adt[i][j] = ((d_a << 16) << 1) as u32;
207 } else {
208 self.delta_tables.ydt[i][j] = ((ydt [lo] + (ydt [hi] << 8) + (ydt [hi] << 16)) << 1) as u32;
209 self.delta_tables.fat_ydt[i][j] = ((yfdt[lo] + (yfdt[hi] << 8) + (yfdt[hi] << 16)) << 1) as u32;
210 self.delta_tables.cdt[i][j] = ((cdt [hi] + (cdt [lo] << 16)) << 1) as u32;
211 self.delta_tables.fat_cdt[i][j] = ((cfdt[hi] + (cfdt[lo] << 16)) << 1) as u32;
212 }
213 }
214 self.delta_tables.ydt[i][len - 1] |= 1;
215 self.delta_tables.cdt[i][len - 1] |= 1;
216 self.delta_tables.adt[i][len - 1] |= 1;
217 self.delta_tables.fat_ydt[i][len - 1] |= 1;
218 self.delta_tables.fat_cdt[i][len - 1] |= 1;
219 }
220
221 self.last_delta_set = delta_set;
222 self.last_table_idx = table_idx;
223 }
224 fn decode_16bit(&mut self, dst: &mut [u16], stride: usize, width: usize, height: usize, mask: &mut MaskState<'_>, index: &mut IndexState<'_>) -> DecoderResult<()> {
225 let mut off = 0;
226 index.get_next()?;
227 for y in 0..height {
228 let mut hor_pred: u32 = 0;
229 for x in (0..width).step_by(4) {
230 if mask.get_next() {
231 match y & 3 {
232 0 => {
233 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
234 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
235 hor_pred = hor_pred.wrapping_add(dc0);
236 hor_pred = hor_pred.wrapping_add(dy0);
237 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
238 self.vert_pred[(x >> 1) + 0] = cur;
239 dst[off + x + 0] = cur as u16;
240 dst[off + x + 1] = (cur >> 16) as u16;
241 if self.blk_w == 2 {
242 let dc1 = index.get_diff16(&self.delta_tables.cdt)?;
243 hor_pred = hor_pred.wrapping_add(dc1);
244 }
245 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
246 hor_pred = hor_pred.wrapping_add(dy1);
247 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
248 self.vert_pred[(x >> 1) + 1] = cur;
249 dst[off + x + 2] = cur as u16;
250 dst[off + x + 3] = (cur >> 16) as u16;
251 },
252 1 | 3 => {
253 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
254 hor_pred = hor_pred.wrapping_add(dy0);
255 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
256 self.vert_pred[(x >> 1) + 0] = cur;
257 dst[off + x + 0] = cur as u16;
258 dst[off + x + 1] = (cur >> 16) as u16;
259 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
260 hor_pred = hor_pred.wrapping_add(dy1);
261 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
262 self.vert_pred[(x >> 1) + 1] = cur;
263 dst[off + x + 2] = cur as u16;
264 dst[off + x + 3] = (cur >> 16) as u16;
265 },
266 2 => {
267 if self.blk_h == 2 {
268 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
269 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
270 hor_pred = hor_pred.wrapping_add(dc0);
271 hor_pred = hor_pred.wrapping_add(dy0);
272 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
273 self.vert_pred[(x >> 1) + 0] = cur;
274 dst[off + x + 0] = cur as u16;
275 dst[off + x + 1] = (cur >> 16) as u16;
276 if self.blk_w == 2 {
277 let dc1 = index.get_diff16(&self.delta_tables.cdt)?;
278 hor_pred = hor_pred.wrapping_add(dc1);
279 }
280 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
281 hor_pred = hor_pred.wrapping_add(dy1);
282 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
283 self.vert_pred[(x >> 1) + 1] = cur;
284 dst[off + x + 2] = cur as u16;
285 dst[off + x + 3] = (cur >> 16) as u16;
286 } else {
287 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
288 hor_pred = hor_pred.wrapping_add(dy0);
289 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
290 self.vert_pred[(x >> 1) + 0] = cur;
291 dst[off + x + 0] = cur as u16;
292 dst[off + x + 1] = (cur >> 16) as u16;
293 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
294 hor_pred = hor_pred.wrapping_add(dy1);
295 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
296 self.vert_pred[(x >> 1) + 1] = cur;
297 dst[off + x + 2] = cur as u16;
298 dst[off + x + 3] = (cur >> 16) as u16;
299 }
300 },
301 _ => unreachable!(),
302 };
303 } else {
304 let cur = u32::from(dst[off + x + 0]) | (u32::from(dst[off + x + 1]) << 16);
305 self.vert_pred[(x >> 1) + 0] = cur;
306 let cur = u32::from(dst[off + x + 2]) | (u32::from(dst[off + x + 3]) << 16);
307 hor_pred = cur.wrapping_sub(self.vert_pred[(x >> 1) + 1]);
308 self.vert_pred[(x >> 1) + 1] = cur;
309 }
310 }
311 if (y & 3) != 3 {
312 mask.reset_row();
313 } else {
314 mask.next_row();
315 }
316 off += stride;
317 }
318 Ok(())
319 }
320 fn decode_sprite(&mut self, dst: &mut [u16], stride: usize, width: usize, height: usize, mask: &mut MaskState<'_>, index: &mut IndexState<'_>) -> DecoderResult<()> {
321 let mut off = 0;
322 let _ = index.get_next();
323 for y in 0..height {
324 let mut hor_pred: u32 = 0;
325 for x in (0..width).step_by(4) {
326 let is_tm = !mask.get_next();
327 let is_sprite = !mask.get_next();
328 if is_tm {
329 if (y & 3) == 0 {
330 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
331 hor_pred = hor_pred.wrapping_add(dc0);
332 }
333 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
334 hor_pred = hor_pred.wrapping_add(dy0);
335 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
336 self.vert_pred[(x >> 1) + 0] = cur;
337 dst[off + x + 0] = cur as u16;
338 dst[off + x + 1] = (cur >> 16) as u16;
339 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
340 hor_pred = hor_pred.wrapping_add(dy1);
341 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
342 self.vert_pred[(x >> 1) + 1] = cur;
343 dst[off + x + 2] = cur as u16;
344 dst[off + x + 3] = (cur >> 16) as u16;
345 } else if is_sprite {
346 if (y & 3) == 0 {
347 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
348 hor_pred = hor_pred.wrapping_add(dc0);
349 }
350 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
351 hor_pred = hor_pred.wrapping_add(dy0);
352 let _da0 = index.get_diff16_noesc(&self.delta_tables.adt)?;
353 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
354 self.vert_pred[(x >> 1) + 0] = cur;
355 dst[off + x + 0] = cur as u16;
356 dst[off + x + 1] = (cur >> 16) as u16;
357 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
358 hor_pred = hor_pred.wrapping_add(dy1);
359 let _da1 = index.get_diff16_noesc(&self.delta_tables.adt)?;
360 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
361 self.vert_pred[(x >> 1) + 1] = cur;
362 dst[off + x + 2] = cur as u16;
363 dst[off + x + 3] = (cur >> 16) as u16;
364 } else {
365 hor_pred = 0;
366 dst[off + x + 0] = 0;
367 dst[off + x + 1] = 0;
368 dst[off + x + 2] = 0;
369 dst[off + x + 3] = 0;
370 self.vert_pred[(x >> 1) + 0] = 0;
371 self.vert_pred[(x >> 1) + 1] = 0;
372 }
373 }
374 if (y & 3) != 3 {
375 mask.reset_row();
376 } else {
377 mask.next_row();
378 }
379 off += stride;
380 }
381 Ok(())
382 }
383 fn decode_24bit(&mut self, dst: &mut [u8], stride: usize, width: usize, height: usize, mask: &mut MaskState<'_>, index: &mut IndexState<'_>) -> DecoderResult<()> {
384 let mut off = 0;
385 index.get_next()?;
386 for y in 0..height {
387 let mut hor_pred: u32 = 0;
388 for x in (0..width).step_by(2) {
389 if mask.get_next() {
390 match y & 3 {
391 0 => {
392 let dc0 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
393 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
394 hor_pred = hor_pred.wrapping_add(dc0);
395 hor_pred = hor_pred.wrapping_add(dy0);
396 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
397 self.vert_pred[x + 0] = cur;
398 dst[off + x*4 + 0] = cur as u8;
399 dst[off + x*4 + 1] = (cur >> 8) as u8;
400 dst[off + x*4 + 2] = (cur >> 16) as u8;
401 dst[off + x*4 + 3] = 0;
402 if self.blk_w == 2 {
403 let dc1 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
404 hor_pred = hor_pred.wrapping_add(dc1);
405 }
406 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
407 hor_pred = hor_pred.wrapping_add(dy1);
408 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
409 self.vert_pred[x + 1] = cur;
410 dst[off + x*4 + 4] = cur as u8;
411 dst[off + x*4 + 5] = (cur >> 8) as u8;
412 dst[off + x*4 + 6] = (cur >> 16) as u8;
413 dst[off + x*4 + 7] = 0;
414 },
415 1 | 3 => {
416 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
417 hor_pred = hor_pred.wrapping_add(dy0);
418 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
419 self.vert_pred[x + 0] = cur;
420 dst[off + x*4 + 0] = cur as u8;
421 dst[off + x*4 + 1] = (cur >> 8) as u8;
422 dst[off + x*4 + 2] = (cur >> 16) as u8;
423 dst[off + x*4 + 3] = 0;
424 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
425 hor_pred = hor_pred.wrapping_add(dy1);
426 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
427 self.vert_pred[x + 1] = cur;
428 dst[off + x*4 + 4] = cur as u8;
429 dst[off + x*4 + 5] = (cur >> 8) as u8;
430 dst[off + x*4 + 6] = (cur >> 16) as u8;
431 dst[off + x*4 + 7] = 0;
432 },
433 2 => {
434 if self.blk_h == 2 {
435 let dc0 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
436 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
437 hor_pred = hor_pred.wrapping_add(dc0);
438 hor_pred = hor_pred.wrapping_add(dy0);
439 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
440 self.vert_pred[x + 0] = cur;
441 dst[off + x*4 + 0] = cur as u8;
442 dst[off + x*4 + 1] = (cur >> 8) as u8;
443 dst[off + x*4 + 2] = (cur >> 16) as u8;
444 dst[off + x*4 + 3] = 0;
445 if self.blk_w == 2 {
446 let dc1 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
447 hor_pred = hor_pred.wrapping_add(dc1);
448 }
449 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
450 hor_pred = hor_pred.wrapping_add(dy1);
451 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
452 self.vert_pred[x + 1] = cur;
453 dst[off + x*4 + 4] = cur as u8;
454 dst[off + x*4 + 5] = (cur >> 8) as u8;
455 dst[off + x*4 + 6] = (cur >> 16) as u8;
456 dst[off + x*4 + 7] = 0;
457 } else {
458 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
459 hor_pred = hor_pred.wrapping_add(dy0);
460 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
461 self.vert_pred[x + 0] = cur;
462 dst[off + x*4 + 0] = cur as u8;
463 dst[off + x*4 + 1] = (cur >> 8) as u8;
464 dst[off + x*4 + 2] = (cur >> 16) as u8;
465 dst[off + x*4 + 3] = 0;
466 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
467 hor_pred = hor_pred.wrapping_add(dy1);
468 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
469 self.vert_pred[x + 1] = cur;
470 dst[off + x*4 + 4] = cur as u8;
471 dst[off + x*4 + 5] = (cur >> 8) as u8;
472 dst[off + x*4 + 6] = (cur >> 16) as u8;
473 dst[off + x*4 + 7] = 0;
474 }
475 },
476 _ => unreachable!(),
477 };
478 } else {
479 let cur = u32::from(dst[off + x*4 + 0])
480 | (u32::from(dst[off + x*4 + 1]) << 8)
481 | (u32::from(dst[off + x*4 + 2]) << 16)
482 | (u32::from(dst[off + x*4 + 3]) << 24);
483 self.vert_pred[x + 0] = cur;
484 let cur = u32::from(dst[off + x*4 + 4])
485 | (u32::from(dst[off + x*4 + 5]) << 8)
486 | (u32::from(dst[off + x*4 + 6]) << 16)
487 | (u32::from(dst[off + x*4 + 7]) << 24);
488 hor_pred = cur.wrapping_sub(self.vert_pred[x + 1]);
489 self.vert_pred[x + 1] = cur;
490 }
491 }
492 if (y & 3) != 3 {
493 mask.reset_row();
494 } else {
495 mask.next_row();
496 }
497 off += stride;
498 }
499 Ok(())
500 }
501}
502
503impl NADecoder for TM1Decoder {
504 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
505 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
506 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, YUV410_FORMAT));
507 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
508 Ok(())
509 } else {
510 Err(DecoderError::InvalidData)
511 }
512 }
513 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
514 let src = pkt.get_buffer();
515 validate!(src.len() > 10);
516 let hdr_size = (src[0].rotate_left(3) & 0x7F) as usize;
517 validate!(hdr_size >= 12 && hdr_size < src.len());
518 let mut hdr: [u8; 127] = [0; 127];
519 for i in 1..hdr_size {
520 hdr[i - 1] = src[i] ^ src[i + 1];
521 }
522 let mut mr = MemoryReader::new_read(&hdr[0..hdr_size-1]);
523 let mut br = ByteReader::new(&mut mr);
524
525 let tm1type = br.read_byte()? as usize;
526 let delta_set = br.read_byte()? as usize;
527 let table_idx = br.read_byte()? as usize;
528 let height = br.read_u16le()? as usize;
529 let width = br.read_u16le()? as usize;
530 let _frameno = br.read_u16le()? as usize;
531 let version = br.read_byte()?;
532 let meta_type = br.read_byte()?;
533 validate!(width > 0 && height > 0);
534 let is_intra;
535 let mut is_sprite = false;
536 let mut spr_xoff = 0;
537 let mut spr_yoff = 0;
538 let mut spr_width = 0;
539 let mut spr_height = 0;
540 if version >= 2 {
541 validate!(meta_type <= 3);
542 if meta_type >= 2 {
543 let frameinfo = br.read_byte()?;
544 let _control = br.read_byte()?;
545
546 is_intra = ((frameinfo & 0x10) != 0) || ((frameinfo & 0x08) == 0);
547 } else {
548 is_intra = true;
549 }
550 if meta_type == 3 {
551 spr_xoff = br.read_u16le()? as usize;
552 spr_yoff = br.read_u16le()? as usize;
553 spr_width = br.read_u16le()? as usize;
554 spr_height = br.read_u16le()? as usize;
555 is_sprite = true;
556 }
557 } else {
558 is_intra = true;
559 }
560 validate!(tm1type < TM1_COMPR_TYPES.len());
561 let cinfo = TM1_COMPR_TYPES[tm1type];
562 if cinfo.is_none() {
563//check for missing ref
564 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
565 frm.set_keyframe(false);
566 frm.set_frame_type(FrameType::Skip);
567 return Ok(frm.into_ref());
568 }
569 let compr_info = cinfo.unwrap();
570 let is_24bit = !is_sprite && compr_info.is_24bit;
571
572 let vec_idx = if ((tm1type & 1) != 0) && (meta_type > 0) { 1 } else { table_idx };
573 validate!((delta_set < DUCK_Y_DELTAS.len()) && (vec_idx < DUCK_VECTABLES.len()));
574 self.set_delta_tables(delta_set, vec_idx, is_24bit);
575
576 let out_width = if is_24bit { width >> 1 } else { width };
577 let mask_row_size = if is_sprite {
578 ((spr_width >> 2) + 3) >> 2
579 } else if is_intra {
580 0
581 } else {
582 ((width >> 2) + 7) >> 3
583 };
584 let mask_size = mask_row_size * (if is_sprite { spr_height >> 2 } else { height >> 2 });
585 let mask_bits = &src[hdr_size..][..mask_size];
586 let index_bytes = &src[hdr_size+mask_size..];
587 validate!(src.len() >= hdr_size + mask_size);
588 self.vert_pred.clear();
589 self.vert_pred.resize(out_width, 0);
590
591 if is_intra || is_sprite {
592 let fmt = if is_24bit { BGR0_FORMAT } else { RGB555_FORMAT };
593 let myinfo = NAVideoInfo::new(out_width, height, false, fmt);
594 let bufinfo = alloc_video_buffer(myinfo, 2)?;
595 self.lastframe.reset();
596 if !is_24bit {
597 self.lastframe.set16(bufinfo.get_vbuf16().unwrap());
598 } else {
599 self.lastframe.set24(bufinfo.get_vbuf().unwrap());
600 }
601 }
602
603 self.blk_w = compr_info.block_w;
604 self.blk_h = compr_info.block_h;
605 let mut mask = MaskState::new(is_intra && !is_sprite, mask_bits, mask_row_size);
606 let mut index = IndexState::new(index_bytes);
607 index.tbl0 = vec_idx == 0;
608 let mut padded_idx_bytes = Vec::new();
609 if index.tbl0 || version == 1 || (version == 2 && meta_type == 1) {
610 // old format, use padded buffer as the source instead
611 padded_idx_bytes.extend_from_slice(index_bytes);
612 padded_idx_bytes.resize(index_bytes.len() + 4, 0);
613 index = IndexState::new(&padded_idx_bytes);
614 index.tbl0 = vec_idx == 0;
615 }
616 let bufinfo;
617 if !is_24bit {
618 if let Some(mut buf) = self.lastframe.get16() {
619 let stride = buf.get_stride(0);
620 {
621 let data = buf.get_data_mut().unwrap();
622 if !is_sprite {
623 self.decode_16bit(data.as_mut_slice(), stride, out_width, height, &mut mask, &mut index)?;
624 } else {
625 validate!(spr_xoff + spr_width <= out_width);
626 validate!(spr_yoff + spr_height <= height);
627 for el in data.iter_mut() { *el = 0; }
628 let dst = &mut data[spr_xoff + spr_yoff * stride..];
629 self.decode_sprite(dst, stride, spr_width, spr_height, &mut mask, &mut index)?;
630 }
631 }
632 bufinfo = NABufferType::Video16(buf);
633 } else {
634 return Err(DecoderError::MissingReference);
635 }
636 } else if let Some(mut buf) = self.lastframe.get24() {
637 let stride = buf.get_stride(0);
638 {
639 let data = buf.get_data_mut().unwrap();
640 self.decode_24bit(data.as_mut_slice(), stride, out_width, height, &mut mask, &mut index)?;
641 }
642 bufinfo = NABufferType::VideoPacked(buf);
643 } else {
644 return Err(DecoderError::MissingReference);
645 }
646
647 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
648 frm.set_keyframe(is_intra || is_sprite);
649 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
650 Ok(frm.into_ref())
651 }
652 fn flush(&mut self) {
653 self.lastframe.reset();
654 }
655}
656
657impl NAOptionHandler for TM1Decoder {
658 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
659 fn set_options(&mut self, _options: &[NAOption]) { }
660 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
661}
662
663pub fn get_decoder() -> Box<dyn NADecoder + Send> {
664 Box::new(TM1Decoder::new())
665}
666
667#[cfg(test)]
668mod test {
669 use nihav_core::codecs::RegisteredDecoders;
670 use nihav_core::demuxers::RegisteredDemuxers;
671 use nihav_codec_support::test::dec_video::*;
672 use crate::duck_register_all_decoders;
673 use nihav_commonfmt::generic_register_all_demuxers;
674 #[test]
675 fn test_tm1() {
676 let mut dmx_reg = RegisteredDemuxers::new();
677 generic_register_all_demuxers(&mut dmx_reg);
678 let mut dec_reg = RegisteredDecoders::new();
679 duck_register_all_decoders(&mut dec_reg);
680
681 // sample: https://samples.mplayerhq.hu/V-codecs/DUCK/phant2-940.duk
682 test_decoding("avi", "truemotion1", "assets/Duck/phant2-940.duk", Some(12), &dmx_reg, &dec_reg,
683 ExpectedTestResult::MD5Frames(vec![
684 [0x989e62b8, 0x5d85c23c, 0x1cffba6d, 0xe599f1c4],
685 [0xc4231321, 0x25561487, 0x9db11f57, 0x4faeb9a5],
686 [0x36e3a831, 0xdbd21f89, 0x0a446071, 0xf6d31ee7],
687 [0x0af640af, 0x64bc2bac, 0x0e95dd72, 0x9e55360b],
688 [0xbc9c5f8b, 0x6c06f2bc, 0x216f4129, 0x3a421337],
689 [0xd8ea7297, 0xce5f79fc, 0x46071f4c, 0xaed7fb7a],
690 [0x87617060, 0x72ce8df8, 0xde42eaa6, 0x804a6f45],
691 [0xfd8c45b3, 0xf424b683, 0xb4d6a9bd, 0xc622d0b9],
692 [0x6c233746, 0xba8ed68e, 0xc0ed0e85, 0xc99e1dc0],
693 [0x5842aac0, 0xd3d78242, 0x5da21218, 0xea1ed0ad],
694 [0xdea0db20, 0xe2ce3586, 0xf7386649, 0xecc374f9],
695 [0xb80ae9cb, 0x04eb938e, 0xd8a337ee, 0x0054b5ed],
696 [0xf8b80e1d, 0xd8eb3d6c, 0xa99b23ff, 0x562851a1]]));
697 test_decoding("avi", "truemotion1", "assets/Duck/SPRITES.AVI", Some(2), &dmx_reg, &dec_reg,
698 ExpectedTestResult::MD5([0xb89a4275, 0xf9797f5f, 0xe53c1ccd, 0xfa163e02]));
699 //let file = "assets/Duck/AVI-DUCK-dk3.duk";
700 //let file = "assets/Duck/phant2-940.duk";
701 //let file = "assets/Duck/bugsampler-m01-16bit.avi";
702 //let file = "assets/Duck/sonic3dblast_intro.avi";
703 //let file = "assets/Duck/BUTTONS.AVI";
704 //let file = "assets/Duck/SPRITES.AVI";
705 //let file = "assets/Duck/TRICORD.AVI";
706 //test_file_decoding("avi", file, Some(42), true, false, None/*Some("tm1-")*/, &dmx_reg, &dec_reg);
707 }
708 #[test]
709 fn test_old_tm1() {
710 let mut dmx_reg = RegisteredDemuxers::new();
711 generic_register_all_demuxers(&mut dmx_reg);
712 let mut dec_reg = RegisteredDecoders::new();
713 duck_register_all_decoders(&mut dec_reg);
714
715 // sample from The Horde demo
716 test_decoding("avi", "truemotion1", "assets/Duck/segue00.duk", Some(5), &dmx_reg, &dec_reg,
717 ExpectedTestResult::MD5Frames(vec![
718 [0xc9b65289, 0x7f64d11d, 0xbfb6cbc5, 0x25778bec],
719 [0xc9b65289, 0x7f64d11d, 0xbfb6cbc5, 0x25778bec],
720 [0x8f1b56dd, 0x19c042f3, 0xcb0a220f, 0xc5942c0e],
721 [0xa0373260, 0xf6c86a10, 0xa4267f65, 0xa5f112d7],
722 [0xb0c2e64c, 0xc11a3e5a, 0x6fad1e3d, 0x9aa3b54f],
723 [0x2a25cd1b, 0x1012d3a6, 0x4258be61, 0x0e3b6df6]]));
724 }
725}