Statistics
| Branch: | Revision:

ffmpeg / libavcodec / qtrle.c @ 2029f312

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 "avcodec.h"
41
#include "dsputil.h"
42

    
43
typedef struct QtrleContext {
44

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

    
49
    unsigned char *buf;
50
    int size;
51

    
52
} QtrleContext;
53

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

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

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

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

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

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

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

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

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

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

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

    
139
                CHECK_PIXEL_PTR(rle_code * 8);
140

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

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

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

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

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

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

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

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

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

    
226
                CHECK_PIXEL_PTR(rle_code * 4);
227

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

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

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

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

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

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

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

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

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

    
304
                CHECK_PIXEL_PTR(rle_code * 2);
305

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

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

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

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

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

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

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

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

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

    
383
                CHECK_PIXEL_PTR(rle_code * 3);
384

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

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

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

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

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

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

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

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

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

    
465
                CHECK_PIXEL_PTR(rle_code * 4);
466

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

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

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

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

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

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

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

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

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

    
529
    return 0;
530
}
531

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
614
    return 0;
615
}
616

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