|
|
|
@ -127,13 +127,15 @@ 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]; |
|
|
|
@ -141,7 +143,8 @@ static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned c |
|
|
|
|
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++; |
|
|
|
@ -166,7 +169,8 @@ 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; |
|
|
|
@ -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,7 +204,8 @@ 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; |
|
|
|
@ -230,10 +237,11 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
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); |
|
|
|
|
palette_colors_count = AV_RL16(buf + 1); |
|
|
|
|
bitmap_frame_type = buf[3]; |
|
|
|
|
buf += 4; |
|
|
|
|
|
|
|
|
@ -251,13 +259,14 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
for (i = 0; i < palette_colors_count; ++i) { |
|
|
|
|
cin->palette[buf[0]] = 0xFFU << 24 | AV_RL24(buf+1); |
|
|
|
|
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, |
|
|
|
@ -277,7 +286,8 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
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_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], |
|
|
|
@ -315,7 +325,8 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, |
|
|
|
|
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; |
|
|
|
@ -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, |
|
|
|
|