VirtualBox

source: vbox/trunk/src/libs/ffmpeg-20060710/libavcodec/qtrle.c@ 10184

最後變更 在這個檔案從10184是 5776,由 vboxsync 提交於 17 年 前

ffmpeg: exported to OSE

檔案大小: 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 ([email protected])
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
42typedef 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
67static void qtrle_decode_1bpp(QtrleContext *s)
68{
69}
70
71static void qtrle_decode_2bpp(QtrleContext *s)
72{
73}
74
75static 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
166static 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
248static 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
326static 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
405static 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
490static 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
532static 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
607static 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
617AVCodec 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
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette