From aab0cfb7e37992b1c1ef34740d199cc2bdc4ce40 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 15 Aug 2023 12:18:02 +0200 Subject: [PATCH 1/4] avcodec/adpcm: refactor ADPCM_MS decoder Signed-off-by: Paul B Mahol --- libavcodec/adpcm.c | 63 ++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 59b9ef3497..b0c3b91a3b 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -535,12 +535,12 @@ static inline int16_t adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble) { int predictor; - predictor = (((c->sample1) * (c->coeff1)) + ((c->sample2) * (c->coeff2))) / 64; - predictor += ((nibble & 0x08)?(nibble - 0x10):(nibble)) * c->idelta; + predictor = ((c->sample1 * c->coeff1) + (c->sample2 * c->coeff2)) / 64; + predictor += ((nibble & 0x08)?(nibble - 0x10):nibble) * c->idelta; c->sample2 = c->sample1; c->sample1 = av_clip_int16(predictor); - c->idelta = (ff_adpcm_AdaptationTable[(int)nibble] * c->idelta) >> 8; + c->idelta = (ff_adpcm_AdaptationTable[nibble] * c->idelta) >> 8; if (c->idelta < 16) c->idelta = 16; if (c->idelta > INT_MAX/768) { av_log(NULL, AV_LOG_WARNING, "idelta overflow\n"); @@ -1236,6 +1236,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, if (avctx->ch_layout.nb_channels > 2) { for (int channel = 0; channel < avctx->ch_layout.nb_channels; channel++) { + ADPCMChannelStatus *status = &c->status[channel]; samples = samples_p[channel]; block_predictor = bytestream2_get_byteu(&gb); if (block_predictor > 6) { @@ -1243,28 +1244,30 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, channel, block_predictor); return AVERROR_INVALIDDATA; } - c->status[channel].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; - c->status[channel].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; - c->status[channel].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); - c->status[channel].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); - c->status[channel].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); - *samples++ = c->status[channel].sample2; - *samples++ = c->status[channel].sample1; - for (int n = (nb_samples - 2) >> 1; n > 0; n--) { + status->coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + status->coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + status->idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + status->sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + status->sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + samples[0] = status->sample2; + samples[1] = status->sample1; + for (int n = 2; n < nb_samples; n += 2) { int byte = bytestream2_get_byteu(&gb); - *samples++ = adpcm_ms_expand_nibble(&c->status[channel], byte >> 4 ); - *samples++ = adpcm_ms_expand_nibble(&c->status[channel], byte & 0x0F); + samples[n ] = adpcm_ms_expand_nibble(status, byte >> 4 ); + samples[n+1] = adpcm_ms_expand_nibble(status, byte & 0x0F); } } } else { + ADPCMChannelStatus *status0 = &c->status[0]; + ADPCMChannelStatus *status1 = &c->status[st]; block_predictor = bytestream2_get_byteu(&gb); if (block_predictor > 6) { av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[0] = %d\n", block_predictor); return AVERROR_INVALIDDATA; } - c->status[0].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; - c->status[0].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + status0->coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + status0->coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; if (st) { block_predictor = bytestream2_get_byteu(&gb); if (block_predictor > 6) { @@ -1272,27 +1275,27 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, block_predictor); return AVERROR_INVALIDDATA; } - c->status[1].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; - c->status[1].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + status1->coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + status1->coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; } - c->status[0].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + status0->idelta = sign_extend(bytestream2_get_le16u(&gb), 16); if (st){ - c->status[1].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + status1->idelta = sign_extend(bytestream2_get_le16u(&gb), 16); } - c->status[0].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); - if (st) c->status[1].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); - c->status[0].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); - if (st) c->status[1].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + status0->sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st) status1->sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + status0->sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st) status1->sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); - *samples++ = c->status[0].sample2; - if (st) *samples++ = c->status[1].sample2; - *samples++ = c->status[0].sample1; - if (st) *samples++ = c->status[1].sample1; - for (int n = (nb_samples - 2) >> (1 - st); n > 0; n--) { + *samples++ = status0->sample2; + if (st) *samples++ = status1->sample2; + *samples++ = status0->sample1; + if (st) *samples++ = status1->sample1; + for (int n = 0; n < (nb_samples - 2) * (st + 1); n += 2) { int byte = bytestream2_get_byteu(&gb); - *samples++ = adpcm_ms_expand_nibble(&c->status[0 ], byte >> 4 ); - *samples++ = adpcm_ms_expand_nibble(&c->status[st], byte & 0x0F); + samples[n ] = adpcm_ms_expand_nibble(status0, byte >> 4 ); + samples[n+1] = adpcm_ms_expand_nibble(status1, byte & 0x0F); } } ) /* End of CASE */ -- 2.39.1