]> git.sesse.net Git - ffmpeg/blob - libavcodec/qtrle.c
06ea48ed6347202db87ca8ac93bf8a1fad30abc0
[ffmpeg] / libavcodec / qtrle.c
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  * @file qtrle.c
24  * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
25  * For more information about the QT RLE format, visit:
26  *   http://www.pcisys.net/~melanson/codecs/
27  *
28  * The QT RLE decoder has seven modes of operation:
29  * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
30  * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555
31  * data. 24-bit data is RGB24 and 32-bit data is RGB32.
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
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 = AV_RB16(&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 = AV_RB16(&s->buf[stream_ptr]);
104         stream_ptr += 4;
105         lines_to_change = AV_RB16(&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 = AV_RB16(&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 = AV_RB16(&s->buf[stream_ptr]);
195         stream_ptr += 4;
196         lines_to_change = AV_RB16(&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 = AV_RB16(&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 = AV_RB16(&s->buf[stream_ptr]);
277         stream_ptr += 4;
278         lines_to_change = AV_RB16(&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 = AV_RB16(&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 = AV_RB16(&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 = AV_RB16(&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 = AV_RB16(&s->buf[stream_ptr]);
355         stream_ptr += 4;
356         lines_to_change = AV_RB16(&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 = AV_RB16(&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 = AV_RB16(&s->buf[stream_ptr]);
435         stream_ptr += 4;
436         lines_to_change = AV_RB16(&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 = 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_RGB32;
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     dsputil_init(&s->dsp, avctx);
525
526     s->frame.data[0] = NULL;
527
528     return 0;
529 }
530
531 static int qtrle_decode_frame(AVCodecContext *avctx,
532                               void *data, int *data_size,
533                               uint8_t *buf, int buf_size)
534 {
535     QtrleContext *s = avctx->priv_data;
536
537     s->buf = buf;
538     s->size = buf_size;
539
540     s->frame.reference = 1;
541     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
542                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
543     if (avctx->reget_buffer(avctx, &s->frame)) {
544         av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
545         return -1;
546     }
547
548     switch (avctx->bits_per_sample) {
549     case 1:
550     case 33:
551         qtrle_decode_1bpp(s);
552         break;
553
554     case 2:
555     case 34:
556         qtrle_decode_2bpp(s);
557         break;
558
559     case 4:
560     case 36:
561         qtrle_decode_4bpp(s);
562         /* make the palette available on the way out */
563         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
564         if (s->avctx->palctrl->palette_changed) {
565             s->frame.palette_has_changed = 1;
566             s->avctx->palctrl->palette_changed = 0;
567         }
568         break;
569
570     case 8:
571     case 40:
572         qtrle_decode_8bpp(s);
573         /* make the palette available on the way out */
574         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
575         if (s->avctx->palctrl->palette_changed) {
576             s->frame.palette_has_changed = 1;
577             s->avctx->palctrl->palette_changed = 0;
578         }
579         break;
580
581     case 16:
582         qtrle_decode_16bpp(s);
583         break;
584
585     case 24:
586         qtrle_decode_24bpp(s);
587         break;
588
589     case 32:
590         qtrle_decode_32bpp(s);
591         break;
592
593     default:
594         av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
595             avctx->bits_per_sample);
596         break;
597     }
598
599     *data_size = sizeof(AVFrame);
600     *(AVFrame*)data = s->frame;
601
602     /* always report that the buffer was completely consumed */
603     return buf_size;
604 }
605
606 static int qtrle_decode_end(AVCodecContext *avctx)
607 {
608     QtrleContext *s = avctx->priv_data;
609
610     if (s->frame.data[0])
611         avctx->release_buffer(avctx, &s->frame);
612
613     return 0;
614 }
615
616 AVCodec qtrle_decoder = {
617     "qtrle",
618     CODEC_TYPE_VIDEO,
619     CODEC_ID_QTRLE,
620     sizeof(QtrleContext),
621     qtrle_decode_init,
622     NULL,
623     qtrle_decode_end,
624     qtrle_decode_frame,
625     CODEC_CAP_DR1,
626 };
627