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
40
44
45 #define COLORS_PER_TABLE 256
46
48
51
53
54 /* SMC color tables */
58
61
62 #define GET_BLOCK_COUNT() \
63 (opcode & 0x10) ? (1 + bytestream2_get_byte(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_ERROR, "block counter just went negative (this should not happen)\n"); \
77 return AVERROR_INVALIDDATA; \
78 } \
79 }
80
82 {
84 int width =
s->avctx->width;
86 int stride =
s->frame->linesize[0];
88 int chunk_size;
90 uint8_t opcode;
91 int n_blocks;
92 unsigned int color_flags;
93 unsigned int color_flags_a;
94 unsigned int color_flags_b;
95 unsigned int flag_mask;
96
97 uint8_t *
const pixels =
s->frame->data[0];
98
99 int image_size =
height *
s->frame->linesize[0];
100 int row_ptr = 0;
101 int pixel_ptr = 0;
102 int pixel_x, pixel_y;
104 int block_ptr;
105 int prev_block_ptr;
106 int prev_block_ptr1, prev_block_ptr2;
107 int prev_block_flag;
108 int total_blocks;
109 int color_table_index; /* indexes to color pair, quad, or octet tables */
111
112 int color_pair_index = 0;
113 int color_quad_index = 0;
114 int color_octet_index = 0;
115
116 /* make the palette available */
118
120 chunk_size = bytestream2_get_be24(gb);
121 if (chunk_size != buf_size)
122 av_log(
s->avctx,
AV_LOG_WARNING,
"MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
123 chunk_size, buf_size);
124
125 chunk_size = buf_size;
126 total_blocks = ((
s->avctx->width + 3) / 4) * ((
s->avctx->height + 3) / 4);
127
128 /* traverse through the blocks */
129 while (total_blocks) {
130 /* sanity checks */
131 /* make sure the row pointer hasn't gone wild */
132 if (row_ptr >= image_size) {
134 row_ptr, image_size);
136 }
140 }
141
142 opcode = bytestream2_get_byteu(gb);
143 switch (opcode & 0xF0) {
144 /* skip n blocks */
145 case 0x00:
146 case 0x10:
148 while (n_blocks--) {
150 }
151 break;
152
153 /* repeat last block n times */
154 case 0x20:
155 case 0x30:
157
158 /* sanity check */
159 if ((row_ptr == 0) && (pixel_ptr == 0)) {
160 av_log(
s->avctx,
AV_LOG_ERROR,
"encountered repeat block opcode (%02X) but no blocks rendered yet\n",
161 opcode & 0xF0);
163 }
164
165 /* figure out where the previous block started */
166 if (pixel_ptr == 0)
167 prev_block_ptr1 =
168 (row_ptr -
s->avctx->width * 4) +
s->avctx->width - 4;
169 else
170 prev_block_ptr1 = row_ptr + pixel_ptr - 4;
171
172 while (n_blocks--) {
173 block_ptr = row_ptr + pixel_ptr;
174 prev_block_ptr = prev_block_ptr1;
175 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
176 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
177 pixels[block_ptr++] = pixels[prev_block_ptr++];
178 }
179 block_ptr += row_inc;
180 prev_block_ptr += row_inc;
181 }
183 }
184 break;
185
186 /* repeat previous pair of blocks n times */
187 case 0x40:
188 case 0x50:
190 n_blocks *= 2;
191
192 /* sanity check */
193 if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
194 av_log(
s->avctx,
AV_LOG_ERROR,
"encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
195 opcode & 0xF0);
197 }
198
199 /* figure out where the previous 2 blocks started */
200 if (pixel_ptr == 0)
201 prev_block_ptr1 = (row_ptr -
s->avctx->width * 4) +
202 s->avctx->width - 4 * 2;
203 else if (pixel_ptr == 4)
204 prev_block_ptr1 = (row_ptr -
s->avctx->width * 4) + row_inc;
205 else
206 prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2;
207
208 if (pixel_ptr == 0)
209 prev_block_ptr2 = (row_ptr -
s->avctx->width * 4) + row_inc;
210 else
211 prev_block_ptr2 = row_ptr + pixel_ptr - 4;
212
213 prev_block_flag = 0;
214 while (n_blocks--) {
215 block_ptr = row_ptr + pixel_ptr;
216 if (prev_block_flag)
217 prev_block_ptr = prev_block_ptr2;
218 else
219 prev_block_ptr = prev_block_ptr1;
220 prev_block_flag = !prev_block_flag;
221
222 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
223 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
224 pixels[block_ptr++] = pixels[prev_block_ptr++];
225 }
226 block_ptr += row_inc;
227 prev_block_ptr += row_inc;
228 }
230 }
231 break;
232
233 /* 1-color block encoding */
234 case 0x60:
235 case 0x70:
237 pixel = bytestream2_get_byte(gb);
238
239 while (n_blocks--) {
240 block_ptr = row_ptr + pixel_ptr;
241 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
242 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
243 pixels[block_ptr++] =
pixel;
244 }
245 block_ptr += row_inc;
246 }
248 }
249 break;
250
251 /* 2-color block encoding */
252 case 0x80:
253 case 0x90:
254 n_blocks = (opcode & 0x0F) + 1;
255
256 /* figure out which color pair to use to paint the 2-color block */
257 if ((opcode & 0xF0) == 0x80) {
258 /* fetch the next 2 colors from bytestream and store in next
259 * available entry in the color pair table */
261 pixel = bytestream2_get_byte(gb);
262 color_table_index =
CPAIR * color_pair_index +
i;
263 s->color_pairs[color_table_index] =
pixel;
264 }
265 /* this is the base index to use for this block */
266 color_table_index =
CPAIR * color_pair_index;
267 color_pair_index++;
268 /* wraparound */
270 color_pair_index = 0;
271 } else
272 color_table_index =
CPAIR * bytestream2_get_byte(gb);
273
274 while (n_blocks--) {
275 color_flags = bytestream2_get_be16(gb);
276 flag_mask = 0x8000;
277 block_ptr = row_ptr + pixel_ptr;
278 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
279 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
280 if (color_flags & flag_mask)
281 pixel = color_table_index + 1;
282 else
283 pixel = color_table_index;
284 flag_mask >>= 1;
285 pixels[block_ptr++] =
s->color_pairs[
pixel];
286 }
287 block_ptr += row_inc;
288 }
290 }
291 break;
292
293 /* 4-color block encoding */
294 case 0xA0:
295 case 0xB0:
296 n_blocks = (opcode & 0x0F) + 1;
297
298 /* figure out which color quad to use to paint the 4-color block */
299 if ((opcode & 0xF0) == 0xA0) {
300 /* fetch the next 4 colors from bytestream and store in next
301 * available entry in the color quad table */
303 pixel = bytestream2_get_byte(gb);
304 color_table_index =
CQUAD * color_quad_index +
i;
305 s->color_quads[color_table_index] =
pixel;
306 }
307 /* this is the base index to use for this block */
308 color_table_index =
CQUAD * color_quad_index;
309 color_quad_index++;
310 /* wraparound */
312 color_quad_index = 0;
313 } else
314 color_table_index =
CQUAD * bytestream2_get_byte(gb);
315
316 while (n_blocks--) {
317 color_flags = bytestream2_get_be32(gb);
318 /* flag mask actually acts as a bit shift count here */
319 flag_mask = 30;
320 block_ptr = row_ptr + pixel_ptr;
321 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
322 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
323 pixel = color_table_index +
324 ((color_flags >> flag_mask) & 0x03);
325 flag_mask -= 2;
326 pixels[block_ptr++] =
s->color_quads[
pixel];
327 }
328 block_ptr += row_inc;
329 }
331 }
332 break;
333
334 /* 8-color block encoding */
335 case 0xC0:
336 case 0xD0:
337 n_blocks = (opcode & 0x0F) + 1;
338
339 /* figure out which color octet to use to paint the 8-color block */
340 if ((opcode & 0xF0) == 0xC0) {
341 /* fetch the next 8 colors from bytestream and store in next
342 * available entry in the color octet table */
344 pixel = bytestream2_get_byte(gb);
345 color_table_index =
COCTET * color_octet_index +
i;
346 s->color_octets[color_table_index] =
pixel;
347 }
348 /* this is the base index to use for this block */
349 color_table_index =
COCTET * color_octet_index;
350 color_octet_index++;
351 /* wraparound */
353 color_octet_index = 0;
354 } else
355 color_table_index =
COCTET * bytestream2_get_byte(gb);
356
357 while (n_blocks--) {
358 /*
359 For this input of 6 hex bytes:
360 01 23 45 67 89 AB
361 Mangle it to this output:
362 flags_a = xx012456, flags_b = xx89A37B
363 */
364 /* build the color flags */
365 int val1 = bytestream2_get_be16(gb);
366 int val2 = bytestream2_get_be16(gb);
367 int val3 = bytestream2_get_be16(gb);
368 color_flags_a = ((val1 & 0xFFF0) << 8) | (val2 >> 4);
369 color_flags_b = ((val3 & 0xFFF0) << 8) |
370 ((val1 & 0x0F) << 8) | ((val2 & 0x0F) << 4) | (val3 & 0x0F);
371
372 color_flags = color_flags_a;
373 /* flag mask actually acts as a bit shift count here */
374 flag_mask = 21;
375 block_ptr = row_ptr + pixel_ptr;
376 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
377 /* reload flags at third row (iteration pixel_y == 2) */
378 if (pixel_y == 2) {
379 color_flags = color_flags_b;
380 flag_mask = 21;
381 }
382 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
383 pixel = color_table_index +
384 ((color_flags >> flag_mask) & 0x07);
385 flag_mask -= 3;
386 pixels[block_ptr++] =
s->color_octets[
pixel];
387 }
388 block_ptr += row_inc;
389 }
391 }
392 break;
393
394 /* 16-color block encoding (every pixel is a different color) */
395 case 0xE0:
396 case 0xF0:
397 n_blocks = (opcode & 0x0F) + 1;
398
399 while (n_blocks--) {
400 block_ptr = row_ptr + pixel_ptr;
401 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
402 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
403 pixels[block_ptr++] = bytestream2_get_byte(gb);
404 }
405 block_ptr += row_inc;
406 }
408 }
409 break;
410 }
411 }
412
413 return 0;
414 }
415
417 {
419
422
426
427 return 0;
428 }
429
431 void *
data,
int *got_frame,
433 {
434 const uint8_t *buf = avpkt->
data;
435 int buf_size = avpkt->
size;
438 int total_blocks = ((
s->avctx->width + 3) / 4) * ((
s->avctx->height + 3) / 4);
439
440 if (total_blocks / 1024 > avpkt->
size)
442
444
447
449
453
454 *got_frame = 1;
457
458 /* always report that the buffer was completely consumed */
459 return buf_size;
460 }
461
463 {
465
467
468 return 0;
469 }
470
482 };