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