#include "avcodec.h"
#include "libavutil/audioconvert.h"
+#include "mathops.h"
#define ALT_BITSTREAM_READER_LE
#include "get_bits.h"
return -1;
}
b1 = get_bits_count(gb);
- i1 = get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3);
+ i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) : 0;
b1 = get_bits_count(gb) - b1;
b2 = get_bits_count(gb);
- i2 = get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3);
+ i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) : 0;
b2 = get_bits_count(gb) - b2;
+ if (i1 < 0 || i2 < 0)
+ return -1;
val = ctx->recode1[i1] | (ctx->recode2[i2] << 8);
if(val == ctx->escapes[0]) {
ctx->last[0] = hc->current;
smk->mmap_tbl[0] = 0;
smk->mmap_last[0] = smk->mmap_last[1] = smk->mmap_last[2] = 1;
} else {
- smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size);
+ if (smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size))
+ return -1;
}
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n");
smk->mclr_tbl[0] = 0;
smk->mclr_last[0] = smk->mclr_last[1] = smk->mclr_last[2] = 1;
} else {
- smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size);
+ if (smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size))
+ return -1;
}
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n");
smk->full_tbl[0] = 0;
smk->full_last[0] = smk->full_last[1] = smk->full_last[2] = 1;
} else {
- smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size);
+ if (smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size))
+ return -1;
}
if(!get_bits1(&gb)) {
av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n");
smk->type_tbl[0] = 0;
smk->type_last[0] = smk->type_last[1] = smk->type_last[2] = 1;
} else {
- smacker_decode_header_tree(smk, &gb, &smk->type_tbl, smk->type_last, type_size);
+ if (smacker_decode_header_tree(smk, &gb, &smk->type_tbl, smk->type_last, type_size))
+ return -1;
}
return 0;
if(buf_size <= 769)
return 0;
- smk->pic.reference = 1;
+ smk->pic.reference = 3;
smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
if(avctx->reget_buffer(avctx, &smk->pic) < 0){
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
- decode_header_trees(c);
-
+ if (decode_header_trees(c))
+ return -1;
return 0;
}
static av_cold int smka_decode_init(AVCodecContext *avctx)
{
+ if (avctx->channels < 1 || avctx->channels > 2) {
+ av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
+ return AVERROR(EINVAL);
+ }
avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
avctx->sample_fmt = avctx->bits_per_coded_sample == 8 ? AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16;
return 0;
HuffContext h[4];
VLC vlc[4];
int16_t *samples = data;
- int8_t *samples8 = data;
+ uint8_t *samples8 = data;
int val;
int i, res;
int unp_size;
int bits, stereo;
int pred[2] = {0, 0};
+ if (buf_size <= 4) {
+ av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
+ return AVERROR(EINVAL);
+ }
+
unp_size = AV_RL32(buf);
init_get_bits(&gb, buf + 4, (buf_size - 4) * 8);
av_log(avctx, AV_LOG_ERROR, "Frame is too large to fit in buffer\n");
return -1;
}
+ if (stereo ^ (avctx->channels != 1)) {
+ av_log(avctx, AV_LOG_ERROR, "channels mismatch\n");
+ return AVERROR(EINVAL);
+ }
+ if (bits && avctx->sample_fmt == AV_SAMPLE_FMT_U8) {
+ av_log(avctx, AV_LOG_ERROR, "sample format mismatch\n");
+ return AVERROR(EINVAL);
+ }
memset(vlc, 0, sizeof(VLC) * 4);
memset(h, 0, sizeof(HuffContext) * 4);
if(bits) { //decode 16-bit data
for(i = stereo; i >= 0; i--)
pred[i] = av_bswap16(get_bits(&gb, 16));
- for(i = 0; i < stereo; i++)
+ for(i = 0; i <= stereo; i++)
*samples++ = pred[i];
- for(i = 0; i < unp_size / 2; i++) {
+ for(; i < unp_size / 2; i++) {
if(i & stereo) {
if(vlc[2].table)
res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3);
else
res = 0;
val |= h[3].values[res] << 8;
- pred[1] += (int16_t)val;
- *samples++ = pred[1];
+ pred[1] += sign_extend(val, 16);
+ *samples++ = av_clip_int16(pred[1]);
} else {
if(vlc[0].table)
res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
else
res = 0;
val |= h[1].values[res] << 8;
- pred[0] += val;
- *samples++ = pred[0];
+ pred[0] += sign_extend(val, 16);
+ *samples++ = av_clip_int16(pred[0]);
}
}
} else { //8-bit data
for(i = stereo; i >= 0; i--)
pred[i] = get_bits(&gb, 8);
- for(i = 0; i < stereo; i++)
+ for(i = 0; i <= stereo; i++)
*samples8++ = pred[i];
- for(i = 0; i < unp_size; i++) {
+ for(; i < unp_size; i++) {
if(i & stereo){
if(vlc[1].table)
res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);
else
res = 0;
- pred[1] += (int8_t)h[1].values[res];
- *samples8++ = pred[1];
+ pred[1] += sign_extend(h[1].values[res], 8);
+ *samples8++ = av_clip_uint8(pred[1]);
} else {
if(vlc[0].table)
res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);
else
res = 0;
- pred[0] += (int8_t)h[0].values[res];
- *samples8++ = pred[0];
+ pred[0] += sign_extend(h[0].values[res], 8);
+ *samples8++ = av_clip_uint8(pred[0]);
}
}
}