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