ffmpeg / libavcodec / qtrle.c @ 5509bffa
History | View | Annotate | Download (18.4 KB)
1 |
/*
|
---|---|
2 |
* Quicktime Animation (RLE) Video Decoder
|
3 |
* Copyright (C) 2004 the ffmpeg project
|
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 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18 |
*
|
19 |
*/
|
20 |
|
21 |
/**
|
22 |
* @file qtrle.c
|
23 |
* QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
|
24 |
* For more information about the QT RLE format, visit:
|
25 |
* http://www.pcisys.net/~melanson/codecs/
|
26 |
*
|
27 |
* The QT RLE decoder has seven modes of operation:
|
28 |
* 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
|
29 |
* the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555
|
30 |
* data. 24-bit data is RGB24 and 32-bit data is RGBA32.
|
31 |
*/
|
32 |
|
33 |
#include <stdio.h> |
34 |
#include <stdlib.h> |
35 |
#include <string.h> |
36 |
#include <unistd.h> |
37 |
|
38 |
#include "common.h" |
39 |
#include "avcodec.h" |
40 |
#include "dsputil.h" |
41 |
|
42 |
typedef struct QtrleContext { |
43 |
|
44 |
AVCodecContext *avctx; |
45 |
DSPContext dsp; |
46 |
AVFrame frame; |
47 |
|
48 |
unsigned char *buf; |
49 |
int size;
|
50 |
|
51 |
} QtrleContext; |
52 |
|
53 |
#define CHECK_STREAM_PTR(n) \
|
54 |
if ((stream_ptr + n) > s->size) { \
|
55 |
av_log (s->avctx, AV_LOG_INFO, "Problem: stream_ptr out of bounds (%d >= %d)\n", \
|
56 |
stream_ptr + n, s->size); \ |
57 |
return; \
|
58 |
} |
59 |
|
60 |
#define CHECK_PIXEL_PTR(n) \
|
61 |
if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \ |
62 |
av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \
|
63 |
pixel_ptr + n, pixel_limit); \ |
64 |
return; \
|
65 |
} \ |
66 |
|
67 |
static void qtrle_decode_1bpp(QtrleContext *s) |
68 |
{ |
69 |
} |
70 |
|
71 |
static void qtrle_decode_2bpp(QtrleContext *s) |
72 |
{ |
73 |
} |
74 |
|
75 |
static void qtrle_decode_4bpp(QtrleContext *s) |
76 |
{ |
77 |
int stream_ptr;
|
78 |
int header;
|
79 |
int start_line;
|
80 |
int lines_to_change;
|
81 |
int rle_code;
|
82 |
int row_ptr, pixel_ptr;
|
83 |
int row_inc = s->frame.linesize[0]; |
84 |
unsigned char pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8; /* 8 palette indices */ |
85 |
unsigned char *rgb = s->frame.data[0]; |
86 |
int pixel_limit = s->frame.linesize[0] * s->avctx->height; |
87 |
|
88 |
/* check if this frame is even supposed to change */
|
89 |
if (s->size < 8) |
90 |
return;
|
91 |
|
92 |
/* start after the chunk size */
|
93 |
stream_ptr = 4;
|
94 |
|
95 |
/* fetch the header */
|
96 |
CHECK_STREAM_PTR(2);
|
97 |
header = BE_16(&s->buf[stream_ptr]); |
98 |
stream_ptr += 2;
|
99 |
|
100 |
/* if a header is present, fetch additional decoding parameters */
|
101 |
if (header & 0x0008) { |
102 |
CHECK_STREAM_PTR(8);
|
103 |
start_line = BE_16(&s->buf[stream_ptr]); |
104 |
stream_ptr += 4;
|
105 |
lines_to_change = BE_16(&s->buf[stream_ptr]); |
106 |
stream_ptr += 4;
|
107 |
} else {
|
108 |
start_line = 0;
|
109 |
lines_to_change = s->avctx->height; |
110 |
} |
111 |
|
112 |
row_ptr = row_inc * start_line; |
113 |
while (lines_to_change--) {
|
114 |
CHECK_STREAM_PTR(2);
|
115 |
pixel_ptr = row_ptr + (8 * (s->buf[stream_ptr++] - 1)); |
116 |
|
117 |
while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { |
118 |
if (rle_code == 0) { |
119 |
/* there's another skip code in the stream */
|
120 |
CHECK_STREAM_PTR(1);
|
121 |
pixel_ptr += (8 * (s->buf[stream_ptr++] - 1)); |
122 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
123 |
} else if (rle_code < 0) { |
124 |
/* decode the run length code */
|
125 |
rle_code = -rle_code; |
126 |
/* get the next 4 bytes from the stream, treat them as palette
|
127 |
* indices, and output them rle_code times */
|
128 |
CHECK_STREAM_PTR(4);
|
129 |
pi1 = ((s->buf[stream_ptr]) >> 4) & 0x0f; |
130 |
pi2 = (s->buf[stream_ptr++]) & 0x0f;
|
131 |
pi3 = ((s->buf[stream_ptr]) >> 4) & 0x0f; |
132 |
pi4 = (s->buf[stream_ptr++]) & 0x0f;
|
133 |
pi5 = ((s->buf[stream_ptr]) >> 4) & 0x0f; |
134 |
pi6 = (s->buf[stream_ptr++]) & 0x0f;
|
135 |
pi7 = ((s->buf[stream_ptr]) >> 4) & 0x0f; |
136 |
pi8 = (s->buf[stream_ptr++]) & 0x0f;
|
137 |
|
138 |
CHECK_PIXEL_PTR(rle_code * 8);
|
139 |
|
140 |
while (rle_code--) {
|
141 |
rgb[pixel_ptr++] = pi1; |
142 |
rgb[pixel_ptr++] = pi2; |
143 |
rgb[pixel_ptr++] = pi3; |
144 |
rgb[pixel_ptr++] = pi4; |
145 |
rgb[pixel_ptr++] = pi5; |
146 |
rgb[pixel_ptr++] = pi6; |
147 |
rgb[pixel_ptr++] = pi7; |
148 |
rgb[pixel_ptr++] = pi8; |
149 |
} |
150 |
} else {
|
151 |
/* copy the same pixel directly to output 4 times */
|
152 |
rle_code *= 4;
|
153 |
CHECK_STREAM_PTR(rle_code); |
154 |
CHECK_PIXEL_PTR(rle_code*2);
|
155 |
|
156 |
while (rle_code--) {
|
157 |
rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f; |
158 |
rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
|
159 |
} |
160 |
} |
161 |
} |
162 |
row_ptr += row_inc; |
163 |
} |
164 |
} |
165 |
|
166 |
static void qtrle_decode_8bpp(QtrleContext *s) |
167 |
{ |
168 |
int stream_ptr;
|
169 |
int header;
|
170 |
int start_line;
|
171 |
int lines_to_change;
|
172 |
int rle_code;
|
173 |
int row_ptr, pixel_ptr;
|
174 |
int row_inc = s->frame.linesize[0]; |
175 |
unsigned char pi1, pi2, pi3, pi4; /* 4 palette indices */ |
176 |
unsigned char *rgb = s->frame.data[0]; |
177 |
int pixel_limit = s->frame.linesize[0] * s->avctx->height; |
178 |
|
179 |
/* check if this frame is even supposed to change */
|
180 |
if (s->size < 8) |
181 |
return;
|
182 |
|
183 |
/* start after the chunk size */
|
184 |
stream_ptr = 4;
|
185 |
|
186 |
/* fetch the header */
|
187 |
CHECK_STREAM_PTR(2);
|
188 |
header = BE_16(&s->buf[stream_ptr]); |
189 |
stream_ptr += 2;
|
190 |
|
191 |
/* if a header is present, fetch additional decoding parameters */
|
192 |
if (header & 0x0008) { |
193 |
CHECK_STREAM_PTR(8);
|
194 |
start_line = BE_16(&s->buf[stream_ptr]); |
195 |
stream_ptr += 4;
|
196 |
lines_to_change = BE_16(&s->buf[stream_ptr]); |
197 |
stream_ptr += 4;
|
198 |
} else {
|
199 |
start_line = 0;
|
200 |
lines_to_change = s->avctx->height; |
201 |
} |
202 |
|
203 |
row_ptr = row_inc * start_line; |
204 |
while (lines_to_change--) {
|
205 |
CHECK_STREAM_PTR(2);
|
206 |
pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1)); |
207 |
|
208 |
while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { |
209 |
if (rle_code == 0) { |
210 |
/* there's another skip code in the stream */
|
211 |
CHECK_STREAM_PTR(1);
|
212 |
pixel_ptr += (4 * (s->buf[stream_ptr++] - 1)); |
213 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
214 |
} else if (rle_code < 0) { |
215 |
/* decode the run length code */
|
216 |
rle_code = -rle_code; |
217 |
/* get the next 4 bytes from the stream, treat them as palette
|
218 |
* indices, and output them rle_code times */
|
219 |
CHECK_STREAM_PTR(4);
|
220 |
pi1 = s->buf[stream_ptr++]; |
221 |
pi2 = s->buf[stream_ptr++]; |
222 |
pi3 = s->buf[stream_ptr++]; |
223 |
pi4 = s->buf[stream_ptr++]; |
224 |
|
225 |
CHECK_PIXEL_PTR(rle_code * 4);
|
226 |
|
227 |
while (rle_code--) {
|
228 |
rgb[pixel_ptr++] = pi1; |
229 |
rgb[pixel_ptr++] = pi2; |
230 |
rgb[pixel_ptr++] = pi3; |
231 |
rgb[pixel_ptr++] = pi4; |
232 |
} |
233 |
} else {
|
234 |
/* copy the same pixel directly to output 4 times */
|
235 |
rle_code *= 4;
|
236 |
CHECK_STREAM_PTR(rle_code); |
237 |
CHECK_PIXEL_PTR(rle_code); |
238 |
|
239 |
while (rle_code--) {
|
240 |
rgb[pixel_ptr++] = s->buf[stream_ptr++]; |
241 |
} |
242 |
} |
243 |
} |
244 |
row_ptr += row_inc; |
245 |
} |
246 |
} |
247 |
|
248 |
static void qtrle_decode_16bpp(QtrleContext *s) |
249 |
{ |
250 |
int stream_ptr;
|
251 |
int header;
|
252 |
int start_line;
|
253 |
int lines_to_change;
|
254 |
int rle_code;
|
255 |
int row_ptr, pixel_ptr;
|
256 |
int row_inc = s->frame.linesize[0]; |
257 |
unsigned short rgb16; |
258 |
unsigned char *rgb = s->frame.data[0]; |
259 |
int pixel_limit = s->frame.linesize[0] * s->avctx->height; |
260 |
|
261 |
/* check if this frame is even supposed to change */
|
262 |
if (s->size < 8) |
263 |
return;
|
264 |
|
265 |
/* start after the chunk size */
|
266 |
stream_ptr = 4;
|
267 |
|
268 |
/* fetch the header */
|
269 |
CHECK_STREAM_PTR(2);
|
270 |
header = BE_16(&s->buf[stream_ptr]); |
271 |
stream_ptr += 2;
|
272 |
|
273 |
/* if a header is present, fetch additional decoding parameters */
|
274 |
if (header & 0x0008) { |
275 |
CHECK_STREAM_PTR(8);
|
276 |
start_line = BE_16(&s->buf[stream_ptr]); |
277 |
stream_ptr += 4;
|
278 |
lines_to_change = BE_16(&s->buf[stream_ptr]); |
279 |
stream_ptr += 4;
|
280 |
} else {
|
281 |
start_line = 0;
|
282 |
lines_to_change = s->avctx->height; |
283 |
} |
284 |
|
285 |
row_ptr = row_inc * start_line; |
286 |
while (lines_to_change--) {
|
287 |
CHECK_STREAM_PTR(2);
|
288 |
pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2; |
289 |
|
290 |
while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { |
291 |
if (rle_code == 0) { |
292 |
/* there's another skip code in the stream */
|
293 |
CHECK_STREAM_PTR(1);
|
294 |
pixel_ptr += (s->buf[stream_ptr++] - 1) * 2; |
295 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
296 |
} else if (rle_code < 0) { |
297 |
/* decode the run length code */
|
298 |
rle_code = -rle_code; |
299 |
CHECK_STREAM_PTR(2);
|
300 |
rgb16 = BE_16(&s->buf[stream_ptr]); |
301 |
stream_ptr += 2;
|
302 |
|
303 |
CHECK_PIXEL_PTR(rle_code * 2);
|
304 |
|
305 |
while (rle_code--) {
|
306 |
*(unsigned short *)(&rgb[pixel_ptr]) = rgb16; |
307 |
pixel_ptr += 2;
|
308 |
} |
309 |
} else {
|
310 |
CHECK_STREAM_PTR(rle_code * 2);
|
311 |
CHECK_PIXEL_PTR(rle_code * 2);
|
312 |
|
313 |
/* copy pixels directly to output */
|
314 |
while (rle_code--) {
|
315 |
rgb16 = BE_16(&s->buf[stream_ptr]); |
316 |
stream_ptr += 2;
|
317 |
*(unsigned short *)(&rgb[pixel_ptr]) = rgb16; |
318 |
pixel_ptr += 2;
|
319 |
} |
320 |
} |
321 |
} |
322 |
row_ptr += row_inc; |
323 |
} |
324 |
} |
325 |
|
326 |
static void qtrle_decode_24bpp(QtrleContext *s) |
327 |
{ |
328 |
int stream_ptr;
|
329 |
int header;
|
330 |
int start_line;
|
331 |
int lines_to_change;
|
332 |
int rle_code;
|
333 |
int row_ptr, pixel_ptr;
|
334 |
int row_inc = s->frame.linesize[0]; |
335 |
unsigned char r, g, b; |
336 |
unsigned char *rgb = s->frame.data[0]; |
337 |
int pixel_limit = s->frame.linesize[0] * s->avctx->height; |
338 |
|
339 |
/* check if this frame is even supposed to change */
|
340 |
if (s->size < 8) |
341 |
return;
|
342 |
|
343 |
/* start after the chunk size */
|
344 |
stream_ptr = 4;
|
345 |
|
346 |
/* fetch the header */
|
347 |
CHECK_STREAM_PTR(2);
|
348 |
header = BE_16(&s->buf[stream_ptr]); |
349 |
stream_ptr += 2;
|
350 |
|
351 |
/* if a header is present, fetch additional decoding parameters */
|
352 |
if (header & 0x0008) { |
353 |
CHECK_STREAM_PTR(8);
|
354 |
start_line = BE_16(&s->buf[stream_ptr]); |
355 |
stream_ptr += 4;
|
356 |
lines_to_change = BE_16(&s->buf[stream_ptr]); |
357 |
stream_ptr += 4;
|
358 |
} else {
|
359 |
start_line = 0;
|
360 |
lines_to_change = s->avctx->height; |
361 |
} |
362 |
|
363 |
row_ptr = row_inc * start_line; |
364 |
while (lines_to_change--) {
|
365 |
CHECK_STREAM_PTR(2);
|
366 |
pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3; |
367 |
|
368 |
while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { |
369 |
if (rle_code == 0) { |
370 |
/* there's another skip code in the stream */
|
371 |
CHECK_STREAM_PTR(1);
|
372 |
pixel_ptr += (s->buf[stream_ptr++] - 1) * 3; |
373 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
374 |
} else if (rle_code < 0) { |
375 |
/* decode the run length code */
|
376 |
rle_code = -rle_code; |
377 |
CHECK_STREAM_PTR(3);
|
378 |
r = s->buf[stream_ptr++]; |
379 |
g = s->buf[stream_ptr++]; |
380 |
b = s->buf[stream_ptr++]; |
381 |
|
382 |
CHECK_PIXEL_PTR(rle_code * 3);
|
383 |
|
384 |
while (rle_code--) {
|
385 |
rgb[pixel_ptr++] = r; |
386 |
rgb[pixel_ptr++] = g; |
387 |
rgb[pixel_ptr++] = b; |
388 |
} |
389 |
} else {
|
390 |
CHECK_STREAM_PTR(rle_code * 3);
|
391 |
CHECK_PIXEL_PTR(rle_code * 3);
|
392 |
|
393 |
/* copy pixels directly to output */
|
394 |
while (rle_code--) {
|
395 |
rgb[pixel_ptr++] = s->buf[stream_ptr++]; |
396 |
rgb[pixel_ptr++] = s->buf[stream_ptr++]; |
397 |
rgb[pixel_ptr++] = s->buf[stream_ptr++]; |
398 |
} |
399 |
} |
400 |
} |
401 |
row_ptr += row_inc; |
402 |
} |
403 |
} |
404 |
|
405 |
static void qtrle_decode_32bpp(QtrleContext *s) |
406 |
{ |
407 |
int stream_ptr;
|
408 |
int header;
|
409 |
int start_line;
|
410 |
int lines_to_change;
|
411 |
int rle_code;
|
412 |
int row_ptr, pixel_ptr;
|
413 |
int row_inc = s->frame.linesize[0]; |
414 |
unsigned char a, r, g, b; |
415 |
unsigned int argb; |
416 |
unsigned char *rgb = s->frame.data[0]; |
417 |
int pixel_limit = s->frame.linesize[0] * s->avctx->height; |
418 |
|
419 |
/* check if this frame is even supposed to change */
|
420 |
if (s->size < 8) |
421 |
return;
|
422 |
|
423 |
/* start after the chunk size */
|
424 |
stream_ptr = 4;
|
425 |
|
426 |
/* fetch the header */
|
427 |
CHECK_STREAM_PTR(2);
|
428 |
header = BE_16(&s->buf[stream_ptr]); |
429 |
stream_ptr += 2;
|
430 |
|
431 |
/* if a header is present, fetch additional decoding parameters */
|
432 |
if (header & 0x0008) { |
433 |
CHECK_STREAM_PTR(8);
|
434 |
start_line = BE_16(&s->buf[stream_ptr]); |
435 |
stream_ptr += 4;
|
436 |
lines_to_change = BE_16(&s->buf[stream_ptr]); |
437 |
stream_ptr += 4;
|
438 |
} else {
|
439 |
start_line = 0;
|
440 |
lines_to_change = s->avctx->height; |
441 |
} |
442 |
|
443 |
row_ptr = row_inc * start_line; |
444 |
while (lines_to_change--) {
|
445 |
CHECK_STREAM_PTR(2);
|
446 |
pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4; |
447 |
|
448 |
while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) { |
449 |
if (rle_code == 0) { |
450 |
/* there's another skip code in the stream */
|
451 |
CHECK_STREAM_PTR(1);
|
452 |
pixel_ptr += (s->buf[stream_ptr++] - 1) * 4; |
453 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
454 |
} else if (rle_code < 0) { |
455 |
/* decode the run length code */
|
456 |
rle_code = -rle_code; |
457 |
CHECK_STREAM_PTR(4);
|
458 |
a = s->buf[stream_ptr++]; |
459 |
r = s->buf[stream_ptr++]; |
460 |
g = s->buf[stream_ptr++]; |
461 |
b = s->buf[stream_ptr++]; |
462 |
argb = (a << 24) | (r << 16) | (g << 8) | (b << 0); |
463 |
|
464 |
CHECK_PIXEL_PTR(rle_code * 4);
|
465 |
|
466 |
while (rle_code--) {
|
467 |
*(unsigned int *)(&rgb[pixel_ptr]) = argb; |
468 |
pixel_ptr += 4;
|
469 |
} |
470 |
} else {
|
471 |
CHECK_STREAM_PTR(rle_code * 4);
|
472 |
CHECK_PIXEL_PTR(rle_code * 4);
|
473 |
|
474 |
/* copy pixels directly to output */
|
475 |
while (rle_code--) {
|
476 |
a = s->buf[stream_ptr++]; |
477 |
r = s->buf[stream_ptr++]; |
478 |
g = s->buf[stream_ptr++]; |
479 |
b = s->buf[stream_ptr++]; |
480 |
argb = (a << 24) | (r << 16) | (g << 8) | (b << 0); |
481 |
*(unsigned int *)(&rgb[pixel_ptr]) = argb; |
482 |
pixel_ptr += 4;
|
483 |
} |
484 |
} |
485 |
} |
486 |
row_ptr += row_inc; |
487 |
} |
488 |
} |
489 |
|
490 |
static int qtrle_decode_init(AVCodecContext *avctx) |
491 |
{ |
492 |
QtrleContext *s = (QtrleContext *)avctx->priv_data; |
493 |
|
494 |
s->avctx = avctx; |
495 |
switch (avctx->bits_per_sample) {
|
496 |
case 1: |
497 |
case 2: |
498 |
case 4: |
499 |
case 8: |
500 |
case 33: |
501 |
case 34: |
502 |
case 36: |
503 |
case 40: |
504 |
avctx->pix_fmt = PIX_FMT_PAL8; |
505 |
break;
|
506 |
|
507 |
case 16: |
508 |
avctx->pix_fmt = PIX_FMT_RGB555; |
509 |
break;
|
510 |
|
511 |
case 24: |
512 |
avctx->pix_fmt = PIX_FMT_RGB24; |
513 |
break;
|
514 |
|
515 |
case 32: |
516 |
avctx->pix_fmt = PIX_FMT_RGBA32; |
517 |
break;
|
518 |
|
519 |
default:
|
520 |
av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
|
521 |
avctx->bits_per_sample); |
522 |
break;
|
523 |
} |
524 |
avctx->has_b_frames = 0;
|
525 |
dsputil_init(&s->dsp, avctx); |
526 |
|
527 |
s->frame.data[0] = NULL; |
528 |
|
529 |
return 0; |
530 |
} |
531 |
|
532 |
static int qtrle_decode_frame(AVCodecContext *avctx, |
533 |
void *data, int *data_size, |
534 |
uint8_t *buf, int buf_size)
|
535 |
{ |
536 |
QtrleContext *s = (QtrleContext *)avctx->priv_data; |
537 |
|
538 |
s->buf = buf; |
539 |
s->size = buf_size; |
540 |
|
541 |
s->frame.reference = 1;
|
542 |
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | |
543 |
FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE; |
544 |
if (avctx->reget_buffer(avctx, &s->frame)) {
|
545 |
av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
546 |
return -1; |
547 |
} |
548 |
|
549 |
switch (avctx->bits_per_sample) {
|
550 |
case 1: |
551 |
case 33: |
552 |
qtrle_decode_1bpp(s); |
553 |
break;
|
554 |
|
555 |
case 2: |
556 |
case 34: |
557 |
qtrle_decode_2bpp(s); |
558 |
break;
|
559 |
|
560 |
case 4: |
561 |
case 36: |
562 |
qtrle_decode_4bpp(s); |
563 |
/* make the palette available on the way out */
|
564 |
memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
|
565 |
if (s->avctx->palctrl->palette_changed) {
|
566 |
s->frame.palette_has_changed = 1;
|
567 |
s->avctx->palctrl->palette_changed = 0;
|
568 |
} |
569 |
break;
|
570 |
|
571 |
case 8: |
572 |
case 40: |
573 |
qtrle_decode_8bpp(s); |
574 |
/* make the palette available on the way out */
|
575 |
memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
|
576 |
if (s->avctx->palctrl->palette_changed) {
|
577 |
s->frame.palette_has_changed = 1;
|
578 |
s->avctx->palctrl->palette_changed = 0;
|
579 |
} |
580 |
break;
|
581 |
|
582 |
case 16: |
583 |
qtrle_decode_16bpp(s); |
584 |
break;
|
585 |
|
586 |
case 24: |
587 |
qtrle_decode_24bpp(s); |
588 |
break;
|
589 |
|
590 |
case 32: |
591 |
qtrle_decode_32bpp(s); |
592 |
break;
|
593 |
|
594 |
default:
|
595 |
av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
|
596 |
avctx->bits_per_sample); |
597 |
break;
|
598 |
} |
599 |
|
600 |
*data_size = sizeof(AVFrame);
|
601 |
*(AVFrame*)data = s->frame; |
602 |
|
603 |
/* always report that the buffer was completely consumed */
|
604 |
return buf_size;
|
605 |
} |
606 |
|
607 |
static int qtrle_decode_end(AVCodecContext *avctx) |
608 |
{ |
609 |
QtrleContext *s = (QtrleContext *)avctx->priv_data; |
610 |
|
611 |
if (s->frame.data[0]) |
612 |
avctx->release_buffer(avctx, &s->frame); |
613 |
|
614 |
return 0; |
615 |
} |
616 |
|
617 |
AVCodec qtrle_decoder = { |
618 |
"qtrle",
|
619 |
CODEC_TYPE_VIDEO, |
620 |
CODEC_ID_QTRLE, |
621 |
sizeof(QtrleContext),
|
622 |
qtrle_decode_init, |
623 |
NULL,
|
624 |
qtrle_decode_end, |
625 |
qtrle_decode_frame, |
626 |
CODEC_CAP_DR1, |
627 |
}; |
628 |
|