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