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;
}
Example #3
0
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 */