Statistics
| Branch: | Revision:

ffmpeg / libavcodec / qtrle.c @ 2912e87a

History | View | Annotate | Download (17.4 KB)

1
/*
2
 * Quicktime Animation (RLE) Video Decoder
3
 * Copyright (C) 2004 the ffmpeg project
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav 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
 * Libav 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 Libav; 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
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

    
38
#include "libavutil/intreadwrite.h"
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

    
65
static void qtrle_decode_1bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
66
{
67
    int rle_code;
68
    int pixel_ptr = 0;
69
    int row_inc = s->frame.linesize[0];
70
    unsigned char pi0, pi1;  /* 2 8-pixel values */
71
    unsigned char *rgb = s->frame.data[0];
72
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
73
    int skip;
74

    
75
    while (lines_to_change) {
76
        CHECK_STREAM_PTR(2);
77
        skip = s->buf[stream_ptr++];
78
        rle_code = (signed char)s->buf[stream_ptr++];
79
        if (rle_code == 0)
80
            break;
81
        if(skip & 0x80) {
82
            lines_to_change--;
83
            row_ptr += row_inc;
84
            pixel_ptr = row_ptr + 2 * (skip & 0x7f);
85
        } else
86
            pixel_ptr += 2 * skip;
87
        CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
88

    
89
        if (rle_code < 0) {
90
            /* decode the run length code */
91
            rle_code = -rle_code;
92
            /* get the next 2 bytes from the stream, treat them as groups
93
             * of 8 pixels, and output them rle_code times */
94
            CHECK_STREAM_PTR(2);
95
            pi0 = s->buf[stream_ptr++];
96
            pi1 = s->buf[stream_ptr++];
97
            CHECK_PIXEL_PTR(rle_code * 2);
98

    
99
            while (rle_code--) {
100
                rgb[pixel_ptr++] = pi0;
101
                rgb[pixel_ptr++] = pi1;
102
            }
103
        } else {
104
            /* copy the same pixel directly to output 2 times */
105
            rle_code *= 2;
106
            CHECK_STREAM_PTR(rle_code);
107
            CHECK_PIXEL_PTR(rle_code);
108

    
109
            while (rle_code--)
110
                rgb[pixel_ptr++] = s->buf[stream_ptr++];
111
        }
112
    }
113
}
114

    
115
static inline void qtrle_decode_2n4bpp(QtrleContext *s, int stream_ptr,
116
                             int row_ptr, int lines_to_change, int bpp)
117
{
118
    int rle_code, i;
119
    int pixel_ptr;
120
    int row_inc = s->frame.linesize[0];
121
    unsigned char pi[16];  /* 16 palette indices */
122
    unsigned char *rgb = s->frame.data[0];
123
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
124
    int num_pixels = (bpp == 4) ? 8 : 16;
125

    
126
    while (lines_to_change--) {
127
        CHECK_STREAM_PTR(2);
128
        pixel_ptr = row_ptr + (num_pixels * (s->buf[stream_ptr++] - 1));
129

    
130
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
131
            if (rle_code == 0) {
132
                /* there's another skip code in the stream */
133
                CHECK_STREAM_PTR(1);
134
                pixel_ptr += (num_pixels * (s->buf[stream_ptr++] - 1));
135
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
136
            } else if (rle_code < 0) {
137
                /* decode the run length code */
138
                rle_code = -rle_code;
139
                /* get the next 4 bytes from the stream, treat them as palette
140
                 * indexes, and output them rle_code times */
141
                CHECK_STREAM_PTR(4);
142
                for (i = num_pixels-1; i >= 0; i--) {
143
                    pi[num_pixels-1-i] = (s->buf[stream_ptr] >> ((i*bpp) & 0x07)) & ((1<<bpp)-1);
144
                    stream_ptr+= ((i & ((num_pixels>>2)-1)) == 0);
145
                }
146
                CHECK_PIXEL_PTR(rle_code * num_pixels);
147
                while (rle_code--) {
148
                    for (i = 0; i < num_pixels; i++)
149
                        rgb[pixel_ptr++] = pi[i];
150
                }
151
            } else {
152
                /* copy the same pixel directly to output 4 times */
153
                rle_code *= 4;
154
                CHECK_STREAM_PTR(rle_code);
155
                CHECK_PIXEL_PTR(rle_code*(num_pixels>>2));
156
                while (rle_code--) {
157
                    if(bpp == 4) {
158
                        rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f;
159
                        rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
160
                    } else {
161
                        rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 6) & 0x03;
162
                        rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x03;
163
                        rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 2) & 0x03;
164
                        rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x03;
165
                    }
166
                }
167
            }
