int mmap_last[3], mclr_last[3], full_last[3], type_last[3];
} SmackVContext;
+typedef struct HuffEntry {
+ uint8_t value;
+ uint8_t length;
+} HuffEntry;
+
/**
* Context used for code reconstructing
*/
typedef struct HuffContext {
int current;
- uint32_t bits[256];
- uint8_t lengths[256];
- uint8_t values[256];
+ HuffEntry entries[256];
} HuffContext;
/* common parameters used for decode_bigtree */
* Can read SMKTREE_DECODE_MAX_RECURSION before the first check;
* does not overread gb on success.
*/
-static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length)
+static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, int length)
{
if (length > SMKTREE_DECODE_MAX_RECURSION || length > 3 * SMKTREE_BITS) {
av_log(NULL, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n");
}
if (get_bits_left(gb) < 8)
return AVERROR_INVALIDDATA;
- hc->bits[hc->current] = prefix;
- hc->lengths[hc->current] = length;
- hc->values[hc->current] = get_bits(gb, 8);
- hc->current++;
+ hc->entries[hc->current++] = (HuffEntry){ get_bits(gb, 8), length };
return 0;
} else { //Node
int r;
length++;
- r = smacker_decode_tree(gb, hc, prefix, length);
+ r = smacker_decode_tree(gb, hc, length);
if(r)
return r;
- return smacker_decode_tree(gb, hc, prefix | (1U << (length - 1)), length);
+ return smacker_decode_tree(gb, hc, length);
}
}
i ? "high" : "low");
continue;
}
- err = smacker_decode_tree(gb, &h, 0, 0);
+ err = smacker_decode_tree(gb, &h, 0);
if (err < 0)
goto error;
skip_bits1(gb);
if (h.current > 1) {
- err = ff_init_vlc_sparse(&vlc[i], SMKTREE_BITS, h.current,
- h.lengths, sizeof(*h.lengths), sizeof(*h.lengths),
- h.bits, sizeof(*h.bits), sizeof(*h.bits),
- h.values, sizeof(*h.values), sizeof(*h.values),
- INIT_VLC_LE);
+ err = ff_init_vlc_from_lengths(&vlc[i], SMKTREE_BITS, h.current,
+ &h.entries[0].length, sizeof(*h.entries),
+ &h.entries[0].value, sizeof(*h.entries), 1,
+ 0, INIT_VLC_OUTPUT_LE, smk->avctx);
if (err < 0) {
av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n");
goto error;
}
} else
- ctx.vals[i] = h.values[0];
+ ctx.vals[i] = h.entries[0].value;
}
escapes[0] = get_bits(gb, 16);
case SMK_BLK_FULL:
mode = 0;
if(avctx->codec_tag == MKTAG('S', 'M', 'K', '4')) { // In case of Smacker v4 we have three modes
+ if (get_bits_left(&gb) < 1)
+ return AVERROR_INVALIDDATA;
if(get_bits1(&gb)) mode = 1;
else if(get_bits1(&gb)) mode = 2;
}
HuffContext h;
h.current = 0;
skip_bits1(&gb);
- if ((ret = smacker_decode_tree(&gb, &h, 0, 0)) < 0)
+ if ((ret = smacker_decode_tree(&gb, &h, 0)) < 0)
goto error;
skip_bits1(&gb);
if (h.current > 1) {
- ret = ff_init_vlc_sparse(&vlc[i], SMKTREE_BITS, h.current,
- h.lengths, sizeof(*h.lengths), sizeof(*h.lengths),
- h.bits, sizeof(*h.bits), sizeof(*h.bits),
- h.values, sizeof(*h.values), sizeof(*h.values),
- INIT_VLC_LE);
+ ret = ff_init_vlc_from_lengths(&vlc[i], SMKTREE_BITS, h.current,
+ &h.entries[0].length, sizeof(*h.entries),
+ &h.entries[0].value, sizeof(*h.entries), 1,
+ 0, INIT_VLC_OUTPUT_LE, avctx);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n");
goto error;
}
} else
- values[i] = h.values[0];
+ values[i] = h.entries[0].value;
}
/* this codec relies on wraparound instead of clipping audio */
if(bits) { //decode 16-bit data
return ret;
}
-AVCodec ff_smacker_decoder = {
+const AVCodec ff_smacker_decoder = {
.name = "smackvid",
.long_name = NULL_IF_CONFIG_SMALL("Smacker video"),
.type = AVMEDIA_TYPE_VIDEO,
.close = decode_end,
.decode = decode_frame,
.capabilities = AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
};
-AVCodec ff_smackaud_decoder = {
+const AVCodec ff_smackaud_decoder = {
.name = "smackaud",
.long_name = NULL_IF_CONFIG_SMALL("Smacker audio"),
.type = AVMEDIA_TYPE_AUDIO,
.init = smka_decode_init,
.decode = smka_decode_frame,
.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
};