/src/ffmpeg/libavcodec/truemotion1.c
Line | Count | Source |
1 | | /* |
2 | | * Duck TrueMotion 1.0 Decoder |
3 | | * Copyright (C) 2003 Alex Beregszaszi & Mike Melanson |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | /** |
23 | | * @file |
24 | | * Duck TrueMotion v1 Video Decoder by |
25 | | * Alex Beregszaszi and |
26 | | * Mike Melanson (melanson@pcisys.net) |
27 | | * |
28 | | * The TrueMotion v1 decoder presently only decodes 16-bit TM1 data and |
29 | | * outputs RGB555 (or RGB565) data. 24-bit TM1 data is not supported yet. |
30 | | */ |
31 | | |
32 | | #include <stdio.h> |
33 | | #include <stdlib.h> |
34 | | #include <string.h> |
35 | | |
36 | | #include "avcodec.h" |
37 | | #include "codec_internal.h" |
38 | | #include "decode.h" |
39 | | #include "libavutil/imgutils.h" |
40 | | #include "libavutil/internal.h" |
41 | | #include "libavutil/intreadwrite.h" |
42 | | #include "libavutil/mem.h" |
43 | | |
44 | | #include "truemotion1data.h" |
45 | | |
46 | | typedef struct TrueMotion1Context { |
47 | | AVCodecContext *avctx; |
48 | | AVFrame *frame; |
49 | | |
50 | | const uint8_t *buf; |
51 | | int size; |
52 | | |
53 | | const uint8_t *mb_change_bits; |
54 | | int mb_change_bits_row_size; |
55 | | const uint8_t *index_stream; |
56 | | int index_stream_size; |
57 | | |
58 | | int flags; |
59 | | int x, y, w, h; |
60 | | |
61 | | uint32_t y_predictor_table[1024]; |
62 | | uint32_t c_predictor_table[1024]; |
63 | | uint32_t fat_y_predictor_table[1024]; |
64 | | uint32_t fat_c_predictor_table[1024]; |
65 | | |
66 | | int compression; |
67 | | int block_type; |
68 | | int block_width; |
69 | | int block_height; |
70 | | |
71 | | int16_t ydt[8]; |
72 | | int16_t cdt[8]; |
73 | | int16_t fat_ydt[8]; |
74 | | int16_t fat_cdt[8]; |
75 | | |
76 | | int last_deltaset, last_vectable; |
77 | | |
78 | | unsigned int *vert_pred; |
79 | | int vert_pred_size; |
80 | | |
81 | | } TrueMotion1Context; |
82 | | |
83 | 156k | #define FLAG_SPRITE 32 |
84 | 443k | #define FLAG_KEYFRAME 16 |
85 | 5.63k | #define FLAG_INTERFRAME 8 |
86 | 140k | #define FLAG_INTERPOLATED 4 |
87 | | |
88 | | struct frame_header { |
89 | | uint8_t header_size; |
90 | | uint8_t compression; |
91 | | uint8_t deltaset; |
92 | | uint8_t vectable; |
93 | | uint16_t ysize; |
94 | | uint16_t xsize; |
95 | | uint16_t checksum; |
96 | | uint8_t version; |
97 | | uint8_t header_type; |
98 | | uint8_t flags; |
99 | | uint8_t control; |
100 | | uint16_t xoffset; |
101 | | uint16_t yoffset; |
102 | | uint16_t width; |
103 | | uint16_t height; |
104 | | }; |
105 | | |
106 | 124k | #define ALGO_NOP 0 |
107 | | #define ALGO_RGB16V 1 |
108 | | #define ALGO_RGB16H 2 |
109 | 302k | #define ALGO_RGB24H 3 |
110 | | |
111 | | /* these are the various block sizes that can occupy a 4x4 block */ |
112 | 13.6M | #define BLOCK_2x2 0 |
113 | | #define BLOCK_2x4 1 |
114 | 7.95M | #define BLOCK_4x2 2 |
115 | | #define BLOCK_4x4 3 |
116 | | |
117 | | typedef struct comp_types { |
118 | | int algorithm; |
119 | | int block_width; // vres |
120 | | int block_height; // hres |
121 | | int block_type; |
122 | | } comp_types; |
123 | | |
124 | | /* { valid for metatype }, algorithm, num of deltas, vert res, horiz res */ |
125 | | static const comp_types compression_types[17] = { |
126 | | { ALGO_NOP, 0, 0, 0 }, |
127 | | |
128 | | { ALGO_RGB16V, 4, 4, BLOCK_4x4 }, |
129 | | { ALGO_RGB16H, 4, 4, BLOCK_4x4 }, |
130 | | { ALGO_RGB16V, 4, 2, BLOCK_4x2 }, |
131 | | { ALGO_RGB16H, 4, 2, BLOCK_4x2 }, |
132 | | |
133 | | { ALGO_RGB16V, 2, 4, BLOCK_2x4 }, |
134 | | { ALGO_RGB16H, 2, 4, BLOCK_2x4 }, |
135 | | { ALGO_RGB16V, 2, 2, BLOCK_2x2 }, |
136 | | { ALGO_RGB16H, 2, 2, BLOCK_2x2 }, |
137 | | |
138 | | { ALGO_NOP, 4, 4, BLOCK_4x4 }, |
139 | | { ALGO_RGB24H, 4, 4, BLOCK_4x4 }, |
140 | | { ALGO_NOP, 4, 2, BLOCK_4x2 }, |
141 | | { ALGO_RGB24H, 4, 2, BLOCK_4x2 }, |
142 | | |
143 | | { ALGO_NOP, 2, 4, BLOCK_2x4 }, |
144 | | { ALGO_RGB24H, 2, 4, BLOCK_2x4 }, |
145 | | { ALGO_NOP, 2, 2, BLOCK_2x2 }, |
146 | | { ALGO_RGB24H, 2, 2, BLOCK_2x2 } |
147 | | }; |
148 | | |
149 | | static void select_delta_tables(TrueMotion1Context *s, int delta_table_index) |
150 | 15.4k | { |
151 | 15.4k | int i; |
152 | | |
153 | 15.4k | if (delta_table_index > 3) |
154 | 8.23k | return; |
155 | | |
156 | 7.21k | memcpy(s->ydt, ydts[delta_table_index], 8 * sizeof(int16_t)); |
157 | 7.21k | memcpy(s->cdt, cdts[delta_table_index], 8 * sizeof(int16_t)); |
158 | 7.21k | memcpy(s->fat_ydt, fat_ydts[delta_table_index], 8 * sizeof(int16_t)); |
159 | 7.21k | memcpy(s->fat_cdt, fat_cdts[delta_table_index], 8 * sizeof(int16_t)); |
160 | | |
161 | | /* Y skinny deltas need to be halved for some reason; maybe the |
162 | | * skinny Y deltas should be modified */ |
163 | 64.9k | for (i = 0; i < 8; i++) |
164 | 57.7k | { |
165 | | /* drop the lsb before dividing by 2-- net effect: round down |
166 | | * when dividing a negative number (e.g., -3/2 = -2, not -1) */ |
167 | 57.7k | s->ydt[i] &= 0xFFFE; |
168 | 57.7k | s->ydt[i] /= 2; |
169 | 57.7k | } |
170 | 7.21k | } |
171 | | |
172 | | #if HAVE_BIGENDIAN |
173 | | static int make_ydt15_entry(int p2, int p1, int16_t *ydt) |
174 | | #else |
175 | | static int make_ydt15_entry(int p1, int p2, int16_t *ydt) |
176 | | #endif |
177 | 2.94M | { |
178 | 2.94M | int lo, hi; |
179 | | |
180 | 2.94M | lo = ydt[p1]; |
181 | 2.94M | lo += (lo * 32) + (lo * 1024); |
182 | 2.94M | hi = ydt[p2]; |
183 | 2.94M | hi += (hi * 32) + (hi * 1024); |
184 | 2.94M | return (lo + (hi * (1U << 16))) * 2; |
185 | 2.94M | } |
186 | | |
187 | | static int make_cdt15_entry(int p1, int p2, int16_t *cdt) |
188 | 2.94M | { |
189 | 2.94M | int r, b, lo; |
190 | | |
191 | 2.94M | b = cdt[p2]; |
192 | 2.94M | r = cdt[p1] * 1024; |
193 | 2.94M | lo = b + r; |
194 | 2.94M | return (lo + (lo * (1U << 16))) * 2; |
195 | 2.94M | } |
196 | | |
197 | | #if HAVE_BIGENDIAN |
198 | | static int make_ydt16_entry(int p2, int p1, int16_t *ydt) |
199 | | #else |
200 | | static int make_ydt16_entry(int p1, int p2, int16_t *ydt) |
201 | | #endif |
202 | 0 | { |
203 | 0 | int lo, hi; |
204 | |
|
205 | 0 | lo = ydt[p1]; |
206 | 0 | lo += (lo << 6) + (lo << 11); |
207 | 0 | hi = ydt[p2]; |
208 | 0 | hi += (hi << 6) + (hi << 11); |
209 | 0 | return (lo + (hi << 16)) << 1; |
210 | 0 | } |
211 | | |
212 | | static int make_cdt16_entry(int p1, int p2, int16_t *cdt) |
213 | 0 | { |
214 | 0 | int r, b, lo; |
215 | |
|
216 | 0 | b = cdt[p2]; |
217 | 0 | r = cdt[p1] << 11; |
218 | 0 | lo = b + r; |
219 | 0 | return (lo + (lo * (1 << 16))) * 2; |
220 | 0 | } |
221 | | |
222 | | static int make_ydt24_entry(int p1, int p2, int16_t *ydt) |
223 | 3.70M | { |
224 | 3.70M | int lo, hi; |
225 | | |
226 | 3.70M | lo = ydt[p1]; |
227 | 3.70M | hi = ydt[p2]; |
228 | 3.70M | return (lo + (hi * (1 << 8)) + (hi * (1 << 16))) * 2; |
229 | 3.70M | } |
230 | | |
231 | | static int make_cdt24_entry(int p1, int p2, int16_t *cdt) |
232 | 3.70M | { |
233 | 3.70M | int r, b; |
234 | | |
235 | 3.70M | b = cdt[p2]; |
236 | 3.70M | r = cdt[p1] * (1 << 16); |
237 | 3.70M | return (b+r) * 2; |
238 | 3.70M | } |
239 | | |
240 | | static void gen_vector_table15(TrueMotion1Context *s, const uint8_t *sel_vector_table) |
241 | 5.39k | { |
242 | 5.39k | int len, i, j; |
243 | 5.39k | unsigned char delta_pair; |
244 | | |
245 | 1.38M | for (i = 0; i < 1024; i += 4) |
246 | 1.38M | { |
247 | 1.38M | len = *sel_vector_table++ / 2; |
248 | 4.32M | for (j = 0; j < len; j++) |
249 | 2.94M | { |
250 | 2.94M | delta_pair = *sel_vector_table++; |
251 | 2.94M | s->y_predictor_table[i+j] = 0xfffffffe & |
252 | 2.94M | make_ydt15_entry(delta_pair >> 4, delta_pair & 0xf, s->ydt); |
253 | 2.94M | s->c_predictor_table[i+j] = 0xfffffffe & |
254 | 2.94M | make_cdt15_entry(delta_pair >> 4, delta_pair & 0xf, s->cdt); |
255 | 2.94M | } |
256 | 1.38M | s->y_predictor_table[i+(j-1)] |= 1; |
257 | 1.38M | s->c_predictor_table[i+(j-1)] |= 1; |
258 | 1.38M | } |
259 | 5.39k | } |
260 | | |
261 | | static void gen_vector_table16(TrueMotion1Context *s, const uint8_t *sel_vector_table) |
262 | 0 | { |
263 | 0 | int len, i, j; |
264 | 0 | unsigned char delta_pair; |
265 | |
|
266 | 0 | for (i = 0; i < 1024; i += 4) |
267 | 0 | { |
268 | 0 | len = *sel_vector_table++ / 2; |
269 | 0 | for (j = 0; j < len; j++) |
270 | 0 | { |
271 | 0 | delta_pair = *sel_vector_table++; |
272 | 0 | s->y_predictor_table[i+j] = 0xfffffffe & |
273 | 0 | make_ydt16_entry(delta_pair >> 4, delta_pair & 0xf, s->ydt); |
274 | 0 | s->c_predictor_table[i+j] = 0xfffffffe & |
275 | 0 | make_cdt16_entry(delta_pair >> 4, delta_pair & 0xf, s->cdt); |
276 | 0 | } |
277 | 0 | s->y_predictor_table[i+(j-1)] |= 1; |
278 | 0 | s->c_predictor_table[i+(j-1)] |= 1; |
279 | 0 | } |
280 | 0 | } |
281 | | |
282 | | static void gen_vector_table24(TrueMotion1Context *s, const uint8_t *sel_vector_table) |
283 | 3.36k | { |
284 | 3.36k | int len, i, j; |
285 | 3.36k | unsigned char delta_pair; |
286 | | |
287 | 864k | for (i = 0; i < 1024; i += 4) |
288 | 860k | { |
289 | 860k | len = *sel_vector_table++ / 2; |
290 | 2.71M | for (j = 0; j < len; j++) |
291 | 1.85M | { |
292 | 1.85M | delta_pair = *sel_vector_table++; |
293 | 1.85M | s->y_predictor_table[i+j] = 0xfffffffe & |
294 | 1.85M | make_ydt24_entry(delta_pair >> 4, delta_pair & 0xf, s->ydt); |
295 | 1.85M | s->c_predictor_table[i+j] = 0xfffffffe & |
296 | 1.85M | make_cdt24_entry(delta_pair >> 4, delta_pair & 0xf, s->cdt); |
297 | 1.85M | s->fat_y_predictor_table[i+j] = 0xfffffffe & |
298 | 1.85M | make_ydt24_entry(delta_pair >> 4, delta_pair & 0xf, s->fat_ydt); |
299 | 1.85M | s->fat_c_predictor_table[i+j] = 0xfffffffe & |
300 | 1.85M | make_cdt24_entry(delta_pair >> 4, delta_pair & 0xf, s->fat_cdt); |
301 | 1.85M | } |
302 | 860k | s->y_predictor_table[i+(j-1)] |= 1; |
303 | 860k | s->c_predictor_table[i+(j-1)] |= 1; |
304 | 860k | s->fat_y_predictor_table[i+(j-1)] |= 1; |
305 | 860k | s->fat_c_predictor_table[i+(j-1)] |= 1; |
306 | 860k | } |
307 | 3.36k | } |
308 | | |
309 | | /* Returns the number of bytes consumed from the bytestream. Returns -1 if |
310 | | * there was an error while decoding the header */ |
311 | | static int truemotion1_decode_header(TrueMotion1Context *s) |
312 | 304k | { |
313 | 304k | int i, ret; |
314 | 304k | int width_shift = 0; |
315 | 304k | int new_pix_fmt; |
316 | 304k | struct frame_header header; |
317 | 304k | uint8_t header_buffer[128] = { 0 }; /* logical maximum size of the header */ |
318 | 304k | const uint8_t *sel_vector_table; |
319 | | |
320 | 304k | header.header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f; |
321 | 304k | if (s->buf[0] < 0x10) |
322 | 21.0k | { |
323 | 21.0k | av_log(s->avctx, AV_LOG_ERROR, "invalid header size (%d)\n", s->buf[0]); |
324 | 21.0k | return AVERROR_INVALIDDATA; |
325 | 21.0k | } |
326 | | |
327 | 283k | if (header.header_size + 1 > s->size) { |
328 | 126k | av_log(s->avctx, AV_LOG_ERROR, "Input packet too small.\n"); |
329 | 126k | return AVERROR_INVALIDDATA; |
330 | 126k | } |
331 | | |
332 | | /* unscramble the header bytes with a XOR operation */ |
333 | 2.35M | for (i = 1; i < header.header_size; i++) |
334 | 2.19M | header_buffer[i - 1] = s->buf[i] ^ s->buf[i + 1]; |
335 | | |
336 | 157k | header.compression = header_buffer[0]; |
337 | 157k | header.deltaset = header_buffer[1]; |
338 | 157k | header.vectable = header_buffer[2]; |
339 | 157k | header.ysize = AV_RL16(&header_buffer[3]); |
340 | 157k | header.xsize = AV_RL16(&header_buffer[5]); |
341 | 157k | header.checksum = AV_RL16(&header_buffer[7]); |
342 | 157k | header.version = header_buffer[9]; |
343 | 157k | header.header_type = header_buffer[10]; |
344 | 157k | header.flags = header_buffer[11]; |
345 | 157k | header.control = header_buffer[12]; |
346 | | |
347 | | /* Version 2 */ |
348 | 157k | if (header.version >= 2) |
349 | 28.3k | { |
350 | 28.3k | if (header.header_type > 3) |
351 | 681 | { |
352 | 681 | av_log(s->avctx, AV_LOG_ERROR, "invalid header type (%d)\n", header.header_type); |
353 | 681 | return AVERROR_INVALIDDATA; |
354 | 27.7k | } else if ((header.header_type == 2) || (header.header_type == 3)) { |
355 | 5.63k | s->flags = header.flags; |
356 | 5.63k | if (!(s->flags & FLAG_INTERFRAME)) |
357 | 4.14k | s->flags |= FLAG_KEYFRAME; |
358 | 5.63k | } else |
359 | 22.0k | s->flags = FLAG_KEYFRAME; |
360 | 28.3k | } else /* Version 1 */ |
361 | 129k | s->flags = FLAG_KEYFRAME; |
362 | | |
363 | 156k | if (s->flags & FLAG_SPRITE) { |
364 | 265 | avpriv_request_sample(s->avctx, "Frame with sprite"); |
365 | | /* FIXME header.width, height, xoffset and yoffset aren't initialized */ |
366 | 265 | return AVERROR_PATCHWELCOME; |
367 | 156k | } else { |
368 | 156k | s->w = header.xsize; |
369 | 156k | s->h = header.ysize; |
370 | 156k | if (header.header_type < 2) { |
371 | 149k | if ((s->w < 213) && (s->h >= 176)) |
372 | 140k | { |
373 | 140k | s->flags |= FLAG_INTERPOLATED; |
374 | 140k | avpriv_request_sample(s->avctx, "Interpolated frame"); |
375 | 140k | } |
376 | 149k | } |
377 | 156k | } |
378 | | |
379 | 156k | if (header.compression >= 17) { |
380 | 1.75k | av_log(s->avctx, AV_LOG_ERROR, "invalid compression type (%d)\n", header.compression); |
381 | 1.75k | return AVERROR_INVALIDDATA; |
382 | 1.75k | } |
383 | | |
384 | 154k | if ((header.deltaset != s->last_deltaset) || |
385 | 140k | (header.vectable != s->last_vectable)) |
386 | 15.4k | select_delta_tables(s, header.deltaset); |
387 | | |
388 | 154k | if ((header.compression & 1) && header.header_type) |
389 | 7.62k | sel_vector_table = pc_tbl2; |
390 | 147k | else { |
391 | 147k | if (header.vectable > 0 && header.vectable < 4) |
392 | 143k | sel_vector_table = tables[header.vectable - 1]; |
393 | 3.38k | else { |
394 | 3.38k | av_log(s->avctx, AV_LOG_ERROR, "invalid vector table id (%d)\n", header.vectable); |
395 | 3.38k | return AVERROR_INVALIDDATA; |
396 | 3.38k | } |
397 | 147k | } |
398 | | |
399 | 151k | if (compression_types[header.compression].algorithm == ALGO_RGB24H) { |
400 | 23.4k | new_pix_fmt = AV_PIX_FMT_0RGB32; |
401 | 23.4k | width_shift = 1; |
402 | 23.4k | } else |
403 | 127k | new_pix_fmt = AV_PIX_FMT_RGB555; // RGB565 is supported as well |
404 | | |
405 | 151k | s->w >>= width_shift; |
406 | 151k | if (s->w & 1) { |
407 | 1.04k | avpriv_request_sample(s->avctx, "Frame with odd width"); |
408 | 1.04k | return AVERROR_PATCHWELCOME; |
409 | 1.04k | } |
410 | | |
411 | 150k | if (s->h & 3) { |
412 | 2.17k | avpriv_request_sample(s->avctx, "Frame with height not being a multiple of 4"); |
413 | 2.17k | return AVERROR_PATCHWELCOME; |
414 | 2.17k | } |
415 | | |
416 | 148k | if (s->w != s->avctx->width || s->h != s->avctx->height || |
417 | 135k | new_pix_fmt != s->avctx->pix_fmt) { |
418 | 12.6k | av_frame_unref(s->frame); |
419 | 12.6k | s->avctx->sample_aspect_ratio = (AVRational){ 1 << width_shift, 1 }; |
420 | 12.6k | s->avctx->pix_fmt = new_pix_fmt; |
421 | | |
422 | 12.6k | if ((ret = ff_set_dimensions(s->avctx, s->w, s->h)) < 0) |
423 | 1.98k | return ret; |
424 | | |
425 | 10.6k | ff_set_sar(s->avctx, s->avctx->sample_aspect_ratio); |
426 | | |
427 | 10.6k | av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); |
428 | 10.6k | if (!s->vert_pred) |
429 | 0 | return AVERROR(ENOMEM); |
430 | 10.6k | } |
431 | | |
432 | | /* There is 1 change bit per 4 pixels, so each change byte represents |
433 | | * 32 pixels; divide width by 4 to obtain the number of change bits and |
434 | | * then round up to the nearest byte. */ |
435 | 146k | s->mb_change_bits_row_size = ((s->avctx->width >> (2 - width_shift)) + 7) >> 3; |
436 | | |
437 | 146k | if ((header.deltaset != s->last_deltaset) || (header.vectable != s->last_vectable)) |
438 | 8.76k | { |
439 | 8.76k | if (compression_types[header.compression].algorithm == ALGO_RGB24H) |
440 | 3.36k | gen_vector_table24(s, sel_vector_table); |
441 | 5.39k | else |
442 | 5.39k | if (s->avctx->pix_fmt == AV_PIX_FMT_RGB555) |
443 | 5.39k | gen_vector_table15(s, sel_vector_table); |
444 | 0 | else |
445 | 0 | gen_vector_table16(s, sel_vector_table); |
446 | 8.76k | } |
447 | | |
448 | | /* set up pointers to the other key data chunks */ |
449 | 146k | s->mb_change_bits = s->buf + header.header_size; |
450 | 146k | if (s->flags & FLAG_KEYFRAME) { |
451 | | /* no change bits specified for a keyframe; only index bytes */ |
452 | 145k | s->index_stream = s->mb_change_bits; |
453 | 145k | if (s->avctx->width * s->avctx->height / 2048 + header.header_size > s->size) |
454 | 3.97k | return AVERROR_INVALIDDATA; |
455 | 145k | } else { |
456 | | /* one change bit per 4x4 block */ |
457 | 1.17k | s->index_stream = s->mb_change_bits + |
458 | 1.17k | (s->mb_change_bits_row_size * (s->avctx->height >> 2)); |
459 | 1.17k | } |
460 | 142k | s->index_stream_size = s->size - (s->index_stream - s->buf); |
461 | | |
462 | 142k | s->last_deltaset = header.deltaset; |
463 | 142k | s->last_vectable = header.vectable; |
464 | 142k | s->compression = header.compression; |
465 | 142k | s->block_width = compression_types[header.compression].block_width; |
466 | 142k | s->block_height = compression_types[header.compression].block_height; |
467 | 142k | s->block_type = compression_types[header.compression].block_type; |
468 | | |
469 | 142k | if (s->avctx->debug & FF_DEBUG_PICT_INFO) |
470 | 0 | av_log(s->avctx, AV_LOG_INFO, "tables: %d / %d c:%d %dx%d t:%d %s%s%s%s\n", |
471 | 0 | s->last_deltaset, s->last_vectable, s->compression, s->block_width, |
472 | 0 | s->block_height, s->block_type, |
473 | 0 | s->flags & FLAG_KEYFRAME ? " KEY" : "", |
474 | 0 | s->flags & FLAG_INTERFRAME ? " INTER" : "", |
475 | 0 | s->flags & FLAG_SPRITE ? " SPRITE" : "", |
476 | 0 | s->flags & FLAG_INTERPOLATED ? " INTERPOL" : ""); |
477 | | |
478 | 142k | return header.header_size; |
479 | 146k | } |
480 | | |
481 | | static av_cold int truemotion1_decode_init(AVCodecContext *avctx) |
482 | 2.39k | { |
483 | 2.39k | TrueMotion1Context *s = avctx->priv_data; |
484 | | |
485 | 2.39k | s->avctx = avctx; |
486 | | |
487 | | // FIXME: it may change ? |
488 | | // if (avctx->bits_per_sample == 24) |
489 | | // avctx->pix_fmt = AV_PIX_FMT_RGB24; |
490 | | // else |
491 | | // avctx->pix_fmt = AV_PIX_FMT_RGB555; |
492 | | |
493 | 2.39k | s->frame = av_frame_alloc(); |
494 | 2.39k | if (!s->frame) |
495 | 0 | return AVERROR(ENOMEM); |
496 | | |
497 | | /* there is a vertical predictor for each pixel in a line; each vertical |
498 | | * predictor is 0 to start with */ |
499 | 2.39k | av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); |
500 | 2.39k | if (!s->vert_pred) |
501 | 130 | return AVERROR(ENOMEM); |
502 | | |
503 | 2.26k | return 0; |
504 | 2.39k | } |
505 | | |
506 | | /* |
507 | | Block decoding order: |
508 | | |
509 | | dxi: Y-Y |
510 | | dxic: Y-C-Y |
511 | | dxic2: Y-C-Y-C |
512 | | |
513 | | hres,vres,i,i%vres (0 < i < 4) |
514 | | 2x2 0: 0 dxic2 |
515 | | 2x2 1: 1 dxi |
516 | | 2x2 2: 0 dxic2 |
517 | | 2x2 3: 1 dxi |
518 | | 2x4 0: 0 dxic2 |
519 | | 2x4 1: 1 dxi |
520 | | 2x4 2: 2 dxi |
521 | | 2x4 3: 3 dxi |
522 | | 4x2 0: 0 dxic |
523 | | 4x2 1: 1 dxi |
524 | | 4x2 2: 0 dxic |
525 | | 4x2 3: 1 dxi |
526 | | 4x4 0: 0 dxic |
527 | | 4x4 1: 1 dxi |
528 | | 4x4 2: 2 dxi |
529 | | 4x4 3: 3 dxi |
530 | | */ |
531 | | |
532 | 96.1M | #define GET_NEXT_INDEX() \ |
533 | 96.1M | {\ |
534 | 96.1M | if (index_stream_index >= s->index_stream_size) { \ |
535 | 134k | av_log(s->avctx, AV_LOG_INFO, " help! truemotion1 decoder went out of bounds\n"); \ |
536 | 134k | return; \ |
537 | 134k | } \ |
538 | 96.1M | index = s->index_stream[index_stream_index++] * 4; \ |
539 | 95.9M | } |
540 | | |
541 | 104M | #define INC_INDEX \ |
542 | 104M | do { \ |
543 | 104M | if (index >= 1023) { \ |
544 | 6.61k | av_log(s->avctx, AV_LOG_ERROR, "Invalid index value.\n"); \ |
545 | 6.61k | return; \ |
546 | 6.61k | } \ |
547 | 104M | index++; \ |
548 | 104M | } while (0) |
549 | | |
550 | | #define APPLY_C_PREDICTOR() \ |
551 | 19.8M | predictor_pair = s->c_predictor_table[index]; \ |
552 | 19.8M | horiz_pred += (predictor_pair >> 1); \ |
553 | 19.8M | if (predictor_pair & 1) { \ |
554 | 8.67M | GET_NEXT_INDEX() \ |
555 | 8.63M | if (!index) { \ |
556 | 3.56M | GET_NEXT_INDEX() \ |
557 | 3.56M | predictor_pair = s->c_predictor_table[index]; \ |
558 | 3.56M | horiz_pred += ((predictor_pair >> 1) * 5); \ |
559 | 3.56M | if (predictor_pair & 1) \ |
560 | 3.56M | GET_NEXT_INDEX() \ |
561 | 3.56M | else \ |
562 | 3.56M | INC_INDEX; \ |
563 | 3.56M | } \ |
564 | 8.63M | } else \ |
565 | 19.8M | INC_INDEX; |
566 | | |
567 | | #define APPLY_C_PREDICTOR_24() \ |
568 | 18.2M | predictor_pair = s->c_predictor_table[index]; \ |
569 | 18.2M | horiz_pred += (predictor_pair >> 1); \ |
570 | 18.2M | if (predictor_pair & 1) { \ |
571 | 8.09M | GET_NEXT_INDEX() \ |
572 | 8.09M | if (!index) { \ |
573 | 3.23M | GET_NEXT_INDEX() \ |
574 | 3.22M | predictor_pair = s->fat_c_predictor_table[index]; \ |
575 | 3.22M | horiz_pred += (predictor_pair >> 1); \ |
576 | 3.22M | if (predictor_pair & 1) \ |
577 | 3.22M | GET_NEXT_INDEX() \ |
578 | 3.22M | else \ |
579 | 3.22M | INC_INDEX; \ |
580 | 3.22M | } \ |
581 | 8.09M | } else \ |
582 | 18.2M | INC_INDEX; |
583 | | |
584 | | |
585 | | #define APPLY_Y_PREDICTOR() \ |
586 | 57.6M | predictor_pair = s->y_predictor_table[index]; \ |
587 | 57.6M | horiz_pred += (predictor_pair >> 1); \ |
588 | 57.6M | if (predictor_pair & 1) { \ |
589 | 25.0M | GET_NEXT_INDEX() \ |
590 | 24.9M | if (!index) { \ |
591 | 10.3M | GET_NEXT_INDEX() \ |
592 | 10.2M | predictor_pair = s->y_predictor_table[index]; \ |
593 | 10.2M | horiz_pred += ((predictor_pair >> 1) * 5); \ |
594 | 10.2M | if (predictor_pair & 1) \ |
595 | 10.2M | GET_NEXT_INDEX() \ |
596 | 10.2M | else \ |
597 | 10.2M | INC_INDEX; \ |
598 | 10.2M | } \ |
599 | 24.9M | } else \ |
600 | 57.6M | INC_INDEX; |
601 | | |
602 | | #define APPLY_Y_PREDICTOR_24() \ |
603 | 51.9M | predictor_pair = s->y_predictor_table[index]; \ |
604 | 51.9M | horiz_pred += (predictor_pair >> 1); \ |
605 | 51.9M | if (predictor_pair & 1) { \ |
606 | 22.8M | GET_NEXT_INDEX() \ |
607 | 22.8M | if (!index) { \ |
608 | 9.34M | GET_NEXT_INDEX() \ |
609 | 9.34M | predictor_pair = s->fat_y_predictor_table[index]; \ |
610 | 9.34M | horiz_pred += (predictor_pair >> 1); \ |
611 | 9.34M | if (predictor_pair & 1) \ |
612 | 9.34M | GET_NEXT_INDEX() \ |
613 | 9.34M | else \ |
614 | 9.34M | INC_INDEX; \ |
615 | 9.34M | } \ |
616 | 22.8M | } else \ |
617 | 51.9M | INC_INDEX; |
618 | | |
619 | | #define OUTPUT_PIXEL_PAIR() \ |
620 | 109M | *current_pixel_pair = *vert_pred + horiz_pred; \ |
621 | 109M | *vert_pred++ = *current_pixel_pair++; |
622 | | |
623 | | static void truemotion1_decode_16bit(TrueMotion1Context *s) |
624 | 123k | { |
625 | 123k | int y; |
626 | 123k | int pixels_left; /* remaining pixels on this line */ |
627 | 123k | unsigned int predictor_pair; |
628 | 123k | unsigned int horiz_pred; |
629 | 123k | unsigned int *vert_pred; |
630 | 123k | unsigned int *current_pixel_pair; |
631 | 123k | unsigned char *current_line = s->frame->data[0]; |
632 | 123k | int keyframe = s->flags & FLAG_KEYFRAME; |
633 | | |
634 | | /* these variables are for managing the stream of macroblock change bits */ |
635 | 123k | const unsigned char *mb_change_bits = s->mb_change_bits; |
636 | 123k | unsigned char mb_change_byte; |
637 | 123k | unsigned char mb_change_byte_mask; |
638 | 123k | int mb_change_index; |
639 | | |
640 | | /* these variables are for managing the main index stream */ |
641 | 123k | int index_stream_index = 0; /* yes, the index into the index stream */ |
642 | 123k | int index; |
643 | | |
644 | | /* clean out the line buffer */ |
645 | 123k | memset(s->vert_pred, 0, s->avctx->width * sizeof(unsigned int)); |
646 | | |
647 | 123k | GET_NEXT_INDEX(); |
648 | | |
649 | 2.14M | for (y = 0; y < s->avctx->height; y++) { |
650 | | |
651 | | /* re-init variables for the next line iteration */ |
652 | 2.14M | horiz_pred = 0; |
653 | 2.14M | current_pixel_pair = (unsigned int *)current_line; |
654 | 2.14M | vert_pred = s->vert_pred; |
655 | 2.14M | mb_change_index = 0; |
656 | 2.14M | if (!keyframe) |
657 | 683k | mb_change_byte = mb_change_bits[mb_change_index++]; |
658 | 2.14M | mb_change_byte_mask = 0x01; |
659 | 2.14M | pixels_left = s->avctx->width; |
660 | | |
661 | 31.5M | while (pixels_left > 0) { |
662 | | |
663 | 29.4M | if (keyframe || ((mb_change_byte & mb_change_byte_mask) == 0)) { |
664 | | |
665 | 28.8M | switch (y & 3) { |
666 | 7.30M | case 0: |
667 | | /* if macroblock width is 2, apply C-Y-C-Y; else |
668 | | * apply C-Y-Y */ |
669 | 7.30M | if (s->block_width == 2) { |
670 | 3.61M | APPLY_C_PREDICTOR(); |
671 | 3.61M | APPLY_Y_PREDICTOR(); |
672 | 3.61M | OUTPUT_PIXEL_PAIR(); |
673 | 3.61M | APPLY_C_PREDICTOR(); |
674 | 3.61M | APPLY_Y_PREDICTOR(); |
675 | 3.61M | OUTPUT_PIXEL_PAIR(); |
676 | 3.69M | } else { |
677 | 3.69M | APPLY_C_PREDICTOR(); |
678 | 3.69M | APPLY_Y_PREDICTOR(); |
679 | 3.68M | OUTPUT_PIXEL_PAIR(); |
680 | 3.68M | APPLY_Y_PREDICTOR(); |
681 | 3.67M | OUTPUT_PIXEL_PAIR(); |
682 | 3.67M | } |
683 | 7.28M | break; |
684 | | |
685 | 7.28M | case 1: |
686 | 14.3M | case 3: |
687 | | /* always apply 2 Y predictors on these iterations */ |
688 | 14.3M | APPLY_Y_PREDICTOR(); |
689 | 14.3M | OUTPUT_PIXEL_PAIR(); |
690 | 14.3M | APPLY_Y_PREDICTOR(); |
691 | 14.3M | OUTPUT_PIXEL_PAIR(); |
692 | 14.3M | break; |
693 | | |
694 | 7.18M | case 2: |
695 | | /* this iteration might be C-Y-C-Y, Y-Y, or C-Y-Y |
696 | | * depending on the macroblock type */ |
697 | 7.18M | if (s->block_type == BLOCK_2x2) { |
698 | 2.96M | APPLY_C_PREDICTOR(); |
699 | 2.96M | APPLY_Y_PREDICTOR(); |
700 | 2.96M | OUTPUT_PIXEL_PAIR(); |
701 | 2.96M | APPLY_C_PREDICTOR(); |
702 | 2.96M | APPLY_Y_PREDICTOR(); |
703 | 2.96M | OUTPUT_PIXEL_PAIR(); |
704 | 4.22M | } else if (s->block_type == BLOCK_4x2) { |
705 | 3.00M | APPLY_C_PREDICTOR(); |
706 | 2.96M | APPLY_Y_PREDICTOR(); |
707 | 2.95M | OUTPUT_PIXEL_PAIR(); |
708 | 2.95M | APPLY_Y_PREDICTOR(); |
709 | 2.95M | OUTPUT_PIXEL_PAIR(); |
710 | 2.95M | } else { |
711 | 1.21M | APPLY_Y_PREDICTOR(); |
712 | 1.21M | OUTPUT_PIXEL_PAIR(); |
713 | 1.21M | APPLY_Y_PREDICTOR(); |
714 | 1.21M | OUTPUT_PIXEL_PAIR(); |
715 | 1.21M | } |
716 | 7.13M | break; |
717 | 28.8M | } |
718 | | |
719 | 28.8M | } else { |
720 | | |
721 | | /* skip (copy) four pixels, but reassign the horizontal |
722 | | * predictor */ |
723 | 614k | *vert_pred++ = *current_pixel_pair++; |
724 | 614k | horiz_pred = *current_pixel_pair - *vert_pred; |
725 | 614k | *vert_pred++ = *current_pixel_pair++; |
726 | | |
727 | 614k | } |
728 | | |
729 | 29.3M | if (!keyframe) { |
730 | 690k | mb_change_byte_mask <<= 1; |
731 | | |
732 | | /* next byte */ |
733 | 690k | if (!mb_change_byte_mask) { |
734 | 882 | mb_change_byte = mb_change_bits[mb_change_index++]; |
735 | 882 | mb_change_byte_mask = 0x01; |
736 | 882 | } |
737 | 690k | } |
738 | | |
739 | 29.3M | pixels_left -= 4; |
740 | 29.3M | } |
741 | | |
742 | | /* next change row */ |
743 | 2.02M | if (((y + 1) & 3) == 0) |
744 | 467k | mb_change_bits += s->mb_change_bits_row_size; |
745 | | |
746 | 2.02M | current_line += s->frame->linesize[0]; |
747 | 2.02M | } |
748 | 123k | } |
749 | | |
750 | | static void truemotion1_decode_24bit(TrueMotion1Context *s) |
751 | 18.0k | { |
752 | 18.0k | int y; |
753 | 18.0k | int pixels_left; /* remaining pixels on this line */ |
754 | 18.0k | unsigned int predictor_pair; |
755 | 18.0k | unsigned int horiz_pred; |
756 | 18.0k | unsigned int *vert_pred; |
757 | 18.0k | unsigned int *current_pixel_pair; |
758 | 18.0k | unsigned char *current_line = s->frame->data[0]; |
759 | 18.0k | int keyframe = s->flags & FLAG_KEYFRAME; |
760 | | |
761 | | /* these variables are for managing the stream of macroblock change bits */ |
762 | 18.0k | const unsigned char *mb_change_bits = s->mb_change_bits; |
763 | 18.0k | unsigned char mb_change_byte; |
764 | 18.0k | unsigned char mb_change_byte_mask; |
765 | 18.0k | int mb_change_index; |
766 | | |
767 | | /* these variables are for managing the main index stream */ |
768 | 18.0k | int index_stream_index = 0; /* yes, the index into the index stream */ |
769 | 18.0k | int index; |
770 | | |
771 | | /* clean out the line buffer */ |
772 | 18.0k | memset(s->vert_pred, 0, s->avctx->width * sizeof(unsigned int)); |
773 | | |
774 | 18.0k | GET_NEXT_INDEX(); |
775 | | |
776 | 1.10M | for (y = 0; y < s->avctx->height; y++) { |
777 | | |
778 | | /* re-init variables for the next line iteration */ |
779 | 1.10M | horiz_pred = 0; |
780 | 1.10M | current_pixel_pair = (unsigned int *)current_line; |
781 | 1.10M | vert_pred = s->vert_pred; |
782 | 1.10M | mb_change_index = 0; |
783 | 1.10M | mb_change_byte = mb_change_bits[mb_change_index++]; |
784 | 1.10M | mb_change_byte_mask = 0x01; |
785 | 1.10M | pixels_left = s->avctx->width; |
786 | | |
787 | 27.0M | while (pixels_left > 0) { |
788 | | |
789 | 25.9M | if (keyframe || ((mb_change_byte & mb_change_byte_mask) == 0)) { |
790 | | |
791 | 25.9M | switch (y & 3) { |
792 | 6.55M | case 0: |
793 | | /* if macroblock width is 2, apply C-Y-C-Y; else |
794 | | * apply C-Y-Y */ |
795 | 6.55M | if (s->block_width == 2) { |
796 | 3.80M | APPLY_C_PREDICTOR_24(); |
797 | 3.80M | APPLY_Y_PREDICTOR_24(); |
798 | 3.80M | OUTPUT_PIXEL_PAIR(); |
799 | 3.80M | APPLY_C_PREDICTOR_24(); |
800 | 3.80M | APPLY_Y_PREDICTOR_24(); |
801 | 3.79M | OUTPUT_PIXEL_PAIR(); |
802 | 3.79M | } else { |
803 | 2.74M | APPLY_C_PREDICTOR_24(); |
804 | 2.74M | APPLY_Y_PREDICTOR_24(); |
805 | 2.74M | OUTPUT_PIXEL_PAIR(); |
806 | 2.74M | APPLY_Y_PREDICTOR_24(); |
807 | 2.74M | OUTPUT_PIXEL_PAIR(); |
808 | 2.74M | } |
809 | 6.54M | break; |
810 | | |
811 | 6.54M | case 1: |
812 | 12.9M | case 3: |
813 | | /* always apply 2 Y predictors on these iterations */ |
814 | 12.9M | APPLY_Y_PREDICTOR_24(); |
815 | 12.9M | OUTPUT_PIXEL_PAIR(); |
816 | 12.9M | APPLY_Y_PREDICTOR_24(); |
817 | 12.9M | OUTPUT_PIXEL_PAIR(); |
818 | 12.9M | break; |
819 | | |
820 | 6.47M | case 2: |
821 | | /* this iteration might be C-Y-C-Y, Y-Y, or C-Y-Y |
822 | | * depending on the macroblock type */ |
823 | 6.47M | if (s->block_type == BLOCK_2x2) { |
824 | 2.74M | APPLY_C_PREDICTOR_24(); |
825 | 2.74M | APPLY_Y_PREDICTOR_24(); |
826 | 2.74M | OUTPUT_PIXEL_PAIR(); |
827 | 2.74M | APPLY_C_PREDICTOR_24(); |
828 | 2.74M | APPLY_Y_PREDICTOR_24(); |
829 | 2.74M | OUTPUT_PIXEL_PAIR(); |
830 | 3.73M | } else if (s->block_type == BLOCK_4x2) { |
831 | 2.44M | APPLY_C_PREDICTOR_24(); |
832 | 2.44M | APPLY_Y_PREDICTOR_24(); |
833 | 2.44M | OUTPUT_PIXEL_PAIR(); |
834 | 2.44M | APPLY_Y_PREDICTOR_24(); |
835 | 2.44M | OUTPUT_PIXEL_PAIR(); |
836 | 2.44M | } else { |
837 | 1.28M | APPLY_Y_PREDICTOR_24(); |
838 | 1.28M | OUTPUT_PIXEL_PAIR(); |
839 | 1.28M | APPLY_Y_PREDICTOR_24(); |
840 | 1.28M | OUTPUT_PIXEL_PAIR(); |
841 | 1.28M | } |
842 | 6.46M | break; |
843 | 25.9M | } |
844 | | |
845 | 25.9M | } else { |
846 | | |
847 | | /* skip (copy) four pixels, but reassign the horizontal |
848 | | * predictor */ |
849 | 7.23k | *vert_pred++ = *current_pixel_pair++; |
850 | 7.23k | horiz_pred = *current_pixel_pair - *vert_pred; |
851 | 7.23k | *vert_pred++ = *current_pixel_pair++; |
852 | | |
853 | 7.23k | } |
854 | | |
855 | 25.9M | if (!keyframe) { |
856 | 14.6k | mb_change_byte_mask <<= 1; |
857 | | |
858 | | /* next byte */ |
859 | 14.6k | if (!mb_change_byte_mask) { |
860 | 1.46k | mb_change_byte = mb_change_bits[mb_change_index++]; |
861 | 1.46k | mb_change_byte_mask = 0x01; |
862 | 1.46k | } |
863 | 14.6k | } |
864 | | |
865 | 25.9M | pixels_left -= 2; |
866 | 25.9M | } |
867 | | |
868 | | /* next change row */ |
869 | 1.08M | if (((y + 1) & 3) == 0) |
870 | 265k | mb_change_bits += s->mb_change_bits_row_size; |
871 | | |
872 | 1.08M | current_line += s->frame->linesize[0]; |
873 | 1.08M | } |
874 | 17.7k | } |
875 | | |
876 | | |
877 | | static int truemotion1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, |
878 | | int *got_frame, AVPacket *avpkt) |
879 | 304k | { |
880 | 304k | const uint8_t *buf = avpkt->data; |
881 | 304k | int ret, buf_size = avpkt->size; |
882 | 304k | TrueMotion1Context *s = avctx->priv_data; |
883 | | |
884 | 304k | s->buf = buf; |
885 | 304k | s->size = buf_size; |
886 | | |
887 | 304k | if ((ret = truemotion1_decode_header(s)) < 0) |
888 | 162k | return ret; |
889 | | |
890 | 142k | if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
891 | 217 | return ret; |
892 | | |
893 | 142k | if (compression_types[s->compression].algorithm == ALGO_RGB24H) { |
894 | 18.0k | truemotion1_decode_24bit(s); |
895 | 124k | } else if (compression_types[s->compression].algorithm != ALGO_NOP) { |
896 | 123k | truemotion1_decode_16bit(s); |
897 | 123k | } |
898 | | |
899 | 142k | if ((ret = av_frame_ref(rframe, s->frame)) < 0) |
900 | 0 | return ret; |
901 | | |
902 | 142k | *got_frame = 1; |
903 | | |
904 | | /* report that the buffer was completely consumed */ |
905 | 142k | return buf_size; |
906 | 142k | } |
907 | | |
908 | | static av_cold int truemotion1_decode_end(AVCodecContext *avctx) |
909 | 2.39k | { |
910 | 2.39k | TrueMotion1Context *s = avctx->priv_data; |
911 | | |
912 | 2.39k | av_frame_free(&s->frame); |
913 | 2.39k | av_freep(&s->vert_pred); |
914 | | |
915 | 2.39k | return 0; |
916 | 2.39k | } |
917 | | |
918 | | const FFCodec ff_truemotion1_decoder = { |
919 | | .p.name = "truemotion1", |
920 | | CODEC_LONG_NAME("Duck TrueMotion 1.0"), |
921 | | .p.type = AVMEDIA_TYPE_VIDEO, |
922 | | .p.id = AV_CODEC_ID_TRUEMOTION1, |
923 | | .priv_data_size = sizeof(TrueMotion1Context), |
924 | | .init = truemotion1_decode_init, |
925 | | .close = truemotion1_decode_end, |
926 | | FF_CODEC_DECODE_CB(truemotion1_decode_frame), |
927 | | .p.capabilities = AV_CODEC_CAP_DR1, |
928 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
929 | | }; |