diff aac.c @ 7523:a3f7ffdb676d libavcodec

Sync already committed code with that in SoC and commit more OKed hunks of code
author superdump
date Sat, 09 Aug 2008 10:46:27 +0000
parents d6012be599d3
children 4fca7939ad48
line wrap: on
line diff
--- a/aac.c	Sat Aug 09 01:17:34 2008 +0000
+++ b/aac.c	Sat Aug 09 10:46:27 2008 +0000
@@ -82,6 +82,7 @@
 
 #include "aac.h"
 #include "aactab.h"
+#include "aacdectab.h"
 #include "mpeg4audio.h"
 
 #include <assert.h>
@@ -91,6 +92,7 @@
 
 #ifndef CONFIG_HARDCODED_TABLES
     static float ff_aac_ivquant_tab[IVQUANT_SIZE];
+    static float ff_aac_pow2sf_tab[316];
 #endif /* CONFIG_HARDCODED_TABLES */
 
 static VLC vlc_scalefactors;
@@ -104,27 +106,29 @@
     num_assoc_data  = get_bits(gb, 3);
     num_cc          = get_bits(gb, 4);
 
-    newpcs->mono_mixdown_tag   = get_bits1(gb) ? get_bits(gb, 4) : -1;
-    newpcs->stereo_mixdown_tag = get_bits1(gb) ? get_bits(gb, 4) : -1;
+    if (get_bits1(gb))
+        skip_bits(gb, 4); // mono_mixdown_tag
+    if (get_bits1(gb))
+        skip_bits(gb, 4); // stereo_mixdown_tag
 
-    if (get_bits1(gb)) {
-        newpcs->mixdown_coeff_index = get_bits(gb, 2);
-        newpcs->pseudo_surround     = get_bits1(gb);
-    }
+    if (get_bits1(gb))
+        skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
 
-    program_config_element_parse_tags(newpcs->che_type[ID_CPE], newpcs->che_type[ID_SCE], AAC_CHANNEL_FRONT, gb, num_front);
-    program_config_element_parse_tags(newpcs->che_type[ID_CPE], newpcs->che_type[ID_SCE], AAC_CHANNEL_SIDE,  gb, num_side );
-    program_config_element_parse_tags(newpcs->che_type[ID_CPE], newpcs->che_type[ID_SCE], AAC_CHANNEL_BACK,  gb, num_back );
-    program_config_element_parse_tags(NULL,                     newpcs->che_type[ID_LFE], AAC_CHANNEL_LFE,   gb, num_lfe  );
+    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 );
+    decode_channel_map(NULL,                  new_che_pos[TYPE_LFE], AAC_CHANNEL_LFE,   gb, num_lfe  );
 
     skip_bits_long(gb, 4 * num_assoc_data);
 
-    program_config_element_parse_tags(newpcs->che_type[ID_CCE], newpcs->che_type[ID_CCE], AAC_CHANNEL_CC,    gb, num_cc   );
+    decode_channel_map(new_che_pos[TYPE_CCE], new_che_pos[TYPE_CCE], AAC_CHANNEL_CC,    gb, num_cc   );
 
     align_get_bits(gb);
 
     /* comment field, first byte is length */
     skip_bits_long(gb, 8 * get_bits(gb, 8));
