📄 smc.c
字号:
pixels[block_ptr++] = pixel;
}
block_ptr += row_inc;
}
ADVANCE_BLOCK();
}
break;
/* 2-color block encoding */
case 0x80:
case 0x90:
n_blocks = (opcode & 0x0F) + 1;
/* figure out which color pair to use to paint the 2-color block */
if ((opcode & 0xF0) == 0x80) {
/* 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 = s->buf[stream_ptr++];
color_table_index = CPAIR * color_pair_index + i;
s->color_pairs[color_table_index] = pixel;
}
/* this is the base index to use for this block */
color_table_index = CPAIR * color_pair_index;
color_pair_index++;
/* wraparound */
if (color_pair_index == COLORS_PER_TABLE)
color_pair_index = 0;
} else
color_table_index = CPAIR * s->buf[stream_ptr++];
while (n_blocks--) {
color_flags = AV_RB16(&s->buf[stream_ptr]);
stream_ptr += 2;
flag_mask = 0x8000;
block_ptr = row_ptr + pixel_ptr;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
for (pixel_x = 0; pixel_x < 4; pixel_x++) {
if (color_flags & flag_mask)
pixel = color_table_index + 1;
else
pixel = color_table_index;
flag_mask >>= 1;
pixels[block_ptr++] = s->color_pairs[pixel];
}
block_ptr += row_inc;
}
ADVANCE_BLOCK();
}
break;
/* 4-color block encoding */
case 0xA0:
case 0xB0:
n_blocks = (opcode & 0x0F) + 1;
/* figure out which color quad to use to paint the 4-color block */
if ((opcode & 0xF0) == 0xA0) {
/* 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 = s->buf[stream_ptr++];
color_table_index = CQUAD * color_quad_index + i;
s->color_quads[color_table_index] = pixel;
}
/* this is the base index to use for this block */
color_table_index = CQUAD * color_quad_index;
color_quad_index++;
/* wraparound */
if (color_quad_index == COLORS_PER_TABLE)
color_quad_index = 0;
} else
color_table_index = CQUAD * s->buf[stream_ptr++];
while (n_blocks--) {
color_flags = AV_RB32(&s->buf[stream_ptr]);
stream_ptr += 4;
/* flag mask actually acts as a bit shift count here */
flag_mask = 30;
block_ptr = row_ptr + pixel_ptr;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
for (pixel_x = 0; pixel_x < 4; pixel_x++) {
pixel = color_table_index +
((color_flags >> flag_mask) & 0x03);
flag_mask -= 2;
pixels[block_ptr++] = s->color_quads[pixel];
}
block_ptr += row_inc;
}
ADVANCE_BLOCK();
}
break;
/* 8-color block encoding */
case 0xC0:
case 0xD0:
n_blocks = (opcode & 0x0F) + 1;
/* figure out which color octet to use to paint the 8-color block */
if ((opcode & 0xF0) == 0xC0) {
/* 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 = s->buf[stream_ptr++];
color_table_index = COCTET * color_octet_index + i;
s->color_octets[color_table_index] = pixel;
}
/* this is the base index to use for this block */
color_table_index = COCTET * color_octet_index;
color_octet_index++;
/* wraparound */
if (color_octet_index == COLORS_PER_TABLE)
color_octet_index = 0;
} else
color_table_index = COCTET * s->buf[stream_ptr++];
while (n_blocks--) {
/*
For this input of 6 hex bytes:
01 23 45 67 89 AB
Mangle it to this output:
flags_a = xx012456, flags_b = xx89A37B
*/
/* build the color flags */
color_flags_a = color_flags_b = 0;
color_flags_a =
(s->buf[stream_ptr + 0] << 16) |
((s->buf[stream_ptr + 1] & 0xF0) << 8) |
((s->buf[stream_ptr + 2] & 0xF0) << 4) |
((s->buf[stream_ptr + 2] & 0x0F) << 4) |
((s->buf[stream_ptr + 3] & 0xF0) >> 4);
color_flags_b =
(s->buf[stream_ptr + 4] << 16) |
((s->buf[stream_ptr + 5] & 0xF0) << 8) |
((s->buf[stream_ptr + 1] & 0x0F) << 8) |
((s->buf[stream_ptr + 3] & 0x0F) << 4) |
(s->buf[stream_ptr + 5] & 0x0F);
stream_ptr += 6;
color_flags = color_flags_a;
/* flag mask actually acts as a bit shift count here */
flag_mask = 21;
block_ptr = row_ptr + pixel_ptr;
for (pixel_y = 0; pixel_y < 4; pixel_y++) {
/* reload flags at third row (iteration pixel_y == 2) */
if (pixel_y == 2) {
color_flags = color_flags_b;
flag_mask = 21;
}
for (pixel_x = 0; pixel_x < 4; pixel_x++) {
pixel = color_table_index +
((color_flags >> flag_mask) & 0x07);
flag_mask -= 3;
pixels[block_ptr++] = s->color_octets[pixel];
}
block_ptr += row_inc;
}
ADVANCE_BLOCK();
}
break;
/* 16-color block encoding (every pixel is a different color) */
case 0xE0:
n_blocks = (opcode & 0x0F) + 1;
while (n_blocks--) {
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++] = s->buf[stream_ptr++];
}
block_ptr += row_inc;
}
ADVANCE_BLOCK();
}
break;
case 0xF0:
av_log(s->avctx, AV_LOG_INFO, "0xF0 opcode seen in SMC chunk (contact the developers)\n");
break;
}
}
}
static int smc_decode_init(AVCodecContext *avctx)
{
SmcContext *s = avctx->priv_data;
s->avctx = avctx;
avctx->pix_fmt = PIX_FMT_PAL8;
dsputil_init(&s->dsp, avctx);
s->frame.data[0] = NULL;
return 0;
}
static int smc_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
SmcContext *s = avctx->priv_data;
s->buf = buf;
s->size = buf_size;
s->frame.reference = 1;
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
if (avctx->reget_buffer(avctx, &s->frame)) {
av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
return -1;
}
smc_decode_stream(s);
*data_size = sizeof(AVFrame);
*(AVFrame*)data = s->frame;
/* always report that the buffer was completely consumed */
return buf_size;
}
static int smc_decode_end(AVCodecContext *avctx)
{
SmcContext *s = avctx->priv_data;
if (s->frame.data[0])
avctx->release_buffer(avctx, &s->frame);
return 0;
}
AVCodec smc_decoder = {
"smc",
CODEC_TYPE_VIDEO,
CODEC_ID_SMC,
sizeof(SmcContext),
smc_decode_init,
NULL,
smc_decode_end,
smc_decode_frame,
CODEC_CAP_DR1,
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -