avoid buf_size == 0 checks in every decoder
[ffmpeg.git] / 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     s->buf = buf;
534     s->size = buf_size;
535
536     s->frame.reference = 1;
537     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
538                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
539     if (avctx->reget_buffer(avctx, &s->frame)) {
540         av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
541         return -1;
542     }
543
544     switch (avctx->bits_per_sample) {
545     case 1:
546     case 33:
547         qtrle_decode_1bpp(s);
548         break;
549
550     case 2:
551     case 34:
552         qtrle_decode_2bpp(s);
553         break;
554
555     case 4:
556     case 36:
557         qtrle_decode_4bpp(s);
558         /* make the palette available on the way out */
559         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
560         if (s->avctx->palctrl->palette_changed) {
561             s->frame.palette_has_changed = 1;
562             s->avctx->palctrl->palette_changed = 0;
563         }
564         break;
565
566     case 8:
567     case 40:
568         qtrle_decode_8bpp(s);
569         /* make the palette available on the way out */
570         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
571         if (s->avctx->palctrl->palette_changed) {
572             s->frame.palette_has_changed = 1;
573             s->avctx->palctrl->palette_changed = 0;
574         }
575         break;
576
577     case 16:
578         qtrle_decode_16bpp(s);
579         break;
580
581     case 24:
582         qtrle_decode_24bpp(s);
583         break;
584
585     case 32:
586         qtrle_decode_32bpp(s);
587         break;
588
589     default:
590         av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
591             avctx->bits_per_sample);
592         break;
593     }
594
595     *data_size = sizeof(AVFrame);
596     *(AVFrame*)data = s->frame;
597
598     /* always report that the buffer was completely consumed */
599     return buf_size;
600 }
601
602 static int qtrle_decode_end(AVCodecContext *avctx)
603 {
604     QtrleContext *s = (QtrleContext *)avctx->priv_data;
605
606     if (s->frame.data[0])
607         avctx->release_buffer(avctx, &s->frame);
608
609     return 0;
610 }
611
612 AVCodec qtrle_decoder = {
613     "qtrle",
614     CODEC_TYPE_VIDEO,
615     CODEC_ID_QTRLE,
616     sizeof(QtrleContext),
617     qtrle_decode_init,
618     NULL,
619     qtrle_decode_end,
620     qtrle_decode_frame,
621     CODEC_CAP_DR1,
622 };
623