+    return 0;
+}
 
 static av_cold int aac_decode_init(AVCodecContext * avccontext) {
     AACContext * ac = avccontext->priv_data;
@@ -132,6 +136,10 @@
 
     ac->avccontext = avccontext;
 
+    if (avccontext->extradata_size <= 0 ||
+        decode_audio_specific_config(ac, avccontext->extradata, avccontext->extradata_size))
+        return -1;
+
     avccontext->sample_rate = ac->m4ac.sample_rate;
     avccontext->frame_size  = 1024;
 
@@ -166,6 +174,8 @@
 #ifndef CONFIG_HARDCODED_TABLES
     for (i = 1 - IVQUANT_SIZE/2; i < IVQUANT_SIZE/2; i++)
         ff_aac_ivquant_tab[i + IVQUANT_SIZE/2 - 1] =  cbrt(fabs(i)) * i;
+    for (i = 0; i < 316; i++)
+        ff_aac_pow2sf_tab[i] = pow(2, (i - 200)/4.);
 #endif /* CONFIG_HARDCODED_TABLES */
 
     INIT_VLC_STATIC(&vlc_scalefactors, 7, sizeof(ff_aac_scalefactor_code)/sizeof(ff_aac_scalefactor_code[0]),
@@ -200,6 +210,112 @@
         return cbrtf(fabsf(a)) * a;
 }
 
+        int band_type_run_end[120], GetBitContext * gb, IndividualChannelStream * ics) {
+    int g, idx = 0;
+    const int bits = (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) ? 3 : 5;
+    for (g = 0; g < ics->num_window_groups; g++) {
+        int k = 0;
+        while (k < ics->max_sfb) {
+            uint8_t sect_len = k;
+            int sect_len_incr;
+            int sect_band_type = get_bits(gb, 4);
+            if (sect_band_type == 12) {
+                av_log(ac->avccontext, AV_LOG_ERROR, "invalid band type\n");
+                return -1;
+            }
+            while ((sect_len_incr = get_bits(gb, bits)) == (1 << bits)-1)
+                sect_len += sect_len_incr;
+            sect_len += sect_len_incr;
+            if (sect_len > ics->max_sfb) {
+                av_log(ac->avccontext, AV_LOG_ERROR,
+                    "Number of bands (%d) exceeds limit (%d).\n",
+                    sect_len, ics->max_sfb);
+                return -1;
+            }
+
+ *
+ * @param   mix_gain            channel gain (Not used by AAC bitstream.)
+ * @param   global_gain         first scalefactor value as scalefactors are differentially coded
+ * @param   band_type           array of the used band type
+ * @param   band_type_run_end   array of the last scalefactor band of a band type run
+ * @param   sf                  array of scalefactors or intensity stereo positions
+ *
+ * @return  Returns error status. 0 - OK, !0 - error
+ */
+static int decode_scalefactors(AACContext * ac, float sf[120], GetBitContext * gb,
+        float mix_gain, unsigned int global_gain, IndividualChannelStream * ics,
+        enum BandType band_type[120], int band_type_run_end[120]) {
+    const int sf_offset = ac->sf_offset + (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE ? 12 : 0);
+    int g, i, idx = 0;
+    int offset[3] = { global_gain, global_gain - 90, 100 };
+    int noise_flag = 1;
+    static const char *sf_str[3] = { "Global gain", "Noise gain", "Intensity stereo position" };
+    ics->intensity_present = 0;
+    for (g = 0; g < ics->num_window_groups; g++) {
+        for (i = 0; i < ics->max_sfb;) {
+            int run_end = band_type_run_end[idx];
+            if (band_type[idx] == ZERO_BT) {
+                for(; i < run_end; i++, idx++)
+                    sf[idx] = 0.;
+            }else if((band_type[idx] == INTENSITY_BT) || (band_type[idx] == INTENSITY_BT2)) {
+                ics->intensity_present = 1;
+                for(; i < run_end; i++, idx++) {
+                    offset[2] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
+                    if(offset[2] > 255U) {
+                        av_log(ac->avccontext, AV_LOG_ERROR,
+                            "%s (%d) out of range.\n", sf_str[2], offset[2]);
+                        return -1;
+                    }
+                    sf[idx]  = ff_aac_pow2sf_tab[-offset[2] + 300];
+                    sf[idx] *= mix_gain;
+                }
+            }else if(band_type[idx] == NOISE_BT) {
+                for(; i < run_end; i++, idx++) {
+                    if(noise_flag-- > 0)
+                        offset[1] += get_bits(gb, 9) - 256;
+                    else
+                        offset[1] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
+                    if(offset[1] > 255U) {
+                        av_log(ac->avccontext, AV_LOG_ERROR,
+                            "%s (%d) out of range.\n", sf_str[1], offset[1]);
+                        return -1;
+                    }
+                    sf[idx]  = -ff_aac_pow2sf_tab[ offset[1] + sf_offset];
+                    sf[idx] *= mix_gain;
+                }
+            }else {
+                for(; i < run_end; i++, idx++) {
+                    offset[0] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
+                    if(offset[0] > 255U) {
+                        av_log(ac->avccontext, AV_LOG_ERROR,
+                            "%s (%d) out of range.\n", sf_str[0], offset[0]);
+                        return -1;
+                    }
+                    sf[idx] = -ff_aac_pow2sf_tab[ offset[0] + sf_offset];
+                    sf[idx] *= mix_gain;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+/**
+ * Decode pulse data; reference: table 4.7.
+ */
+static void decode_pulses(Pulse * pulse, GetBitContext * gb) {
+    int i;
+    pulse->num_pulse = get_bits(gb, 2) + 1;
+    pulse->start = get_bits(gb, 6);
+    for (i = 0; i < pulse->num_pulse; i++) {
+        pulse->offset[i] = get_bits(gb, 5);
+        pulse->amp   [i] = get_bits(gb, 4);
+    }
+}
+
+/**
+ * Add pulses with particular amplitudes to the quantized spectral data; reference: 4.6.3.3.
+ *
  * @param   pulse   pointer to pulse data struct
  * @param   icoef   array of quantized spectral data
  */
@@ -213,18 +329,97 @@
     }
 }
 
+/**
+ * Parse Spectral Band Replication extension data; reference: table 4.55.
+ *
+ * @param   crc flag indicating the presence of CRC checksum
+ * @param   cnt length of TYPE_FIL syntactic element in bytes
+ * @return  Returns number of bytes consumed from the TYPE_FIL element.
+ */
+static int decode_sbr_extension(AACContext * ac, GetBitContext * gb, int crc, int cnt) {
+    // TODO : sbr_extension implementation
+    av_log(ac->avccontext, AV_LOG_DEBUG, "aac: SBR not yet supported.\n");
+    skip_bits_long(gb, 8*cnt - 4); // -4 due to reading extension type
+    return cnt;
+}
+
+    int crc_flag = 0;
+    int res = cnt;
+    switch (get_bits(gb, 4)) { // extension type
+        case EXT_SBR_DATA_CRC:
+            crc_flag++;
+        case EXT_SBR_DATA:
+            res = decode_sbr_extension(ac, gb, crc_flag, cnt);
+            break;
+        case EXT_DYNAMIC_RANGE:
+            res = decode_dynamic_range(&ac->che_drc, gb, cnt);
+            break;
+        case EXT_FILL:
+        case EXT_FILL_DATA:
+        case EXT_DATA_ELEMENT:
+        default:
+            skip_bits_long(gb, 8*cnt - 4);
+            break;
+    };
+    return res;
+}
+
+/**
+ * Apply dependent channel coupling (applied before IMDCT).
+ *
+ * @param   index   index into coupling gain array
+ */
+static void apply_dependent_coupling(AACContext * ac, SingleChannelElement * sce, ChannelElement * cc, int index) {
+    IndividualChannelStream * ics = &cc->ch[0].ics;
+    const uint16_t * offsets = ics->swb_offset;
+    float * dest = sce->coeffs;
+    const float * src = cc->ch[0].coeffs;
+    int g, i, group, k, idx = 0;
+    if(ac->m4ac.object_type == AOT_AAC_LTP) {
+        av_log(ac->avccontext, AV_LOG_ERROR,
+               "Dependent coupling is not supported together with LTP\n");
+        return;
+    }
+    for (g = 0; g < ics->num_window_groups; g++) {
+        for (i = 0; i < ics->max_sfb; i++, idx++) {
+            if (cc->ch[0].band_type[idx] != ZERO_BT) {
+                float gain = cc->coup.gain[index][idx] * sce->mixing_gain;
+                for (group = 0; group < ics->group_len[g]; group++) {
+                    for (k = offsets[i]; k < offsets[i+1]; k++) {
+                        // XXX dsputil-ize
+                        dest[group*128+k] += gain * src[group*128+k];
+                    }
+                }
+            }
+        }
+        dest += ics->group_len[g]*128;
+        src  += ics->group_len[g]*128;
+    }
+}
+
+/**
+ * Apply independent channel coupling (applied after IMDCT).
+ *
+ * @param   index   index into coupling gain array
+ */
+static void apply_independent_coupling(AACContext * ac, SingleChannelElement * sce, ChannelElement * cc, int index) {
+    int i;
+    float gain = cc->coup.gain[index][0] * sce->mixing_gain;
+    for (i = 0; i < 1024; i++)
+        sce->ret[i] += gain * (cc->ch[0].ret[i] - ac->add_bias);
+}
+
 static av_cold int aac_decode_close(AVCodecContext * avccontext) {
     AACContext * ac = avccontext->priv_data;
     int i, j;
 
-    for (i = 0; i < MAX_TAGID; i++) {
+    for (i = 0; i < MAX_ELEM_ID; i++) {
         for(j = 0; j < 4; j++)
             av_freep(&ac->che[j][i]);
     }
 
     ff_mdct_end(&ac->mdct);
     ff_mdct_end(&ac->mdct_small);
-    av_freep(&ac->interleaved_output);
     return 0 ;
 }
 
@@ -238,4 +433,5 @@
     aac_decode_close,
     aac_decode_frame,
     .long_name = NULL_IF_CONFIG_SMALL("Advanced Audio Coding"),
+    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
 };