OSDN Git Service

avcodec/vp9block: fix runtime error: signed integer overflow: 196675 * 20670 cannot...
[android-x86/external-ffmpeg.git] / libavcodec / smc.c
1 /*
2  * Quicktime Graphics (SMC) Video Decoder
3  * Copyright (C) 2003 The FFmpeg project
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 SMC Video Decoder by Mike Melanson (melanson@pcisys.net)
25  * For more information about the SMC format, visit:
26  *   http://www.pcisys.net/~melanson/codecs/
27  *
28  * The SMC decoder outputs PAL8 colorspace data.
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "libavutil/intreadwrite.h"
36 #include "avcodec.h"
37 #include "bytestream.h"
38 #include "internal.h"
39
40 #define CPAIR 2
41 #define CQUAD 4
42 #define COCTET 8
43
44 #define COLORS_PER_TABLE 256
45
46 typedef struct SmcContext {
47
48     AVCodecContext *avctx;
49     AVFrame *frame;
50
51     GetByteContext gb;
52
53     /* SMC color tables */
54     unsigned char color_pairs[COLORS_PER_TABLE * CPAIR];
55     unsigned char color_quads[COLORS_PER_TABLE * CQUAD];
56     unsigned char color_octets[COLORS_PER_TABLE * COCTET];
57
58     uint32_t pal[256];
59 } SmcContext;
60
61 #define GET_BLOCK_COUNT() \
62   (opcode & 0x10) ? (1 + bytestream2_get_byte(&s->gb)) : 1 + (opcode & 0x0F);
63
64 #define ADVANCE_BLOCK() \
65 { \
66     pixel_ptr += 4; \
67     if (pixel_ptr >= width) \
68     { \
69         pixel_ptr = 0; \
70         row_ptr += stride * 4; \
71     } \
72     total_blocks--; \
73     if (total_blocks < !!n_blocks) \
74     { \
75         av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)\n"); \
76         return; \
77     } \
78 }
79
80 static void smc_decode_stream(SmcContext *s)
81 {
82     int width = s->avctx->width;
83     int height = s->avctx->height;
84     int stride = s->frame->linesize[0];
85     int i;
86     int chunk_size;
87     int buf_size = bytestream2_size(&s->gb);
88     unsigned char opcode;
89     int n_blocks;
90     unsigned int color_flags;
91     unsigned int color_flags_a;
92     unsigned int color_flags_b;
93     unsigned int flag_mask;
94
95     unsigned char * const pixels = s->frame->data[0];
96
97     int image_size = height * s->frame->linesize[0];
98     int row_ptr = 0;
99     int pixel_ptr = 0;
100     int pixel_x, pixel_y;
101     int row_inc = stride - 4;
102     int block_ptr;
103     int prev_block_ptr;
104     int prev_block_ptr1, prev_block_ptr2;
105     int prev_block_flag;
106     int total_blocks;
107     int color_table_index;  /* indexes to color pair, quad, or octet tables */
108     int pixel;
109
110     int color_pair_index = 0;
111     int color_quad_index = 0;
112     int color_octet_index = 0;
113
114     /* make the palette available */
115     memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE);
116
117     bytestream2_skip(&s->gb, 1);
118     chunk_size = bytestream2_get_be24(&s->gb);
119     if (chunk_size != buf_size)
120         av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
121             chunk_size, buf_size);
122
123     chunk_size = buf_size;
124     total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
125
126     /* traverse through the blocks */
127     while (total_blocks) {
128         /* sanity checks */
129         /* make sure the row pointer hasn't gone wild */
130         if (row_ptr >= image_size) {
131             av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)\n",
132                 row_ptr, image_size);
133             return;
134         }
135
136         opcode = bytestream2_get_byte(&s->gb);
137         switch (opcode & 0xF0) {
138         /* skip n blocks */
139         case 0x00:
140         case 0x10:
141             n_blocks = GET_BLOCK_COUNT();
142             while (n_blocks--) {
143                 ADVANCE_BLOCK();
144             }
145             break;
146
147         /* repeat last block n times */
148         case 0x20:
149         case 0x30:
150             n_blocks = GET_BLOCK_COUNT();
151
152             /* sanity check */
153             if ((row_ptr == 0) && (pixel_ptr == 0)) {
154                 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yet\n",
155                     opcode & 0xF0);
156                 return;
157             }
158
159             /* figure out where the previous block started */
160             if (pixel_ptr == 0)
161                 prev_block_ptr1 =
162                     (row_ptr - s->avctx->width * 4) + s->avctx->width - 4;
163             else
164                 prev_block_ptr1 = row_ptr + pixel_ptr - 4;
165
166             while (n_blocks--) {
167                 block_ptr = row_ptr + pixel_ptr;
168                 prev_block_ptr = prev_block_ptr1;
169                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
170                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
171                         pixels[block_ptr++] = pixels[prev_block_ptr++];
172                     }
173                     block_ptr += row_inc;
174                     prev_block_ptr += row_inc;
175                 }
176                 ADVANCE_BLOCK();
177             }
178             break;
179
180         /* repeat previous pair of blocks n times */
181         case 0x40:
182         case 0x50:
183             n_blocks = GET_BLOCK_COUNT();
184             n_blocks *= 2;
185
186             /* sanity check */
187             if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
188                 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
189                     opcode & 0xF0);
190                 return;
191             }
192
193             /* figure out where the previous 2 blocks started */
194             if (pixel_ptr == 0)
195                 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) +
196                     s->avctx->width - 4 * 2;
197             else if (pixel_ptr == 4)
198                 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc;
199             else
200                 prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2;
201
202             if (pixel_ptr == 0)
203                 prev_block_ptr2 = (row_ptr - s->avctx->width * 4) + row_inc;
204             else
205                 prev_block_ptr2 = row_ptr + pixel_ptr - 4;
206
207             prev_block_flag = 0;
208             while (n_blocks--) {
209                 block_ptr = row_ptr + pixel_ptr;
210                 if (prev_block_flag)
211                     prev_block_ptr = prev_block_ptr2;
212                 else
213                     prev_block_ptr = prev_block_ptr1;
214                 prev_block_flag = !prev_block_flag;
215
216                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
217                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
218                         pixels[block_ptr++] = pixels[prev_block_ptr++];
219                     }
220                     block_ptr += row_inc;
221                     prev_block_ptr += row_inc;
222                 }
223                 ADVANCE_BLOCK();
224             }
225             break;
226
227         /* 1-color block encoding */
228         case 0x60:
229         case 0x70:
230             n_blocks = GET_BLOCK_COUNT();
231             pixel = bytestream2_get_byte(&s->gb);
232
233             while (n_blocks--) {
234                 block_ptr = row_ptr + pixel_ptr;
235                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
236                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
237                         pixels[block_ptr++] = pixel;
238                     }
239                     block_ptr += row_inc;
240                 }
241                 ADVANCE_BLOCK();
242             }
243             break;
244
245         /* 2-color block encoding */
246         case 0x80:
247         case 0x90:
248             n_blocks = (opcode & 0x0F) + 1;
249
250             /* figure out which color pair to use to paint the 2-color block */
251             if ((opcode & 0xF0) == 0x80) {
252                 /* fetch the next 2 colors from bytestream and store in next
253                  * available entry in the color pair table */
254                 for (i = 0; i < CPAIR; i++) {
255                     pixel = bytestream2_get_byte(&s->gb);
256                     color_table_index = CPAIR * color_pair_index + i;
257                     s->color_pairs[color_table_index] = pixel;
258                 }
259                 /* this is the base index to use for this block */
260                 color_table_index = CPAIR * color_pair_index;
261                 color_pair_index++;
262                 /* wraparound */
263                 if (color_pair_index == COLORS_PER_TABLE)
264                     color_pair_index = 0;
265             } else
266                 color_table_index = CPAIR * bytestream2_get_byte(&s->gb);
267
268             while (n_blocks--) {
269                 color_flags = bytestream2_get_be16(&s->gb);
270                 flag_mask = 0x8000;
271                 block_ptr = row_ptr + pixel_ptr;
272                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
273                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
274                         if (color_flags & flag_mask)
275                             pixel = color_table_index + 1;
276                         else
277                             pixel = color_table_index;
278                         flag_mask >>= 1;
279                         pixels[block_ptr++] = s->color_pairs[pixel];
280                     }
281                     block_ptr += row_inc;
282                 }
283                 ADVANCE_BLOCK();
284             }
285             break;
286
287         /* 4-color block encoding */
288         case 0xA0:
289         case 0xB0:
290             n_blocks = (opcode & 0x0F) + 1;
291
292             /* figure out which color quad to use to paint the 4-color block */
293             if ((opcode & 0xF0) == 0xA0) {
294                 /* fetch the next 4 colors from bytestream and store in next
295                  * available entry in the color quad table */
296                 for (i = 0; i < CQUAD; i++) {
297                     pixel = bytestream2_get_byte(&s->gb);
298                     color_table_index = CQUAD * color_quad_index + i;
299                     s->color_quads[color_table_index] = pixel;
300                 }
301                 /* this is the base index to use for this block */
302                 color_table_index = CQUAD * color_quad_index;
303                 color_quad_index++;
304                 /* wraparound */
305                 if (color_quad_index == COLORS_PER_TABLE)
306                     color_quad_index = 0;
307             } else
308                 color_table_index = CQUAD * bytestream2_get_byte(&s->gb);
309
310             while (n_blocks--) {
311                 color_flags = bytestream2_get_be32(&s->gb);
312                 /* flag mask actually acts as a bit shift count here */
313                 flag_mask = 30;
314                 block_ptr = row_ptr + pixel_ptr;
315                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
316                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
317                         pixel = color_table_index +
318                             ((color_flags >> flag_mask) & 0x03);
319                         flag_mask -= 2;
320                         pixels[block_ptr++] = s->color_quads[pixel];
321                     }
322                     block_ptr += row_inc;
323                 }
324                 ADVANCE_BLOCK();
325             }
326             break;
327
328         /* 8-color block encoding */
329         case 0xC0:
330         case 0xD0:
331             n_blocks = (opcode & 0x0F) + 1;
332
333             /* figure out which color octet to use to paint the 8-color block */
334             if ((opcode & 0xF0) == 0xC0) {
335                 /* fetch the next 8 colors from bytestream and store in next
336                  * available entry in the color octet table */
337                 for (i = 0; i < COCTET; i++) {
338                     pixel = bytestream2_get_byte(&s->gb);
339                     color_table_index = COCTET * color_octet_index + i;
340                     s->color_octets[color_table_index] = pixel;
341                 }
342                 /* this is the base index to use for this block */
343                 color_table_index = COCTET * color_octet_index;
344                 color_octet_index++;
345                 /* wraparound */
346                 if (color_octet_index == COLORS_PER_TABLE)
347                     color_octet_index = 0;
348             } else
349                 color_table_index = COCTET * bytestream2_get_byte(&s->gb);
350
351             while (n_blocks--) {
352                 /*
353                   For this input of 6 hex bytes:
354                     01 23 45 67 89 AB
355                   Mangle it to this output:
356                     flags_a = xx012456, flags_b = xx89A37B
357                 */
358                 /* build the color flags */
359                 int val1 = bytestream2_get_be16(&s->gb);
360                 int val2 = bytestream2_get_be16(&s->gb);
361                 int val3 = bytestream2_get_be16(&s->gb);
362                 color_flags_a = ((val1 & 0xFFF0) << 8) | (val2 >> 4);
363                 color_flags_b = ((val3 & 0xFFF0) << 8) |
364                     ((val1 & 0x0F) << 8) | ((val2 & 0x0F) << 4) | (val3 & 0x0F);
365
366                 color_flags = color_flags_a;
367                 /* flag mask actually acts as a bit shift count here */
368                 flag_mask = 21;
369                 block_ptr = row_ptr + pixel_ptr;
370                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
371                     /* reload flags at third row (iteration pixel_y == 2) */
372                     if (pixel_y == 2) {
373                         color_flags = color_flags_b;
374                         flag_mask = 21;
375                     }
376                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
377                         pixel = color_table_index +
378                             ((color_flags >> flag_mask) & 0x07);
379                         flag_mask -= 3;
380                         pixels[block_ptr++] = s->color_octets[pixel];
381                     }
382                     block_ptr += row_inc;
383                 }
384                 ADVANCE_BLOCK();
385             }
386             break;
387
388         /* 16-color block encoding (every pixel is a different color) */
389         case 0xE0:
390             n_blocks = (opcode & 0x0F) + 1;
391
392             while (n_blocks--) {
393                 block_ptr = row_ptr + pixel_ptr;
394                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
395                     for (pixel_x = 0; pixel_x < 4; pixel_x++) {
396                         pixels[block_ptr++] = bytestream2_get_byte(&s->gb);
397                     }
398                     block_ptr += row_inc;
399                 }
400                 ADVANCE_BLOCK();
401             }
402             break;
403
404         case 0xF0:
405             avpriv_request_sample(s->avctx, "0xF0 opcode");
406             break;
407         }
408     }
409
410     return;
411 }
412
413 static av_cold int smc_decode_init(AVCodecContext *avctx)
414 {
415     SmcContext *s = avctx->priv_data;
416
417     s->avctx = avctx;
418     avctx->pix_fmt = AV_PIX_FMT_PAL8;
419
420     s->frame = av_frame_alloc();
421     if (!s->frame)
422         return AVERROR(ENOMEM);
423
424     return 0;
425 }
426
427 static int smc_decode_frame(AVCodecContext *avctx,
428                              void *data, int *got_frame,
429                              AVPacket *avpkt)
430 {
431     const uint8_t *buf = avpkt->data;
432     int buf_size = avpkt->size;
433     SmcContext *s = avctx->priv_data;
434     int pal_size;
435     const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
436     int ret;
437
438     bytestream2_init(&s->gb, buf, buf_size);
439
440     if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
441         return ret;
442
443     if (pal && pal_size == AVPALETTE_SIZE) {
444         s->frame->palette_has_changed = 1;
445         memcpy(s->pal, pal, AVPALETTE_SIZE);
446     } else if (pal) {
447         av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
448     }
449
450     smc_decode_stream(s);
451
452     *got_frame      = 1;
453     if ((ret = av_frame_ref(data, s->frame)) < 0)
454         return ret;
455
456     /* always report that the buffer was completely consumed */
457     return buf_size;
458 }
459
460 static av_cold int smc_decode_end(AVCodecContext *avctx)
461 {
462     SmcContext *s = avctx->priv_data;
463
464     av_frame_free(&s->frame);
465
466     return 0;
467 }
468
469 AVCodec ff_smc_decoder = {
470     .name           = "smc",
471     .long_name      = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"),
472     .type           = AVMEDIA_TYPE_VIDEO,
473     .id             = AV_CODEC_ID_SMC,
474     .priv_data_size = sizeof(SmcContext),
475     .init           = smc_decode_init,
476     .close          = smc_decode_end,
477     .decode         = smc_decode_frame,
478     .capabilities   = AV_CODEC_CAP_DR1,
479 };