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