summaryrefslogtreecommitdiff
path: root/libavcodec/nellymoserdec.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-10-03 01:02:45 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-10-03 01:02:45 +0200
commit487e088e5e7f4cade6bce5e9a3cff28fce303af1 (patch)
treeb11de275564c0afeb4166c97acf6a9b4e0995dba /libavcodec/nellymoserdec.c
parentcffd20b90ee6f35e37cdb51dd94e6b2174fd31b6 (diff)
parent5674d4b0a35a34b75e3533a8580e0b5a0a8895a7 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: mpc8: check output buffer size before decoding mpc7: return error if packet is too small. mpc7: check output buffer size before decoding nellymoserdec: allocate float_buf only when decoding to int16 nellymoserdec: use NELLY_BUF_LEN instead of 128 nellymoserdec: use NELLY_BLOCK_LEN instead of 64 when appropriate. nellymoserdec: allow user to request SAMPLE_FMT_FLT for output samples. nellymoser: check output buffer size before decoding win32: improve threading algorithm warning Conflicts: libavcodec/nellymoserdec.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/nellymoserdec.c')
-rw-r--r--libavcodec/nellymoserdec.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/libavcodec/nellymoserdec.c b/libavcodec/nellymoserdec.c
index 23fecbfa26..04d966173a 100644
--- a/libavcodec/nellymoserdec.c
+++ b/libavcodec/nellymoserdec.c
@@ -47,8 +47,8 @@
typedef struct NellyMoserDecodeContext {
AVCodecContext* avctx;
- DECLARE_ALIGNED(32, float, float_buf)[NELLY_SAMPLES];
- float state[128];
+ float *float_buf;
+ float state[NELLY_BUF_LEN];
AVLFG random_state;
GetBitContext gb;
float scale_bias;
@@ -137,15 +137,25 @@ static av_cold int decode_init(AVCodecContext * avctx) {
ff_mdct_init(&s->imdct_ctx, 8, 1, 1.0);
dsputil_init(&s->dsp, avctx);
- ff_fmt_convert_init(&s->fmt_conv, avctx);
- s->scale_bias = 1.0/(1*8);
+ if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) {
+ s->scale_bias = 1.0/(32768*8);
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
+ } else {
+ s->scale_bias = 1.0/(1*8);
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ ff_fmt_convert_init(&s->fmt_conv, avctx);
+ s->float_buf = av_mallocz(NELLY_SAMPLES * sizeof(*s->float_buf));
+ if (!s->float_buf) {
+ av_log(avctx, AV_LOG_ERROR, "error allocating float buffer\n");
+ return AVERROR(ENOMEM);
+ }
+ }
/* Generate overlap window */
if (!ff_sine_128[127])
ff_init_ff_sine_windows(7);
- avctx->sample_fmt = AV_SAMPLE_FMT_S16;
avctx->channel_layout = AV_CH_LAYOUT_MONO;
return 0;
}
@@ -157,19 +167,25 @@ static int decode_tag(AVCodecContext * avctx,
int buf_size = avpkt->size;
NellyMoserDecodeContext *s = avctx->priv_data;
int data_max = *data_size;
- int blocks, i;
- int16_t* samples;
+ int blocks, i, block_size;
+ int16_t *samples_s16 = data;
+ float *samples_flt = data;
*data_size = 0;
- samples = (int16_t*)data;
- if (buf_size < avctx->block_align)
+ if (buf_size < avctx->block_align) {
return buf_size;
+ }
- if (buf_size % 64) {
+ if (buf_size % NELLY_BLOCK_LEN) {
av_log(avctx, AV_LOG_ERROR, "Tag size %d.\n", buf_size);
return buf_size;
}
- blocks = buf_size / 64;
+ block_size = NELLY_SAMPLES * av_get_bytes_per_sample(avctx->sample_fmt);
+ blocks = FFMIN(buf_size / NELLY_BLOCK_LEN, data_max / block_size);
+ if (blocks <= 0) {
+ av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n");
+ return AVERROR(EINVAL);
+ }
/* Normal numbers of blocks for sample rates:
* 8000 Hz - 1
* 11025 Hz - 2
@@ -179,12 +195,17 @@ static int decode_tag(AVCodecContext * avctx,
*/
for (i=0 ; i<blocks ; i++) {
- if ((i + 1) * NELLY_SAMPLES * sizeof(int16_t) > data_max)
- return i > 0 ? i * NELLY_BLOCK_LEN : -1;
- nelly_decode_block(s, &buf[i*NELLY_BLOCK_LEN], s->float_buf);
- s->fmt_conv.float_to_int16(&samples[i*NELLY_SAMPLES], s->float_buf, NELLY_SAMPLES);
- *data_size += NELLY_SAMPLES*sizeof(int16_t);
+ if (avctx->sample_fmt == SAMPLE_FMT_FLT) {
+ nelly_decode_block(s, buf, samples_flt);
+ samples_flt += NELLY_SAMPLES;
+ } else {
+ nelly_decode_block(s, buf, s->float_buf);
+ s->fmt_conv.float_to_int16(samples_s16, s->float_buf, NELLY_SAMPLES);
+ samples_s16 += NELLY_SAMPLES;
+ }
+ buf += NELLY_BLOCK_LEN;
}
+ *data_size = blocks * block_size;
return buf_size;
}
@@ -192,6 +213,7 @@ static int decode_tag(AVCodecContext * avctx,
static av_cold int decode_end(AVCodecContext * avctx) {
NellyMoserDecodeContext *s = avctx->priv_data;
+ av_freep(&s->float_buf);
ff_mdct_end(&s->imdct_ctx);
return 0;
}
@@ -205,5 +227,8 @@ AVCodec ff_nellymoser_decoder = {
.close = decode_end,
.decode = decode_tag,
.long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
+ AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
};