|
|
|
@ -127,27 +127,30 @@ static av_cold int cinvideo_decode_init(AVCodecContext *avctx) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cin_apply_delta_data(const unsigned char *src, unsigned char *dst, int size) |
|
|
|
|
static void cin_apply_delta_data(const unsigned char *src, unsigned char *dst, |
|
|
|
|
int size) |
|
|
|
|
{ |
|
|
|
|
while (size--) |
|
|
|
|
*dst++ += *src++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) |
|
|
|
|
static int cin_decode_huffman(const unsigned char *src, int src_size, |
|
|
|
|
unsigned char *dst, int dst_size) |
|
|
|
|
{ |
|
|
|
|
int b, huff_code = 0; |
|
|
|
|
unsigned char huff_code_table[15]; |
|
|
|
|
unsigned char *dst_cur = dst; |
|
|
|
|
unsigned char *dst_end = dst + dst_size; |
|
|
|
|
unsigned char *dst_cur = dst; |
|
|
|
|
unsigned char *dst_end = dst + dst_size; |
|
|
|
|
const unsigned char *src_end = src + src_size; |
|
|
|
|
|
|
|
|
|
memcpy(huff_code_table, src, 15); src += 15; |
|
|
|
|
memcpy(huff_code_table, src, 15); |
|
|
|
|
src += 15; |
|
|
|
|
|
|
|
|
|
while (src < src_end) { |
|
|
|
|
huff_code = *src++; |
|
|
|
|
if ((huff_code >> 4) == 15) { |
|
|
|
|
b = huff_code << 4; |
|
|
|
|
huff_code = *src++; |
|
|
|
|
b = huff_code << 4; |
|
|
|
|
huff_code = *src++; |
|
|
|
|
*dst_cur++ = b | (huff_code >> 4); |
|
|
|
|
} else |
|
|
|
|
*dst_cur++ = huff_code_table[huff_code >> 4]; |
|
|
|
@ -166,11 +169,12 @@ static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned c |
|
|
|
|
return dst_cur - dst; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int cin_decode_lzss(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) |
|
|
|
|
static int cin_decode_lzss(const unsigned char *src, int src_size, |
|
|
|
|
unsigned char *dst, int dst_size) |
|
|
|
|
{ |
|
|
|
|
uint16_t cmd; |
|
|
|
|
int i, sz, offset, code; |
|
|
|
|
unsigned char *dst_end = dst + dst_size, *dst_start = dst; |
|
|
|
|
unsigned char *dst_end = dst + dst_size, *dst_start = dst; |
|
|
|
|
const unsigned char *src_end = src + src_size; |
|
|
|
|
|
|
|
|
|
while (src < src_end && dst < dst_end) { |
|
|
|
@ -179,13 +183,15 @@ static int cin_decode_lzss(const unsigned char *src, int src_size, unsigned char |
|
|
|
|
if (code & (1 << i)) { |
|
|
|
|
*dst++ = *src++; |
|
|
|
|
} else { |
|
|
|
|
cmd = AV_RL16(src); src += 2; |
|
|
|
|
cmd = AV_RL16(src); |
|
|
|
|
src += 2; |
|
|
|
|
offset = cmd >> 4; |
|
|
|
|
if ((int) (dst - dst_start) < offset + 1) |
|
|
|
|
if ((int)(dst - dst_start) < offset + 1) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
sz = (cmd & 0xF) + 2; |
|
|
|
|
/* don't use memcpy/memmove here as the decoding routine (ab)uses */ |
|
|
|
|
/* buffer overlappings to repeat bytes in the destination */ |
|
|
|
|
/* don't use memcpy/memmove here as the decoding routine
|
|
|
|
|
* (ab)uses buffer overlappings to repeat bytes in the |
|
|
|
|
* destination */ |
|
|
|
|
sz = FFMIN(sz, dst_end - dst); |
|
|
|
|
while (sz--) { |
|
|
|
|
*dst = *(dst - offset - 1); |
|
|
|
@ -198,10 +204,11 @@ static int cin_decode_lzss(const unsigned char *src, int src_size, unsigned char |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int cin_decode_rle(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) |
|
|
|
|
static int cin_decode_rle(const unsigned char *src, int src_size, |
|
|
|
|
unsigned char *dst, int dst_size) |
|
|
|
|
{ |
|
|
|
|
int len, code; |
|
|
|
|
unsigned char *dst_end = dst + dst_size; |
|
|
|
|
unsigned char *dst_end = dst + dst_size; |
|
|
|
|
const unsigned char *src_end = src + src_size; |
|
|
|
|
|
|
|
|
|
while (src + 1 < src_end && dst < dst_end) { |
|
|
|
@ -227,15 +234,16 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
void *data, int *got_frame, |
|
|
|
|
AVPacket *avpkt) |
|
|
|
|
{ |
|
|
|
|
const uint8_t *buf = avpkt->data; |
|
|
|
|
int buf_size = avpkt->size; |
|
|
|
|
const uint8_t *buf = avpkt->data; |
|
|
|
|
int buf_size = avpkt->size; |
|
|
|
|
CinVideoContext *cin = avctx->priv_data; |
|
|
|
|
int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size, res = 0; |
|
|
|
|
int i, y, palette_type, palette_colors_count, |
|
|
|
|
bitmap_frame_type, bitmap_frame_size, res = 0; |
|
|
|
|
|
|
|
|
|
palette_type = buf[0]; |
|
|
|
|
palette_colors_count = AV_RL16(buf+1); |
|
|
|
|
bitmap_frame_type = buf[3]; |
|
|
|
|
buf += 4; |
|
|
|
|
palette_type = buf[0]; |
|
|
|
|
palette_colors_count = AV_RL16(buf + 1); |
|
|
|
|
bitmap_frame_type = buf[3]; |
|
|
|
|
buf += 4; |
|
|
|
|
|
|
|
|
|
bitmap_frame_size = buf_size - 4; |
|
|
|
|
|
|
|
|
@ -246,46 +254,48 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
if (palette_colors_count > 256) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
for (i = 0; i < palette_colors_count; ++i) { |
|
|
|
|
cin->palette[i] = 0xFFU << 24 | bytestream_get_le24(&buf); |
|
|
|
|
cin->palette[i] = 0xFFU << 24 | bytestream_get_le24(&buf); |
|
|
|
|
bitmap_frame_size -= 3; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
for (i = 0; i < palette_colors_count; ++i) { |
|
|
|
|
cin->palette[buf[0]] = 0xFFU << 24 | AV_RL24(buf+1); |
|
|
|
|
buf += 4; |
|
|
|
|
bitmap_frame_size -= 4; |
|
|
|
|
cin->palette[buf[0]] = 0xFFU << 24 | AV_RL24(buf + 1); |
|
|
|
|
buf += 4; |
|
|
|
|
bitmap_frame_size -= 4; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* note: the decoding routines below assumes that surface.width = surface.pitch */ |
|
|
|
|
/* note: the decoding routines below assumes that
|
|
|
|
|
* surface.width = surface.pitch */ |
|
|
|
|
switch (bitmap_frame_type) { |
|
|
|
|
case 9: |
|
|
|
|
cin_decode_rle(buf, bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
break; |
|
|
|
|
case 34: |
|
|
|
|
cin_decode_rle(buf, bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
break; |
|
|
|
|
case 35: |
|
|
|
|
bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); |
|
|
|
|
cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
break; |
|
|
|
|
case 36: |
|
|
|
|
bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_INT_BMP], |
|
|
|
|
cin->bitmap_size); |
|
|
|
|
cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
break; |
|
|
|
|
case 37: |
|
|
|
|
cin_decode_huffman(buf, bitmap_frame_size, |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
break; |
|
|
|
|
case 38: |
|
|
|
|
res = cin_decode_lzss(buf, bitmap_frame_size, |
|
|
|
@ -301,7 +311,7 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
if (res < 0) |
|
|
|
|
return res; |
|
|
|
|
cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -312,10 +322,11 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
cin->frame.palette_has_changed = 1; |
|
|
|
|
for (y = 0; y < cin->avctx->height; ++y) |
|
|
|
|
memcpy(cin->frame.data[0] + (cin->avctx->height - 1 - y) * cin->frame.linesize[0], |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width, |
|
|
|
|
cin->avctx->width); |
|
|
|
|
cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width, |
|
|
|
|
cin->avctx->width); |
|
|
|
|
|
|
|
|
|
FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]); |
|
|
|
|
FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], |
|
|
|
|
cin->bitmap_table[CIN_PRE_BMP]); |
|
|
|
|
|
|
|
|
|
if ((res = av_frame_ref(data, &cin->frame)) < 0) |
|
|
|
|
return res; |
|
|
|
@ -352,9 +363,9 @@ static av_cold int cinaudio_decode_init(AVCodecContext *avctx) |
|
|
|
|
static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
|
int *got_frame_ptr, AVPacket *avpkt) |
|
|
|
|
{ |
|
|
|
|
AVFrame *frame = data; |
|
|
|
|
const uint8_t *buf = avpkt->data; |
|
|
|
|
CinAudioContext *cin = avctx->priv_data; |
|
|
|
|
AVFrame *frame = data; |
|
|
|
|
const uint8_t *buf = avpkt->data; |
|
|
|
|
CinAudioContext *cin = avctx->priv_data; |
|
|
|
|
const uint8_t *buf_end = buf + avpkt->size; |
|
|
|
|
int16_t *samples; |
|
|
|
|
int delta, ret; |
|
|
|
@ -368,13 +379,13 @@ static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
|
delta = cin->delta; |
|
|
|
|
if (cin->initial_decode_frame) { |
|
|
|
|
cin->initial_decode_frame = 0; |
|
|
|
|
delta = sign_extend(AV_RL16(buf), 16); |
|
|
|
|
buf += 2; |
|
|
|
|
*samples++ = delta; |
|
|
|
|
delta = sign_extend(AV_RL16(buf), 16); |
|
|
|
|
buf += 2; |
|
|
|
|
*samples++ = delta; |
|
|
|
|
} |
|
|
|
|
while (buf < buf_end) { |
|
|
|
|
delta += cinaudio_delta16_table[*buf++]; |
|
|
|
|
delta = av_clip_int16(delta); |
|
|
|
|
delta += cinaudio_delta16_table[*buf++]; |
|
|
|
|
delta = av_clip_int16(delta); |
|
|
|
|
*samples++ = delta; |
|
|
|
|
} |
|
|
|
|
cin->delta = delta; |
|
|
|
@ -384,7 +395,6 @@ static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, |
|
|
|
|
return avpkt->size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AVCodec ff_dsicinvideo_decoder = { |
|
|
|
|
.name = "dsicinvideo", |
|
|
|
|
.type = AVMEDIA_TYPE_VIDEO, |
|
|
|
|