* 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;
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);
/**
* 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;
}
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;
}
static int aac_decode_frame(AVCodecContext *avctx, void *data,
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);
},
.capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
.channel_layouts = aac_channel_layout,
+ .flush = flush,
};