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