Int get_prog_config( tDec_Int_File *pVars, ProgConfig *pScratchPCE) { Int i; UInt tag; Int numChars; UInt temp; Bool flag; Int status = SUCCESS; BITS *pInputStream = &(pVars->inputStream); /* * The tag is used at the very end to see if this PCE is * the one to be used. Otherwise it does not need to be saved for the * the simple configurations to be used in this version of an AAC * decoder. * * All of the bits of this PCE must be read even if this PCE will not * be used. They are read into a temporary PCE, then later it is decided * whether to keep this PCE. * * To allow quick removal of the fields from the ProgConfig structure * that will probably not be used at a later date, * while still advancing the bitstream pointer,the return value of * getbits is saved into a temporary variable, then transfered to * the structure item. */ tag = get9_n_lessbits(LEN_TAG, pInputStream); pScratchPCE->profile = get9_n_lessbits(LEN_PROFILE, pInputStream); pScratchPCE->sampling_rate_idx = get9_n_lessbits(LEN_SAMP_IDX, pInputStream); if (!pVars->adif_test && (pScratchPCE->sampling_rate_idx != pVars->prog_config.sampling_rate_idx)) { #ifdef AAC_PLUS /* * PCE carries the baseline frequency, if SBR or PS are used, the frequencies will not match * so check for this unique case, and let decoding continue if this is a redundant PCE */ if ((pScratchPCE->sampling_rate_idx != (pVars->prog_config.sampling_rate_idx + 3)) || (pVars->mc_info.upsamplingFactor != 2)) #endif { /* rewind the pointer as implicit channel configuration maybe the case */ pInputStream->usedBits -= (LEN_TAG + LEN_PROFILE + LEN_SAMP_IDX); return (1); /* mismatch cannot happen */ } } /* * Retrieve the number of element lists for each of * front, side, back, lfe, data, and coupling. * * For two-channel stereo or mono, only the data in the front needs * to be saved. However, ALL fields need to be skipped over in some * fashion. Also, the number of elements needs to be temporarily saved * to call get_ele_list(). If that function was changed to pass in * the number of points to be read, the memory set aside inside the * ProgConfig structure could be removed. */ /* * The next six function calls could be combined into one, then use * shifts and masks to retrieve the individual fields. */ temp = get9_n_lessbits(LEN_NUM_ELE, pInputStream); pScratchPCE->front.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_ELE, pInputStream); pScratchPCE->side.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_ELE, pInputStream); pScratchPCE->back.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_LFE, pInputStream); pScratchPCE->lfe.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_DAT, pInputStream); pScratchPCE->data.num_ele = temp; /* Needed only to read in the element list. */ temp = get9_n_lessbits(LEN_NUM_CCE, pInputStream); pScratchPCE->coupling.num_ele = temp; /* * Read in mix down data. * * Whether these fields can be removed and have proper operation * will be determined at a later date. */ /* Read presence of mono_mix */ flag = get1bits(pInputStream);/* LEN_MIX_PRES,*/ pScratchPCE->mono_mix.present = flag; if (flag != FALSE) { temp = get9_n_lessbits(LEN_TAG, pInputStream); pScratchPCE->mono_mix.ele_tag = temp; } /* end if (flag != FALSE) */ /* Read presence of stereo mix */ flag = get1bits(pInputStream); /* LEN_MIX_PRES,*/ pScratchPCE->stereo_mix.present = flag; if (flag != FALSE) { temp = get9_n_lessbits(LEN_TAG, pInputStream); pScratchPCE->stereo_mix.ele_tag = temp; } /* end if (flag != FALSE) */ /* Read presence of matrix mix */ flag = get1bits(pInputStream); /* LEN_MIX_PRES,*/ pScratchPCE->matrix_mix.present = flag; if (flag != FALSE) { temp = get9_n_lessbits(LEN_MMIX_IDX, pInputStream); pScratchPCE->matrix_mix.ele_tag = temp; temp = get1bits(pInputStream); /* LEN_PSUR_ENAB,*/ pScratchPCE->matrix_mix.pseudo_enab = temp; } /* end if (flag != FALSE) */ /* * Get each of the element lists. Only the front information will be * used for the PV decoder, but the usedBits field of pInputStream must * be advanced appropriately. * * This could be optimized by advancing the bit stream for the * elements that do not need to be read. */ get_ele_list(&pScratchPCE->front, pInputStream, TRUE); get_ele_list(&pScratchPCE->side, pInputStream, TRUE); get_ele_list(&pScratchPCE->back, pInputStream, TRUE); get_ele_list(&pScratchPCE->lfe, pInputStream, FALSE); get_ele_list(&pScratchPCE->data, pInputStream, FALSE); get_ele_list(&pScratchPCE->coupling, pInputStream, TRUE); /* * The standard requests a byte alignment before reading in the * comment. This can be done because LEN_COMMENT_BYTES == 8. */ byte_align(pInputStream); numChars = get9_n_lessbits(LEN_COMMENT_BYTES, pInputStream); /* * Ignore the comment - it requires 65 bytes to store (or worse on DSP). * If this field is restored, make sure to append a trailing '\0' */ for (i = numChars; i > 0; i--) { pScratchPCE->comments[i] = (Char) get9_n_lessbits(LEN_BYTE, pInputStream); } /* end for */ if (pVars->current_program < 0) { /* * If this is the first PCE, it becomes the current, regardless of * its tag number. */ pVars->current_program = tag; pVars->mc_info.ch_info[0].tag = 0; } /* end if (pVars->current_program < 0) */ if (tag == (UInt)pVars->current_program) { /* * This branch is reached under two conditions: * 1) This is the first PCE found, it was selected in the above if * block. In all encoders found thus far, the tag value has been * zero. * 2) A PCE has been sent by the encoder with a tag that matches the * the first one sent. It will then be re-read. No encoder found * * Regardless, the temporary PCE will now be copied into the * the one official program configuration. */ /* * Keep adts setting in case of a redundant PCE (only applicable when * using aac-lib own adts parser) */ pScratchPCE->file_is_adts = pVars->prog_config.file_is_adts; pScratchPCE->headerless_frames = pVars->prog_config.headerless_frames; pv_memcpy(&pVars->prog_config, pScratchPCE, sizeof(ProgConfig)); tag = 0; /* * Check that dual-mono does not carry more than 2 tracks, otherwise flag an non-supported error */ if ((pVars->prog_config.front.num_ele > 2) && !(pVars->prog_config.front.ele_is_cpe[tag])) { status = 1; } /* * Check that stereo does not carry more than 1 track, otherwise flag an non-supported error */ if ((pVars->prog_config.front.num_ele > 1) && (pVars->prog_config.front.ele_is_cpe[tag])) { status = 1; } if (!status) { /* enter configuration into MC_Info structure */ status = set_mc_info(&pVars->mc_info, (tMP4AudioObjectType)(pVars->prog_config.profile + 1), pVars->prog_config.sampling_rate_idx, pVars->prog_config.front.ele_tag[tag], pVars->prog_config.front.ele_is_cpe[tag], pVars->winmap, pVars->SFBWidth128); if (pVars->mc_info.upsamplingFactor == 2) { /* * prog_config.sampling_rate_idx corresponds to the aac base layer, * if the upsampling factor is active, then the output frequency needs * to be adjusted accordingly */ pVars->prog_config.sampling_rate_idx -= 3; } } } /* end if (tag == pVars->current_program) */ return (status); }
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ Int get_GA_specific_config( tDec_Int_File * const pVars, BITS *pInputStream, UInt channel_config, const tMP4AudioObjectType audioObjectType ) { Int status = SUCCESS; UInt dependsOnCoreCoder; /* Int coreCoderDelay; */ UInt extFlag; /* These variables are left for future implementation */ /* UInt layer_num; */ /* UInt numOfSubFrame; */ /* UInt layer_len; */ /* UInt aacSectionDataResilienceFlag; */ /* UInt aacScalefactorDataResilienceFlag; */ /* UInt aacSpectralDataResilienceFlag; */ Int extFlag3; /* * frame length flag == 0, 1024 samples/frame * frame length flag == 1, 960 samples/frame */ get1bits(/* LEN_FRAME_LEN_FLAG,*/ pInputStream); /* * dependsOnCoreCoder == 1, core coder has different sampling rate * in a scalable bitstream */ dependsOnCoreCoder = get1bits(/* LEN_DEPEND_ON_CORE,*/ pInputStream); if (dependsOnCoreCoder != FALSE) { /*coreCoderDelay = * getbits( * LEN_CORE_DELAY, * pInputStream); */ status = 1; /* do not support scalable coding in this release */ } /* * extension flag indicates if Amendment 1 objects are used or not * extension flag == 0 objects = 1, 2, 3, 4, 6, 7 * extension flag == 1 objects = 17, 19, 20, 21, 22, 23 */ extFlag = get1bits(pInputStream); /* LEN_EXT_FLAG,*/ /* Force checks for implicit channel configuration */ pVars->mc_info.implicit_channeling = 1; if (status == SUCCESS) { if (channel_config == 0) { status = get_prog_config(pVars, &pVars->scratch.scratch_prog_config); if (status != SUCCESS) { pVars->prog_config.front.ele_is_cpe[0] = 0; /* default to mono */ pVars->mc_info.nch = 1; pVars->prog_config.front.ele_tag[0] = 0; status = SUCCESS; } } else { /* * dummy tag = 0 and * set up decoding configurations */ channel_config--; pVars->prog_config.front.ele_is_cpe[0] = channel_config; pVars->prog_config.front.ele_tag[0] = 0; status = set_mc_info( &(pVars->mc_info), audioObjectType, /* previously profile */ pVars->prog_config.sampling_rate_idx, pVars->prog_config.front.ele_tag[0], pVars->prog_config.front.ele_is_cpe[0], pVars->winmap, /*pVars->pWinSeqInfo,*/ pVars->SFBWidth128); } /* if (channel_config) */ } /* if(status) */ /* * This layer_num is not found in ISO/IEC specs, * but it is defined in San Diego spec for scalable bitstream */ if ((audioObjectType == MP4AUDIO_AAC_SCALABLE) || (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE)) { /*layer_num = * getbits( * LEN_LAYER_NUM, * pInputStream); */ status = 1; /* for this release only */ } if (extFlag) { /* * currently do not implement these functionalities * defined in Amendment 1 * keep it here for future release */ if (audioObjectType == MP4AUDIO_ER_BSAC) { status = 1; /* NOT SUPPORTED */ /* numOfSubFrame = getbits( LEN_SUB_FRAME, pInputStream); layer_len = getbits( LEN_LAYER_LEN, pInputStream); */ } /* * The following code is equivalent to * if ((audioObjectType == 17) || (audioObjectType == 18) || * (audioObjectType == 19) || (audioObjectType == 20) || * (audioObjectType == 21) || (audioObjectType == 23)) */ if (((audioObjectType > 16) && (audioObjectType < 22)) || (audioObjectType == 23)) { status = 1; /* NOT SUPPORTED */ /* aacSectionDataResilienceFlag = getbits( LEN_SECT_RES_FLAG, pInputStream); aacScalefactorDataResilienceFlag = getbits( LEN_SCF_RES_FLAG, pInputStream); aacSpectralDataResilienceFlag = getbits( LEN_SPEC_RES_FLAG, pInputStream); */ } /* * this flag is tbd in version 3 of ISO/IEC spec * if the encoder generates this bit, then it has to be read * current adif2mp4ff does not write this bit. If this bit is to * be read, it can be done by the following code: */ extFlag3 = get1bits(pInputStream); /* LEN_EXT_FLAG3 */ if (extFlag3) { status = 1; /* NOT SUPPORTED */ } } return status; }
Int PVMP4SetAudioConfig( tPVMP4AudioDecoderExternal *pExt, void *pMem, Int upsamplingFactor, Int samp_rate, Int num_ch, tMP4AudioObjectType audioObjectType) { tDec_Int_File *pVars; /* Helper pointer */ Int status = MP4AUDEC_INCOMPLETE_FRAME; /* * Initialize "helper" pointers to existing memory. */ pVars = (tDec_Int_File *)pMem; /* * Translate input buffer variables. */ pVars->inputStream.pBuffer = pExt->pInputBuffer; pVars->inputStream.availableBits = 0; pVars->inputStream.usedBits = 0; /* * get sampling rate index */ switch (samp_rate) { case 96000: pVars->prog_config.sampling_rate_idx = 0; break; case 88200: pVars->prog_config.sampling_rate_idx = 1; break; case 64000: pVars->prog_config.sampling_rate_idx = 2; break; case 48000: pVars->prog_config.sampling_rate_idx = 3; break; case 44100: pVars->prog_config.sampling_rate_idx = 4; break; case 32000: pVars->prog_config.sampling_rate_idx = 5; break; case 24000: pVars->prog_config.sampling_rate_idx = 6; break; case 22050: pVars->prog_config.sampling_rate_idx = 7; break; case 16000: pVars->prog_config.sampling_rate_idx = 8; break; case 12000: pVars->prog_config.sampling_rate_idx = 9; break; case 11025: pVars->prog_config.sampling_rate_idx = 10; break; case 8000: pVars->prog_config.sampling_rate_idx = 11; break; case 7350: pVars->prog_config.sampling_rate_idx = 12; break; default: status = -1; break; } pVars->mc_info.sbrPresentFlag = 0; pVars->mc_info.psPresentFlag = 0; #ifdef AAC_PLUS pVars->mc_info.bDownSampledSbr = 0; #endif pVars->mc_info.implicit_channeling = 0; pVars->mc_info.nch = num_ch; pVars->mc_info.upsamplingFactor = upsamplingFactor; /* * Set number of channels */ if (num_ch == 2) { pVars->prog_config.front.ele_is_cpe[0] = 1; } else if (num_ch == 1) { pVars->prog_config.front.ele_is_cpe[0] = 0; } else { status = -1; /* do not support more than two channels */ pVars->status = status; return (status); } /* * Set AAC bitstream */ if ((audioObjectType == MP4AUDIO_AAC_LC) || (audioObjectType == MP4AUDIO_LTP)) { pVars->aacPlusEnabled = false; status = set_mc_info(&(pVars->mc_info), audioObjectType, /* previously profile */ pVars->prog_config.sampling_rate_idx, pVars->prog_config.front.ele_tag[0], pVars->prog_config.front.ele_is_cpe[0], pVars->winmap, /*pVars->pWinSeqInfo,*/ pVars->SFBWidth128); } else if ((audioObjectType == MP4AUDIO_SBR) || (audioObjectType == MP4AUDIO_PS)) { pVars->aacPlusEnabled = true; status = set_mc_info(&(pVars->mc_info), MP4AUDIO_AAC_LC, pVars->prog_config.sampling_rate_idx, pVars->prog_config.front.ele_tag[0], pVars->prog_config.front.ele_is_cpe[0], pVars->winmap, /*pVars->pWinSeqInfo,*/ pVars->SFBWidth128); pVars->mc_info.sbrPresentFlag = 1; if (audioObjectType == MP4AUDIO_PS) { pVars->mc_info.psPresentFlag = 1; } if (upsamplingFactor == 1) { #ifdef AAC_PLUS pVars->mc_info.bDownSampledSbr = 1; #endif /* * Disable SBR decoding for any sbr-downsampled file whose SF is >= 24 KHz */ if (pVars->prog_config.sampling_rate_idx < 6) { pVars->aacPlusEnabled = false; } } } else { status = -1; } /* * Translate from units of bits back into units of words. */ pExt->inputBufferUsedLength = 0; pExt->remainderBits = 0; pVars->bno++; pExt->samplingRate = samp_rate * upsamplingFactor; pExt->aacPlusEnabled = pVars->aacPlusEnabled; /* * we default to 2 channel, even for mono files, (where channels have same content) * this is done to ensure support for enhanced aac+ with implicit signalling */ pExt->encodedChannels = 2; pExt->frameLength = 1024; #ifdef AAC_PLUS pExt->aacPlusUpsamplingFactor = upsamplingFactor; #endif pVars->status = status; return (status); } /* PVMP4AudioDecoderDecodeFrame */