]> git.sesse.net Git - ffmpeg/blob - libavcodec/qtrle.c
well that does not need to be there anymore
[ffmpeg] / libavcodec / qtrle.c
1 /*
2  * Quicktime Animation (RLE) Video Decoder
3  * Copyright (C) 2004 the ffmpeg project
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 /**
22  * @file qtrle.c
23  * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
24  * For more information about the QT RLE format, visit:
25  *   http://www.pcisys.net/~melanson/codecs/
26  *
27  * The QT RLE decoder has seven modes of operation:
28  * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
29  * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555
30  * data. 24-bit data is RGB24 and 32-bit data is RGBA32.
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include "common.h"
39 #include "avcodec.h"
40 #include "dsputil.h"
41
42 typedef struct QtrleContext {
43
44     AVCodecContext *avctx;
45     DSPContext dsp;
46     AVFrame frame;
47
48     unsigned char *buf;
49     int size;
50
51 } QtrleContext;
52
53 #define CHECK_STREAM_PTR(n) \
54   if ((stream_ptr + n) > s->size) { \
55     av_log (s->avctx, AV_LOG_INFO, "Problem: stream_ptr out of bounds (%d >= %d)\n", \
56       stream_ptr + n, s->size); \
57     return; \
58   }
59
60 #define CHECK_PIXEL_PTR(n) \
61   if (pixel_ptr + n > pixel_limit) { \
62     av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
63       pixel_ptr + n, pixel_limit); \
64     return; \
65   } \
66
67 static void qtrle_decode_1bpp(QtrleContext *s)
68 {
69 }
70
71 static void qtrle_decode_2bpp(QtrleContext *s)
72 {
73 }
74
75 static void qtrle_decode_4bpp(QtrleContext *s)
76 {
77     int stream_ptr;
78     int header;
79     int start_line;
80     int lines_to_change;
81     int rle_code;
82     int row_ptr, pixel_ptr;
83     int row_inc = s->frame.linesize[0];
84     unsigned char pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8;  /* 8 palette indices */
85     unsigned char *rgb = s->frame.data[0];
86     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
87
88     /* check if this frame is even supposed to change */
89     if (s->size < 8)
90         return;
91
92     /* start after the chunk size */
93     stream_ptr = 4;
94
95     /* fetch the header */
96     CHECK_STREAM_PTR(2);
97     header = BE_16(&s->buf[stream_ptr]);
98     stream_ptr += 2;
99
100     /* if a header is present, fetch additional decoding parameters */
101     if (header & 0x0008) {
102         CHECK_STREAM_PTR(8);
103         start_line = BE_16(&s->buf[stream_ptr]);
104         stream_ptr += 4;
105         lines_to_change = BE_16(&s->buf[stream_ptr]);
106         stream_ptr += 4;
107     } else {
108         start_line = 0;
109         lines_to_change = s->avctx->height;
110     }
111
112     row_ptr = row_inc * start_line;
113     while (lines_to_change--) {
114         CHECK_STREAM_PTR(2);
115         pixel_ptr = row_ptr + (8 * (s->buf[stream_ptr++] - 1));
116
117         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
118             if (rle_code == 0) {
119                 /* there's another skip code in the stream */
120                 CHECK_STREAM_PTR(1);
121                 pixel_ptr += (8 * (s->buf[stream_ptr++] - 1));
122             } else if (rle_code < 0) {
123                 /* decode the run length code */
124                 rle_code = -rle_code;
125                 /* get the next 4 bytes from the stream, treat them as palette
126                  * indices, and output them rle_code times */
127                 CHECK_STREAM_PTR(4);
128                 pi1 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
129                 pi2 = (s->buf[stream_ptr++]) & 0x0f;
130                 pi3 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
131                 pi4 = (s->buf[stream_ptr++]) & 0x0f;
132                 pi5 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
133                 pi6 = (s->buf[stream_ptr++]) & 0x0f;
134                 pi7 = ((s->buf[stream_ptr]) >> 4) & 0x0f;
135                 pi8 = (s->buf[stream_ptr++]) & 0x0f;
136
137                 CHECK_PIXEL_PTR(rle_code * 8);
138
139                 while (rle_code--) {
140                     rgb[pixel_ptr++] = pi1;
141                     rgb[pixel_ptr++] = pi2;
142                     rgb[pixel_ptr++] = pi3;
143                     rgb[pixel_ptr++] = pi4;
144                     rgb[pixel_ptr++] = pi5;
145                     rgb[pixel_ptr++] = pi6;
146                     rgb[pixel_ptr++] = pi7;
147                     rgb[pixel_ptr++] = pi8;
148                 }
149             } else {
150                 /* copy the same pixel directly to output 4 times */
151                 rle_code *= 4;
152                 CHECK_STREAM_PTR(rle_code);
153                 CHECK_PIXEL_PTR(rle_code*2);
154
155                 while (rle_code--) {
156                     rgb[pixel_ptr++] = ((s->buf[stream_ptr]) >> 4) & 0x0f;
157                     rgb[pixel_ptr++] = (s->buf[stream_ptr++]) & 0x0f;
158                 }
159             }
160         }
161         row_ptr += row_inc;
162     }
163 }
164
165 static void qtrle_decode_8bpp(QtrleContext *s)
166 {
167     int stream_ptr;
168     int header;
169     int start_line;
170     int lines_to_change;
171     int rle_code;
172     int row_ptr, pixel_ptr;
173     int row_inc = s->frame.linesize[0];
174     unsigned char pi1, pi2, pi3, pi4;  /* 4 palette indices */
175     unsigned char *rgb = s->frame.data[0];
176     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
177
178     /* check if this frame is even supposed to change */
179     if (s->size < 8)
180         return;
181
182     /* start after the chunk size */
183     stream_ptr = 4;
184
185     /* fetch the header */
186     CHECK_STREAM_PTR(2);
187     header = BE_16(&s->buf[stream_ptr]);
188     stream_ptr += 2;
189
190     /* if a header is present, fetch additional decoding parameters */
191     if (header & 0x0008) {
192         CHECK_STREAM_PTR(8);
193         start_line = BE_16(&s->buf[stream_ptr]);
194         stream_ptr += 4;
195         lines_to_change = BE_16(&s->buf[stream_ptr]);
196         stream_ptr += 4;
197     } else {
198         start_line = 0;
199         lines_to_change = s->avctx->height;
200     }
201
202     row_ptr = row_inc * start_line;
203     while (lines_to_change--) {
204         CHECK_STREAM_PTR(2);
205         pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
206
207         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
208             if (rle_code == 0) {
209                 /* there's another skip code in the stream */
210                 CHECK_STREAM_PTR(1);
211                 pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
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
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     signed char 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 = BE_16(&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 = BE_16(&s->buf[stream_ptr]);
275         stream_ptr += 4;
276         lines_to_change = BE_16(&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             } else if (rle_code < 0) {
294                 /* decode the run length code */
295                 rle_code = -rle_code;
296                 CHECK_STREAM_PTR(2);
297                 rgb16 = BE_16(&s->buf[stream_ptr]);
298                 stream_ptr += 2;
299
300                 CHECK_PIXEL_PTR(rle_code * 2);
301
302                 while (rle_code--) {
303                     *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
304                     pixel_ptr += 2;
305                 }
306             } else {
307                 CHECK_STREAM_PTR(rle_code * 2);
308                 CHECK_PIXEL_PTR(rle_code * 2);
309
310                 /* copy pixels directly to output */
311                 while (rle_code--) {
312                     rgb16 = BE_16(&s->buf[stream_ptr]);
313                     stream_ptr += 2;
314                     *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
315                     pixel_ptr += 2;
316                 }
317             }
318         }
319         row_ptr += row_inc;
320     }
321 }
322
323 static void qtrle_decode_24bpp(QtrleContext *s)
324 {
325     int stream_ptr;
326     int header;
327     int start_line;
328     int lines_to_change;
329     signed char rle_code;
330     int row_ptr, pixel_ptr;
331     int row_inc = s->frame.linesize[0];
332     unsigned char r, g, b;
333     unsigned char *rgb = s->frame.data[0];
334     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
335
336     /* check if this frame is even supposed to change */
337     if (s->size < 8)
338         return;
339
340     /* start after the chunk size */
341     stream_ptr = 4;
342
343     /* fetch the header */
344     CHECK_STREAM_PTR(2);
345     header = BE_16(&s->buf[stream_ptr]);
346     stream_ptr += 2;
347
348     /* if a header is present, fetch additional decoding parameters */
349     if (header & 0x0008) {
350         CHECK_STREAM_PTR(8);
351         start_line = BE_16(&s->buf[stream_ptr]);
352         stream_ptr += 4;
353         lines_to_change = BE_16(&s->buf[stream_ptr]);
354         stream_ptr += 4;
355     } else {
356         start_line = 0;
357         lines_to_change = s->avctx->height;
358     }
359
360     row_ptr = row_inc * start_line;
361     while (lines_to_change--) {
362         CHECK_STREAM_PTR(2);
363         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
364
365         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
366             if (rle_code == 0) {
367                 /* there's another skip code in the stream */
368                 CHECK_STREAM_PTR(1);
369                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 3;
370             } else if (rle_code < 0) {
371                 /* decode the run length code */
372                 rle_code = -rle_code;
373                 CHECK_STREAM_PTR(3);
374                 r = s->buf[stream_ptr++];
375                 g = s->buf[stream_ptr++];
376                 b = s->buf[stream_ptr++];
377
378                 CHECK_PIXEL_PTR(rle_code * 3);
379
380                 while (rle_code--) {
381                     rgb[pixel_ptr++] = r;
382                     rgb[pixel_ptr++] = g;
383                     rgb[pixel_ptr++] = b;
384                 }
385             } else {
386                 CHECK_STREAM_PTR(rle_code * 3);
387                 CHECK_PIXEL_PTR(rle_code * 3);
388
389                 /* copy pixels directly to output */
390                 while (rle_code--) {
391                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
392                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
393                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
394                 }
395             }
396         }
397         row_ptr += row_inc;
398     }
399 }
400
401 static void qtrle_decode_32bpp(QtrleContext *s)
402 {
403     int stream_ptr;
404     int header;
405     int start_line;
406     int lines_to_change;
407     signed char rle_code;
408     int row_ptr, pixel_ptr;
409     int row_inc = s->frame.linesize[0];
410     unsigned char r, g, b;
411     unsigned int argb;
412     unsigned char *rgb = s->frame.data[0];
413     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
414
415     /* check if this frame is even supposed to change */
416     if (s->size < 8)
417         return;
418
419     /* start after the chunk size */
420     stream_ptr = 4;
421
422     /* fetch the header */
423     CHECK_STREAM_PTR(2);
424     header = BE_16(&s->buf[stream_ptr]);
425     stream_ptr += 2;
426
427     /* if a header is present, fetch additional decoding parameters */
428     if (header & 0x0008) {
429         CHECK_STREAM_PTR(8);
430         start_line = BE_16(&s->buf[stream_ptr]);
431         stream_ptr += 4;
432         lines_to_change = BE_16(&s->buf[stream_ptr]);
433         stream_ptr += 4;
434     } else {
435         start_line = 0;
436         lines_to_change = s->avctx->height;
437     }
438
439     row_ptr = row_inc * start_line;
440     while (lines_to_change--) {
441         CHECK_STREAM_PTR(2);
442         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
443
444         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
445             if (rle_code == 0) {
446                 /* there's another skip code in the stream */
447                 CHECK_STREAM_PTR(1);
448                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
449             } else if (rle_code < 0) {
450                 /* decode the run length code */
451                 rle_code = -rle_code;
452                 CHECK_STREAM_PTR(4);
453                 stream_ptr++;  /* skip the alpha (?) byte */
454                 r = s->buf[stream_ptr++];
455                 g = s->buf[stream_ptr++];
456                 b = s->buf[stream_ptr++];
457                 argb = (r << 16) | (g << 8) | (b << 0);
458
459                 CHECK_PIXEL_PTR(rle_code * 4);
460
461                 while (rle_code--) {
462                     *(unsigned int *)(&rgb[pixel_ptr]) = argb;
463                     pixel_ptr += 4;
464                 }
465             } else {
466                 CHECK_STREAM_PTR(rle_code * 4);
467                 CHECK_PIXEL_PTR(rle_code * 4);
468
469                 /* copy pixels directly to output */
470                 while (rle_code--) {
471                     stream_ptr++;  /* skip the alpha (?) byte */
472                     r = s->buf[stream_ptr++];
473                     g = s->buf[stream_ptr++];
474                     b = s->buf[stream_ptr++];
475                     argb = (r << 16) | (g << 8) | (b << 0);
476                     *(unsigned int *)(&rgb[pixel_ptr]) = argb;
477                     pixel_ptr += 4;
478                 }
479             }
480         }
481         row_ptr += row_inc;
482     }
483 }
484
485 static int qtrle_decode_init(AVCodecContext *avctx)
486 {
487     QtrleContext *s = (QtrleContext *)avctx->priv_data;
488
489     s->avctx = avctx;
490     switch (avctx->bits_per_sample) {
491     case 1:
492     case 2:
493     case 4:
494     case 8:
495     case 33:
496     case 34:
497     case 36:
498     case 40:
499         avctx->pix_fmt = PIX_FMT_PAL8;
500         break;
501
502     case 16:
503         avctx->pix_fmt = PIX_FMT_RGB555;
504         break;
505
506     case 24:
507         avctx->pix_fmt = PIX_FMT_RGB24;
508         break;
509
510     case 32:
511         avctx->pix_fmt = PIX_FMT_RGBA32;
512         break;
513
514     default:
515         av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
516             avctx->bits_per_sample);
517         break;
518     }
519     avctx->has_b_frames = 0;
520     dsputil_init(&s->dsp, avctx);
521
522     s->frame.data[0] = NULL;
523
524     return 0;
525 }
526
527 static int qtrle_decode_frame(AVCodecContext *avctx,
528                               void *data, int *data_size,
529                               uint8_t *buf, int buf_size)
530 {
531     QtrleContext *s = (QtrleContext *)avctx->priv_data;
532
533     /* no supplementary picture */
534     if (buf_size == 0)
535         return 0;
536
537     s->buf = buf;
538     s->size = buf_size;
539
540     s->frame.reference = 1;
541     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
542                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
543     if (avctx->reget_buffer(avctx, &s->frame)) {
544         av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
545         return -1;
546     }
547
548     switch (avctx->bits_per_sample) {
549     case 1:
550     case 33:
551         qtrle_decode_1bpp(s);
552         break;
553
554     case 2:
555     case 34:
556         qtrle_decode_2bpp(s);
557         break;
558
559     case 4:
560     case 36:
561         qtrle_decode_4bpp(s);
562         /* make the palette available on the way out */
563         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
564         if (s->avctx->palctrl->palette_changed) {
565             s->frame.palette_has_changed = 1;
566             s->avctx->palctrl->palette_changed = 0;
567         }
568         break;
569
570     case 8:
571     case 40:
572         qtrle_decode_8bpp(s);
573         /* make the palette available on the way out */
574         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
575         if (s->avctx->palctrl->palette_changed) {
576             s->frame.palette_has_changed = 1;
577             s->avctx->palctrl->palette_changed = 0;
578         }
579         break;
580
581     case 16:
582         qtrle_decode_16bpp(s);
583         break;
584
585     case 24:
586         qtrle_decode_24bpp(s);
587         break;
588
589     case 32:
590         qtrle_decode_32bpp(s);
591         break;
592
593     default:
594         av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
595             avctx->bits_per_sample);
596         break;
597     }
598
599     *data_size = sizeof(AVFrame);
600     *(AVFrame*)data = s->frame;
601
602     /* always report that the buffer was completely consumed */
603     return buf_size;
604 }
605
606 static int qtrle_decode_end(AVCodecContext *avctx)
607 {
608     QtrleContext *s = (QtrleContext *)avctx->priv_data;
609
610     if (s->frame.data[0])
611         avctx->release_buffer(avctx, &s->frame);
612
613     return 0;
614 }
615
616 AVCodec qtrle_decoder = {
617     "qtrle",
618     CODEC_TYPE_VIDEO,
619     CODEC_ID_QTRLE,
620     sizeof(QtrleContext),
621     qtrle_decode_init,
622     NULL,
623     qtrle_decode_end,
624     qtrle_decode_frame,
625     CODEC_CAP_DR1,
626 };
627