* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
* Copyright (c) 2010 Janne Grunau <janne-ffmpeg@jannau.net>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "aacsbr.h"
#include "mpeg4audio.h"
#include "aacadtsdec.h"
+#include "libavutil/intfloat.h"
#include <assert.h>
#include <errno.h>
# include "arm/aac.h"
#endif
-union float754 {
- float f;
- uint32_t i;
-};
-
static VLC vlc_scalefactors;
static VLC vlc_spectral[11];
}
}
+static int count_channels(enum ChannelPosition che_pos[4][MAX_ELEM_ID])
+{
+ int i, type, sum = 0;
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ for (type = 0; type < 4; type++) {
+ sum += (1 + (type == TYPE_CPE)) *
+ (che_pos[type][i] != AAC_CHANNEL_OFF &&
+ che_pos[type][i] != AAC_CHANNEL_CC);
+ }
+ }
+ return sum;
+}
+
/**
* Check for the channel element in the current channel position configuration.
* If it exists, make sure the appropriate element is allocated and map the
- * channel order to match the internal Libav channel layout.
+ * channel order to match the internal FFmpeg channel layout.
*
* @param che_pos current channel position configuration
* @param type channel element type
}
memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
-
- avctx->channel_layout = 0;
}
avctx->channels = channels;
return 0;
}
+static void flush(AVCodecContext *avctx)
+{
+ AACContext *ac= avctx->priv_data;
+ int type, i, j;
+
+ for (type = 3; type >= 0; type--) {
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *che = ac->che[type][i];
+ if (che) {
+ for (j = 0; j <= 1; j++) {
+ memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
+ }
+ }
+ }
+ }
+}
+
/**
* Decode an array of 4 bit element IDs, optionally interleaved with a stereo/mono switching bit.
*
if (get_bits1(gb))
skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
+ if (get_bits_left(gb) < 4 * (num_front + num_side + num_back + num_lfe + num_assoc_data + num_cc)) {
+ av_log(avctx, AV_LOG_ERROR, overread_err);
+ return -1;
+ }
decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_FRONT, gb, num_front);
decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_SIDE, gb, num_side );
decode_channel_map(new_che_pos[TYPE_CPE], new_che_pos[TYPE_SCE], AAC_CHANNEL_BACK, gb, num_back );
if ((ret = set_default_channel_config(avctx, new_che_pos, channel_config)))
return ret;
}
+
+ if (count_channels(new_che_pos) > 1) {
+ m4ac->ps = 0;
+ } else if (m4ac->sbr == 1 && m4ac->ps == -1)
+ m4ac->ps = 1;
+
if (ac && (ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config, OC_GLOBAL_HDR)))
return ret;
* @param ac pointer to AACContext, may be null
* @param avctx pointer to AVCCodecContext, used for logging
* @param m4ac pointer to MPEG4AudioConfig, used for parsing
- * @param data pointer to AVCodecContext extradata
- * @param data_size size of AVCCodecContext extradata
+ * @param data pointer to buffer holding an audio specific config
+ * @param bit_size size of audio specific config or data in bits
+ * @param sync_extension look for an appended sync extension
*
* @return Returns error status or number of consumed bits. <0 - error
*/
static int decode_audio_specific_config(AACContext *ac,
AVCodecContext *avctx,
MPEG4AudioConfig *m4ac,
- const uint8_t *data, int data_size)
+ const uint8_t *data, int bit_size,
+ int sync_extension)
{
GetBitContext gb;
int i;
av_dlog(avctx, "%02x ", avctx->extradata[i]);
av_dlog(avctx, "\n");
- init_get_bits(&gb, data, data_size * 8);
+ init_get_bits(&gb, data, bit_size);
- if ((i = avpriv_mpeg4audio_get_config(m4ac, data, data_size)) < 0)
+ if ((i = avpriv_mpeg4audio_get_config(m4ac, data, bit_size, sync_extension)) < 0)
return -1;
if (m4ac->sampling_index > 12) {
av_log(avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", m4ac->sampling_index);
return -1;
}
- if (m4ac->sbr == 1 && m4ac->ps == -1)
- m4ac->ps = 1;
skip_bits_long(&gb, i);
if (avctx->extradata_size > 0) {
if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac,
avctx->extradata,
- avctx->extradata_size) < 0)
+ avctx->extradata_size*8, 1) < 0)
return -1;
} else {
int sr, i;
cbrt_tableinit();
+ avcodec_get_frame_defaults(&ac->frame);
+ avctx->coded_frame = &ac->frame;
+
return 0;
}
/**
* Decode Individual Channel Stream info; reference: table 4.6.
- *
- * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
*/
static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics,
- GetBitContext *gb, int common_window)
+ GetBitContext *gb)
{
if (get_bits1(gb)) {
av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n");
- memset(ics, 0, sizeof(IndividualChannelStream));
- return -1;
+ return AVERROR_INVALIDDATA;
}
ics->window_sequence[1] = ics->window_sequence[0];
ics->window_sequence[0] = get_bits(gb, 2);
if (ics->predictor_present) {
if (ac->m4ac.object_type == AOT_AAC_MAIN) {
if (decode_prediction(ac, ics, gb)) {
- memset(ics, 0, sizeof(IndividualChannelStream));
- return -1;
+ return AVERROR_INVALIDDATA;
}
} else if (ac->m4ac.object_type == AOT_AAC_LC) {
av_log(ac->avctx, AV_LOG_ERROR, "Prediction is not allowed in AAC-LC.\n");
- memset(ics, 0, sizeof(IndividualChannelStream));
- return -1;
+ return AVERROR_INVALIDDATA;
} else {
if ((ics->ltp.present = get_bits(gb, 1)))
decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
av_log(ac->avctx, AV_LOG_ERROR,
"Number of scalefactor bands in group (%d) exceeds limit (%d).\n",
ics->max_sfb, ics->num_swb);
- memset(ics, 0, sizeof(IndividualChannelStream));
- return -1;
+ return AVERROR_INVALIDDATA;
}
return 0;
av_log(ac->avctx, AV_LOG_ERROR, "invalid band type\n");
return -1;
}
- while ((sect_len_incr = get_bits(gb, bits)) == (1 << bits) - 1)
+ while ((sect_len_incr = get_bits(gb, bits)) == (1 << bits) - 1 && get_bits_left(gb) >= bits)
sect_end += sect_len_incr;
sect_end += sect_len_incr;
- if (get_bits_left(gb) < 0) {
+ if (get_bits_left(gb) < 0 || sect_len_incr == (1 << bits) - 1) {
av_log(ac->avctx, AV_LOG_ERROR, overread_err);
return -1;
}
static inline float *VMUL2S(float *dst, const float *v, unsigned idx,
unsigned sign, const float *scale)
{
- union float754 s0, s1;
+ union av_intfloat32 s0, s1;
s0.f = s1.f = *scale;
s0.i ^= sign >> 1 << 31;
unsigned sign, const float *scale)
{
unsigned nz = idx >> 12;
- union float754 s = { .f = *scale };
- union float754 t;
+ union av_intfloat32 s = { .f = *scale };
+ union av_intfloat32 t;
t.i = s.i ^ (sign & 1U<<31);
*dst++ = v[idx & 3] * t.f;
static av_always_inline float flt16_round(float pf)
{
- union float754 tmp;
+ union av_intfloat32 tmp;
tmp.f = pf;
tmp.i = (tmp.i + 0x00008000U) & 0xFFFF0000U;
return tmp.f;
static av_always_inline float flt16_even(float pf)
{
- union float754 tmp;
+ union av_intfloat32 tmp;
tmp.f = pf;
tmp.i = (tmp.i + 0x00007FFFU + (tmp.i & 0x00010000U >> 16)) & 0xFFFF0000U;
return tmp.f;
static av_always_inline float flt16_trunc(float pf)
{
- union float754 pun;
+ union av_intfloat32 pun;
pun.f = pf;
pun.i &= 0xFFFF0000U;
return pun.f;
global_gain = get_bits(gb, 8);
if (!common_window && !scale_flag) {
- if (decode_ics_info(ac, ics, gb, 0) < 0)
- return -1;
+ if (decode_ics_info(ac, ics, gb) < 0)
+ return AVERROR_INVALIDDATA;
}
if (decode_band_types(ac, sce->band_type, sce->band_type_run_end, gb, ics) < 0)
common_window = get_bits1(gb);
if (common_window) {
- if (decode_ics_info(ac, &cpe->ch[0].ics, gb, 1))
- return -1;
+ if (decode_ics_info(ac, &cpe->ch[0].ics, gb))
+ return AVERROR_INVALIDDATA;
i = cpe->ch[1].ics.use_kb_window[0];
cpe->ch[1].ics = cpe->ch[0].ics;
cpe->ch[1].ics.use_kb_window[1] = i;
}
if (!ac->avctx->sample_rate)
ac->avctx->sample_rate = hdr_info.sample_rate;
- if (hdr_info.num_aac_frames == 1) {
- if (!hdr_info.crc_absent)
- skip_bits(gb, 16);
- } else {
+ if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
+ // This is 2 for "VLB " audio in NSV files.
+ // See samples/nsv/vlb_audio.
av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame is", 0);
- return -1;
+ ac->warned_num_aac_frames = 1;
}
+ if (!hdr_info.crc_absent)
+ skip_bits(gb, 16);
}
return size;
}
static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
- int *data_size, GetBitContext *gb)
+ int *got_frame_ptr, GetBitContext *gb)
{
AACContext *ac = avctx->priv_data;
ChannelElement *che = NULL, *che_prev = NULL;
enum RawDataBlockType elem_type, elem_type_prev = TYPE_END;
- int err, elem_id, data_size_tmp;
+ int err, elem_id;
int samples = 0, multiplier, audio_found = 0;
if (show_bits(gb, 12) == 0xfff) {
elem_id = get_bits(gb, 4);
if (elem_type < TYPE_DSE) {
+ if (!ac->tags_mapped && elem_type == TYPE_CPE && ac->m4ac.chan_config==1) {
+ enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]= {0};
+ ac->m4ac.chan_config=2;
+
+ if (set_default_channel_config(ac->avctx, new_che_pos, 2)<0)
+ return -1;
+ if (output_configure(ac, ac->che_pos, new_che_pos, 2, OC_TRIAL_FRAME)<0)
+ return -1;
+ }
if (!(che=get_che(ac, elem_type, elem_id))) {
av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
elem_type, elem_id);
if ((err = decode_pce(avctx, &ac->m4ac, new_che_pos, gb)))
break;
if (ac->output_configured > OC_TRIAL_PCE)
- av_log(avctx, AV_LOG_ERROR,
- "Not evaluating a further program_config_element as this construct is dubious at best.\n");
- else
- err = output_configure(ac, ac->che_pos, new_che_pos, 0, OC_TRIAL_PCE);
+ av_log(avctx, AV_LOG_INFO,
+ "Evaluating a further program_config_element.\n");
+ err = output_configure(ac, ac->che_pos, new_che_pos, 0, OC_TRIAL_PCE);
+ if (!err)
+ ac->m4ac.chan_config = 0;
break;
}
avctx->frame_size = samples;
}
- data_size_tmp = samples * avctx->channels *
- av_get_bytes_per_sample(avctx->sample_fmt);
- if (*data_size < data_size_tmp) {
- av_log(avctx, AV_LOG_ERROR,
- "Output buffer too small (%d) or trying to output too many samples (%d) for this frame.\n",
- *data_size, data_size_tmp);
- return -1;
- }
- *data_size = data_size_tmp;
-
if (samples) {
+ /* get output buffer */
+ ac->frame.nb_samples = samples;
+ if ((err = avctx->get_buffer(avctx, &ac->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return err;
+ }
+
if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT)
- ac->fmt_conv.float_interleave(data, (const float **)ac->output_data,
+ ac->fmt_conv.float_interleave((float *)ac->frame.data[0],
+ (const float **)ac->output_data,
samples, avctx->channels);
else
- ac->fmt_conv.float_to_int16_interleave(data, (const float **)ac->output_data,
+ ac->fmt_conv.float_to_int16_interleave((int16_t *)ac->frame.data[0],
+ (const float **)ac->output_data,
samples, avctx->channels);
+
+ *(AVFrame *)data = ac->frame;
}
+ *got_frame_ptr = !!samples;
if (ac->output_configured && audio_found)
ac->output_configured = OC_LOCKED;
}
static int aac_decode_frame(AVCodecContext *avctx, void *data,
- int *data_size, AVPacket *avpkt)
+ int *got_frame_ptr, AVPacket *avpkt)
{
+ AACContext *ac = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
GetBitContext gb;
int buf_consumed;
int buf_offset;
int err;
+ int new_extradata_size;
+ const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
+ AV_PKT_DATA_NEW_EXTRADATA,
+ &new_extradata_size);
+
+ if (new_extradata) {
+ av_free(avctx->extradata);
+ avctx->extradata = av_mallocz(new_extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata)
+ return AVERROR(ENOMEM);
+ avctx->extradata_size = new_extradata_size;
+ memcpy(avctx->extradata, new_extradata, new_extradata_size);
+ if (decode_audio_specific_config(ac, ac->avctx, &ac->m4ac,
+ avctx->extradata,
+ avctx->extradata_size*8, 1) < 0)
+ return AVERROR_INVALIDDATA;
+ }
init_get_bits(&gb, buf, buf_size * 8);
- if ((err = aac_decode_frame_int(avctx, data, data_size, &gb)) < 0)
+ if ((err = aac_decode_frame_int(avctx, data, got_frame_ptr, &gb)) < 0)
return err;
buf_consumed = (get_bits_count(&gb) + 7) >> 3;
}
static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
- GetBitContext *gb)
+ GetBitContext *gb, int asclen)
{
- AVCodecContext *avctx = latmctx->aac_ctx.avctx;
- MPEG4AudioConfig m4ac;
- int config_start_bit = get_bits_count(gb);
- int bits_consumed, esize;
+ AACContext *ac = &latmctx->aac_ctx;
+ AVCodecContext *avctx = ac->avctx;
+ MPEG4AudioConfig m4ac = {0};
+ int config_start_bit = get_bits_count(gb);
+ int sync_extension = 0;
+ int bits_consumed, esize;
+
+ if (asclen) {
+ sync_extension = 1;
+ asclen = FFMIN(asclen, get_bits_left(gb));
+ } else
+ asclen = get_bits_left(gb);
if (config_start_bit % 8) {
av_log_missing_feature(latmctx->aac_ctx.avctx, "audio specific "
"config not byte aligned.\n", 1);
return AVERROR_INVALIDDATA;
- } else {
- bits_consumed =
- decode_audio_specific_config(NULL, avctx, &m4ac,
+ }
+ bits_consumed = decode_audio_specific_config(NULL, avctx, &m4ac,
gb->buffer + (config_start_bit / 8),
- get_bits_left(gb) / 8);
+ asclen, sync_extension);
- if (bits_consumed < 0)
- return AVERROR_INVALIDDATA;
+ if (bits_consumed < 0)
+ return AVERROR_INVALIDDATA;
+
+ if (ac->m4ac.sample_rate != m4ac.sample_rate ||
+ ac->m4ac.chan_config != m4ac.chan_config) {
+
+ av_log(avctx, AV_LOG_INFO, "audio config changed\n");
+ latmctx->initialized = 0;
esize = (bits_consumed+7) / 8;
- if (avctx->extradata_size <= esize) {
+ if (avctx->extradata_size < esize) {
av_free(avctx->extradata);
avctx->extradata = av_malloc(esize + FF_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
avctx->extradata_size = esize;
memcpy(avctx->extradata, gb->buffer + (config_start_bit/8), esize);
memset(avctx->extradata+esize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
-
- skip_bits_long(gb, bits_consumed);
}
+ skip_bits_long(gb, bits_consumed);
return bits_consumed;
}
// for all but first stream: use_same_config = get_bits(gb, 1);
if (!audio_mux_version) {
- if ((ret = latm_decode_audio_specific_config(latmctx, gb)) < 0)
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb, 0)) < 0)
return ret;
} else {
int ascLen = latm_get_value(gb);
- if ((ret = latm_decode_audio_specific_config(latmctx, gb)) < 0)
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0)
return ret;
ascLen -= ret;
skip_bits_long(gb, ascLen);
}
-static int latm_decode_frame(AVCodecContext *avctx, void *out, int *out_size,
- AVPacket *avpkt)
+static int latm_decode_frame(AVCodecContext *avctx, void *out,
+ int *got_frame_ptr, AVPacket *avpkt)
{
struct LATMContext *latmctx = avctx->priv_data;
int muxlength, err;
if (!latmctx->initialized) {
if (!avctx->extradata) {
- *out_size = 0;
+ *got_frame_ptr = 0;
return avpkt->size;
} else {
if ((err = decode_audio_specific_config(
&latmctx->aac_ctx, avctx, &latmctx->aac_ctx.m4ac,
- avctx->extradata, avctx->extradata_size)) < 0)
+ avctx->extradata, avctx->extradata_size*8, 1)) < 0)
return err;
latmctx->initialized = 1;
}
return AVERROR_INVALIDDATA;
}
- if ((err = aac_decode_frame_int(avctx, out, out_size, &gb)) < 0)
+ if ((err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb)) < 0)
return err;
return muxlength;
.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
},
- .capabilities = CODEC_CAP_CHANNEL_CONF,
+ .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
.channel_layouts = aac_channel_layout,
};
.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
},
- .capabilities = CODEC_CAP_CHANNEL_CONF,
+ .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
.channel_layouts = aac_channel_layout,
+ .flush = flush,
};