| @@ -38,82 +38,95 @@ static av_cold int adx_decode_init(AVCodecContext *avctx) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* 18 bytes <-> 32 samples */ | |||||
| static void adx_decode(int16_t *out,const unsigned char *in, | |||||
| ADXChannelState *prev) | |||||
| /** | |||||
| * Decode 32 samples from 18 bytes. | |||||
| * | |||||
| * A 16-bit scalar value is applied to 32 residuals, which then have a | |||||
| * 2nd-order LPC filter applied to it to form the output signal for a single | |||||
| * channel. | |||||
| */ | |||||
| static void adx_decode(int16_t *out, const uint8_t *in, ADXChannelState *prev) | |||||
| { | { | ||||
| int scale = AV_RB16(in); | int scale = AV_RB16(in); | ||||
| int i; | int i; | ||||
| int s0,s1,s2,d; | |||||
| int s0, s1, s2, d; | |||||
| in+=2; | |||||
| in += 2; | |||||
| s1 = prev->s1; | s1 = prev->s1; | ||||
| s2 = prev->s2; | s2 = prev->s2; | ||||
| for(i=0;i<16;i++) { | |||||
| d = in[i]; | |||||
| d = ((signed char)d >> 4); | |||||
| s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14; | |||||
| for (i = 0; i < 16; i++) { | |||||
| d = in[i]; | |||||
| d = (signed char)d >> 4; | |||||
| s0 = (BASEVOL * d * scale + SCALE1 * s1 - SCALE2 * s2) >> 14; | |||||
| s2 = s1; | s2 = s1; | ||||
| s1 = av_clip_int16(s0); | s1 = av_clip_int16(s0); | ||||
| *out++=s1; | |||||
| *out++ = s1; | |||||
| d = in[i]; | |||||
| d = ((signed char)(d<<4) >> 4); | |||||
| s0 = (BASEVOL*d*scale + SCALE1*s1 - SCALE2*s2)>>14; | |||||
| d = in[i]; | |||||
| d = (signed char)(d << 4) >> 4; | |||||
| s0 = (BASEVOL * d * scale + SCALE1 * s1 - SCALE2 * s2) >> 14; | |||||
| s2 = s1; | s2 = s1; | ||||
| s1 = av_clip_int16(s0); | s1 = av_clip_int16(s0); | ||||
| *out++=s1; | |||||
| *out++ = s1; | |||||
| } | } | ||||
| prev->s1 = s1; | prev->s1 = s1; | ||||
| prev->s2 = s2; | prev->s2 = s2; | ||||
| } | } | ||||
| static void adx_decode_stereo(int16_t *out,const unsigned char *in, | |||||
| static void adx_decode_stereo(int16_t *out,const uint8_t *in, | |||||
| ADXChannelState *prev) | ADXChannelState *prev) | ||||
| { | { | ||||
| short tmp[32*2]; | short tmp[32*2]; | ||||
| int i; | int i; | ||||
| adx_decode(tmp ,in ,prev); | |||||
| adx_decode(tmp+32,in+18,prev+1); | |||||
| for(i=0;i<32;i++) { | |||||
| out[i*2] = tmp[i]; | |||||
| adx_decode(tmp, in, prev); | |||||
| adx_decode(tmp+32, in+18, prev+1); | |||||
| for (i = 0; i < 32; i++) { | |||||
| out[i*2 ] = tmp[i ]; | |||||
| out[i*2+1] = tmp[i+32]; | out[i*2+1] = tmp[i+32]; | ||||
| } | } | ||||
| } | } | ||||
| /* return data offset or 0 */ | |||||
| static int adx_decode_header(AVCodecContext *avctx,const unsigned char *buf,size_t bufsize) | |||||
| /** | |||||
| * Decode stream header. | |||||
| * | |||||
| * @param avctx codec context | |||||
| * @param buf packet data | |||||
| * @param bufsize packet size | |||||
| * @return data offset or 0 if header is invalid | |||||
| */ | |||||
| static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, | |||||
| int bufsize) | |||||
| { | { | ||||
| int offset; | int offset; | ||||
| if (buf[0]!=0x80) return 0; | |||||
| offset = (AV_RB32(buf)^0x80000000)+4; | |||||
| if (bufsize<offset || memcmp(buf+offset-6,"(c)CRI",6)) return 0; | |||||
| if (buf[0] != 0x80) | |||||
| return 0; | |||||
| offset = (AV_RB32(buf) ^ 0x80000000) + 4; | |||||
| if (bufsize < offset || memcmp(buf + offset - 6, "(c)CRI", 6)) | |||||
| return 0; | |||||
| avctx->channels = buf[7]; | avctx->channels = buf[7]; | ||||
| avctx->sample_rate = AV_RB32(buf+8); | |||||
| avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; | |||||
| avctx->sample_rate = AV_RB32(buf + 8); | |||||
| avctx->bit_rate = avctx->sample_rate * avctx->channels * 18 * 8 / 32; | |||||
| return offset; | return offset; | ||||
| } | } | ||||
| static int adx_decode_frame(AVCodecContext *avctx, | |||||
| void *data, int *data_size, | |||||
| AVPacket *avpkt) | |||||
| static int adx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||||
| AVPacket *avpkt) | |||||
| { | { | ||||
| const uint8_t *buf0 = avpkt->data; | const uint8_t *buf0 = avpkt->data; | ||||
| int buf_size = avpkt->size; | |||||
| ADXContext *c = avctx->priv_data; | |||||
| int16_t *samples = data; | |||||
| const uint8_t *buf = buf0; | |||||
| int rest = buf_size; | |||||
| int buf_size = avpkt->size; | |||||
| ADXContext *c = avctx->priv_data; | |||||
| int16_t *samples = data; | |||||
| const uint8_t *buf = buf0; | |||||
| int rest = buf_size; | |||||
| if (!c->header_parsed) { | if (!c->header_parsed) { | ||||
| int hdrsize = adx_decode_header(avctx,buf,rest); | |||||
| if (hdrsize==0) return -1; | |||||
| int hdrsize = adx_decode_header(avctx, buf, rest); | |||||
| if (!hdrsize) | |||||
| return -1; | |||||
| c->header_parsed = 1; | c->header_parsed = 1; | ||||
| buf += hdrsize; | buf += hdrsize; | ||||
| rest -= hdrsize; | rest -= hdrsize; | ||||
| @@ -121,46 +134,46 @@ static int adx_decode_frame(AVCodecContext *avctx, | |||||
| /* 18 bytes of data are expanded into 32*2 bytes of audio, | /* 18 bytes of data are expanded into 32*2 bytes of audio, | ||||
| so guard against buffer overflows */ | so guard against buffer overflows */ | ||||
| if(rest/18 > *data_size/64) | |||||
| rest = (*data_size/64) * 18; | |||||
| if (rest / 18 > *data_size / 64) | |||||
| rest = (*data_size / 64) * 18; | |||||
| if (c->in_temp) { | if (c->in_temp) { | ||||
| int copysize = 18*avctx->channels - c->in_temp; | |||||
| memcpy(c->dec_temp+c->in_temp,buf,copysize); | |||||
| int copysize = 18 * avctx->channels - c->in_temp; | |||||
| memcpy(c->dec_temp + c->in_temp, buf, copysize); | |||||
| rest -= copysize; | rest -= copysize; | ||||
| buf += copysize; | buf += copysize; | ||||
| if (avctx->channels==1) { | |||||
| adx_decode(samples,c->dec_temp,c->prev); | |||||
| if (avctx->channels == 1) { | |||||
| adx_decode(samples, c->dec_temp, c->prev); | |||||
| samples += 32; | samples += 32; | ||||
| } else { | } else { | ||||
| adx_decode_stereo(samples,c->dec_temp,c->prev); | |||||
| adx_decode_stereo(samples, c->dec_temp, c->prev); | |||||
| samples += 32*2; | samples += 32*2; | ||||
| } | } | ||||
| } | } | ||||
| if (avctx->channels==1) { | |||||
| while(rest>=18) { | |||||
| adx_decode(samples,buf,c->prev); | |||||
| rest-=18; | |||||
| buf+=18; | |||||
| samples+=32; | |||||
| if (avctx->channels == 1) { | |||||
| while (rest >= 18) { | |||||
| adx_decode(samples, buf, c->prev); | |||||
| rest -= 18; | |||||
| buf += 18; | |||||
| samples += 32; | |||||
| } | } | ||||
| } else { | } else { | ||||
| while(rest>=18*2) { | |||||
| adx_decode_stereo(samples,buf,c->prev); | |||||
| rest-=18*2; | |||||
| buf+=18*2; | |||||
| samples+=32*2; | |||||
| while (rest >= 18 * 2) { | |||||
| adx_decode_stereo(samples, buf, c->prev); | |||||
| rest -= 18 * 2; | |||||
| buf += 18 * 2; | |||||
| samples += 32 * 2; | |||||
| } | } | ||||
| } | } | ||||
| c->in_temp = rest; | c->in_temp = rest; | ||||
| if (rest) { | if (rest) { | ||||
| memcpy(c->dec_temp,buf,rest); | |||||
| buf+=rest; | |||||
| memcpy(c->dec_temp, buf, rest); | |||||
| buf += rest; | |||||
| } | } | ||||
| *data_size = (uint8_t*)samples - (uint8_t*)data; | *data_size = (uint8_t*)samples - (uint8_t*)data; | ||||
| return buf-buf0; | |||||
| return buf - buf0; | |||||
| } | } | ||||
| AVCodec ff_adpcm_adx_decoder = { | AVCodec ff_adpcm_adx_decoder = { | ||||
| @@ -170,6 +183,5 @@ AVCodec ff_adpcm_adx_decoder = { | |||||
| .priv_data_size = sizeof(ADXContext), | .priv_data_size = sizeof(ADXContext), | ||||
| .init = adx_decode_init, | .init = adx_decode_init, | ||||
| .decode = adx_decode_frame, | .decode = adx_decode_frame, | ||||
| .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), | |||||
| .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), | |||||
| }; | }; | ||||