|
|
|
@ -60,7 +60,7 @@ typedef struct SmcContext { |
|
|
|
|
} SmcContext; |
|
|
|
|
|
|
|
|
|
#define GET_BLOCK_COUNT() \ |
|
|
|
|
(opcode & 0x10) ? (1 + bytestream2_get_byte(&s->gb)) : 1 + (opcode & 0x0F); |
|
|
|
|
(opcode & 0x10) ? (1 + bytestream2_get_byte(gb)) : 1 + (opcode & 0x0F); |
|
|
|
|
|
|
|
|
|
#define ADVANCE_BLOCK() \ |
|
|
|
|
{ \
|
|
|
|
@ -80,12 +80,13 @@ typedef struct SmcContext { |
|
|
|
|
|
|
|
|
|
static int smc_decode_stream(SmcContext *s) |
|
|
|
|
{ |
|
|
|
|
GetByteContext *gb = &s->gb; |
|
|
|
|
int width = s->avctx->width; |
|
|
|
|
int height = s->avctx->height; |
|
|
|
|
int stride = s->frame->linesize[0]; |
|
|
|
|
int i; |
|
|
|
|
int chunk_size; |
|
|
|
|
int buf_size = bytestream2_size(&s->gb); |
|
|
|
|
int buf_size = bytestream2_size(gb); |
|
|
|
|
uint8_t opcode; |
|
|
|
|
int n_blocks; |
|
|
|
|
unsigned int color_flags; |
|
|
|
@ -115,8 +116,8 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
/* make the palette available */ |
|
|
|
|
memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE); |
|
|
|
|
|
|
|
|
|
bytestream2_skip(&s->gb, 1); |
|
|
|
|
chunk_size = bytestream2_get_be24(&s->gb); |
|
|
|
|
bytestream2_skip(gb, 1); |
|
|
|
|
chunk_size = bytestream2_get_be24(gb); |
|
|
|
|
if (chunk_size != buf_size) |
|
|
|
|
av_log(s->avctx, AV_LOG_WARNING, "MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n", |
|
|
|
|
chunk_size, buf_size); |
|
|
|
@ -133,12 +134,12 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
row_ptr, image_size); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
if (bytestream2_get_bytes_left(&s->gb) < 1) { |
|
|
|
|
if (bytestream2_get_bytes_left(gb) < 1) { |
|
|
|
|
av_log(s->avctx, AV_LOG_ERROR, "input too small\n"); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
opcode = bytestream2_get_byteu(&s->gb); |
|
|
|
|
opcode = bytestream2_get_byteu(gb); |
|
|
|
|
switch (opcode & 0xF0) { |
|
|
|
|
/* skip n blocks */ |
|
|
|
|
case 0x00: |
|
|
|
@ -233,7 +234,7 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
case 0x60: |
|
|
|
|
case 0x70: |
|
|
|
|
n_blocks = GET_BLOCK_COUNT(); |
|
|
|
|
pixel = bytestream2_get_byte(&s->gb); |
|
|
|
|
pixel = bytestream2_get_byte(gb); |
|
|
|
|
|
|
|
|
|
while (n_blocks--) { |
|
|
|
|
block_ptr = row_ptr + pixel_ptr; |
|
|
|
@ -257,7 +258,7 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
/* fetch the next 2 colors from bytestream and store in next
|
|
|
|
|
* available entry in the color pair table */ |
|
|
|
|
for (i = 0; i < CPAIR; i++) { |
|
|
|
|
pixel = bytestream2_get_byte(&s->gb); |
|
|
|
|
pixel = bytestream2_get_byte(gb); |
|
|
|
|
color_table_index = CPAIR * color_pair_index + i; |
|
|
|
|
s->color_pairs[color_table_index] = pixel; |
|
|
|
|
} |
|
|
|
@ -268,10 +269,10 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
if (color_pair_index == COLORS_PER_TABLE) |
|
|
|
|
color_pair_index = 0; |
|
|
|
|
} else |
|
|
|
|
color_table_index = CPAIR * bytestream2_get_byte(&s->gb); |
|
|
|
|
color_table_index = CPAIR * bytestream2_get_byte(gb); |
|
|
|
|
|
|
|
|
|
while (n_blocks--) { |
|
|
|
|
color_flags = bytestream2_get_be16(&s->gb); |
|
|
|
|
color_flags = bytestream2_get_be16(gb); |
|
|
|
|
flag_mask = 0x8000; |
|
|
|
|
block_ptr = row_ptr + pixel_ptr; |
|
|
|
|
for (pixel_y = 0; pixel_y < 4; pixel_y++) { |
|
|
|
@ -299,7 +300,7 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
/* fetch the next 4 colors from bytestream and store in next
|
|
|
|
|
* available entry in the color quad table */ |
|
|
|
|
for (i = 0; i < CQUAD; i++) { |
|
|
|
|
pixel = bytestream2_get_byte(&s->gb); |
|
|
|
|
pixel = bytestream2_get_byte(gb); |
|
|
|
|
color_table_index = CQUAD * color_quad_index + i; |
|
|
|
|
s->color_quads[color_table_index] = pixel; |
|
|
|
|
} |
|
|
|
@ -310,10 +311,10 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
if (color_quad_index == COLORS_PER_TABLE) |
|
|
|
|
color_quad_index = 0; |
|
|
|
|
} else |
|
|
|
|
color_table_index = CQUAD * bytestream2_get_byte(&s->gb); |
|
|
|
|
color_table_index = CQUAD * bytestream2_get_byte(gb); |
|
|
|
|
|
|
|
|
|
while (n_blocks--) { |
|
|
|
|
color_flags = bytestream2_get_be32(&s->gb); |
|
|
|
|
color_flags = bytestream2_get_be32(gb); |
|
|
|
|
/* flag mask actually acts as a bit shift count here */ |
|
|
|
|
flag_mask = 30; |
|
|
|
|
block_ptr = row_ptr + pixel_ptr; |
|
|
|
@ -340,7 +341,7 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
/* fetch the next 8 colors from bytestream and store in next
|
|
|
|
|
* available entry in the color octet table */ |
|
|
|
|
for (i = 0; i < COCTET; i++) { |
|
|
|
|
pixel = bytestream2_get_byte(&s->gb); |
|
|
|
|
pixel = bytestream2_get_byte(gb); |
|
|
|
|
color_table_index = COCTET * color_octet_index + i; |
|
|
|
|
s->color_octets[color_table_index] = pixel; |
|
|
|
|
} |
|
|
|
@ -351,7 +352,7 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
if (color_octet_index == COLORS_PER_TABLE) |
|
|
|
|
color_octet_index = 0; |
|
|
|
|
} else |
|
|
|
|
color_table_index = COCTET * bytestream2_get_byte(&s->gb); |
|
|
|
|
color_table_index = COCTET * bytestream2_get_byte(gb); |
|
|
|
|
|
|
|
|
|
while (n_blocks--) { |
|
|
|
|
/*
|
|
|
|
@ -361,9 +362,9 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
flags_a = xx012456, flags_b = xx89A37B |
|
|
|
|
*/ |
|
|
|
|
/* build the color flags */ |
|
|
|
|
int val1 = bytestream2_get_be16(&s->gb); |
|
|
|
|
int val2 = bytestream2_get_be16(&s->gb); |
|
|
|
|
int val3 = bytestream2_get_be16(&s->gb); |
|
|
|
|
int val1 = bytestream2_get_be16(gb); |
|
|
|
|
int val2 = bytestream2_get_be16(gb); |
|
|
|
|
int val3 = bytestream2_get_be16(gb); |
|
|
|
|
color_flags_a = ((val1 & 0xFFF0) << 8) | (val2 >> 4); |
|
|
|
|
color_flags_b = ((val3 & 0xFFF0) << 8) | |
|
|
|
|
((val1 & 0x0F) << 8) | ((val2 & 0x0F) << 4) | (val3 & 0x0F); |
|
|
|
@ -399,7 +400,7 @@ static int smc_decode_stream(SmcContext *s) |
|
|
|
|
block_ptr = row_ptr + pixel_ptr; |
|
|
|
|
for (pixel_y = 0; pixel_y < 4; pixel_y++) { |
|
|
|
|
for (pixel_x = 0; pixel_x < 4; pixel_x++) { |
|
|
|
|
pixels[block_ptr++] = bytestream2_get_byte(&s->gb); |
|
|
|
|
pixels[block_ptr++] = bytestream2_get_byte(gb); |
|
|
|
|
} |
|
|
|
|
block_ptr += row_inc; |
|
|
|
|
} |
|
|
|
|