1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-01-08 13:22:53 +02:00

avcodec/adpcm: refactor init/flush code

Most of the codecs just need everything zeroed. Those that don't
are either handled inline during decode, or pull state from
extradata.

Move state reset/init functionality into adpcm_flush(), and
invoke it from adpcm_decode_init().

Signed-off-by: Zane van Iperen <zane@zanevaniperen.com>
This commit is contained in:
Zane van Iperen 2021-03-31 17:23:34 +10:00
parent 9e89a23eac
commit c012f9b265
No known key found for this signature in database
GPG Key ID: 68616B2D8AC4DCC5

View File

@ -103,6 +103,8 @@ typedef struct ADPCMDecodeContext {
int has_status; /**< Status flag. Reset to 0 after a flush. */ int has_status; /**< Status flag. Reset to 0 after a flush. */
} ADPCMDecodeContext; } ADPCMDecodeContext;
static void adpcm_flush(AVCodecContext *avctx);
static av_cold int adpcm_decode_init(AVCodecContext * avctx) static av_cold int adpcm_decode_init(AVCodecContext * avctx)
{ {
ADPCMDecodeContext *c = avctx->priv_data; ADPCMDecodeContext *c = avctx->priv_data;
@ -150,38 +152,10 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
} }
switch(avctx->codec->id) { switch(avctx->codec->id) {
case AV_CODEC_ID_ADPCM_CT:
c->status[0].step = c->status[1].step = 511;
break;
case AV_CODEC_ID_ADPCM_IMA_WAV: case AV_CODEC_ID_ADPCM_IMA_WAV:
if (avctx->bits_per_coded_sample < 2 || avctx->bits_per_coded_sample > 5) if (avctx->bits_per_coded_sample < 2 || avctx->bits_per_coded_sample > 5)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
break; break;
case AV_CODEC_ID_ADPCM_IMA_APC:
if (avctx->extradata && avctx->extradata_size >= 8) {
c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata ), 18);
c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 4), 18);
}
break;
case AV_CODEC_ID_ADPCM_IMA_APM:
if (avctx->extradata) {
if (avctx->extradata_size >= 28) {
c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 16), 18);
c->status[0].step_index = av_clip(AV_RL32(avctx->extradata + 20), 0, 88);
c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 4), 18);
c->status[1].step_index = av_clip(AV_RL32(avctx->extradata + 8), 0, 88);
} else if (avctx->extradata_size >= 16) {
c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 0), 18);
c->status[0].step_index = av_clip(AV_RL32(avctx->extradata + 4), 0, 88);
c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 8), 18);
c->status[1].step_index = av_clip(AV_RL32(avctx->extradata + 12), 0, 88);
}
}
break;
case AV_CODEC_ID_ADPCM_IMA_WS:
if (avctx->extradata && avctx->extradata_size >= 2)
c->vqa_version = AV_RL16(avctx->extradata);
break;
case AV_CODEC_ID_ADPCM_ARGO: case AV_CODEC_ID_ADPCM_ARGO:
if (avctx->bits_per_coded_sample != 4 || avctx->block_align != 17 * avctx->channels) if (avctx->bits_per_coded_sample != 4 || avctx->block_align != 17 * avctx->channels)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
@ -228,6 +202,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_fmt = AV_SAMPLE_FMT_S16;
} }
adpcm_flush(avctx);
return 0; return 0;
} }
@ -2110,29 +2085,41 @@ static void adpcm_flush(AVCodecContext *avctx)
{ {
ADPCMDecodeContext *c = avctx->priv_data; ADPCMDecodeContext *c = avctx->priv_data;
/* Just nuke the entire state and re-init. */
memset(c, 0, sizeof(ADPCMDecodeContext));
switch(avctx->codec_id) { switch(avctx->codec_id) {
case AV_CODEC_ID_ADPCM_AICA: case AV_CODEC_ID_ADPCM_CT:
for (int channel = 0; channel < avctx->channels; channel++) c->status[0].step = c->status[1].step = 511;
c->status[channel].step = 0;
break; break;
case AV_CODEC_ID_ADPCM_ARGO: case AV_CODEC_ID_ADPCM_IMA_APC:
for (int channel = 0; channel < avctx->channels; channel++) { if (avctx->extradata && avctx->extradata_size >= 8) {
c->status[channel].sample1 = 0; c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata ), 18);
c->status[channel].sample2 = 0; c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 4), 18);
} }
break; break;
case AV_CODEC_ID_ADPCM_IMA_ALP: case AV_CODEC_ID_ADPCM_IMA_APM:
case AV_CODEC_ID_ADPCM_IMA_CUNNING: if (avctx->extradata) {
case AV_CODEC_ID_ADPCM_IMA_SSI: if (avctx->extradata_size >= 28) {
case AV_CODEC_ID_ADPCM_ZORK: c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 16), 18);
for (int channel = 0; channel < avctx->channels; channel++) { c->status[0].step_index = av_clip(AV_RL32(avctx->extradata + 20), 0, 88);
c->status[channel].predictor = 0; c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 4), 18);
c->status[channel].step_index = 0; c->status[1].step_index = av_clip(AV_RL32(avctx->extradata + 8), 0, 88);
} else if (avctx->extradata_size >= 16) {
c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 0), 18);
c->status[0].step_index = av_clip(AV_RL32(avctx->extradata + 4), 0, 88);
c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 8), 18);
c->status[1].step_index = av_clip(AV_RL32(avctx->extradata + 12), 0, 88);
}
} }
break; break;
case AV_CODEC_ID_ADPCM_IMA_WS:
if (avctx->extradata && avctx->extradata_size >= 2)
c->vqa_version = AV_RL16(avctx->extradata);
break;
default: default:
/* Other codecs may want to handle this during decoding. */ /* Other codecs may want to handle this during decoding. */
c->has_status = 0; c->has_status = 0;