diff options
author | Robert Swain <robert.swain@gmail.com> | 2008-08-09 10:46:27 +0000 |
---|---|---|
committer | Robert Swain <robert.swain@gmail.com> | 2008-08-09 10:46:27 +0000 |
commit | cc0591dab0a5508518413260c77750577c30b0d6 (patch) | |
tree | ab5427e05448ea28c2aba903ee62d72903dbe1bd /libavcodec/aac.c | |
parent | 5f7f9719acb145620ffca333e73b4bcfb1807783 (diff) | |
download | ffmpeg-cc0591dab0a5508518413260c77750577c30b0d6.tar.gz |
Sync already committed code with that in SoC and commit more OKed hunks of code
Originally committed as revision 14674 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/aac.c')
-rw-r--r-- | libavcodec/aac.c | 222 |
1 files changed, 209 insertions, 13 deletions
diff --git a/libavcodec/aac.c b/libavcodec/aac.c index 47237ff44e..cd59c2031a 100644 --- a/libavcodec/aac.c +++ b/libavcodec/aac.c @@ -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 @@ static VLC vlc_spectral[11]; 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 @@ static av_cold int aac_decode_init(AVCodecContext * avccontext) { 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 @@ static av_cold int aac_decode_init(AVCodecContext * avccontext) { #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 @@ static inline float ivquant(int a) { 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 @@ static void add_pulses(int icoef[1024], const Pulse * pulse, const IndividualCha } } +/** + * 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 @@ AVCodec aac_decoder = { 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}, }; |