You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
adpcm_ima_ws: fix stereo decoding
Stereo ADPCM IMA WS is planar for VQA version 3 and 2-sample interleaved for VQA version 2.
This commit is contained in:
@@ -86,6 +86,7 @@ static const int swf_index_tables[4][16] = {
|
|||||||
typedef struct ADPCMDecodeContext {
|
typedef struct ADPCMDecodeContext {
|
||||||
AVFrame frame;
|
AVFrame frame;
|
||||||
ADPCMChannelStatus status[6];
|
ADPCMChannelStatus status[6];
|
||||||
|
int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */
|
||||||
} ADPCMDecodeContext;
|
} ADPCMDecodeContext;
|
||||||
|
|
||||||
static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
||||||
@@ -126,6 +127,10 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
|||||||
c->status[1].predictor = AV_RL32(avctx->extradata + 4);
|
c->status[1].predictor = AV_RL32(avctx->extradata + 4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CODEC_ID_ADPCM_IMA_WS:
|
||||||
|
if (avctx->extradata && avctx->extradata_size >= 42)
|
||||||
|
c->vqa_version = AV_RL16(avctx->extradata);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -774,7 +779,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3);
|
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_ADPCM_IMA_WS:
|
|
||||||
case CODEC_ID_ADPCM_IMA_APC:
|
case CODEC_ID_ADPCM_IMA_APC:
|
||||||
while (src < buf + buf_size) {
|
while (src < buf + buf_size) {
|
||||||
uint8_t v = *src++;
|
uint8_t v = *src++;
|
||||||
@@ -782,6 +786,30 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
|
*samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CODEC_ID_ADPCM_IMA_WS:
|
||||||
|
for (channel = 0; channel < avctx->channels; channel++) {
|
||||||
|
const uint8_t *src0;
|
||||||
|
int src_stride;
|
||||||
|
int16_t *smp = samples + channel;
|
||||||
|
|
||||||
|
if (c->vqa_version == 3) {
|
||||||
|
src0 = src + channel * buf_size / 2;
|
||||||
|
src_stride = 1;
|
||||||
|
} else {
|
||||||
|
src0 = src + channel;
|
||||||
|
src_stride = avctx->channels;
|
||||||
|
}
|
||||||
|
for (n = nb_samples / 2; n > 0; n--) {
|
||||||
|
uint8_t v = *src0;
|
||||||
|
src0 += src_stride;
|
||||||
|
*smp = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3);
|
||||||
|
smp += avctx->channels;
|
||||||
|
*smp = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3);
|
||||||
|
smp += avctx->channels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src = buf + buf_size;
|
||||||
|
break;
|
||||||
case CODEC_ID_ADPCM_XA:
|
case CODEC_ID_ADPCM_XA:
|
||||||
while (buf_size >= 128) {
|
while (buf_size >= 128) {
|
||||||
xa_decode(samples, src, &c->status[0], &c->status[1],
|
xa_decode(samples, src, &c->status[0], &c->status[1],
|
||||||
|
@@ -128,6 +128,12 @@ static int wsvqa_read_header(AVFormatContext *s,
|
|||||||
st->start_time = 0;
|
st->start_time = 0;
|
||||||
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
|
|
||||||
|
st->codec->extradata_size = VQA_HEADER_SIZE;
|
||||||
|
st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (!st->codec->extradata)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
memcpy(st->codec->extradata, header, VQA_HEADER_SIZE);
|
||||||
|
|
||||||
if (!sample_rate)
|
if (!sample_rate)
|
||||||
sample_rate = 22050;
|
sample_rate = 22050;
|
||||||
st->codec->sample_rate = sample_rate;
|
st->codec->sample_rate = sample_rate;
|
||||||
|
Reference in New Issue
Block a user