X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fsmacker.c;h=75ab5d71205eb69afa0f7e1c777ca7b4e806cc1d;hb=1ab74bc19354aedfb9afe71515952254753a75cc;hp=e588b03820e0bb6531f68b1158679d2ac471468f;hpb=010e345afe5d9744956dbc6253a4999e6851e7e9;p=ffmpeg diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index e588b03820e..75ab5d71205 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -62,14 +62,17 @@ typedef struct SmackVContext { 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 */ @@ -105,7 +108,7 @@ enum SmkBlockTypes { * 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"); @@ -119,18 +122,15 @@ static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t pref } 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); } } @@ -216,22 +216,21 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int 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, - INIT_VLC_DEFAULT_SIZES(h.lengths), - INIT_VLC_DEFAULT_SIZES(h.bits), - INIT_VLC_DEFAULT_SIZES(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); @@ -448,6 +447,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, 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; } @@ -595,11 +596,10 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int16_t *samples; uint8_t *samples8; uint8_t values[4]; - int val; int i, res, ret; int unp_size; int bits, stereo; - int pred[2] = {0, 0}; + unsigned pred[2], val; if (buf_size <= 4) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); @@ -649,60 +649,45 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, 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, - INIT_VLC_DEFAULT_SIZES(h.lengths), - INIT_VLC_DEFAULT_SIZES(h.bits), - INIT_VLC_DEFAULT_SIZES(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 for(i = stereo; i >= 0; i--) - pred[i] = sign_extend(av_bswap16(get_bits(&gb, 16)), 16); + pred[i] = av_bswap16(get_bits(&gb, 16)); for(i = 0; i <= stereo; i++) *samples++ = pred[i]; for(; i < unp_size / 2; i++) { + unsigned idx = 2 * (i & stereo); if (get_bits_left(&gb) < 0) { ret = AVERROR_INVALIDDATA; goto error; } - if(i & stereo) { - if(vlc[2].table) - res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3); - else - res = values[2]; - val = res; - if(vlc[3].table) - res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3); - else - res = values[3]; - val |= res << 8; - pred[1] += (unsigned)sign_extend(val, 16); - *samples++ = pred[1]; - } else { - if(vlc[0].table) - res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); - else - res = values[0]; - val = res; - if(vlc[1].table) - res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); - else - res = values[1]; - val |= res << 8; - pred[0] += (unsigned)sign_extend(val, 16); - *samples++ = pred[0]; - } + if (vlc[idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val = res; + if (vlc[++idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val |= res << 8; + pred[idx / 2] += val; + *samples++ = pred[idx / 2]; } } else { //8-bit data for(i = stereo; i >= 0; i--) @@ -710,25 +695,17 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, for(i = 0; i <= stereo; i++) *samples8++ = pred[i]; for(; i < unp_size; i++) { + unsigned idx = i & stereo; if (get_bits_left(&gb) < 0) { ret = AVERROR_INVALIDDATA; goto error; } - if(i & stereo){ - if(vlc[1].table) - res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); - else - res = values[1]; - pred[1] += sign_extend(res, 8); - *samples8++ = pred[1]; - } else { - if(vlc[0].table) - res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); - else - res = values[0]; - pred[0] += sign_extend(res, 8); - *samples8++ = pred[0]; - } + if (vlc[idx].table) + val = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + val = values[idx]; + pred[idx] += val; + *samples8++ = pred[idx]; } } @@ -743,7 +720,7 @@ error: 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, @@ -753,10 +730,10 @@ AVCodec ff_smacker_decoder = { .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, @@ -764,4 +741,5 @@ AVCodec ff_smackaud_decoder = { .init = smka_decode_init, .decode = smka_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, };