168
        }
169
        row_ptr += row_inc;
170
    }
171
}
172

    
173
static void qtrle_decode_8bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
174
{
175
    int rle_code;
176
    int pixel_ptr;
177
    int row_inc = s->frame.linesize[0];
178
    unsigned char pi1, pi2, pi3, pi4;  /* 4 palette indexes */
179
    unsigned char *rgb = s->frame.data[0];
180
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
181

    
182
    while (lines_to_change--) {
183
        CHECK_STREAM_PTR(2);
184
        pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
185

    
186
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
187
            if (rle_code == 0) {
188
                /* there's another skip code in the stream */
189
                CHECK_STREAM_PTR(1);
190
                pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
191
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
192
            } else if (rle_code < 0) {
193
                /* decode the run length code */
194
                rle_code = -rle_code;
195
                /* get the next 4 bytes from the stream, treat them as palette
196
                 * indexes, and output them rle_code times */
197
                CHECK_STREAM_PTR(4);
198
                pi1 = s->buf[stream_ptr++];
199
                pi2 = s->buf[stream_ptr++];
200
                pi3 = s->buf[stream_ptr++];
201
                pi4 = s->buf[stream_ptr++];
202

    
203
                CHECK_PIXEL_PTR(rle_code * 4);
204

    
205
                while (rle_code--) {
206
                    rgb[pixel_ptr++] = pi1;
207
                    rgb[pixel_ptr++] = pi2;
208
                    rgb[pixel_ptr++] = pi3;
209
                    rgb[pixel_ptr++] = pi4;
210
                }
211
            } else {
212
                /* copy the same pixel directly to output 4 times */
213
                rle_code *= 4;
214
                CHECK_STREAM_PTR(rle_code);
215
                CHECK_PIXEL_PTR(rle_code);
216

    
217
                while (rle_code--) {
218
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
219
                }
220
            }
221
        }
222
        row_ptr += row_inc;
223
    }
224
}
225

    
226
static void qtrle_decode_16bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
227
{
228
    int rle_code;
229
    int pixel_ptr;
230
    int row_inc = s->frame.linesize[0];
231
    unsigned short rgb16;
232
    unsigned char *rgb = s->frame.data[0];
233
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
234

    
235
    while (lines_to_change--) {
236
        CHECK_STREAM_PTR(2);
237
        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
238

    
239
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
240
            if (rle_code == 0) {
241
                /* there's another skip code in the stream */
242
                CHECK_STREAM_PTR(1);
243
                pixel_ptr += (s->buf[stream_ptr++] - 1) * 2;
244
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
245
            } else if (rle_code < 0) {
246
                /* decode the run length code */
247
                rle_code = -rle_code;
248
                CHECK_STREAM_PTR(2);
249
                rgb16 = AV_RB16(&s->buf[stream_ptr]);
250
                stream_ptr += 2;
251

    
252
                CHECK_PIXEL_PTR(rle_code * 2);
253

    
254
                while (rle_code--) {
255
                    *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
256
                    pixel_ptr += 2;
257
                }
258
            } else {
259
                CHECK_STREAM_PTR(rle_code * 2);
260
                CHECK_PIXEL_PTR(rle_code * 2);
261

    
262
                /* copy pixels directly to output */
263
                while (rle_code--) {
264
                    rgb16 = AV_RB16(&s->buf[stream_ptr]);
265
                    stream_ptr += 2;
266
                    *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
267
                    pixel_ptr += 2;
268
                }
269
            }
270
        }
271
        row_ptr += row_inc;
272
    }
