* MPEG Audio decoder
*/
-#include "libavutil/audioconvert.h"
+#include "libavutil/avassert.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "get_bits.h"
+#include "internal.h"
#include "mathops.h"
#include "mpegaudiodsp.h"
-#include "dsputil.h"
/*
* TODO:
int err_recognition;
AVCodecContext* avctx;
MPADSPContext mpadsp;
- DSPContext dsp;
- AVFrame frame;
+ AVFloatDSPContext fdsp;
+ AVFrame *frame;
} MPADecodeContext;
#if CONFIG_FLOAT
# define MULH3(x, y, s) ((s)*(y)*(x))
# define MULLx(x, y, s) ((y)*(x))
# define RENAME(a) a ## _float
-# define OUT_FMT AV_SAMPLE_FMT_FLT
+# define OUT_FMT AV_SAMPLE_FMT_FLT
+# define OUT_FMT_P AV_SAMPLE_FMT_FLTP
#else
# define SHR(a,b) ((a)>>(b))
/* WARNING: only correct for positive numbers */
# define MULH3(x, y, s) MULH((s)*(x), y)
# define MULLx(x, y, s) MULL(x,y,s)
# define RENAME(a) a ## _fixed
-# define OUT_FMT AV_SAMPLE_FMT_S16
+# define OUT_FMT AV_SAMPLE_FMT_S16
+# define OUT_FMT_P AV_SAMPLE_FMT_S16P
#endif
/****************/
s->avctx = avctx;
+ avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
ff_mpadsp_init(&s->mpadsp);
- ff_dsputil_init(&s->dsp, avctx);
- avctx->sample_fmt= OUT_FMT;
+ if (avctx->request_sample_fmt == OUT_FMT &&
+ avctx->codec_id != AV_CODEC_ID_MP3ON4)
+ avctx->sample_fmt = OUT_FMT;
+ else
+ avctx->sample_fmt = OUT_FMT_P;
s->err_recognition = avctx->err_recognition;
if (avctx->codec_id == AV_CODEC_ID_MP3ADU)
s->adu_mode = 1;
- avcodec_get_frame_defaults(&s->frame);
- avctx->coded_frame = &s->frame;
-
return 0;
}
/* NOTE: the 1/sqrt(2) normalization factor is included in the
global gain */
#if CONFIG_FLOAT
- s-> dsp.butterflies_float(g0->sb_hybrid, g1->sb_hybrid, 576);
+ s->fdsp.butterflies_float(g0->sb_hybrid, g1->sb_hybrid, 576);
#else
tab0 = g0->sb_hybrid;
tab1 = g1->sb_hybrid;
g = &s->granules[ch][gr];
s->last_buf_size += g->part2_3_length;
memset(g->sb_hybrid, 0, sizeof(g->sb_hybrid));
+ compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]);
}
}
skip = s->last_buf_size - 8 * main_data_begin;
return nb_granules * 18;
}
-static int mp_decode_frame(MPADecodeContext *s, OUT_INT *samples,
+static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples,
const uint8_t *buf, int buf_size)
{
int i, nb_frames, ch, ret;
default:
nb_frames = mp_decode_layer3(s);
+ if (nb_frames < 0)
+ return nb_frames;
+
s->last_buf_size=0;
if (s->in_gb.buffer) {
align_get_bits(&s->gb);
/* get output buffer */
if (!samples) {
- s->frame.nb_samples = s->avctx->frame_size;
- if ((ret = s->avctx->get_buffer(s->avctx, &s->frame)) < 0) {
+ av_assert0(s->frame != NULL);
+ s->frame->nb_samples = s->avctx->frame_size;
+ if ((ret = ff_get_buffer(s->avctx, s->frame, 0)) < 0) {
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
- samples = (OUT_INT *)s->frame.data[0];
+ samples = (OUT_INT **)s->frame->extended_data;
}
/* apply the synthesis filter */
for (ch = 0; ch < s->nb_channels; ch++) {
- samples_ptr = samples + ch;
+ int sample_stride;
+ if (s->avctx->sample_fmt == OUT_FMT_P) {
+ samples_ptr = samples[ch];
+ sample_stride = 1;
+ } else {
+ samples_ptr = samples[0] + ch;
+ sample_stride = s->nb_channels;
+ }
for (i = 0; i < nb_frames; i++) {
- RENAME(ff_mpa_synth_filter)(
- &s->mpadsp,
- s->synth_buf[ch], &(s->synth_buf_offset[ch]),
- RENAME(ff_mpa_synth_window), &s->dither_state,
- samples_ptr, s->nb_channels,
- s->sb_samples[ch][i]);
- samples_ptr += 32 * s->nb_channels;
+ RENAME(ff_mpa_synth_filter)(&s->mpadsp, s->synth_buf[ch],
+ &(s->synth_buf_offset[ch]),
+ RENAME(ff_mpa_synth_window),
+ &s->dither_state, samples_ptr,
+ sample_stride, s->sb_samples[ch][i]);
+ samples_ptr += 32 * sample_stride;
}
}
int buf_size = avpkt->size;
MPADecodeContext *s = avctx->priv_data;
uint32_t header;
- int out_size;
+ int ret;
if (buf_size < HEADER_SIZE)
return AVERROR_INVALIDDATA;
buf_size= s->frame_size;
}
- out_size = mp_decode_frame(s, NULL, buf, buf_size);
- if (out_size >= 0) {
- *got_frame_ptr = 1;
- *(AVFrame *)data = s->frame;
- avctx->sample_rate = s->sample_rate;
+ s->frame = data;
+
+ ret = mp_decode_frame(s, NULL, buf, buf_size);
+ if (ret >= 0) {
+ s->frame->nb_samples = avctx->frame_size;
+ *got_frame_ptr = 1;
+ avctx->sample_rate = s->sample_rate;
//FIXME maybe move the other codec info stuff from above here too
} else {
av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n");
- /* Only return an error if the bad frame makes up the whole packet.
- If there is more data in the packet, just consume the bad frame
- instead of returning an error, which would discard the whole
- packet. */
+ /* Only return an error if the bad frame makes up the whole packet or
+ * the error is related to buffer management.
+ * If there is more data in the packet, just consume the bad frame
+ * instead of returning an error, which would discard the whole
+ * packet. */
*got_frame_ptr = 0;
- if (buf_size == avpkt->size)
- return out_size;
+ if (buf_size == avpkt->size || ret != AVERROR_INVALIDDATA)
+ return ret;
}
s->frame_size = 0;
return buf_size;
int buf_size = avpkt->size;
MPADecodeContext *s = avctx->priv_data;
uint32_t header;
- int len, out_size;
+ int len, ret;
len = buf_size;
s->frame_size = len;
- out_size = mp_decode_frame(s, NULL, buf, buf_size);
- if (out_size < 0) {
+ s->frame = data;
+
+ ret = mp_decode_frame(s, NULL, buf, buf_size);
+ if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n");
- return AVERROR_INVALIDDATA;
+ return ret;
}
- *got_frame_ptr = 1;
- *(AVFrame *)data = s->frame;
+ *got_frame_ptr = 1;
return buf_size;
}
* Context for MP3On4 decoder
*/
typedef struct MP3On4DecodeContext {
- AVFrame *frame;
int frames; ///< number of mp3 frames per block (number of mp3 decoder instances)
int syncword; ///< syncword patch
const uint8_t *coff; ///< channel offsets in output buffer
MPADecodeContext *mp3decctx[5]; ///< MPADecodeContext for every decoder instance
- OUT_INT *decoded_buf; ///< output buffer for decoded samples
} MP3On4DecodeContext;
#include "mpeg4audio.h"
for (i = 0; i < s->frames; i++)
av_free(s->mp3decctx[i]);
- av_freep(&s->decoded_buf);
-
return 0;
}
// Put decoder context in place to make init_decode() happy
avctx->priv_data = s->mp3decctx[0];
decode_init(avctx);
- s->frame = avctx->coded_frame;
// Restore mp3on4 context pointer
avctx->priv_data = s;
s->mp3decctx[0]->adu_mode = 1; // Set adu mode
s->mp3decctx[i]->mpadsp = s->mp3decctx[0]->mpadsp;
}
- /* Allocate buffer for multi-channel output if needed */
- if (s->frames > 1) {
- s->decoded_buf = av_malloc(MPA_FRAME_SIZE * MPA_MAX_CHANNELS *
- sizeof(*s->decoded_buf));
- if (!s->decoded_buf)
- goto alloc_fail;
- }
-
return 0;
alloc_fail:
decode_close_mp3on4(avctx);
static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
int *got_frame_ptr, AVPacket *avpkt)
{
+ AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
MP3On4DecodeContext *s = avctx->priv_data;
MPADecodeContext *m;
int fsize, len = buf_size, out_size = 0;
uint32_t header;
- OUT_INT *out_samples;
- OUT_INT *outptr, *bp;
- int fr, j, n, ch, ret;
+ OUT_INT **out_samples;
+ OUT_INT *outptr[2];
+ int fr, ch, ret;
/* get output buffer */
- s->frame->nb_samples = MPA_FRAME_SIZE;
- if ((ret = avctx->get_buffer(avctx, s->frame)) < 0) {
+ frame->nb_samples = MPA_FRAME_SIZE;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
- out_samples = (OUT_INT *)s->frame->data[0];
+ out_samples = (OUT_INT **)frame->extended_data;
// Discard too short frames
if (buf_size < HEADER_SIZE)
return AVERROR_INVALIDDATA;
- // If only one decoder interleave is not needed
- outptr = s->frames == 1 ? out_samples : s->decoded_buf;
-
avctx->bit_rate = 0;
ch = 0;
}
ch += m->nb_channels;
- out_size += mp_decode_frame(m, outptr, buf, fsize);
+ outptr[0] = out_samples[s->coff[fr]];
+ if (m->nb_channels > 1)
+ outptr[1] = out_samples[s->coff[fr] + 1];
+
+ if ((ret = mp_decode_frame(m, outptr, buf, fsize)) < 0)
+ return ret;
+
+ out_size += ret;
buf += fsize;
len -= fsize;
- if (s->frames > 1) {
- n = m->avctx->frame_size*m->nb_channels;
- /* interleave output data */
- bp = out_samples + s->coff[fr];
- if (m->nb_channels == 1) {
- for (j = 0; j < n; j++) {
- *bp = s->decoded_buf[j];
- bp += avctx->channels;
- }
- } else {
- for (j = 0; j < n; j++) {
- bp[0] = s->decoded_buf[j++];
- bp[1] = s->decoded_buf[j];
- bp += avctx->channels;
- }
- }
- }
avctx->bit_rate += m->bit_rate;
}
/* update codec info */
avctx->sample_rate = s->mp3decctx[0]->sample_rate;
- s->frame->nb_samples = out_size / (avctx->channels * sizeof(OUT_INT));
- *got_frame_ptr = 1;
- *(AVFrame *)data = *s->frame;
+ frame->nb_samples = out_size / (avctx->channels * sizeof(OUT_INT));
+ *got_frame_ptr = 1;
return buf_size;
}
.capabilities = CODEC_CAP_DR1,
.flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+ AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
};
#endif
#if CONFIG_MP2_DECODER
.capabilities = CODEC_CAP_DR1,
.flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+ AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
};
#endif
#if CONFIG_MP3_DECODER
.capabilities = CODEC_CAP_DR1,
.flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+ AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
};
#endif
#if CONFIG_MP3ADU_DECODER
.capabilities = CODEC_CAP_DR1,
.flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+ AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
};
#endif
#if CONFIG_MP3ON4_DECODER
.capabilities = CODEC_CAP_DR1,
.flush = flush_mp3on4,
.long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
+ AV_SAMPLE_FMT_NONE },
};
#endif
#endif