mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-28 05:50:43 +00:00
dpcm: calculate and check actual output data size prior to decoding.
This commit is contained in:
parent
3db8db406f
commit
76db17dc7d
@ -178,9 +178,30 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
if (!buf_size)
|
||||
return 0;
|
||||
|
||||
// almost every DPCM variant expands one byte of data into two
|
||||
if(*data_size/2 < buf_size)
|
||||
return -1;
|
||||
/* calculate output size */
|
||||
switch(avctx->codec->id) {
|
||||
case CODEC_ID_ROQ_DPCM:
|
||||
out = buf_size - 8;
|
||||
break;
|
||||
case CODEC_ID_INTERPLAY_DPCM:
|
||||
out = buf_size - 6 - s->channels;
|
||||
break;
|
||||
case CODEC_ID_XAN_DPCM:
|
||||
out = buf_size - 2 * s->channels;
|
||||
break;
|
||||
case CODEC_ID_SOL_DPCM:
|
||||
if (avctx->codec_tag != 3)
|
||||
out = buf_size * 2;
|
||||
else
|
||||
out = buf_size;
|
||||
break;
|
||||
}
|
||||
out *= av_get_bytes_per_sample(avctx->sample_fmt);
|
||||
|
||||
if (*data_size < out) {
|
||||
av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
switch(avctx->codec->id) {
|
||||
|
||||
@ -195,10 +216,10 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
SE_16BIT(predictor[1]);
|
||||
|
||||
/* decode the samples */
|
||||
for (in = 8, out = 0; in < buf_size; in++, out++) {
|
||||
for (in = 8; in < buf_size; in++) {
|
||||
predictor[ch] += s->roq_square_array[buf[in]];
|
||||
predictor[ch] = av_clip_int16(predictor[ch]);
|
||||
output_samples[out] = predictor[ch];
|
||||
*output_samples++ = predictor[ch];
|
||||
|
||||
/* toggle channel */
|
||||
ch ^= stereo;
|
||||
@ -210,23 +231,22 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
predictor[0] = AV_RL16(&buf[in]);
|
||||
in += 2;
|
||||
SE_16BIT(predictor[0])
|
||||
output_samples[out++] = predictor[0];
|
||||
*output_samples++ = predictor[0];
|
||||
if (stereo) {
|
||||
predictor[1] = AV_RL16(&buf[in]);
|
||||
in += 2;
|
||||
SE_16BIT(predictor[1])
|
||||
output_samples[out++] = predictor[1];
|
||||
*output_samples++ = predictor[1];
|
||||
}
|
||||
|
||||
while (in < buf_size) {
|
||||
predictor[ch] += interplay_delta_table[buf[in++]];
|
||||
predictor[ch] = av_clip_int16(predictor[ch]);
|
||||
output_samples[out++] = predictor[ch];
|
||||
*output_samples++ = predictor[ch];
|
||||
|
||||
/* toggle channel */
|
||||
ch ^= stereo;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CODEC_ID_XAN_DPCM:
|
||||
@ -256,7 +276,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
predictor[ch] += diff;
|
||||
|
||||
predictor[ch] = av_clip_int16(predictor[ch]);
|
||||
output_samples[out++] = predictor[ch];
|
||||
*output_samples++ = predictor[ch];
|
||||
|
||||
/* toggle channel */
|
||||
ch ^= stereo;
|
||||
@ -265,8 +285,6 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
case CODEC_ID_SOL_DPCM:
|
||||
in = 0;
|
||||
if (avctx->codec_tag != 3) {
|
||||
if(*data_size/4 < buf_size)
|
||||
return -1;
|
||||
while (in < buf_size) {
|
||||
int n1, n2;
|
||||
n1 = (buf[in] >> 4) & 0xF;
|
||||
@ -274,11 +292,11 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
s->sample[0] += s->sol_table[n1];
|
||||
if (s->sample[0] < 0) s->sample[0] = 0;
|
||||
if (s->sample[0] > 255) s->sample[0] = 255;
|
||||
output_samples[out++] = (s->sample[0] - 128) << 8;
|
||||
*output_samples++ = (s->sample[0] - 128) << 8;
|
||||
s->sample[stereo] += s->sol_table[n2];
|
||||
if (s->sample[stereo] < 0) s->sample[stereo] = 0;
|
||||
if (s->sample[stereo] > 255) s->sample[stereo] = 255;
|
||||
output_samples[out++] = (s->sample[stereo] - 128) << 8;
|
||||
*output_samples++ = (s->sample[stereo] - 128) << 8;
|
||||
}
|
||||
} else {
|
||||
while (in < buf_size) {
|
||||
@ -287,7 +305,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
if (n & 0x80) s->sample[ch] -= s->sol_table[n & 0x7F];
|
||||
else s->sample[ch] += s->sol_table[n & 0x7F];
|
||||
s->sample[ch] = av_clip_int16(s->sample[ch]);
|
||||
output_samples[out++] = s->sample[ch];
|
||||
*output_samples++ = s->sample[ch];
|
||||
/* toggle channel */
|
||||
ch ^= stereo;
|
||||
}
|
||||
@ -295,7 +313,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
||||
break;
|
||||
}
|
||||
|
||||
*data_size = out * sizeof(short);
|
||||
*data_size = out;
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user