Commit 3ffed68c authored by Justin Ruggles's avatar Justin Ruggles

mpegaudiodec: use planar sample format for output unless packed is requested

parent 2d3993ce
...@@ -94,6 +94,7 @@ typedef struct MPADecodeContext { ...@@ -94,6 +94,7 @@ typedef struct MPADecodeContext {
# define MULLx(x, y, s) ((y)*(x)) # define MULLx(x, y, s) ((y)*(x))
# define RENAME(a) a ## _float # 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 #else
# define SHR(a,b) ((a)>>(b)) # define SHR(a,b) ((a)>>(b))
/* WARNING: only correct for positive numbers */ /* WARNING: only correct for positive numbers */
...@@ -104,6 +105,7 @@ typedef struct MPADecodeContext { ...@@ -104,6 +105,7 @@ typedef struct MPADecodeContext {
# define MULLx(x, y, s) MULL(x,y,s) # define MULLx(x, y, s) MULL(x,y,s)
# define RENAME(a) a ## _fixed # 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 #endif
/****************/ /****************/
...@@ -434,7 +436,11 @@ static av_cold int decode_init(AVCodecContext * avctx) ...@@ -434,7 +436,11 @@ static av_cold int decode_init(AVCodecContext * avctx)
ff_mpadsp_init(&s->mpadsp); ff_mpadsp_init(&s->mpadsp);
ff_dsputil_init(&s->dsp, avctx); 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; s->err_recognition = avctx->err_recognition;
if (avctx->codec_id == AV_CODEC_ID_MP3ADU) if (avctx->codec_id == AV_CODEC_ID_MP3ADU)
...@@ -1546,7 +1552,7 @@ static int mp_decode_layer3(MPADecodeContext *s) ...@@ -1546,7 +1552,7 @@ static int mp_decode_layer3(MPADecodeContext *s)
return nb_granules * 18; 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) const uint8_t *buf, int buf_size)
{ {
int i, nb_frames, ch, ret; int i, nb_frames, ch, ret;
...@@ -1609,20 +1615,26 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT *samples, ...@@ -1609,20 +1615,26 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT *samples,
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret; return ret;
} }
samples = (OUT_INT *)s->frame.data[0]; samples = (OUT_INT **)s->frame.extended_data;
} }
/* apply the synthesis filter */ /* apply the synthesis filter */
for (ch = 0; ch < s->nb_channels; ch++) { 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++) { for (i = 0; i < nb_frames; i++) {
RENAME(ff_mpa_synth_filter)( RENAME(ff_mpa_synth_filter)(&s->mpadsp, s->synth_buf[ch],
&s->mpadsp, &(s->synth_buf_offset[ch]),
s->synth_buf[ch], &(s->synth_buf_offset[ch]), RENAME(ff_mpa_synth_window),
RENAME(ff_mpa_synth_window), &s->dither_state, &s->dither_state, samples_ptr,
samples_ptr, s->nb_channels, sample_stride, s->sb_samples[ch][i]);
s->sb_samples[ch][i]); samples_ptr += 32 * sample_stride;
samples_ptr += 32 * s->nb_channels;
} }
} }
...@@ -1760,7 +1772,6 @@ typedef struct MP3On4DecodeContext { ...@@ -1760,7 +1772,6 @@ typedef struct MP3On4DecodeContext {
int syncword; ///< syncword patch int syncword; ///< syncword patch
const uint8_t *coff; ///< channel offsets in output buffer const uint8_t *coff; ///< channel offsets in output buffer
MPADecodeContext *mp3decctx[5]; ///< MPADecodeContext for every decoder instance MPADecodeContext *mp3decctx[5]; ///< MPADecodeContext for every decoder instance
OUT_INT *decoded_buf; ///< output buffer for decoded samples
} MP3On4DecodeContext; } MP3On4DecodeContext;
#include "mpeg4audio.h" #include "mpeg4audio.h"
...@@ -1802,8 +1813,6 @@ static av_cold int decode_close_mp3on4(AVCodecContext * avctx) ...@@ -1802,8 +1813,6 @@ static av_cold int decode_close_mp3on4(AVCodecContext * avctx)
for (i = 0; i < s->frames; i++) for (i = 0; i < s->frames; i++)
av_free(s->mp3decctx[i]); av_free(s->mp3decctx[i]);
av_freep(&s->decoded_buf);
return 0; return 0;
} }
...@@ -1864,14 +1873,6 @@ static int decode_init_mp3on4(AVCodecContext * avctx) ...@@ -1864,14 +1873,6 @@ static int decode_init_mp3on4(AVCodecContext * avctx)
s->mp3decctx[i]->mpadsp = s->mp3decctx[0]->mpadsp; 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; return 0;
alloc_fail: alloc_fail:
decode_close_mp3on4(avctx); decode_close_mp3on4(avctx);
...@@ -1898,9 +1899,9 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, ...@@ -1898,9 +1899,9 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
MPADecodeContext *m; MPADecodeContext *m;
int fsize, len = buf_size, out_size = 0; int fsize, len = buf_size, out_size = 0;
uint32_t header; uint32_t header;
OUT_INT *out_samples; OUT_INT **out_samples;
OUT_INT *outptr, *bp; OUT_INT *outptr[2];
int fr, j, n, ch, ret; int fr, ch, ret;
/* get output buffer */ /* get output buffer */
s->frame->nb_samples = MPA_FRAME_SIZE; s->frame->nb_samples = MPA_FRAME_SIZE;
...@@ -1908,15 +1909,12 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, ...@@ -1908,15 +1909,12 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret; return ret;
} }
out_samples = (OUT_INT *)s->frame->data[0]; out_samples = (OUT_INT **)s->frame->extended_data;
// Discard too short frames // Discard too short frames
if (buf_size < HEADER_SIZE) if (buf_size < HEADER_SIZE)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
// If only one decoder interleave is not needed
outptr = s->frames == 1 ? out_samples : s->decoded_buf;
avctx->bit_rate = 0; avctx->bit_rate = 0;
ch = 0; ch = 0;
...@@ -1944,6 +1942,10 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, ...@@ -1944,6 +1942,10 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
} }
ch += m->nb_channels; ch += m->nb_channels;
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) if ((ret = mp_decode_frame(m, outptr, buf, fsize)) < 0)
return ret; return ret;
...@@ -1951,23 +1953,6 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, ...@@ -1951,23 +1953,6 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
buf += fsize; buf += fsize;
len -= 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; avctx->bit_rate += m->bit_rate;
} }
...@@ -1994,6 +1979,9 @@ AVCodec ff_mp1_decoder = { ...@@ -1994,6 +1979,9 @@ AVCodec ff_mp1_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), .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 #endif
#if CONFIG_MP2_DECODER #if CONFIG_MP2_DECODER
...@@ -2007,6 +1995,9 @@ AVCodec ff_mp2_decoder = { ...@@ -2007,6 +1995,9 @@ AVCodec ff_mp2_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), .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 #endif
#if CONFIG_MP3_DECODER #if CONFIG_MP3_DECODER
...@@ -2020,6 +2011,9 @@ AVCodec ff_mp3_decoder = { ...@@ -2020,6 +2011,9 @@ AVCodec ff_mp3_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), .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 #endif
#if CONFIG_MP3ADU_DECODER #if CONFIG_MP3ADU_DECODER
...@@ -2033,6 +2027,9 @@ AVCodec ff_mp3adu_decoder = { ...@@ -2033,6 +2027,9 @@ AVCodec ff_mp3adu_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), .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 #endif
#if CONFIG_MP3ON4_DECODER #if CONFIG_MP3ON4_DECODER
...@@ -2047,6 +2044,8 @@ AVCodec ff_mp3on4_decoder = { ...@@ -2047,6 +2044,8 @@ AVCodec ff_mp3on4_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush_mp3on4, .flush = flush_mp3on4,
.long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
}; };
#endif #endif
#endif #endif
...@@ -33,6 +33,9 @@ AVCodec ff_mp1float_decoder = { ...@@ -33,6 +33,9 @@ AVCodec ff_mp1float_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
}; };
#endif #endif
#if CONFIG_MP2FLOAT_DECODER #if CONFIG_MP2FLOAT_DECODER
...@@ -46,6 +49,9 @@ AVCodec ff_mp2float_decoder = { ...@@ -46,6 +49,9 @@ AVCodec ff_mp2float_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
}; };
#endif #endif
#if CONFIG_MP3FLOAT_DECODER #if CONFIG_MP3FLOAT_DECODER
...@@ -59,6 +65,9 @@ AVCodec ff_mp3float_decoder = { ...@@ -59,6 +65,9 @@ AVCodec ff_mp3float_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
}; };
#endif #endif
#if CONFIG_MP3ADUFLOAT_DECODER #if CONFIG_MP3ADUFLOAT_DECODER
...@@ -72,6 +81,9 @@ AVCodec ff_mp3adufloat_decoder = { ...@@ -72,6 +81,9 @@ AVCodec ff_mp3adufloat_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush, .flush = flush,
.long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
}; };
#endif #endif
#if CONFIG_MP3ON4FLOAT_DECODER #if CONFIG_MP3ON4FLOAT_DECODER
...@@ -86,5 +98,7 @@ AVCodec ff_mp3on4float_decoder = { ...@@ -86,5 +98,7 @@ AVCodec ff_mp3on4float_decoder = {
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.flush = flush_mp3on4, .flush = flush_mp3on4,
.long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
}; };
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment