Statistics
| Branch: | Revision:

ffmpeg / libavcodec / qtrle.c @ e4141433

History | View | Annotate | Download (18.4 KB)

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
/**
24
 * @file qtrle.c
25
 * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
26
 * For more information about the QT RLE format, visit:
27
 *   http://www.pcisys.net/~melanson/codecs/
28
 *
29
 * The QT RLE decoder has seven modes of operation:
30
 * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
31
 * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555
32
 * data. 24-bit data is RGB24 and 32-bit data is RGB32.
33
 */
34

    
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <unistd.h>
39

    
40
#include "common.h"
41
#include "avcodec.h"
42
#include "dsputil.h"
43

    
44
typedef struct QtrleContext {
45

    
46
    AVCodecContext *avctx;
47
    DSPContext dsp;
48
    AVFrame frame;
49

    
50
    unsigned char *buf;
51
    int size;
52

    
53
} QtrleContext;
54

    
55
#define CHECK_STREAM_PTR(n) \
56
  if ((stream_ptr + n) > s->size) { \
57
    av_log (s->avctx, AV_LOG_INFO, "Problem: stream_ptr out of bounds (%d >= %d)\n", \
58
      stream_ptr + n, s->size); \
59
    return; \
60
  }
61

    
62
#define CHECK_PIXEL_PTR(n) \
63
  if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \
64
    av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \
65
      pixel_ptr + n, pixel_limit); \
66
    return; \
67
  } \
68

    
69
static void qtrle_decode_1bpp(QtrleContext *s)
70
{
71
}
72

    
73
static void qtrle_decode_2bpp(QtrleContext *s)
74
{
75
}
76

    
77
static void qtrle_decode_4bpp(QtrleContext *s)
78
{
79
    int stream_ptr;
80
    int header;
81
    int start_line;
82
    int lines_to_change;
83
    int rle_code;
84
    int row_ptr, pixel_ptr;
85
    int row_inc = s->frame.linesize[0];
86
    unsigned char pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8;  /* 8 palette indices */
87
    unsigned char *rgb = s->frame.data[0];
88
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
89

    
90
    /* check if this frame is even supposed to change */
91
    if (s->size < 8)
92
        return;
93

    
94
    /* start after the chunk size */
95
    stream_ptr = 4;
96

    
97
    /* fetch the header */
98
    CHECK_STREAM_PTR(2);
99
    header = AV_RB16(&s->buf[stream_ptr]);
100
    stream_ptr += 2;
101

    
102
    /* if a header is present, fetch additional decoding parameters */
103
    if (header & 0x0008) {
104
        CHECK_STREAM_PTR(8);
105
        start_line = AV_RB16(&s->buf[stream_ptr]);
106
        stream_ptr += 4;
107
        lines_to_change = AV_RB16(&s->buf[stream_ptr]);
108
        stream_ptr += 4;
109
    } else {
110
        start_line = 0;
111
        lines_to_change = s->avctx->height;
112
    }
113

    
114
    row_ptr = row_inc * start_line;
115
    while (lines_to_change--) {
116
        CHECK_STREAM_PTR(2);
117
        pixel_ptr = row_ptr + (8 * (s->buf[stream_ptr++] - 1));
118

    
119
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
120
            if (rle_code == 0) {
121
                /* there's another skip code in the stream */
122
                CHECK_STREAM_PTR(1);
123
                pixel_ptr += (8 * (s->buf[stream_ptr++] - 1));
124
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
125
            } else if (rle_code < 0) {
126
                /* decode the run length code */
127
                rle_code = -rle_code;
128
                /* get the next 4 bytes from the stream, treat them as palette
129
                 * indices, and output them rle_code times */
130
                CHECK_STREAM_PTR(4);
131
                pi1 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
132
                pi2 = (s->buf[stream_ptr++]) & 0x0f;
133
                pi3 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
134
                pi4 = (s->buf[stream_ptr++]) & 0x0f;
135
                pi5 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
136
                pi6 = (s->buf[stream_ptr++]) & 0x0f;
137
                pi7 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
138
                pi8 = (s->buf[stream_ptr++]) & 0x0f;
139

    
140
                CHECK_PIXEL_PTR(rle_code * 8);
141

    
142
                while (rle_code--) {
143
                    rgb[pixel_ptr++] = pi1;
144
                    rgb[pixel_ptr++] = pi2;
145
                    rgb[pixel_ptr++] = pi3;
146
                    rgb[pixel_ptr++] = pi4;
147
                    rgb[pixel_ptr++] = pi5;
148
                    rgb[pixel_ptr++] = pi6;
149
                    rgb[pixel_ptr++] = pi7;
150
                    rgb[pixel_ptr++] = pi8;
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*2);
157

    
158
                while (rle_code--) {
159
                    rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f;
160
                    rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
161
                }
162
            }
163
        }
164
        row_ptr += row_inc;
165
    }
166
}
167

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

    
181
    /* check if this frame is even supposed to change */
182
    if (s->size < 8)
183
        return;
184

    
185
    /* start after the chunk size */
186
    stream_ptr = 4;
187

    
188
    /* fetch the header */
189
    CHECK_STREAM_PTR(2);
190
    header = AV_RB16(&s->buf[stream_ptr]);
191
    stream_ptr += 2;
192

    
193
    /* if a header is present, fetch additional decoding parameters */
194
    if (header & 0x0008) {
195
        CHECK_STREAM_PTR(8);
196
        start_line = AV_RB16(&s->buf[stream_ptr]);
197
        stream_ptr += 4;
198
        lines_to_change = AV_RB16(&s->buf[stream_ptr]);
199
        stream_ptr += 4;
200
    } else {
201
        start_line = 0;
202
        lines_to_change = s->avctx->height;
203
    }
204

    
205
    row_ptr = row_inc * start_line;
206
    while (lines_to_change--) {
207
        CHECK_STREAM_PTR(2);
208
        pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
209

    
210
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
211
            if (rle_code == 0) {
212
                /* there's another skip code in the stream */
213
                CHECK_STREAM_PTR(1);
214
                pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
215
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
216
            } else if (rle_code < 0) {
217
                /* decode the run length code */
218
                rle_code = -rle_code;
219
                /* get the next 4 bytes from the stream, treat them as palette
220
                 * indices, and output them rle_code times */
221
                CHECK_STREAM_PTR(4);
222
                pi1 = s->buf[stream_ptr++];
223
                pi2 = s->buf[stream_ptr++];
224
                pi3 = s->buf[stream_ptr++];
225
                pi4 = s->buf[stream_ptr++];
226

    
227
                CHECK_PIXEL_PTR(rle_code * 4);
228

    
229
                while (rle_code--) {
230
                    rgb[pixel_ptr++] = pi1;
231
                    rgb[pixel_ptr++] = pi2;
232
                    rgb[pixel_ptr++] = pi3;
233
                    rgb[pixel_ptr++] = pi4;
234
                }
235
            } else {
236
                /* copy the same pixel directly to output 4 times */
237
                rle_code *= 4;
238
                CHECK_STREAM_PTR(rle_code);
239
                CHECK_PIXEL_PTR(rle_code);
240

    
241
                while (rle_code--) {
242
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
243
                }
244
            }
245
        }
246
        row_ptr += row_inc;
247
    }
248
}
249

    
250
static void qtrle_decode_16bpp(QtrleContext *s)
251
{
252
    int stream_ptr;
253
    int header;
254
    int start_line;
255
    int lines_to_change;
256
    int rle_code;
257
    int row_ptr, pixel_ptr;
258
    int row_inc = s->frame.linesize[0];
259
    unsigned short rgb16;
260
    unsigned char *rgb = s->frame.data[0];
261
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
262

    
263
    /* check if this frame is even supposed to change */
264
    if (s->size < 8)
265
        return;
266

    
267
    /* start after the chunk size */
268
    stream_ptr = 4;
269

    
270
    /* fetch the header */
271
    CHECK_STREAM_PTR(2);
272
    header = AV_RB16(&s->buf[stream_ptr]);
273
    stream_ptr += 2;
274

    
275
    /* if a header is present, fetch additional decoding parameters */
276
    if (header & 0x0008) {
277
        CHECK_STREAM_PTR(8);
278
        start_line = AV_RB16(&s->buf[stream_ptr]);
279
        stream_ptr += 4;
280
        lines_to_change = AV_RB16(&s->buf[stream_ptr]);
281
        stream_ptr += 4;
282
    } else {
283
        start_line = 0;
284
        lines_to_change = s->avctx->height;
285
    }
286

    
287
    row_ptr = row_inc * start_line;
288
    while (lines_to_change--) {
289
        CHECK_STREAM_PTR(2);
290
        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
291

    
292
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
293
            if (rle_code == 0) {
294
                /* there's another skip code in the stream */
295
                CHECK_STREAM_PTR(1);
296
                pixel_ptr += (s->buf[stream_ptr++] - 1) * 2;
297
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
298
            } else if (rle_code < 0) {
299
                /* decode the run length code */
300
                rle_code = -rle_code;
301
                CHECK_STREAM_PTR(2);
302
                rgb16 = AV_RB16(&s->buf[stream_ptr]);
303
                stream_ptr += 2;
304

    
305
                CHECK_PIXEL_PTR(rle_code * 2);
306

    
307
                while (rle_code--) {
308
                    *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
309
                    pixel_ptr += 2;
310
                }
311
            } else {
312
                CHECK_STREAM_PTR(rle_code * 2);
313
                CHECK_PIXEL_PTR(rle_code * 2);
314

    
315
                /* copy pixels directly to output */
316
                while (rle_code--) {
317
                    rgb16 = AV_RB16(&s->buf[stream_ptr]);
318
                    stream_ptr += 2;
319
                    *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
320
                    pixel_ptr += 2;
321
                }
322
            }
323
        }
324
        row_ptr += row_inc;
325
    }
326
}
327

    
328
static void qtrle_decode_24bpp(QtrleContext *s)
329
{
330
    int stream_ptr;
331
    int header;
332
    int start_line;
333
    int lines_to_change;
334
    int rle_code;
335
    int row_ptr, pixel_ptr;
336
    int row_inc = s->frame.linesize[0];
337
    unsigned char r, g, b;
338
    unsigned char *rgb = s->frame.data[0];
339
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
340

    
341
    /* check if this frame is even supposed to change */
342
    if (s->size < 8)
343
        return;
344

    
345
    /* start after the chunk size */
346
    stream_ptr = 4;
347

    
348
    /* fetch the header */
349
    CHECK_STREAM_PTR(2);
350
    header = AV_RB16(&s->buf[stream_ptr]);
351
    stream_ptr += 2;
352

    
353
    /* if a header is present, fetch additional decoding parameters */
354
    if (header & 0x0008) {
355
        CHECK_STREAM_PTR(8);
356
        start_line = AV_RB16(&s->buf[stream_ptr]);
357
        stream_ptr += 4;
358
        lines_to_change = AV_RB16(&s->buf[stream_ptr]);
359
        stream_ptr += 4;
360
    } else {
361
        start_line = 0;
362
        lines_to_change = s->avctx->height;
363
    }
364

    
365
    row_ptr = row_inc * start_line;
366
    while (lines_to_change--) {
367
        CHECK_STREAM_PTR(2);
368
        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
369

    
370
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
371
            if (rle_code == 0) {
372
                /* there's another skip code in the stream */
373
                CHECK_STREAM_PTR(1);
374
                pixel_ptr += (s->buf[stream_ptr++] - 1) * 3;
375
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
376
            } else if (rle_code < 0) {
377
                /* decode the run length code */
378
                rle_code = -rle_code;
379
                CHECK_STREAM_PTR(3);
380
                r = s->buf[stream_ptr++];
381
                g = s->buf[stream_ptr++];
382
                b = s->buf[stream_ptr++];
383

    
384
                CHECK_PIXEL_PTR(rle_code * 3);
385

    
386
                while (rle_code--) {
387
                    rgb[pixel_ptr++] = r;
388
                    rgb[pixel_ptr++] = g;
389
                    rgb[pixel_ptr++] = b;
390
                }
391
            } else {
392
                CHECK_STREAM_PTR(rle_code * 3);
393
                CHECK_PIXEL_PTR(rle_code * 3);
394

    
395
                /* copy pixels directly to output */
396
                while (rle_code--) {
397
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
398
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
399
                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
400
                }
401
            }
402
        }
403
        row_ptr += row_inc;
404
    }
