[FFmpeg-soc] [soc]: r1938 - aac/aac.c
andoma
subversion at mplayerhq.hu
Thu Feb 28 10:19:03 CET 2008
Author: andoma
Date: Thu Feb 28 10:19:02 2008
New Revision: 1938
Log:
Redesign channel setup and output mixing in order to fix a bunch of bugs.
* It now honour avctx->request_channels like other multi channel decoders.
* Can decode all the AAC LC conformance vectors without any spurious buffer
overruns or crashes.
Modified:
aac/aac.c
Modified: aac/aac.c
==============================================================================
--- aac/aac.c (original)
+++ aac/aac.c Thu Feb 28 10:19:02 2008
@@ -119,61 +119,25 @@ enum {
//ltp
#define MAX_LTP_LONG_SFB 40
-typedef struct {
- int present;
- int generated;
-
- int num_channels;
-
- int num_front;
- int front_cpe;
- int front_tag[MAX_TAGID];
-
- int num_side;
- int side_cpe;
- int side_tag[MAX_TAGID];
-
- int num_back;
- int back_cpe;
- int back_tag[MAX_TAGID];
-
- int num_lfe;
- int lfe_tag[MAX_TAGID];
+#define AAC_CHANNEL_FRONT 1
+#define AAC_CHANNEL_SIDE 2
+#define AAC_CHANNEL_BACK 3
+#define AAC_CHANNEL_LFE 4
+#define AAC_CHANNEL_CC 5
- int num_assoc_data;
- int assoc_data_tag[MAX_TAGID];
+typedef struct {
+ int sce_type[MAX_TAGID];
+ int cpe_type[MAX_TAGID];
+ int lfe_type[MAX_TAGID];
+ int cc_type[MAX_TAGID];
- int num_cc;
- int cc_ind_sw;
- int cc_tag[MAX_TAGID];
+ int mono_mixdown; //< The SCE tag to use if user requests mono output, -1 if not available
+ int stereo_mixdown; //< The CPE tag to use if user requests stereo output, -1 if not available
+ int mixdown_coeff_index; //< 0-3
+ int pseudo_surround; //< Mix surround channels out of phase
- int mono_mixdown;
- int stereo_mixdown;
- int matrix_mixdown;
- int pseudo_surround;
} program_config_struct;
-enum {
- MIXMODE_DEFAULT = 0,
- MIXMODE_1TO1,
- MIXMODE_2TO1,
- MIXMODE_1TO2,
- MIXMODE_2TO2,
- MIXMODE_MATRIX1,
- MIXMODE_MATRIX2,
- MIXMODE_UNKNOWN
-};
-
-typedef struct {
- int mode;
- int c_tag;
- int lr_tag;
- int sur_tag;
- float sce_gain[MAX_TAGID];
- float cpe_gain[MAX_TAGID][2];
- float lfe_gain[MAX_TAGID];
-} mix_config_struct;
-
typedef struct {
int present;
int lag;
@@ -309,11 +273,9 @@ typedef struct {
int ext_sampling_index;
int sample_rate;
int ext_sample_rate;
- int channels;
// decoder param
program_config_struct pcs;
- mix_config_struct mix;
sce_struct * che_sce[MAX_TAGID];
cpe_struct * che_cpe[MAX_TAGID];
sce_struct * che_lfe[MAX_TAGID];
@@ -341,7 +303,10 @@ typedef struct {
DECLARE_ALIGNED_16(float, ivquant_tab[256]);
DECLARE_ALIGNED_16(float, revers[1024]);
float* interleaved_output;
- float* iop;
+ float *output_data[MAX_CHANNELS];
+ sce_struct *mm_center; //< Center SCE to use for matrix mixdown
+ cpe_struct *mm_front; //< Front CPE to use for matrix mixdown
+ cpe_struct *mm_back; //< Back CPE to use for matrix mixdown
MDCTContext mdct;
MDCTContext mdct_small;
@@ -468,184 +433,297 @@ static void cc_freep(cc_struct **s) {
av_freep(s);
}
-// General functions
-#define TAG_MASK 0x00f
-#define FLAG_SCE 0x100
-#define FLAG_CPE 0x200
-#define FLAG_LFE 0x400
-#define FLAG_CCE 0x800
-
-static int program_config_element_add_channel(AACContext * ac, int flag_tag) {
+/**
+ * Configure output channel order and optional mixing based on the current
+ * program config element and user requested channels.
+ *
+ * \param nwepcs New program config struct. We only do somthing if it differs from the current one.
+ */
+static int output_configure(AACContext *ac, program_config_struct *newpcs) {
+ AVCodecContext *avctx = ac->avccontext;
program_config_struct * pcs = &ac->pcs;
- if (pcs->present)
- return 0;
- pcs->generated = 1;
- switch (ac->channels) {
- case 8:
- case 7:
- if ((pcs->num_channels == 3) && (FLAG_CPE & flag_tag)) {
- pcs->num_side = 1;
- pcs->side_cpe = 1;
- pcs->side_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 5;
- return 0;
- }
- if ((pcs->num_channels == 5) && (FLAG_CPE & flag_tag)) {
- pcs->num_back = 1;
- pcs->back_cpe = 1;
- pcs->back_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 7;
- return 0;
- }
- if ((pcs->num_channels == 7) && (FLAG_LFE & flag_tag)) {
- pcs->num_lfe = 1;
- pcs->lfe_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 8;
- return 0;
- }
- goto lab3;
- case 6:
- if ((pcs->num_channels == 5) && (FLAG_LFE & flag_tag)) {
- pcs->num_lfe = 1;
- pcs->lfe_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 6;
- return 0;
- }
- case 5:
- if ((pcs->num_channels == 3) && (FLAG_CPE & flag_tag)) {
- pcs->num_back = 1;
- pcs->back_cpe = 1;
- pcs->back_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 5;
- return 0;
- }
- goto lab3;
- case 4:
- if ((pcs->num_channels == 3) && (FLAG_SCE & flag_tag)) {
- pcs->num_back = 1;
- pcs->back_cpe = 0;
- pcs->back_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 4;
- return 0;
- }
-lab3:
- case 3:
- if ((pcs->num_channels == 1) && (FLAG_CPE & flag_tag)) {
- pcs->num_front = 2;
- pcs->front_cpe = 2;
- pcs->front_tag[1] = flag_tag & TAG_MASK;
- pcs->num_channels = 3;
- return 0;
- }
- case 1:
- if ((pcs->num_channels == 0) && (FLAG_SCE & flag_tag)) {
- pcs->num_front = 1;
- pcs->front_cpe = 0;
- pcs->front_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 1;
- return 0;
- }
- break;
- case 2:
- if ((pcs->num_channels == 0) && (FLAG_CPE & flag_tag)) {
- pcs->num_front = 1;
- pcs->front_cpe = 1;
- pcs->front_tag[0] = flag_tag & TAG_MASK;
- pcs->num_channels = 2;
- return 0;
+ int i, channels = 0, ch;
+ float a, b;
+ cpe_struct *front = NULL, *back = NULL;
+ sce_struct *center = NULL;
+
+ static const float mixdowncoeff[4] = {
+ /* Matrix mixdown coefficient, Table 4.70 */
+ 1. / M_SQRT2,
+ 1. / 2.,
+ 1. / (2 * M_SQRT2),
+ 0
+ };
+
+ if(!memcmp(&ac->pcs, newpcs, sizeof(program_config_struct)))
+ return 0; /* no change */
+
+ memcpy(pcs, newpcs, sizeof(program_config_struct));
+
+ /* Allocate or free elements depending on if they are in the
+ current program config struct */
+
+ for(i = 0; i < MAX_TAGID; i++) {
+ channels += !!pcs->sce_type[i] + !!pcs->cpe_type[i] * 2 + !!pcs->lfe_type[i];
+
+ if(pcs->sce_type[i]) {
+ if(!ac->che_sce[i]) ac->che_sce[i] = av_mallocz(sizeof(sce_struct));
+ } else
+ sce_freep(&ac->che_sce[i]);
+
+ if(pcs->cpe_type[i]) {
+ if(!ac->che_cpe[i]) ac->che_cpe[i] = av_mallocz(sizeof(cpe_struct));
+ } else
+ cpe_freep(&ac->che_cpe[i]);
+
+ if(pcs->lfe_type[i]) {
+ if(!ac->che_lfe[i]) ac->che_lfe[i] = av_mallocz(sizeof(sce_struct));
+ } else
+ sce_freep(&ac->che_lfe[i]);
+
+ if(pcs->cc_type[i]) {
+ if(!ac->che_cc[i]) ac->che_cc[i] = av_mallocz(sizeof(cc_struct));
+ } else
+ cc_freep(&ac->che_cc[i]);
+ }
+
+ /* Setup default 1:1 output mapping.
+ *
+ * For a 5.1 stream the output order will be:
+ * [ Front Left ] [ Front Right ] [ Center ] [ LFE ] [ Surround Left ] [ Surround Right ]
+ *
+ * While at it: locate front, center and back for matrix mixdown further down
+ */
+
+ ch = 0;
+ for(i = 0; i < MAX_TAGID; i++) {
+
+ if(pcs->cpe_type[i]) {
+ ac->output_data[ch++] = ac->che_cpe[i]->ch[0].ret;
+ ac->output_data[ch++] = ac->che_cpe[i]->ch[1].ret;
+
+ ac->che_cpe[i]->ch[0].mixing_gain = 1.0f;
+ ac->che_cpe[i]->ch[1].mixing_gain = 1.0f;
+
+ if(front == NULL && pcs->cpe_type[i] == AAC_CHANNEL_FRONT)
+ front = ac->che_cpe[i];
+
+ if(back == NULL && pcs->cpe_type[i] == AAC_CHANNEL_BACK)
+ back = ac->che_cpe[i];
+ }
+
+ if(pcs->sce_type[i]) {
+ ac->output_data[ch++] = ac->che_sce[i]->ret;
+ ac->che_sce[i]->mixing_gain = 1.0f;
+
+ if(center == NULL && pcs->sce_type[i] == AAC_CHANNEL_FRONT)
+ center = ac->che_sce[i];
+ }
+ if(ac->che_lfe[i]) {
+ ac->output_data[ch++] = ac->che_lfe[i]->ret;
+ ac->che_sce[i]->mixing_gain = 1.0f;
+ }
+ }
+ assert(ch == channels);
+
+ ac->mm_front = ac->mm_back = NULL;
+ ac->mm_center = NULL;
+
+ /* Check for matrix mixdown to mono or stereo */
+
+ if(avctx->request_channels != 0 && avctx->request_channels <= 2 &&
+ avctx->request_channels != channels) {
+
+ if((avctx->request_channels == 1 && pcs->mono_mixdown != -1) ||
+ (avctx->request_channels == 2 && pcs->stereo_mixdown != -1)) {
+ /* Add support for this as soon as we get a sample so we can figure out
+ exactly how this is supposed to work */
+ av_log(avctx, AV_LOG_ERROR,
+ "Mixdown using pre-mixed elements is not supported, please file a bug. "
+ "Reverting to matrix mixdown\n");
+ }
+
+ /* We need 'center + L + R + sL + sR' for matrix mixdown */
+ if(front && center && back) {
+ a = mixdowncoeff[pcs->mixdown_coeff_index];
+
+ if(avctx->request_channels == 2) {
+ b = 1. / (1. + (1. / M_SQRT2) + a * (pcs->pseudo_surround ? 2. : 1.));
+
+ front->ch[0].mixing_gain = b;
+ front->ch[1].mixing_gain = b;
+ center->mixing_gain = b / M_SQRT2;
+ back->ch[0].mixing_gain = b * a;
+ back->ch[1].mixing_gain = b * a;
+ } else {
+ b = 1. / (3. + 2. * a);
+ front->ch[0].mixing_gain = b;
+ front->ch[1].mixing_gain = b;
+ center->mixing_gain = b;
+ back->ch[0].mixing_gain = b * a;
+ back->ch[1].mixing_gain = b * a;
}
- break;
+ ac->mm_front = front;
+ ac->mm_center = center;
+ ac->mm_back = back;
+
+ channels = avctx->request_channels;
+ } else {
+ av_log(avctx, AV_LOG_WARNING, "Matrix mixing from %d to %d channels in not supported",
+ channels, avctx->request_channels);
+ }
}
- pcs->generated = 0;
- return -1;
+
+ avctx->channels = channels;
+ ac->interleaved_output = av_realloc(ac->interleaved_output, channels * 1024 * sizeof(float));
+ return ac->interleaved_output ? 0 : -1;
}
+
+/**
+ * Decode an array of 4 bit tag IDs, optionally interleaved with a stereo/mono switching bit.
+ *
+ * @param cpe_map Stereo (Channel Pair Element) map, NULL if stereo bit is not present
+ * @param sce_map Mono (Single Channel Element) map
+ * @param type Speaker type/position for these channels
+ */
+static void program_config_element_parse_tags(GetBitContext * gb, int *cpe_map,
+ int *sce_map, int n, int type) {
+ int *map;
+ while(n--) {
+ map = cpe_map && get_bits1(gb) ? cpe_map : sce_map; // stereo or mono map
+ map[get_bits(gb, 4)] = type;
+ }
+}
+
+
/**
* Parse program config element
* reference: Table 4.2
- *
- * XXX: Needs fixup
*/
static int program_config_element(AACContext * ac, GetBitContext * gb) {
- program_config_struct * pcs = &ac->pcs;
- int id, object_type, i;
- assert(ac->channels == 0);
- pcs->present = 1;
- id = get_bits(gb, 4);
- object_type = get_bits(gb, 2);
+ program_config_struct pcs;
+ int i, num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc;
+
+ memset(&pcs, 0, sizeof(program_config_struct));
+
+ skip_bits(gb, 4); // element_instance_tag
+ skip_bits(gb, 2); // object_type
ac->sampling_index = get_bits(gb, 4);
- assert(ac->sampling_index <= 12);
+ if(ac->sampling_index > 12) {
+ av_log(ac->avccontext, AV_LOG_ERROR, "Invalid sampling rate index %d", ac->sampling_index);
+ return -1;
+ }
ac->sample_rate = sampling_table[ac->sampling_index];
- pcs->num_front = get_bits(gb, 4);
- pcs->num_side = get_bits(gb, 4);
- pcs->num_back = get_bits(gb, 4);
- pcs->num_lfe = get_bits(gb, 2);
- pcs->num_assoc_data = get_bits(gb, 3);
- pcs->num_cc = get_bits(gb, 4);
+ num_front = get_bits(gb, 4);
+ num_side = get_bits(gb, 4);
+ num_back = get_bits(gb, 4);
+ num_lfe = get_bits(gb, 2);
+ num_assoc_data = get_bits(gb, 3);
+ num_cc = get_bits(gb, 4);
- pcs->mono_mixdown = get_bits1(gb) ? get_bits(gb, 4) + 1: 0;
- pcs->stereo_mixdown = get_bits1(gb) ? get_bits(gb, 4) + 1: 0;
- assert(pcs->mono_mixdown == 0 && pcs->stereo_mixdown == 0);
+ pcs.mono_mixdown = get_bits1(gb) ? get_bits(gb, 4) : -1;
+ pcs.stereo_mixdown = get_bits1(gb) ? get_bits(gb, 4) : -1;
if (get_bits1(gb)) {
- pcs->matrix_mixdown = get_bits(gb, 2) + 1;
- pcs->pseudo_surround = get_bits1(gb);
+ pcs.mixdown_coeff_index = get_bits(gb, 2);
+ pcs.pseudo_surround = get_bits1(gb);
} else {
- pcs->matrix_mixdown = 0;
- pcs->pseudo_surround = 0;
+ pcs.mixdown_coeff_index = 0;
+ pcs.pseudo_surround = 0;
}
- pcs->front_cpe = 0;
- ac->channels += pcs->num_front;
- for (i = 0; i < pcs->num_front; i++) {
- if (get_bits1(gb)) {
- pcs->front_cpe |= (1 << i);
- ac->channels++;
- }
- pcs->front_tag[i] = get_bits(gb, 4);
- }
- pcs->side_cpe = 0;
- ac->channels += pcs->num_side;
- for (i = 0; i < pcs->num_side; i++) {
- if (get_bits1(gb)) {
- pcs->side_cpe |= (1 << i);
- ac->channels++;
- }
- pcs->side_tag[i] = get_bits(gb, 4);
- }
- pcs->back_cpe = 0;
- ac->channels += pcs->num_back;
- for (i = 0; i < pcs->num_back; i++) {
- if (get_bits1(gb)) {
- pcs->back_cpe |= (1 << i);
- ac->channels++;
- }
- pcs->back_tag[i] = get_bits(gb, 4);
- }
- ac->channels += pcs->num_lfe;
- for (i = 0; i < pcs->num_lfe; i++)
- pcs->lfe_tag[i] = get_bits(gb, 4);
+ program_config_element_parse_tags(gb, pcs.cpe_type, pcs.sce_type, num_front, AAC_CHANNEL_FRONT);
+ program_config_element_parse_tags(gb, pcs.cpe_type, pcs.sce_type, num_side, AAC_CHANNEL_SIDE );
+ program_config_element_parse_tags(gb, pcs.cpe_type, pcs.sce_type, num_back, AAC_CHANNEL_BACK );
+ program_config_element_parse_tags(gb, NULL, pcs.lfe_type, num_lfe, AAC_CHANNEL_LFE );
- pcs->num_channels = ac->channels;
// not a real audio channel
- for (i = 0; i < pcs->num_assoc_data; i++)
- pcs->assoc_data_tag[i] = get_bits(gb, 4);
- pcs->cc_ind_sw = 0;
- for (i = 0; i < pcs->num_cc; i++) {
- pcs->cc_ind_sw |= (get_bits1(gb) << i);
- pcs->cc_tag[i] = get_bits(gb, 4);
+ for (i = 0; i < num_assoc_data; i++)
+ skip_bits(gb, 4);
+
+ for (i = 0; i < num_cc; i++) {
+ skip_bits1(gb); // cc_ind_sw
+ pcs.cc_type[get_bits(gb, 4)] = AAC_CHANNEL_CC;
}
+
align_get_bits(gb);
+
+ /* comment field, first byte is length */
skip_bits_long(gb, 8 * get_bits(gb, 8));
- return 0;
+ return output_configure(ac, &pcs);
+}
+
+/**
+ * Set up program_config_struct, but based on a default channel configuration
+ * as specified in Table 1.17
+ */
+static int program_config_element_default(AACContext *ac, int channels)
+{
+ program_config_struct pcs;
+
+ memset(&pcs, 0, sizeof(program_config_struct));
+
+ /* Premixed downmix outputs are not available */
+ pcs.mono_mixdown = -1;
+ pcs.stereo_mixdown = -1;
+
+ switch(channels) {
+ case 1: /* Mono */
+ pcs.sce_type[0] = AAC_CHANNEL_FRONT;
+ break;
+
+ case 2: /* Stereo */
+ pcs.cpe_type[0] = AAC_CHANNEL_FRONT;
+ break;
+
+ case 3: /* Front Center + L + R */
+ pcs.sce_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[0] = AAC_CHANNEL_FRONT;
+ break;
+
+ case 4: /* Front Center + L + R + Back Center */
+ pcs.sce_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[0] = AAC_CHANNEL_FRONT;
+ pcs.sce_type[1] = AAC_CHANNEL_BACK;
+ break;
+
+ case 5: /* Front Center + L + R + Back Stereo */
+ pcs.sce_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[1] = AAC_CHANNEL_BACK;
+ break;
+
+ case 6: /* Front Center + L + R + Back Stereo + LFE */
+ pcs.sce_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[1] = AAC_CHANNEL_BACK;
+ pcs.lfe_type[0] = AAC_CHANNEL_LFE;
+ break;
+
+ case 7: /* Front Center + L + R + Outer Front Left + Outer Front Right + Back Stereo + LFE */
+ pcs.sce_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[0] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[1] = AAC_CHANNEL_FRONT;
+ pcs.cpe_type[2] = AAC_CHANNEL_BACK;
+ pcs.lfe_type[0] = AAC_CHANNEL_LFE;
+ break;
+
+ default:
+ av_log(ac->avccontext, AV_LOG_ERROR, "Invalid default channel configuration (%d channels)",
+ channels);
+ return -1;
+ }
+ return output_configure(ac, &pcs);
}
+
/**
* Parse GA specific configuration
* reference: Table 4.1
*/
-static int GASpecificConfig(AACContext * ac, GetBitContext * gb) {
+static int GASpecificConfig(AACContext * ac, GetBitContext * gb, int channels) {
int ext = 0;
if(get_bits1(gb)) { // frameLengthFlag
@@ -661,8 +739,13 @@ static int GASpecificConfig(AACContext *
ac->audioObjectType == AOT_ER_AAC_SCALABLE)
skip_bits(gb, 3); // layerNr
- if (ac->channels == 0)
- program_config_element(ac, gb);
+ if (channels == 0) {
+ if(program_config_element(ac, gb) < 0)
+ return -1;
+ } else {
+ program_config_element_default(ac, channels);
+ }
+
if (ext) {
switch (ac->audioObjectType) {
case AOT_ER_BSAC:
@@ -721,6 +804,7 @@ static int GetSampleRate(GetBitContext *
*/
static int AudioSpecificConfig(AACContext * ac, void *data, int data_size) {
GetBitContext gb;
+ int channels;
init_get_bits(&gb, data, data_size * 8);
@@ -728,7 +812,7 @@ static int AudioSpecificConfig(AACContex
ac->audioObjectType = GetAudioObjectType(&gb);
if (GetSampleRate(&gb, &ac->sampling_index, &ac->sample_rate)) return -1;
- ac->channels = get_bits(&gb, 4);
+ channels = get_bits(&gb, 4);
ac->sbr_present = 0;
if (ac->audioObjectType == AOT_SBR) {
@@ -744,7 +828,7 @@ static int AudioSpecificConfig(AACContex
case AOT_AAC_LC:
case AOT_AAC_SSR:
case AOT_AAC_LTP:
- if (GASpecificConfig(ac, &gb))
+ if (GASpecificConfig(ac, &gb, channels))
return -1;
break;
default:
@@ -793,33 +877,8 @@ static int aac_decode_init(AVCodecContex
if (AudioSpecificConfig(ac, avccontext->extradata, avccontext->extradata_size))
return -1;
- if (avccontext->channels == 0) {
- avccontext->channels = ac->channels;
- } else if ((avccontext->channels == 1) && ((ac->channels == 7) || (ac->channels == 6) || (ac->channels == 5))) {
- av_log(avccontext, AV_LOG_INFO, "aac: Downmix from %d to mono\n", ac->channels);
- if (!ac->pcs.matrix_mixdown) {
- ac->pcs.matrix_mixdown = 1;
- ac->pcs.pseudo_surround = 0;
- }
- } else if ((avccontext->channels == 2) && ((ac->channels == 7) || (ac->channels == 6) || (ac->channels == 5))){
- av_log(avccontext, AV_LOG_INFO, "aac: Downmix from %d to stereo\n", ac->channels);
- if (!ac->pcs.matrix_mixdown) {
- ac->pcs.matrix_mixdown = 1;
- ac->pcs.pseudo_surround = 0;
- }
- } else if (((avccontext->channels == 2) || (avccontext->channels == 1)) && ((ac->channels == 2) || (ac->channels == 1))){
- // it's ok stereo <-> mono
- } else {
- if (avccontext->channels < ac->channels)
- av_log(avccontext, AV_LOG_INFO, "aac: AAC stream has %d channels but output to %d channels\n",
- ac->channels, avccontext->channels);
- avccontext->channels = ac->channels;
- }
avccontext->sample_rate = ac->sample_rate;
- /* Allocate aligned reorder buffer */
- ac->interleaved_output = av_malloc(ac->channels * 1024 * sizeof(float));
-
for (i = 0; i < 11; i++) {
static const int mod_cb[11] = { 3, 3, 3, 3, 9, 9, 8, 8, 13, 13, 17 };
static const int off_cb[11] = { 1, 1, 0, 0, 4, 4, 0, 0, 0, 0, 0 };
@@ -1359,11 +1418,9 @@ static int single_channel_struct(AACCont
sce_struct * sce;
int id = get_bits(gb, 4);
if (ac->che_sce[id] == NULL) {
- ac->che_sce[id] = av_mallocz(sizeof(sce_struct));
- program_config_element_add_channel(ac, FLAG_SCE | id);
+ return -1;
}
sce = ac->che_sce[id];
- sce->mixing_gain = ac->mix.sce_gain[id];
if (individual_channel_stream(ac, gb, 0, 0, sce))
return -1;
return 0;
@@ -1405,12 +1462,9 @@ static int channel_pair_element(AACConte
cpe_struct * cpe;
int id = get_bits(gb, 4);
if (ac->che_cpe[id] == NULL) {
- ac->che_cpe[id] = av_mallocz(sizeof(cpe_struct));
- program_config_element_add_channel(ac, FLAG_CPE | id);
+ return -1;
}
cpe = ac->che_cpe[id];
- cpe->ch[0].mixing_gain = ac->mix.cpe_gain[id][0];
- cpe->ch[1].mixing_gain = ac->mix.cpe_gain[id][1];
cpe->common_window = get_bits1(gb);
if (cpe->common_window) {
if (ics_info(ac, gb, 1, &cpe->ch[0].ics))
@@ -1448,8 +1502,7 @@ static int coupling_channel_element(AACC
coupling_struct * coup;
int id = get_bits(gb, 4);
if (ac->che_cc[id] == NULL) {
- ac->che_cc[id] = av_mallocz(sizeof(cc_struct));
- program_config_element_add_channel(ac, FLAG_CCE | id);
+ return -1;
}
sce = &ac->che_cc[id]->ch;
sce->mixing_gain = 1.0;
@@ -1514,11 +1567,9 @@ static int lfe_channel_struct(AACContext
sce_struct * sce;
int id = get_bits(gb, 4);
if (ac->che_lfe[id] == NULL) {
- ac->che_lfe[id] = av_mallocz(sizeof(sce_struct));
- program_config_element_add_channel(ac, FLAG_LFE | id);
+ return -1;
}
sce = ac->che_lfe[id];
- sce->mixing_gain = ac->mix.lfe_gain[id];
if (individual_channel_stream(ac, gb, 0, 0, sce))
return -1;
return 0;
@@ -2031,268 +2082,60 @@ static void spec_to_sample(AACContext *
transform_sce_tool(ac, ltp_update_trans);
}
-static int output_coefs(AVCodecContext * avccontext) {
- AACContext * ac = avccontext->priv_data;
- program_config_struct * pcs = &ac->pcs;
- mix_config_struct * mix = &ac->mix;
- int ichannels = ac->channels;
- int ochannels = avccontext->channels;
- int i;
- for (i = 0; i < MAX_TAGID; i++) {
- mix->sce_gain[i] = 1.;
- mix->cpe_gain[i][0] = 1.;
- mix->cpe_gain[i][1] = 1.;
- mix->lfe_gain[i] = 1.;
- }
- mix->c_tag = 0;
- mix->lr_tag = 0;
- mix->sur_tag = 0;
- mix->mode = MIXMODE_UNKNOWN;
- if ((ochannels == 1) && ((ichannels == 2) || (ichannels == 1) || (pcs->mono_mixdown))) {
- int tag = pcs->mono_mixdown ? pcs->mono_mixdown - 1 : ((pcs->num_front == 1) ? pcs->front_tag[0] : 0);
- if (ichannels == 2) {
- mix->mode = MIXMODE_2TO1;
- mix->lr_tag = tag;
- mix->cpe_gain[tag][0] = mix->cpe_gain[tag][1] = 0.5;
- } else {
- mix->mode = MIXMODE_1TO1;
- mix->c_tag = tag;
- }
- } else if ((ochannels == 2) && ((ichannels == 1) || (ichannels == 2) || (pcs->stereo_mixdown))) {
- int tag = pcs->stereo_mixdown ? pcs->stereo_mixdown - 1 : ((pcs->num_front == 1) ? pcs->front_tag[0] : 0);
- if (ichannels == 1) {
- mix->mode = MIXMODE_1TO2;
- mix->c_tag = tag;
- } else {
- mix->mode = MIXMODE_2TO2;
- mix->lr_tag = tag;
- }
- } else if (((ochannels == 1) || (ochannels == 2)) && (pcs->matrix_mixdown)) {
- float alpha_tab[] = {sqrt(2)/2, 1./2, sqrt(2)/4., 0};
- float alpha = alpha_tab[pcs->matrix_mixdown - 1];
- float ialpha = 0;
- if (ochannels == 1) {
- mix->mode = MIXMODE_MATRIX1;
- ialpha = 1. / (3 + 2 * alpha);
- } else {
- mix->mode = MIXMODE_MATRIX2;
- ialpha = pcs->pseudo_surround ? 1. / (1. + sqrt(2) / 2 + 2 * alpha) : 1. / (1. + sqrt(2) / 2 + alpha);
- }
- for (i = 0; i < pcs->num_front; i++) {
- if (pcs->front_cpe & (1 << i)) {
- mix->lr_tag = pcs->front_tag[i];
- mix->cpe_gain[mix->lr_tag][0] = mix->cpe_gain[mix->lr_tag][1] = ialpha;
- break;
- }
- }
- for (i = 0; i < pcs->num_front; i++) {
- if (!(pcs->front_cpe & (1 << i))) {
- mix->c_tag = pcs->front_tag[i];
- mix->sce_gain[mix->c_tag] = ialpha * sqrt(2) / 2.;
- break;
- }
- }
- mix->sur_tag = -1;
- for (i = 0; i < pcs->num_back; i++) {
- if (pcs->back_cpe & (1 << i)) {
- mix->sur_tag = pcs->back_tag[i];
- break;
- }
- }
- if (mix->sur_tag == -1) {
- for (i = 0; i < pcs->num_side; i++) {
- if (pcs->side_cpe & (1 << i)) {
- mix->sur_tag = pcs->back_tag[i];
- break;
- }
- }
- }
- if (mix->sur_tag != -1) {
- mix->cpe_gain[mix->sur_tag][0] = ialpha * alpha;
- mix->cpe_gain[mix->sur_tag][1] = ialpha * alpha;
- }
- } else if (ochannels >= ichannels) {
- mix->mode = MIXMODE_DEFAULT;
- }
- return 0;
-}
static int output_samples(AVCodecContext * avccontext, uint16_t * data, int * data_size) {
AACContext * ac = avccontext->priv_data;
- program_config_struct * pcs = &ac->pcs;
- mix_config_struct * mix = &ac->mix;
- int ichannels = ac->channels;
- int ochannels = avccontext->channels;
- int size = ochannels * 1024 * sizeof(uint16_t);
- int i;
-
- /* set a default float2int16 buffer */
- ac->iop = ac->interleaved_output;
+ int i, ch;
+ float *c, *l, *r, *sl, *sr, *out;
if (!ac->is_saved) {
ac->is_saved = 1;
*data_size = 0;
return 0;
}
- *data_size = size;
- /* the matrixmix modes are probably broken and they shouldn't be here anyway */
- switch (mix->mode) {
- case MIXMODE_DEFAULT:
- break;
- case MIXMODE_1TO1:
- ac->iop = ac->che_sce[mix->c_tag]->ret;
- break;
- case MIXMODE_2TO1:
- for (i = 0; i < 1024; i++)
- ac->interleaved_output[i] = ac->che_cpe[0]->ch[mix->lr_tag].ret[i] + ac->che_cpe[mix->lr_tag]->ch[1].ret[i];
- break;
- case MIXMODE_1TO2:
- for (i = 0; i < 1024; i++)
- ac->interleaved_output[i*2] = ac->interleaved_output[i*2+1] = ac->che_sce[mix->c_tag]->ret[i];
- break;
- case MIXMODE_2TO2:
- for (i = 0; i < 1024; i++) {
- ac->interleaved_output[i*2] = ac->che_cpe[mix->lr_tag]->ch[0].ret[i];
- ac->interleaved_output[i*2+1] = ac->che_cpe[mix->lr_tag]->ch[1].ret[i];
- }
- break;
- case MIXMODE_MATRIX1:
- {
- cpe_struct *ch_lr = ac->che_cpe[mix->lr_tag];
- sce_struct *ch_c = ac->che_sce[mix->c_tag];
- cpe_struct *ch_sur = ac->che_cpe[mix->sur_tag];
- float cBIAS = - ac->add_bias;
- float out[1024];
- if (ch_c) {
- cBIAS += ac->add_bias;
- for (i = 0; i < 1024; i++)
- out[i] = ch_c->ret[i];
- } else {
- memset(out, 0, sizeof(out));
- }
- if (ch_lr) {
- cBIAS += 2 * ac->add_bias;
- for (i = 0; i < 1024; i++)
- out[i] += ch_lr->ch[0].ret[i] + ch_lr->ch[1].ret[i];
- }
- if (ch_sur) {
- cBIAS += 2 * ac->add_bias;
- for (i = 0; i < 1024; i++)
- out[i] += ch_sur->ch[0].ret[i] + ch_sur->ch[1].ret[i];
- }
- for (i = 0; i < 1024; i++)
- ac->interleaved_output[i] = out[i] - cBIAS;
- }
- break;
- case MIXMODE_MATRIX2:
- {
- cpe_struct *ch_lr = ac->che_cpe[mix->lr_tag];
- sce_struct *ch_c = ac->che_sce[mix->c_tag];
- cpe_struct *ch_sur = ac->che_cpe[mix->sur_tag];
- float lBIAS = -ac->add_bias, rBIAS = -ac->add_bias;
- float out[1024][2];
- if (ch_c) {
- lBIAS += ac->add_bias; rBIAS += ac->add_bias;
- for (i = 0; i < 1024; i++) {
- out[i][0] = out[i][1] = ch_c->ret[i];
- }
- } else {
- memset(out, 0, sizeof(out));
- }
- if (ch_lr) {
- lBIAS += ac->add_bias; rBIAS += ac->add_bias;
- for (i = 0; i < 1024; i++) {
- out[i][0] += ch_lr->ch[0].ret[i];
- out[i][1] += ch_lr->ch[1].ret[i];
- }
- }
- if (ch_sur) {
- if (pcs->pseudo_surround) {
- lBIAS -= 2 * ac->add_bias; rBIAS += 2 * ac->add_bias;
- for (i = 0; i < 1024; i++) {
- out[i][0] -= (ch_sur->ch[0].ret[i] + ch_sur->ch[1].ret[i]);
- out[i][1] += (ch_sur->ch[1].ret[i] + ch_sur->ch[0].ret[i]);
- }
- } else {
- lBIAS += ac->add_bias; rBIAS += ac->add_bias;
- for (i = 0; i < 1024; i++) {
- out[i][0] += ch_sur->ch[0].ret[i];
- out[i][1] += ch_sur->ch[1].ret[i];
- }
- }
+ if(ac->mm_center) {
+ /* Matrix mixdown */
+ l = ac->mm_front->ch[0].ret;
+ r = ac->mm_front->ch[1].ret;
+ c = ac->mm_center->ret;
+ sl = ac->mm_back->ch[0].ret;
+ sr = ac->mm_back->ch[1].ret;
+ out = ac->interleaved_output;
+
+ if(avccontext->channels == 2) {
+ if(ac->pcs.pseudo_surround) {
+ for(i = 0; i < 1024; i++) {
+ *out++ = *l++ + *c - *sl - *sr - ac->add_bias * 3;
+ *out++ = *r++ + *c++ + *sl++ + *sr++ - ac->add_bias * 3;
}
- for (i = 0; i < 1024; i++) {
- ac->interleaved_output[i*2] = out[i][0] - lBIAS;
- ac->interleaved_output[i*2+1] = out[i][1] - rBIAS;
+ } else {
+ for(i = 0; i < 1024; i++) {
+ *out++ = *l++ + *c + *sl++ - ac->add_bias * 2;
+ *out++ = *r++ + *c++ + *sr++ - ac->add_bias * 2;
}
}
- break;
- case MIXMODE_UNKNOWN:
- default:
- *data_size = 0;
- return 1;
- }
- if (mix->mode == MIXMODE_DEFAULT) {
- float *order[MAX_CHANNELS];
- int i, j = 0;
- if (pcs->present || pcs->generated) {
- for (i = 0; i < pcs->num_front; i++)
- if (!(pcs->front_cpe & (1 << i)))
- order[j++] = ac->che_sce[pcs->front_tag[i]]->ret;
- for (i = 0; i < pcs->num_front; i++)
- if (pcs->front_cpe & (1 << i)) {
- order[j++] = ac->che_cpe[pcs->front_tag[i]]->ch[0].ret;
- order[j++] = ac->che_cpe[pcs->front_tag[i]]->ch[1].ret;
- }
- for (i = 0; i < pcs->num_side; i++)
- if (!(pcs->side_cpe & (1 << i))) {
- order[j++] = ac->che_sce[pcs->side_tag[i]]->ret;
- } else {
- order[j++] = ac->che_cpe[pcs->side_tag[i]]->ch[0].ret;
- order[j++] = ac->che_cpe[pcs->side_tag[i]]->ch[1].ret;
- }
- for (i = 0; i < pcs->num_back; i++)
- if (pcs->back_cpe & (1 << i)) {
- order[j++] = ac->che_cpe[pcs->back_tag[i]]->ch[0].ret;
- order[j++] = ac->che_cpe[pcs->back_tag[i]]->ch[1].ret;
- }
- for (i = 0; i < pcs->num_back; i++)
- if (!(pcs->back_cpe & (1 << i)))
- order[j++] = ac->che_sce[pcs->back_tag[i]]->ret;
- for (i = 0; i < pcs->num_lfe; i++)
- order[j++] = ac->che_lfe[pcs->lfe_tag[i]]->ret;
+
} else {
- for (i = 0; i < MAX_TAGID; i++)
- if (ac->che_sce[i] != NULL)
- order[j++] = ac->che_sce[i]->ret;
- for (i = 0; i < MAX_TAGID; i++)
- if (ac->che_cpe[i] != NULL) {
- order[j++] = ac->che_cpe[i]->ch[0].ret;
- order[j++] = ac->che_cpe[i]->ch[1].ret;
- }
- for (i = 0; i < MAX_TAGID; i++)
- if (ac->che_lfe[i] != NULL)
- order[j++] = ac->che_lfe[i]->ret;
- }
- assert(j == ichannels);
- for (i = 0; i < ochannels; i++) {
- if (i < ichannels) {
- for (j = 0; j < 1024; j++)
- ac->interleaved_output[j * ochannels + i] = order[i][j];
- } else {
- for (j = 0; j < 1024; j++)
- ac->interleaved_output[j * ochannels + i] = 0.0;
+ assert(avccontext->channels == 1);
+ for(i = 0; i < 1024; i++) {
+ *out++ = *l++ + *r++ + *c++ + *sl++ + *sr++ - ac->add_bias * 4;
}
}
- }
- /* Convert from float to int16 */
- ac->dsp.float_to_int16(data, ac->iop, 1024*ochannels);
+ } else {
+ for(i = 0; i < 1024; i++)
+ for(ch = 0; ch < avccontext->channels; ch++) {
+ ac->interleaved_output[i * avccontext->channels + ch] = ac->output_data[ch][i];
+ }
+ }
- return 0;
+ *data_size = 1024 * avccontext->channels * sizeof(uint16_t);
+ ac->dsp.float_to_int16(data, ac->interleaved_output, *data_size);
+ return 0;
}
+
static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data_size, uint8_t * buf, int buf_size) {
AACContext * ac = avccontext->priv_data;
GetBitContext gb;
@@ -2302,9 +2145,6 @@ static int aac_decode_frame(AVCodecConte
init_get_bits(&gb, buf, buf_size*8);
- if (!ac->is_saved) {
- output_coefs(avccontext);
- }
// parse
while ((id = get_bits(&gb, 3)) != ID_END) {
switch (id) {
More information about the FFmpeg-soc
mailing list