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