405
}
406

    
407
static void qtrle_decode_32bpp(QtrleContext *s)
408
{
409
    int stream_ptr;
410
    int header;
411
    int start_line;
412
    int lines_to_change;
413
    int rle_code;
414
    int row_ptr, pixel_ptr;
415
    int row_inc = s->frame.linesize[0];
416
    unsigned char a, r, g, b;
417
    unsigned int argb;
418
    unsigned char *rgb = s->frame.data[0];
419
    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
420

    
421
    /* check if this frame is even supposed to change */
422
    if (s->size < 8)
423
        return;
424

    
425
    /* start after the chunk size */
426
    stream_ptr = 4;
427

    
428
    /* fetch the header */
429
    CHECK_STREAM_PTR(2);
430
    header = AV_RB16(&s->buf[stream_ptr]);
431
    stream_ptr += 2;
432

    
433
    /* if a header is present, fetch additional decoding parameters */
434
    if (header & 0x0008) {
435
        CHECK_STREAM_PTR(8);
436
        start_line = AV_RB16(&s->buf[stream_ptr]);
437
        stream_ptr += 4;
438
        lines_to_change = AV_RB16(&s->buf[stream_ptr]);
439
        stream_ptr += 4;
440
    } else {
441
        start_line = 0;
442
        lines_to_change = s->avctx->height;
443
    }
444

    
445
    row_ptr = row_inc * start_line;
446
    while (lines_to_change--) {
447
        CHECK_STREAM_PTR(2);
448
        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
449

    
450
        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
451
            if (rle_code == 0) {
452
                /* there's another skip code in the stream */
453
                CHECK_STREAM_PTR(1);
454
                pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
455
                CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
456
            } else if (rle_code < 0) {
457
                /* decode the run length code */
458
                rle_code = -rle_code;
459
                CHECK_STREAM_PTR(4);
460
                a = s->buf[stream_ptr++];
461
                r = s->buf[stream_ptr++];
462
                g = s->buf[stream_ptr++];
463
                b = s->buf[stream_ptr++];
464
                argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
465

    
466
                CHECK_PIXEL_PTR(rle_code * 4);
467

    
468
                while (rle_code--) {
469
                    *(unsigned int *)(&rgb[pixel_ptr]) = argb;
470
                    pixel_ptr += 4;
471
                }
472
            } else {
473
                CHECK_STREAM_PTR(rle_code * 4);
474
                CHECK_PIXEL_PTR(rle_code * 4);
475

    
476
                /* copy pixels directly to output */
477
                while (rle_code--) {
478
                    a = s->buf[stream_ptr++];
479
                    r = s->buf[stream_ptr++];
480
                    g = s->buf[stream_ptr++];
481
                    b = s->buf[stream_ptr++];
482
                    argb = (a << 24) | (r << 16) | (g << 8) | (b << 0);
483
                    *(unsigned int *)(&rgb[pixel_ptr]) = argb;
484
                    pixel_ptr += 4;
485
                }
486
            }
487
        }
488
        row_ptr += row_inc;
489
    }
