]> git.sesse.net Git - ffmpeg/blob - libavcodec/qtrle.c
support skiped blocks in SVQ1
[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 }
78
79 static void qtrle_decode_8bpp(QtrleContext *s)
80 {
81     int stream_ptr;
82     int header;
83     int start_line;
84     int lines_to_change;
85     int rle_code;
86     int row_ptr, pixel_ptr;
87     int row_inc = s->frame.linesize[0];
88     unsigned char pi1, pi2, pi3, pi4;  /* 4 palette indices */
89     unsigned char *rgb = s->frame.data[0];
90     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
91
92     /* check if this frame is even supposed to change */
93     if (s->size < 8)
94         return;
95
96     /* start after the chunk size */
97     stream_ptr = 4;
98
99     /* fetch the header */
100     CHECK_STREAM_PTR(2);
101     header = BE_16(&s->buf[stream_ptr]);
102     stream_ptr += 2;
103
104     /* if a header is present, fetch additional decoding parameters */
105     if (header & 0x0008) {
106         CHECK_STREAM_PTR(8);
107         start_line = BE_16(&s->buf[stream_ptr]);
108         stream_ptr += 4;
109         lines_to_change = BE_16(&s->buf[stream_ptr]);
110         stream_ptr += 4;
111     } else {
112         start_line = 0;
113         lines_to_change = s->avctx->height;
114     }
115
116     row_ptr = row_inc * start_line;
117     while (lines_to_change--) {
118         CHECK_STREAM_PTR(2);
119         pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
120
121         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
122             if (rle_code == 0) {
123                 /* there's another skip code in the stream */
124                 CHECK_STREAM_PTR(1);
125                 pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
126             } else if (rle_code < 0) {
127                 /* decode the run length code */
128                 rle_code = -rle_code;
129                 /* get the next 4 bytes from the stream, treat them as palette
130                  * indices, and output them rle_code times */
131                 CHECK_STREAM_PTR(4);
132                 pi1 = s->buf[stream_ptr++];
133                 pi2 = s->buf[stream_ptr++];
134                 pi3 = s->buf[stream_ptr++];
135                 pi4 = s->buf[stream_ptr++];
136
137                 CHECK_PIXEL_PTR(rle_code * 4);
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                 }
145             } else {
146                 /* copy the same pixel directly to output 4 times */
147                 rle_code *= 4;
148                 CHECK_STREAM_PTR(rle_code);
149                 CHECK_PIXEL_PTR(rle_code);
150
151                 while (rle_code--) {
152                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
153                 }
154             }
155         }
156         row_ptr += row_inc;
157     }
158 }
159
160 static void qtrle_decode_16bpp(QtrleContext *s)
161 {
162     int stream_ptr;
163     int header;
164     int start_line;
165     int lines_to_change;
166     signed char rle_code;
167     int row_ptr, pixel_ptr;
168     int row_inc = s->frame.linesize[0];
169     unsigned short rgb16;
170     unsigned char *rgb = s->frame.data[0];
171     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
172
173     /* check if this frame is even supposed to change */
174     if (s->size < 8)
175         return;
176
177     /* start after the chunk size */
178     stream_ptr = 4;
179
180     /* fetch the header */
181     CHECK_STREAM_PTR(2);
182     header = BE_16(&s->buf[stream_ptr]);
183     stream_ptr += 2;
184
185     /* if a header is present, fetch additional decoding parameters */
186     if (header & 0x0008) {
187         CHECK_STREAM_PTR(8);
188         start_line = BE_16(&s->buf[stream_ptr]);
189         stream_ptr += 4;
190         lines_to_change = BE_16(&s->buf[stream_ptr]);
191         stream_ptr += 4;
192     } else {
193         start_line = 0;
194         lines_to_change = s->avctx->height;
195     }
196
197     row_ptr = row_inc * start_line;
198     while (lines_to_change--) {
199         CHECK_STREAM_PTR(2);
200         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
201
202         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
203             if (rle_code == 0) {
204                 /* there's another skip code in the stream */
205                 CHECK_STREAM_PTR(1);
206                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 2;
207             } else if (rle_code < 0) {
208                 /* decode the run length code */
209                 rle_code = -rle_code;
210                 CHECK_STREAM_PTR(2);
211                 rgb16 = BE_16(&s->buf[stream_ptr]);
212                 stream_ptr += 2;
213
214                 CHECK_PIXEL_PTR(rle_code * 2);
215
216                 while (rle_code--) {
217                     *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
218                     pixel_ptr += 2;
219                 }
220             } else {
221                 CHECK_STREAM_PTR(rle_code * 2);
222                 CHECK_PIXEL_PTR(rle_code * 2);
223
224                 /* copy pixels directly to output */
225                 while (rle_code--) {
226                     rgb16 = BE_16(&s->buf[stream_ptr]);
227                     stream_ptr += 2;
228                     *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
229                     pixel_ptr += 2;
230                 }
231             }
232         }
233         row_ptr += row_inc;
234     }
235 }
236
237 static void qtrle_decode_24bpp(QtrleContext *s)
238 {
239     int stream_ptr;
240     int header;
241     int start_line;
242     int lines_to_change;
243     signed char rle_code;
244     int row_ptr, pixel_ptr;
245     int row_inc = s->frame.linesize[0];
246     unsigned char r, g, b;
247     unsigned char *rgb = s->frame.data[0];
248     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
249
250     /* check if this frame is even supposed to change */
251     if (s->size < 8)
252         return;
253
254     /* start after the chunk size */
255     stream_ptr = 4;
256
257     /* fetch the header */
258     CHECK_STREAM_PTR(2);
259     header = BE_16(&s->buf[stream_ptr]);
260     stream_ptr += 2;
261
262     /* if a header is present, fetch additional decoding parameters */
263     if (header & 0x0008) {
264         CHECK_STREAM_PTR(8);
265         start_line = BE_16(&s->buf[stream_ptr]);
266         stream_ptr += 4;
267         lines_to_change = BE_16(&s->buf[stream_ptr]);
268         stream_ptr += 4;
269     } else {
270         start_line = 0;
271         lines_to_change = s->avctx->height;
272     }
273
274     row_ptr = row_inc * start_line;
275     while (lines_to_change--) {
276         CHECK_STREAM_PTR(2);
277         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
278
279         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
280             if (rle_code == 0) {
281                 /* there's another skip code in the stream */
282                 CHECK_STREAM_PTR(1);
283                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 3;
284             } else if (rle_code < 0) {
285                 /* decode the run length code */
286                 rle_code = -rle_code;
287                 CHECK_STREAM_PTR(3);
288                 r = s->buf[stream_ptr++];
289                 g = s->buf[stream_ptr++];
290                 b = s->buf[stream_ptr++];
291
292                 CHECK_PIXEL_PTR(rle_code * 3);
293
294                 while (rle_code--) {
295                     rgb[pixel_ptr++] = r;
296                     rgb[pixel_ptr++] = g;
297                     rgb[pixel_ptr++] = b;
298                 }
299             } else {
300                 CHECK_STREAM_PTR(rle_code * 3);
301                 CHECK_PIXEL_PTR(rle_code * 3);
302
303                 /* copy pixels directly to output */
304                 while (rle_code--) {
305                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
306                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
307                     rgb[pixel_ptr++] = s->buf[stream_ptr++];
308                 }
309             }
310         }
311         row_ptr += row_inc;
312     }
313 }
314
315 static void qtrle_decode_32bpp(QtrleContext *s)
316 {
317     int stream_ptr;
318     int header;
319     int start_line;
320     int lines_to_change;
321     signed char rle_code;
322     int row_ptr, pixel_ptr;
323     int row_inc = s->frame.linesize[0];
324     unsigned char r, g, b;
325     unsigned int argb;
326     unsigned char *rgb = s->frame.data[0];
327     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
328
329     /* check if this frame is even supposed to change */
330     if (s->size < 8)
331         return;
332
333     /* start after the chunk size */
334     stream_ptr = 4;
335
336     /* fetch the header */
337     CHECK_STREAM_PTR(2);
338     header = BE_16(&s->buf[stream_ptr]);
339     stream_ptr += 2;
340
341     /* if a header is present, fetch additional decoding parameters */
342     if (header & 0x0008) {
343         CHECK_STREAM_PTR(8);
344         start_line = BE_16(&s->buf[stream_ptr]);
345         stream_ptr += 4;
346         lines_to_change = BE_16(&s->buf[stream_ptr]);
347         stream_ptr += 4;
348     } else {
349         start_line = 0;
350         lines_to_change = s->avctx->height;
351     }
352
353     row_ptr = row_inc * start_line;
354     while (lines_to_change--) {
355         CHECK_STREAM_PTR(2);
356         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
357
358         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
359             if (rle_code == 0) {
360                 /* there's another skip code in the stream */
361                 CHECK_STREAM_PTR(1);
362                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
363             } else if (rle_code < 0) {
364                 /* decode the run length code */
365                 rle_code = -rle_code;
366                 CHECK_STREAM_PTR(4);
367                 stream_ptr++;  /* skip the alpha (?) byte */
368                 r = s->buf[stream_ptr++];
369                 g = s->buf[stream_ptr++];
370                 b = s->buf[stream_ptr++];
371                 argb = (r << 16) | (g << 8) | (b << 0);
372
373                 CHECK_PIXEL_PTR(rle_code * 4);
374
375                 while (rle_code--) {
376                     *(unsigned int *)(&rgb[pixel_ptr]) = argb;
377                     pixel_ptr += 4;
378                 }
379             } else {
380                 CHECK_STREAM_PTR(rle_code * 4);
381                 CHECK_PIXEL_PTR(rle_code * 4);
382
383                 /* copy pixels directly to output */
384                 while (rle_code--) {
385                     stream_ptr++;  /* skip the alpha (?) byte */
386                     r = s->buf[stream_ptr++];
387                     g = s->buf[stream_ptr++];
388                     b = s->buf[stream_ptr++];
389                     argb = (r << 16) | (g << 8) | (b << 0);
390                     *(unsigned int *)(&rgb[pixel_ptr]) = argb;
391                     pixel_ptr += 4;
392                 }
393             }
394         }
395         row_ptr += row_inc;
396     }
397 }
398
399 static int qtrle_decode_init(AVCodecContext *avctx)
400 {
401     QtrleContext *s = (QtrleContext *)avctx->priv_data;
402
403     s->avctx = avctx;
404     switch (avctx->bits_per_sample) {
405     case 1:
406     case 2:
407     case 4:
408     case 8:
409     case 33:
410     case 34:
411     case 36:
412     case 40:
413         avctx->pix_fmt = PIX_FMT_PAL8;
414         break;
415
416     case 16:
417         avctx->pix_fmt = PIX_FMT_RGB555;
418         break;
419
420     case 24:
421         avctx->pix_fmt = PIX_FMT_RGB24;
422         break;
423
424     case 32:
425         avctx->pix_fmt = PIX_FMT_RGBA32;
426         break;
427
428     default:
429         av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
430             avctx->bits_per_sample);
431         break;
432     }
433     avctx->has_b_frames = 0;
434     dsputil_init(&s->dsp, avctx);
435
436     s->frame.data[0] = NULL;
437
438     return 0;
439 }
440
441 static int qtrle_decode_frame(AVCodecContext *avctx,
442                               void *data, int *data_size,
443                               uint8_t *buf, int buf_size)
444 {
445     QtrleContext *s = (QtrleContext *)avctx->priv_data;
446
447     /* no supplementary picture */
448     if (buf_size == 0)
449         return 0;
450
451     s->buf = buf;
452     s->size = buf_size;
453
454     s->frame.reference = 1;
455     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
456                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
457     if (avctx->reget_buffer(avctx, &s->frame)) {
458         av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
459         return -1;
460     }
461
462     switch (avctx->bits_per_sample) {
463     case 1:
464     case 33:
465         qtrle_decode_1bpp(s);
466         break;
467
468     case 2:
469     case 34:
470         qtrle_decode_2bpp(s);
471         break;
472
473     case 4:
474     case 36:
475         qtrle_decode_4bpp(s);
476         break;
477
478     case 8:
479     case 40:
480         qtrle_decode_8bpp(s);
481         /* make the palette available on the way out */
482         memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
483         if (s->avctx->palctrl->palette_changed) {
484             s->frame.palette_has_changed = 1;
485             s->avctx->palctrl->palette_changed = 0;
486         }
487         break;
488
489     case 16:
490         qtrle_decode_16bpp(s);
491         break;
492
493     case 24:
494         qtrle_decode_24bpp(s);
495         break;
496
497     case 32:
498         qtrle_decode_32bpp(s);
499         break;
500
501     default:
502         av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
503             avctx->bits_per_sample);
504         break;
505     }
506
507     *data_size = sizeof(AVFrame);
508     *(AVFrame*)data = s->frame;
509
510     /* always report that the buffer was completely consumed */
511     return buf_size;
512 }
513
514 static int qtrle_decode_end(AVCodecContext *avctx)
515 {
516     QtrleContext *s = (QtrleContext *)avctx->priv_data;
517
518     if (s->frame.data[0])
519         avctx->release_buffer(avctx, &s->frame);
520
521     return 0;
522 }
523
524 AVCodec qtrle_decoder = {
525     "qtrle",
526     CODEC_TYPE_VIDEO,
527     CODEC_ID_QTRLE,
528     sizeof(QtrleContext),
529     qtrle_decode_init,
530     NULL,
531     qtrle_decode_end,
532     qtrle_decode_frame,
533     CODEC_CAP_DR1,
534 };
535