273
}
274

    
275
static void qtrle_decode_24bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
276
{
277
    int rle_code;
278
    int pixel_ptr;
279
    int row_inc = s->frame.linesize[0];
280
    unsigned char r, g, b;
281
    unsigned char *rgb = s->frame.data[0];
282
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
283

    
284
    while (lines_to_change--) {
285
        CHECK_STREAM_PTR(2);
286
        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
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) * 3;
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(3);
298
                r = s->buf[stream_ptr++];
299
                g = s->buf[stream_ptr++];
300
                b = s->buf[stream_ptr++];
301

    
302
                CHECK_PIXEL_PTR(rle_code * 3);
303

    
304
                while (rle_code--) {
305
                    rgb[pixel_ptr++] = r;
306
                    rgb[pixel_ptr++] = g;
307
                    rgb[pixel_ptr++] = b;
308
                }
309
            } else {
310
                CHECK_STREAM_PTR(rle_code * 3);
311
                CHECK_PIXEL_PTR(rle_code * 3);
312

    
313
                /* copy pixels directly to output */
314
                while (rle_code--) {
315
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
316
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
317
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
318
                }
319
            }
320
        }
321
        row_ptr += row_inc;
322
    }
323
}
324

    
325
static void qtrle_decode_32bpp(QtrleContext *s, int stream_ptr, int row_ptr, int lines_to_change)
326
{
327
    int rle_code;
328
    int pixel_ptr;
329
    int row_inc = s->frame.linesize[0];
330
    unsigned char a, r, g, b;
331
    unsigned int argb;
332
    unsigned char *rgb = s->frame.data[0];
333
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
334

    
335
    while (lines_to_change--) {
336
        CHECK_STREAM_PTR(2);
337
        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
338

    
339
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
340
            if (rle_code == 0) {
341
                /* there's another skip code in the stream */
342
                CHECK_STREAM_PTR(1);
343
                pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
344
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
345
            } else if (rle_code < 0) {
346
                /* decode the run length code */
347
                rle_code = -rle_code;
348
                CHECK_STREAM_PTR(4);
349
                a = s->buf[stream_ptr++];
350
                r = s->buf[stream_ptr++];
351
                g = s->buf[stream_ptr++];
352
                b = s->buf[stream_ptr++];
353
                argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
354

    
355
                CHECK_PIXEL_PTR(rle_code * 4);
356

    
357
                while (rle_code--) {
358
                    *(unsigned int *)(&rgb[pixel_ptr]) = argb;
359
                    pixel_ptr += 4;
360
                }
361
            } else {
362
                CHECK_STREAM_PTR(rle_code * 4);
363
                CHECK_PIXEL_PTR(rle_code * 4);
364

    
365
                /* copy pixels directly to output */
366
                while (rle_code--) {
367
                    a = s->buf[stream_ptr++];
368
                    r = s->buf[stream_ptr++];
369
                    g = s->buf[stream_ptr++];
370
                    b = s->buf[stream_ptr++];
371
                    argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
372
                    *(unsigned int *)(&rgb[pixel_ptr]) = argb;
373
                    pixel_ptr += 4;
374
                }
375
            }
376
        }
377
        row_ptr += row_inc;
378
    }
379
}
380

    
381
static av_cold int qtrle_decode_init(AVCodecContext *avctx)
382
{
383
    QtrleContext *s = avctx->priv_data;
384

    
385
    s->avctx = avctx;
386
    switch (avctx->bits_per_coded_sample) {
387
    case 1:
388
    case 33:
389
        avctx->pix_fmt = PIX_FMT_MONOWHITE;
390
        break;
391

    
392
    case 2:
393
    case 4:
394
    case 8:
395
    case 34:
396
    case 36:
397
    case 40:
398
        avctx->pix_fmt = PIX_FMT_PAL8;
399
        break;
400

    
401
    case 16:
402
        avctx->pix_fmt = PIX_FMT_RGB555;
403
        break;
404

    
405
    case 24:
406
        avctx->pix_fmt = PIX_FMT_RGB24;
407
        break;
408

    
409
    case 32:
410
        avctx->pix_fmt = PIX_FMT_RGB32;
411
        break;
412

    
413
    default:
414
        av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
415
            avctx->bits_per_coded_sample);
416
        break;
417
    }
418

    
419
    s->frame.data[0] = NULL;