490
}
491

    
492
static int qtrle_decode_init(AVCodecContext *avctx)
493
{
494
    QtrleContext *s = avctx->priv_data;
495

    
496
    s->avctx = avctx;
497
    switch (avctx->bits_per_sample) {
498
    case 1:
499
    case 2:
500
    case 4:
501
    case 8:
502
    case 33:
503
    case 34:
504
    case 36:
505
    case 40:
506
        avctx->pix_fmt = PIX_FMT_PAL8;
507
        break;
508

    
509
    case 16:
510
        avctx->pix_fmt = PIX_FMT_RGB555;
511
        break;
512

    
513
    case 24:
514
        avctx->pix_fmt = PIX_FMT_RGB24;
515
        break;
516

    
517
    case 32:
518
        avctx->pix_fmt = PIX_FMT_RGB32;
519
        break;
520

    
521
    default:
522
        av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
523
            avctx->bits_per_sample);
524
        break;
525
    }
526
    dsputil_init(&s->dsp, avctx);
527

    
528
    s->frame.data[0] = NULL;
529

    
530
    return 0;
531
}
532

    
533
static int qtrle_decode_frame(AVCodecContext *avctx,
534
                              void *data, int *data_size,
535
                              uint8_t *buf, int buf_size)
536
{
537
    QtrleContext *s = avctx->priv_data;
538

    
539
    s->buf = buf;
540
    s->size = buf_size;
541

    
542
    s->frame.reference = 1;
543
    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
544
                            FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
545
    if (avctx->reget_buffer(avctx, &s->frame)) {
546
        av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
547
        return -1;
548
    }
549

    
550
    switch (avctx->bits_per_sample) {
551
    case 1:
552
    case 33:
553
        qtrle_decode_1bpp(s);
554
        break;
555

    
556
    case 2:
557
    case 34:
558
        qtrle_decode_2bpp(s);
559
        break;
560

    
561
    case 4:
562
    case 36:
563
        qtrle_decode_4bpp(s);
564
        /* make the palette available on the way out */
565
        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
566
        if (s->avctx->palctrl->palette_changed) {
567
            s->frame.palette_has_changed = 1;
568
            s->avctx->palctrl->palette_changed = 0;
569
        }
570
        break;
571

    
572
    case 8:
573
    case 40:
574
        qtrle_decode_8bpp(s);
575
        /* make the palette available on the way out */
576
        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
577
        if (s->avctx->palctrl->palette_changed) {
578
            s->frame.palette_has_changed = 1;
579
            s->avctx->palctrl->palette_changed = 0;
580
        }
581
        break;
582

    
583
    case 16:
584
        qtrle_decode_16bpp(s);
585
        break;
586

    
587
    case 24:
588
        qtrle_decode_24bpp(s);
589
        break;
590

    
591
    case 32:
592
        qtrle_decode_32bpp(s);
593
        break;
594

    
595
    default:
596
        av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
597
            avctx->bits_per_sample);
598
        break;
599
    }
600

    
601
    *data_size = sizeof(AVFrame);
602
    *(AVFrame*)data = s->frame;
603

    
604
    /* always report that the buffer was completely consumed */
605
    return buf_size;
606
}
607

    
608
static int qtrle_decode_end(AVCodecContext *avctx)
609
{
610
    QtrleContext *s = avctx->priv_data;
611

    
612
    if (s->frame.data[0])
613
        avctx->release_buffer(avctx, &s->frame);
614

    
615
    return 0;
616
}
617

    
618
AVCodec qtrle_decoder = {
619
    "qtrle",
620
    CODEC_TYPE_VIDEO,
621
    CODEC_ID_QTRLE,
622
    sizeof(QtrleContext),
623
    qtrle_decode_init,
624
    NULL,
625
    qtrle_decode_end,
626
    qtrle_decode_frame,
627
    CODEC_CAP_DR1,
628
};
629