]> git.sesse.net Git - ffmpeg/blob - libavcodec/qtrle.c
qtrle: fix the topmost line for 1bit
[ffmpeg] / libavcodec / qtrle.c
1 /*
2  * Quicktime Animation (RLE) Video Decoder
3  * Copyright (C) 2004 the ffmpeg project
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
25  * For more information about the QT RLE format, visit:
26  *   http://www.pcisys.net/~melanson/codecs/
27  *
28  * The QT RLE decoder has seven modes of operation:
29  * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
30  * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555
31  * data. 24-bit data is RGB24 and 32-bit data is RGB32.
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "avcodec.h"
39 #include "bytestream.h"
40
41 typedef struct QtrleContext {
42     AVCodecContext *avctx;
43     AVFrame frame;
44
45     GetByteContext g;
46     uint32_t pal[256];
47 } QtrleContext;
48
49 #define CHECK_PIXEL_PTR(n) \
50   if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \
51     av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr = %d, pixel_limit = %d\n", \
52       pixel_ptr + n, pixel_limit); \
53     return; \
54   } \
55
56 static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change)
57 {
58     int rle_code;
59     int pixel_ptr;
60     int row_inc = s->frame.linesize[0];
61     unsigned char pi0, pi1;  /* 2 8-pixel values */
62     unsigned char *rgb = s->frame.data[0];
63     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
64     int skip;
65
66     row_ptr  -= row_inc;
67     pixel_ptr = row_ptr;
68     lines_to_change++;
69     while (lines_to_change) {
70         skip     =              bytestream2_get_byte(&s->g);
71         rle_code = (signed char)bytestream2_get_byte(&s->g);
72         if (rle_code == 0)
73             break;
74         if(skip & 0x80) {
75             lines_to_change--;
76             row_ptr += row_inc;
77             pixel_ptr = row_ptr + 2 * (skip & 0x7f);
78         } else
79             pixel_ptr += 2 * skip;
80         CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
81
82         if (rle_code < 0) {
83             /* decode the run length code */
84             rle_code = -rle_code;
85             /* get the next 2 bytes from the stream, treat them as groups
86              * of 8 pixels, and output them rle_code times */
87
88             pi0 = bytestream2_get_byte(&s->g);
89             pi1 = bytestream2_get_byte(&s->g);
90             CHECK_PIXEL_PTR(rle_code * 2);
91
92             while (rle_code--) {
93                 rgb[pixel_ptr++] = pi0;
94                 rgb[pixel_ptr++] = pi1;
95             }
96         } else {
97             /* copy the same pixel directly to output 2 times */
98             rle_code *= 2;
99             CHECK_PIXEL_PTR(rle_code);
100
101             while (rle_code--)
102                 rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
103         }
104     }
105 }
106
107 static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr,
108                                        int lines_to_change, int bpp)
109 {
110     int rle_code, i;
111     int pixel_ptr;
112     int row_inc = s->frame.linesize[0];
113     unsigned char pi[16];  /* 16 palette indices */
114     unsigned char *rgb = s->frame.data[0];
115     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
116     int num_pixels = (bpp == 4) ? 8 : 16;
117
118     while (lines_to_change--) {
119         pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1));
120
121         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
122             if (rle_code == 0) {
123                 /* there's another skip code in the stream */
124                 pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1));
125                 CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
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                  * indexes, and output them rle_code times */
131                 for (i = num_pixels-1; i >= 0; i--) {
132                     pi[num_pixels-1-i] = (bytestream2_peek_byte(&s->g) >> ((i*bpp) & 0x07)) & ((1<<bpp)-1);
133                     bytestream2_skip(&s->g, ((i & ((num_pixels>>2)-1)) == 0));
134                 }
135                 CHECK_PIXEL_PTR(rle_code * num_pixels);
136                 while (rle_code--) {
137                     for (i = 0; i < num_pixels; i++)
138                         rgb[pixel_ptr++] = pi[i];
139                 }
140             } else {
141                 /* copy the same pixel directly to output 4 times */
142                 rle_code *= 4;
143                 CHECK_PIXEL_PTR(rle_code*(num_pixels>>2));
144                 while (rle_code--) {
145                     if(bpp == 4) {
146                         int x = bytestream2_get_byte(&s->g);
147                         rgb[pixel_ptr++] = (x >> 4) & 0x0f;
148                         rgb[pixel_ptr++] =  x       & 0x0f;
149                     } else {
150                         int x = bytestream2_get_byte(&s->g);
151                         rgb[pixel_ptr++] = (x >> 6) & 0x03;
152                         rgb[pixel_ptr++] = (x >> 4) & 0x03;
153                         rgb[pixel_ptr++] = (x >> 2) & 0x03;
154                         rgb[pixel_ptr++] =  x       & 0x03;
155                     }
156                 }
157             }
158         }
159         row_ptr += row_inc;
160     }
161 }
162
163 static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change)
164 {
165     int rle_code;
166     int pixel_ptr;
167     int row_inc = s->frame.linesize[0];
168     unsigned char pi1, pi2, pi3, pi4;  /* 4 palette indexes */
169     unsigned char *rgb = s->frame.data[0];
170     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
171
172     while (lines_to_change--) {
173         pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1));
174
175         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
176             if (rle_code == 0) {
177                 /* there's another skip code in the stream */
178                 pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1));
179                 CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
180             } else if (rle_code < 0) {
181                 /* decode the run length code */
182                 rle_code = -rle_code;
183                 /* get the next 4 bytes from the stream, treat them as palette
184                  * indexes, and output them rle_code times */
185                 pi1 = bytestream2_get_byte(&s->g);
186                 pi2 = bytestream2_get_byte(&s->g);
187                 pi3 = bytestream2_get_byte(&s->g);
188                 pi4 = bytestream2_get_byte(&s->g);
189
190                 CHECK_PIXEL_PTR(rle_code * 4);
191
192                 while (rle_code--) {
193                     rgb[pixel_ptr++] = pi1;
194                     rgb[pixel_ptr++] = pi2;
195                     rgb[pixel_ptr++] = pi3;
196                     rgb[pixel_ptr++] = pi4;
197                 }
198             } else {
199                 /* copy the same pixel directly to output 4 times */
200                 rle_code *= 4;
201                 CHECK_PIXEL_PTR(rle_code);
202
203                 while (rle_code--) {
204                     rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
205                 }
206             }
207         }
208         row_ptr += row_inc;
209     }
210 }
211
212 static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change)
213 {
214     int rle_code;
215     int pixel_ptr;
216     int row_inc = s->frame.linesize[0];
217     unsigned short rgb16;
218     unsigned char *rgb = s->frame.data[0];
219     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
220
221     while (lines_to_change--) {
222         pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2;
223
224         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
225             if (rle_code == 0) {
226                 /* there's another skip code in the stream */
227                 pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2;
228                 CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
229             } else if (rle_code < 0) {
230                 /* decode the run length code */
231                 rle_code = -rle_code;
232                 rgb16 = bytestream2_get_be16(&s->g);
233
234                 CHECK_PIXEL_PTR(rle_code * 2);
235
236                 while (rle_code--) {
237                     *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
238                     pixel_ptr += 2;
239                 }
240             } else {
241                 CHECK_PIXEL_PTR(rle_code * 2);
242
243                 /* copy pixels directly to output */
244                 while (rle_code--) {
245                     rgb16 = bytestream2_get_be16(&s->g);
246                     *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
247                     pixel_ptr += 2;
248                 }
249             }
250         }
251         row_ptr += row_inc;
252     }
253 }
254
255 static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change)
256 {
257     int rle_code;
258     int pixel_ptr;
259     int row_inc = s->frame.linesize[0];
260     unsigned char r, g, b;
261     unsigned char *rgb = s->frame.data[0];
262     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
263
264     while (lines_to_change--) {
265         pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3;
266
267         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
268             if (rle_code == 0) {
269                 /* there's another skip code in the stream */
270                 pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3;
271                 CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
272             } else if (rle_code < 0) {
273                 /* decode the run length code */
274                 rle_code = -rle_code;
275                 r = bytestream2_get_byte(&s->g);
276                 g = bytestream2_get_byte(&s->g);
277                 b = bytestream2_get_byte(&s->g);
278
279                 CHECK_PIXEL_PTR(rle_code * 3);
280
281                 while (rle_code--) {
282                     rgb[pixel_ptr++] = r;
283                     rgb[pixel_ptr++] = g;
284                     rgb[pixel_ptr++] = b;
285                 }
286             } else {
287                 CHECK_PIXEL_PTR(rle_code * 3);
288
289                 /* copy pixels directly to output */
290                 while (rle_code--) {
291                     rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
292                     rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
293                     rgb[pixel_ptr++] = bytestream2_get_byte(&s->g);
294                 }
295             }
296         }
297         row_ptr += row_inc;
298     }
299 }
300
301 static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change)
302 {
303     int rle_code;
304     int pixel_ptr;
305     int row_inc = s->frame.linesize[0];
306     unsigned int argb;
307     unsigned char *rgb = s->frame.data[0];
308     int pixel_limit = s->frame.linesize[0] * s->avctx->height;
309
310     while (lines_to_change--) {
311         pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4;
312
313         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
314             if (rle_code == 0) {
315                 /* there's another skip code in the stream */
316                 pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4;
317                 CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
318             } else if (rle_code < 0) {
319                 /* decode the run length code */
320                 rle_code = -rle_code;
321                 argb = bytestream2_get_be32(&s->g);
322
323                 CHECK_PIXEL_PTR(rle_code * 4);
324
325                 while (rle_code--) {
326                     AV_WN32A(rgb + pixel_ptr, argb);
327                     pixel_ptr += 4;
328                 }
329             } else {
330                 CHECK_PIXEL_PTR(rle_code * 4);
331
332                 /* copy pixels directly to output */
333                 while (rle_code--) {
334                     argb = bytestream2_get_be32(&s->g);
335                     AV_WN32A(rgb + pixel_ptr, argb);
336                     pixel_ptr  += 4;
337                 }
338             }
339         }
340         row_ptr += row_inc;
341     }
342 }
343
344 static av_cold int qtrle_decode_init(AVCodecContext *avctx)
345 {
346     QtrleContext *s = avctx->priv_data;
347
348     s->avctx = avctx;
349     switch (avctx->bits_per_coded_sample) {
350     case 1:
351     case 33:
352         avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
353         break;
354
355     case 2:
356     case 4:
357     case 8:
358     case 34:
359     case 36:
360     case 40:
361         avctx->pix_fmt = AV_PIX_FMT_PAL8;
362         break;
363
364     case 16:
365         avctx->pix_fmt = AV_PIX_FMT_RGB555;
366         break;
367
368     case 24:
369         avctx->pix_fmt = AV_PIX_FMT_RGB24;
370         break;
371
372     case 32:
373         avctx->pix_fmt = AV_PIX_FMT_RGB32;
374         break;
375
376     default:
377         av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
378             avctx->bits_per_coded_sample);
379         return AVERROR_INVALIDDATA;
380     }
381
382     s->frame.data[0] = NULL;
383
384     return 0;
385 }
386
387 static int qtrle_decode_frame(AVCodecContext *avctx,
388                               void *data, int *got_frame,
389                               AVPacket *avpkt)
390 {
391     QtrleContext *s = avctx->priv_data;
392     int header, start_line;
393     int height, row_ptr;
394     int has_palette = 0;
395     int ret;
396
397     bytestream2_init(&s->g, avpkt->data, avpkt->size);
398     s->frame.reference = 1;
399     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
400                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
401     if ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
402         av_log (s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
403         return ret;
404     }
405
406     /* check if this frame is even supposed to change */
407     if (avpkt->size < 8)
408         goto done;
409
410     /* start after the chunk size */
411     bytestream2_seek(&s->g, 4, SEEK_SET);
412
413     /* fetch the header */
414     header = bytestream2_get_be16(&s->g);
415
416     /* if a header is present, fetch additional decoding parameters */
417     if (header & 0x0008) {
418         if (avpkt->size < 14)
419             goto done;
420         start_line = bytestream2_get_be16(&s->g);
421         bytestream2_skip(&s->g, 2);
422         height     = bytestream2_get_be16(&s->g);
423         bytestream2_skip(&s->g, 2);
424     } else {
425         start_line = 0;
426         height     = s->avctx->height;
427     }
428     row_ptr = s->frame.linesize[0] * start_line;
429
430     switch (avctx->bits_per_coded_sample) {
431     case 1:
432     case 33:
433         qtrle_decode_1bpp(s, row_ptr, height);
434         break;
435
436     case 2:
437     case 34:
438         qtrle_decode_2n4bpp(s, row_ptr, height, 2);
439         has_palette = 1;
440         break;
441
442     case 4:
443     case 36:
444         qtrle_decode_2n4bpp(s, row_ptr, height, 4);
445         has_palette = 1;
446         break;
447
448     case 8:
449     case 40:
450         qtrle_decode_8bpp(s, row_ptr, height);
451         has_palette = 1;
452         break;
453
454     case 16:
455         qtrle_decode_16bpp(s, row_ptr, height);
456         break;
457
458     case 24:
459         qtrle_decode_24bpp(s, row_ptr, height);
460         break;
461
462     case 32:
463         qtrle_decode_32bpp(s, row_ptr, height);
464         break;
465
466     default:
467         av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n",
468             avctx->bits_per_coded_sample);
469         break;
470     }
471
472     if(has_palette) {
473         const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
474
475         if (pal) {
476             s->frame.palette_has_changed = 1;
477             memcpy(s->pal, pal, AVPALETTE_SIZE);
478         }
479
480         /* make the palette available on the way out */
481         memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
482     }
483
484 done:
485     *got_frame      = 1;
486     *(AVFrame*)data = s->frame;
487
488     /* always report that the buffer was completely consumed */
489     return avpkt->size;
490 }
491
492 static av_cold int qtrle_decode_end(AVCodecContext *avctx)
493 {
494     QtrleContext *s = avctx->priv_data;
495
496     if (s->frame.data[0])
497         avctx->release_buffer(avctx, &s->frame);
498
499     return 0;
500 }
501
502 AVCodec ff_qtrle_decoder = {
503     .name           = "qtrle",
504     .type           = AVMEDIA_TYPE_VIDEO,
505     .id             = AV_CODEC_ID_QTRLE,
506     .priv_data_size = sizeof(QtrleContext),
507     .init           = qtrle_decode_init,
508     .close          = qtrle_decode_end,
509     .decode         = qtrle_decode_frame,
510     .capabilities   = CODEC_CAP_DR1,
511     .long_name      = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
512 };