Originally committed as revision 1928 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -312,6 +312,33 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble) | |||
| return (short)predictor; | |||
| } | |||
| static inline short adpcm_4xa_expand_nibble(ADPCMChannelStatus *c, char nibble) | |||
| { | |||
| int step_index; | |||
| int predictor; | |||
| int sign, delta, diff, step; | |||
| step = step_table[c->step_index]; | |||
| step_index = c->step_index + index_table[(unsigned)nibble]; | |||
| if (step_index < 0) step_index = 0; | |||
| else if (step_index > 88) step_index = 88; | |||
| sign = nibble & 8; | |||
| delta = nibble & 7; | |||
| diff = (delta*step + (step>>1))>>3; // difference to code above | |||
| predictor = c->predictor; | |||
| if (sign) predictor -= diff; | |||
| else predictor += diff; | |||
| CLAMP_TO_SHORT(predictor); | |||
| c->predictor = predictor; | |||
| c->step_index = step_index; | |||
| return (short)predictor; | |||
| } | |||
| static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, char nibble) | |||
| { | |||
| int predictor; | |||
| @@ -334,7 +361,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, | |||
| { | |||
| ADPCMContext *c = avctx->priv_data; | |||
| ADPCMChannelStatus *cs; | |||
| int n, m, channel; | |||
| int n, m, channel, i; | |||
| int block_predictor[2]; | |||
| short *samples; | |||
| uint8_t *src; | |||
| @@ -444,6 +471,34 @@ static int adpcm_decode_frame(AVCodecContext *avctx, | |||
| } | |||
| src++; | |||
| } | |||
| break; | |||
| case CODEC_ID_ADPCM_4XM: | |||
| cs = &(c->status[0]); | |||
| c->status[0].predictor= (int16_t)(src[0] + (src[1]<<8)); src+=2; | |||
| if(st){ | |||
| c->status[1].predictor= (int16_t)(src[0] + (src[1]<<8)); src+=2; | |||
| } | |||
| c->status[0].step_index= (int16_t)(src[0] + (src[1]<<8)); src+=2; | |||
| if(st){ | |||
| c->status[1].step_index= (int16_t)(src[0] + (src[1]<<8)); src+=2; | |||
| } | |||
| // if (cs->step_index < 0) cs->step_index = 0; | |||
| // if (cs->step_index > 88) cs->step_index = 88; | |||
| m= (buf_size - (src - buf))>>st; | |||
| //printf("%d %d %d %d\n", st, m, c->status[0].predictor, c->status[0].step_index); | |||
| //FIXME / XXX decode chanels individual & interleave samples | |||
| for(i=0; i<m; i++) { | |||
| *samples++ = adpcm_4xa_expand_nibble(&c->status[0], src[i] & 0x0F); | |||
| if (st) | |||
| *samples++ = adpcm_4xa_expand_nibble(&c->status[1], src[i+m] & 0x0F); | |||
| *samples++ = adpcm_4xa_expand_nibble(&c->status[0], src[i] >> 4); | |||
| if (st) | |||
| *samples++ = adpcm_4xa_expand_nibble(&c->status[1], src[i+m] >> 4); | |||
| } | |||
| src += m<<st; | |||
| break; | |||
| case CODEC_ID_ADPCM_MS: | |||
| @@ -529,6 +584,7 @@ AVCodec name ## _decoder = { \ | |||
| ADPCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt); | |||
| ADPCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav); | |||
| ADPCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); | |||
| ADPCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); | |||
| #undef ADPCM_CODEC | |||
| @@ -133,6 +133,7 @@ PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw); | |||
| PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt); | |||
| PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav); | |||
| PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); | |||
| PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); | |||
| #undef PCM_CODEC | |||
| } | |||
| @@ -1269,6 +1269,7 @@ PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw); | |||
| PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt); | |||
| PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav); | |||
| PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); | |||
| PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); | |||
| #undef PCM_CODEC | |||
| @@ -71,6 +71,7 @@ typedef struct AudioTrack { | |||
| int bits; | |||
| int channels; | |||
| int stream_index; | |||
| int adpcm; | |||
| } AudioTrack; | |||
| typedef struct FourxmDemuxContext { | |||
| @@ -172,9 +173,11 @@ static int fourxm_read_header(AVFormatContext *s, | |||
| return AVERROR_NOMEM; | |||
| } | |||
| } | |||
| fourxm->tracks[current_track].adpcm = LE_32(&header[i + 12]); | |||
| fourxm->tracks[current_track].channels = LE_32(&header[i + 36]); | |||
| fourxm->tracks[current_track].sample_rate = LE_32(&header[i + 40]); | |||
| fourxm->tracks[current_track].bits = LE_32(&header[i + 44]); | |||
| printf("bps:%d\n", fourxm->tracks[current_track].bits); | |||
| i += 8 + size; | |||
| /* allocate a new AVStream */ | |||
| @@ -192,7 +195,9 @@ static int fourxm_read_header(AVFormatContext *s, | |||
| st->codec.bit_rate = st->codec.channels * st->codec.sample_rate * | |||
| st->codec.bits_per_sample; | |||
| st->codec.block_align = st->codec.channels * st->codec.bits_per_sample; | |||
| if (st->codec.bits_per_sample == 8) | |||
| if (fourxm->tracks[current_track].adpcm) | |||
| st->codec.codec_id = CODEC_ID_ADPCM_4XM; | |||
| else if (st->codec.bits_per_sample == 8) | |||
| st->codec.codec_id = CODEC_ID_PCM_U8; | |||
| else | |||
| st->codec.codec_id = CODEC_ID_PCM_S16LE; | |||
| @@ -224,7 +229,7 @@ static int fourxm_read_packet(AVFormatContext *s, | |||
| FourxmDemuxContext *fourxm = s->priv_data; | |||
| ByteIOContext *pb = &s->pb; | |||
| unsigned int fourcc_tag; | |||
| unsigned int size; | |||
| unsigned int size, out_size; | |||
| int ret = 0; | |||
| int track_number; | |||
| int packet_read = 0; | |||
| @@ -237,10 +242,9 @@ static int fourxm_read_packet(AVFormatContext *s, | |||
| return ret; | |||
| fourcc_tag = LE_32(&header[0]); | |||
| size = LE_32(&header[4]); | |||
| //printf(" %8X %c%c%c%c %d\n", fourcc_tag, fourcc_tag, fourcc_tag>>8, fourcc_tag>>16, fourcc_tag>>24, size); | |||
| if (url_feof(pb)) | |||
| return -EIO; | |||
| switch (fourcc_tag) { | |||
| case LIST_TAG: | |||
| @@ -277,7 +281,7 @@ if (fourcc_tag == cfrm_TAG) { | |||
| id = LE_32(&pkt->data[12]); | |||
| whole = LE_32(&pkt->data[16]); | |||
| stats[id] += size - 12; | |||
| printf(" cfrm chunk id:%d size:%d whole:%d until now:%d\n", id, size, whole, stats[id]); | |||
| //printf(" cfrm chunk id:%d size:%d whole:%d until now:%d\n", id, size, whole, stats[id]); | |||
| } | |||
| if (ret < 0) | |||
| @@ -290,7 +294,9 @@ printf(" cfrm chunk id:%d size:%d whole:%d until now:%d\n", id, size, whole, sta | |||
| case snd__TAG: | |||
| printf (" snd_ chunk, "); | |||
| track_number = get_le32(pb); | |||
| size = get_le32(pb); | |||
| out_size= get_le32(pb); | |||
| size-=8; | |||
| if (track_number == fourxm->selected_track) { | |||
| printf ("correct track, dispatching...\n"); | |||
| if (av_new_packet(pkt, size)) | |||
| @@ -321,7 +327,6 @@ printf ("wrong track, skipping...\n"); | |||
| break; | |||
| } | |||
| } | |||
| return ret; | |||
| } | |||