420

    
421
    return 0;
422
}
423

    
424
static int qtrle_decode_frame(AVCodecContext *avctx,
425
                              void *data, int *data_size,
426
                              AVPacket *avpkt)
427
{
428
    const uint8_t *buf = avpkt->data;
429
    int buf_size = avpkt->size;
430
    QtrleContext *s = avctx->priv_data;
431
    int header, start_line;
432
    int stream_ptr, height, row_ptr;
433
    int has_palette = 0;
434

    
435
    s->buf = buf;
436
    s->size = buf_size;
437

    
438
    s->frame.reference = 1;
439
    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
440
                            FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
441
    if (avctx->reget_buffer(avctx, &s->frame)) {
442
        av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
443
        return -1;
444
    }
445

    
446
    /* check if this frame is even supposed to change */
447
    if (s->size < 8)
448
        goto done;
449

    
450
    /* start after the chunk size */
451
    stream_ptr = 4;
452

    
453
    /* fetch the header */
454
    header = AV_RB16(&s->buf[stream_ptr]);
455
    stream_ptr += 2;
456

    
457
    /* if a header is present, fetch additional decoding parameters */
458
    if (header & 0x0008) {
459
        if(s->size < 14)
460
            goto done;
461
        start_line = AV_RB16(&s->buf[stream_ptr]);
462
        stream_ptr += 4;
463
        height = AV_RB16(&s->buf[stream_ptr]);
464
        stream_ptr += 4;
465
    } else {
466
        start_line = 0;
467
        height = s->avctx->height;
468
    }
469
    row_ptr = s->frame.linesize[0] * start_line;
470

    
471
    switch (avctx->bits_per_coded_sample) {
472
    case 1:
473
    case 33:
474
        qtrle_decode_1bpp(s, stream_ptr, row_ptr, height);
475
        break;
476

    
477
    case 2:
478
    case 34:
479
        qtrle_decode_2n4bpp(s, stream_ptr, row_ptr, height, 2);
480
        has_palette = 1;
481
        break;
482

    
483
    case 4:
484
    case 36:
485
        qtrle_decode_2n4bpp(s, stream_ptr, row_ptr, height, 4);
486
        has_palette = 1;
487
        break;
488

    
489
    case 8:
490
    case 40:
491
        qtrle_decode_8bpp(s, stream_ptr, row_ptr, height);
492
        has_palette = 1;
493
        break;
494

    
495
    case 16:
496
        qtrle_decode_16bpp(s, stream_ptr, row_ptr, height);
497
        break;
498

    
499
    case 24:
500
        qtrle_decode_24bpp(s, stream_ptr, row_ptr, height);
501
        break;
502

    
503
    case 32:
504
        qtrle_decode_32bpp(s, stream_ptr, row_ptr, height);
505
        break;
506

    
507
    default:
508
        av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
509
            avctx->bits_per_coded_sample);
510
        break;
511
    }
512

    
513
    if(has_palette) {
514
        /* make the palette available on the way out */
515
        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
516
        if (s->avctx->palctrl->palette_changed) {
517
            s->frame.palette_has_changed = 1;
518
            s->avctx->palctrl->palette_changed = 0;
519
        }
520
    }
521

    
522
done:
523
    *data_size = sizeof(AVFrame);
524
    *(AVFrame*)data = s->frame;
525

    
526
    /* always report that the buffer was completely consumed */
527
    return buf_size;
528
}
529

    
530
static av_cold int qtrle_decode_end(AVCodecContext *avctx)
531
{
532
    QtrleContext *s = avctx->priv_data;
533

    
534
    if (s->frame.data[0])
535
        avctx->release_buffer(avctx, &s->frame);
536

    
537
    return 0;
538
}
539

    
540
AVCodec ff_qtrle_decoder = {
541
    "qtrle",
542
    AVMEDIA_TYPE_VIDEO,
543
    CODEC_ID_QTRLE,
544
    sizeof(QtrleContext),
545
    qtrle_decode_init,
546
    NULL,
547
    qtrle_decode_end,
548
    qtrle_decode_frame,
549
    CODEC_CAP_DR1,
550
    .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
551
};
552