mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-11 17:55:21 +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)
|
if (!buf_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// almost every DPCM variant expands one byte of data into two
|
/* calculate output size */
|
||||||
if(*data_size/2 < buf_size)
|
switch(avctx->codec->id) {
|
||||||
return -1;
|
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) {
|
switch(avctx->codec->id) {
|
||||||
|
|
||||||
@ -195,10 +216,10 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
SE_16BIT(predictor[1]);
|
SE_16BIT(predictor[1]);
|
||||||
|
|
||||||
/* decode the samples */
|
/* 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] += s->roq_square_array[buf[in]];
|
||||||
predictor[ch] = av_clip_int16(predictor[ch]);
|
predictor[ch] = av_clip_int16(predictor[ch]);
|
||||||
output_samples[out] = predictor[ch];
|
*output_samples++ = predictor[ch];
|
||||||
|
|
||||||
/* toggle channel */
|
/* toggle channel */
|
||||||
ch ^= stereo;
|
ch ^= stereo;
|
||||||
@ -210,23 +231,22 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
predictor[0] = AV_RL16(&buf[in]);
|
predictor[0] = AV_RL16(&buf[in]);
|
||||||
in += 2;
|
in += 2;
|
||||||
SE_16BIT(predictor[0])
|
SE_16BIT(predictor[0])
|
||||||
output_samples[out++] = predictor[0];
|
*output_samples++ = predictor[0];
|
||||||
if (stereo) {
|
if (stereo) {
|
||||||
predictor[1] = AV_RL16(&buf[in]);
|
predictor[1] = AV_RL16(&buf[in]);
|
||||||
in += 2;
|
in += 2;
|
||||||
SE_16BIT(predictor[1])
|
SE_16BIT(predictor[1])
|
||||||
output_samples[out++] = predictor[1];
|
*output_samples++ = predictor[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
while (in < buf_size) {
|
while (in < buf_size) {
|
||||||
predictor[ch] += interplay_delta_table[buf[in++]];
|
predictor[ch] += interplay_delta_table[buf[in++]];
|
||||||
predictor[ch] = av_clip_int16(predictor[ch]);
|
predictor[ch] = av_clip_int16(predictor[ch]);
|
||||||
output_samples[out++] = predictor[ch];
|
*output_samples++ = predictor[ch];
|
||||||
|
|
||||||
/* toggle channel */
|
/* toggle channel */
|
||||||
ch ^= stereo;
|
ch ^= stereo;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CODEC_ID_XAN_DPCM:
|
case CODEC_ID_XAN_DPCM:
|
||||||
@ -256,7 +276,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
predictor[ch] += diff;
|
predictor[ch] += diff;
|
||||||
|
|
||||||
predictor[ch] = av_clip_int16(predictor[ch]);
|
predictor[ch] = av_clip_int16(predictor[ch]);
|
||||||
output_samples[out++] = predictor[ch];
|
*output_samples++ = predictor[ch];
|
||||||
|
|
||||||
/* toggle channel */
|
/* toggle channel */
|
||||||
ch ^= stereo;
|
ch ^= stereo;
|
||||||
@ -265,8 +285,6 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
case CODEC_ID_SOL_DPCM:
|
case CODEC_ID_SOL_DPCM:
|
||||||
in = 0;
|
in = 0;
|
||||||
if (avctx->codec_tag != 3) {
|
if (avctx->codec_tag != 3) {
|
||||||
if(*data_size/4 < buf_size)
|
|
||||||
return -1;
|
|
||||||
while (in < buf_size) {
|
while (in < buf_size) {
|
||||||
int n1, n2;
|
int n1, n2;
|
||||||
n1 = (buf[in] >> 4) & 0xF;
|
n1 = (buf[in] >> 4) & 0xF;
|
||||||
@ -274,11 +292,11 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
s->sample[0] += s->sol_table[n1];
|
s->sample[0] += s->sol_table[n1];
|
||||||
if (s->sample[0] < 0) s->sample[0] = 0;
|
if (s->sample[0] < 0) s->sample[0] = 0;
|
||||||
if (s->sample[0] > 255) s->sample[0] = 255;
|
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];
|
s->sample[stereo] += s->sol_table[n2];
|
||||||
if (s->sample[stereo] < 0) s->sample[stereo] = 0;
|
if (s->sample[stereo] < 0) s->sample[stereo] = 0;
|
||||||
if (s->sample[stereo] > 255) s->sample[stereo] = 255;
|
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 {
|
} else {
|
||||||
while (in < buf_size) {
|
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];
|
if (n & 0x80) s->sample[ch] -= s->sol_table[n & 0x7F];
|
||||||
else 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]);
|
s->sample[ch] = av_clip_int16(s->sample[ch]);
|
||||||
output_samples[out++] = s->sample[ch];
|
*output_samples++ = s->sample[ch];
|
||||||
/* toggle channel */
|
/* toggle channel */
|
||||||
ch ^= stereo;
|
ch ^= stereo;
|
||||||
}
|
}
|
||||||
@ -295,7 +313,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*data_size = out * sizeof(short);
|
*data_size = out;
|
||||||
return buf_size;
|
return buf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user