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