|
|
|
@ -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]); |
|
|
|
|