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