| @@ -40,6 +40,7 @@ | |||
| #include "libavutil/intreadwrite.h" | |||
| #include "avcodec.h" | |||
| #include "bytestream.h" | |||
| #include "mathops.h" | |||
| typedef struct DPCMContext { | |||
| AVFrame frame; | |||
| @@ -173,20 +174,18 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx) | |||
| static int dpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
| int *got_frame_ptr, AVPacket *avpkt) | |||
| { | |||
| const uint8_t *buf = avpkt->data; | |||
| int buf_size = avpkt->size; | |||
| const uint8_t *buf_end = buf + buf_size; | |||
| DPCMContext *s = avctx->priv_data; | |||
| int out = 0, ret; | |||
| int predictor[2]; | |||
| int ch = 0; | |||
| int stereo = s->channels - 1; | |||
| int16_t *output_samples; | |||
| int16_t *output_samples, *samples_end; | |||
| GetByteContext gb; | |||
| if (stereo && (buf_size & 1)) { | |||
| if (stereo && (buf_size & 1)) | |||
| buf_size--; | |||
| buf_end--; | |||
| } | |||
| bytestream2_init(&gb, avpkt->data, buf_size); | |||
| /* calculate output size */ | |||
| switch(avctx->codec->id) { | |||
| @@ -218,22 +217,23 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
| return ret; | |||
| } | |||
| output_samples = (int16_t *)s->frame.data[0]; | |||
| samples_end = output_samples + out; | |||
| switch(avctx->codec->id) { | |||
| case CODEC_ID_ROQ_DPCM: | |||
| buf += 6; | |||
| bytestream2_skipu(&gb, 6); | |||
| if (stereo) { | |||
| predictor[1] = (int16_t)(bytestream_get_byte(&buf) << 8); | |||
| predictor[0] = (int16_t)(bytestream_get_byte(&buf) << 8); | |||
| predictor[1] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16); | |||
| predictor[0] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16); | |||
| } else { | |||
| predictor[0] = (int16_t)bytestream_get_le16(&buf); | |||
| predictor[0] = sign_extend(bytestream2_get_le16u(&gb), 16); | |||
| } | |||
| /* decode the samples */ | |||
| while (buf < buf_end) { | |||
| predictor[ch] += s->roq_square_array[*buf++]; | |||
| while (output_samples < samples_end) { | |||
| predictor[ch] += s->roq_square_array[bytestream2_get_byteu(&gb)]; | |||
| predictor[ch] = av_clip_int16(predictor[ch]); | |||
| *output_samples++ = predictor[ch]; | |||
| @@ -243,16 +243,16 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
| break; | |||
| case CODEC_ID_INTERPLAY_DPCM: | |||
| buf += 6; /* skip over the stream mask and stream length */ | |||
| bytestream2_skipu(&gb, 6); /* skip over the stream mask and stream length */ | |||
| for (ch = 0; ch < s->channels; ch++) { | |||
| predictor[ch] = (int16_t)bytestream_get_le16(&buf); | |||
| predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); | |||
| *output_samples++ = predictor[ch]; | |||
| } | |||
| ch = 0; | |||
| while (buf < buf_end) { | |||
| predictor[ch] += interplay_delta_table[*buf++]; | |||
| while (output_samples < samples_end) { | |||
| predictor[ch] += interplay_delta_table[bytestream2_get_byteu(&gb)]; | |||
| predictor[ch] = av_clip_int16(predictor[ch]); | |||
| *output_samples++ = predictor[ch]; | |||
| @@ -266,16 +266,19 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
| int shift[2] = { 4, 4 }; | |||
| for (ch = 0; ch < s->channels; ch++) | |||
| predictor[ch] = (int16_t)bytestream_get_le16(&buf); | |||
| predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); | |||
| ch = 0; | |||
| while (buf < buf_end) { | |||
| uint8_t n = *buf++; | |||
| int16_t diff = (n & 0xFC) << 8; | |||
| if ((n & 0x03) == 3) | |||
| while (output_samples < samples_end) { | |||
| int diff = bytestream2_get_byteu(&gb); | |||
| int n = diff & 3; | |||
| if (n == 3) | |||
| shift[ch]++; | |||
| else | |||
| shift[ch] -= (2 * (n & 3)); | |||
| shift[ch] -= (2 * n); | |||
| diff = sign_extend((diff &~ 3) << 8, 16); | |||
| /* saturate the shifter to a lower limit of 0 */ | |||
| if (shift[ch] < 0) | |||
| shift[ch] = 0; | |||
| @@ -293,9 +296,10 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
| } | |||
| case CODEC_ID_SOL_DPCM: | |||
| if (avctx->codec_tag != 3) { | |||
| uint8_t *output_samples_u8 = s->frame.data[0]; | |||
| while (buf < buf_end) { | |||
| uint8_t n = *buf++; | |||
| uint8_t *output_samples_u8 = s->frame.data[0], | |||
| *samples_end_u8 = output_samples_u8 + out; | |||
| while (output_samples_u8 < samples_end_u8) { | |||
| int n = bytestream2_get_byteu(&gb); | |||
| s->sample[0] += s->sol_table[n >> 4]; | |||
| s->sample[0] = av_clip_uint8(s->sample[0]); | |||
| @@ -306,8 +310,8 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, | |||
| *output_samples_u8++ = s->sample[stereo]; | |||
| } | |||
| } else { | |||
| while (buf < buf_end) { | |||
| uint8_t n = *buf++; | |||
| while (output_samples < samples_end) { | |||
| int n = bytestream2_get_byteu(&gb); | |||
| if (n & 0x80) s->sample[ch] -= sol_table_16[n & 0x7F]; | |||
| else s->sample[ch] += sol_table_16[n & 0x7F]; | |||
| s->sample[ch] = av_clip_int16(s->sample[ch]); | |||