blob: 6bddd573694736c13db7ba2611d9c162111f565e [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*
Pathname: get_prog_config.c
------------------------------------------------------------------------------
REVISION HISTORY
Description: Modified from original shareware code
Description: Modified to pass variables by reference to eliminate use
of global variables.
Description: Move functionality from get_adif_header for when to change
the current program configuration, add a temporary config
to read into, clean up code, change function prototype.
Description: Clean up
Description: Update per review comments
Description: Fix double 'could'
Description: change enter_mc_info to set_mc_info
Description: update comments
Description: Replace some instances of getbits to get9_n_lessbits
when the number of bits read is 9 or less and get1bits
when only 1 bit is read.
Who: Date:
Description:
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
pVars = pointer to the structure that holds all information for
this instance of the library. pVars->prog_config is directly
used, and pVars->mc_info, pVars->prog_config, pVars->winmap,
pVars->SFBWidth128 are needed indirectly for calling
set_mc_info. Data type pointer to tDec_Int_File structure.
pScratchPCE = pointer to a temporary ProgConfig structure to be used
to read in the program configuration element.
Local Stores/Buffers/Pointers Needed: None
Global Stores/Buffers/Pointers Needed: None
Outputs:
status = zero if no error was found, non-zero otherwise.
Pointers and Buffers Modified:
pVars->prog_config contents are updated with the PCE read in.
pVars->mc_info contents are updated with channel information.
pVars->winmap contents are updated with window information.
pVars->SFBWidth128 contents are updated with scale factor band width data.
Local Stores Modified: None
Global Stores Modified: None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function reads from the input stream to memory for a temporary
program configuration element (PCE). If the PCE read is the first
encountered it is saved. Or, if the tag of the PCE read matches the tag of
the first PCE encounted, it is saved as well. This is a mechanism for
changing the sampling rate.
------------------------------------------------------------------------------
REQUIREMENTS
This function shall not use static or global variables.
------------------------------------------------------------------------------
REFERENCES
(1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
of moving pictures and associated audio information - Part 7: Advanced
Audio Coding (AAC)", Table 6.21 - Syntax of program_config_element(),
page 16, and section 8.5 "Program Config Element (PCE)", page 30.
(2) MPEG-2 NBC Audio Decoder
"This software module was originally developed by AT&T, Dolby
Laboratories, Fraunhofer Gesellschaft IIS in the course of development
of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
3. This software module is an implementation of a part of one or more
MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
standards free license to this software module or modifications thereof
for use in hardware or software products claiming conformance to the
MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
module in hardware or software products are advised that this use may
infringe existing patents. The original developer of this software
module and his/her company, the subsequent editors and their companies,
and ISO/IEC have no liability for use of this software module or
modifications thereof in an implementation. Copyright is not released
for non MPEG-2 NBC/MPEG-4 Audio conforming products.The original
developer retains full right to use the code for his/her own purpose,
assign or donate the code to a third party and to inhibit third party
from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
This copyright notice must be included in all copies or derivative
works."
Copyright(c)1996.
------------------------------------------------------------------------------
PSEUDO-CODE
status = SUCCESS;
pInputStream = &(pVars->inputStream);
CALL getbits(
neededBits = LEN_TAG,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( tag = returnValue )
CALL getbits(
neededBits = LEN_PROFILE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( pScratchPCE->profile = returnValue )
CALL getbits(
neededBits = LEN_PROFILE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( pScratchPCE->sampling_rate_idx = returnValue )
CALL getbits(
neededBits = LEN_NUM_ELE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->front.num_ele = temp;
CALL getbits(
neededBits = LEN_NUM_ELE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->side.num_ele = temp;
CALL getbits(
neededBits = LEN_NUM_ELE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->back.num_ele = temp;
CALL getbits(
neededBits = LEN_NUM_LFE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->lfe.num_ele = temp;
CALL getbits(
neededBits = LEN_NUM_DAT,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->data.num_ele = temp;
CALL getbits(
neededBits = LEN_NUM_CCE,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->coupling.num_ele = temp;
CALL getbits(
neededBits = LEN_MIX_PRES,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( flag = returnValue )
pScratchPCE->mono_mix.present = flag;
IF (flag != FALSE)
THEN
CALL getbits(
neededBits = LEN_TAG,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->mono_mix.ele_tag = temp;
ENDIF
CALL getbits(
neededBits = LEN_MIX_PRES,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( flag = returnValue )
pScratchPCE->stereo_mix.present = flag;
IF (flag != FALSE)
THEN
CALL getbits(
neededBits = LEN_TAG,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->stereo_mix.ele_tag = temp;
ENDIF
CALL getbits(
neededBits = LEN_MIX_PRES,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( flag = returnValue )
flag =
getbits(
LEN_MIX_PRES,
pInputStream);
pScratchPCE->matrix_mix.present = flag;
IF (flag != FALSE)
THEN
CALL getbits(
neededBits = LEN_MMIX_IDX,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->matrix_mix.ele_tag = temp;
CALL getbits(
neededBits = LEN_PSUR_ENAB,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( temp = returnValue )
pScratchPCE->matrix_mix.pseudo_enab = temp;
ENDIF
CALL get_ele_list(
pElementList = &pScratchPCE->front,
pInputStream = pInputStream,
enableCPE = TRUE )
MODIFYING( pInputStream )
MODIFYING( pScratchPCE->front )
RETURNING( nothing )
CALL get_ele_list(
pElementList = &pScratchPCE->side,
pInputStream = pInputStream,
enableCPE = TRUE )
MODIFYING( pInputStream )
MODIFYING( pScratchPCE->side )
RETURNING( nothing )
CALL get_ele_list(
pElementList = &pScratchPCE->back,
pInputStream = pInputStream,
enableCPE = TRUE )
MODIFYING( pInputStream )
MODIFYING( pScratchPCE->back )
RETURNING( nothing )
CALL get_ele_list(
pElementList = &pScratchPCE->lfe,
pInputStream = pInputStream,
enableCPE = FALSE )
MODIFYING( pInputStream )
MODIFYING( pScratchPCE->lfe )
RETURNING( nothing )
CALL get_ele_list(
pElementList = &pScratchPCE->data,
pInputStream = pInputStream,
enableCPE = FALSE )
MODIFYING( pInputStream )
MODIFYING( pScratchPCE->data )
RETURNING( nothing )
CALL get_ele_list(
pElementList = &pScratchPCE->coupling,
pInputStream = pInputStream,
enableCPE = TRUE )
MODIFYING( pInputStream )
MODIFYING( pScratchPCE->coupling )
RETURNING( nothing )
CALL byte_align(
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( nothing )
CALL getbits(
neededBits = LEN_COMMENT_BYTES,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( numChars = returnValue )
FOR (i = numChars; i > 0; i--)
CALL getbits(
neededBits = LEN_COMMENT_BYTES,
pInputStream = pInputStream )
MODIFYING( pInputStream )
RETURNING( nothing )
ENDFOR
IF (pVars->current_program < 0)
THEN
pVars->current_program = tag;
ENDIF
IF (tag == pVars->current_program)
THEN
CALL pv_memcpy(
to = &pVars->prog_config,
from = pScratchPCE,
n = sizeof(ProgConfig))
MODIFYING( pVars->prog_config )
RETURNING( nothing )
CALL set_mc_info(
pMC_Info = &pVars->mc_info,
objectType = pVars->prog_config.profile + 1,
samplin_rate_idx = pVars->prog_config.sampling_rate_idx,
tag = pVars->prog_config.front.ele_tag[0],
is_cpe = pVars->prog_config.front.ele_is_cpe[0],
pWinSeqInfo = pVars->winmap,
pSfbwidth128 = pVars->SFBWidth128)
MODIFYING( pVars->mc_info )
MODIFYING( pVars->winmap )
MODIFYING( pVars->SFBWidth128 )
RETURN( status = return_value )
ENDIF
MODIFY( pVars->mc_info )
MODIFY( pVars->winmap )
MODIFY( pVars->SFBWidth128 )
RETURN (status)
------------------------------------------------------------------------------
RESOURCES USED
When the code is written for a specific target processor the
the resources used should be documented below.
STACK USAGE: [stack count for this module] + [variable to represent
stack usage for each subroutine called]
where: [stack usage variable] = stack usage for [subroutine
name] (see [filename].ext)
DATA MEMORY USED: x words
PROGRAM MEMORY USED: x words
CLOCK CYCLES: [cycle count equation for this module] + [variable
used to represent cycle count for each subroutine
called]
where: [cycle count variable] = cycle count for [subroutine
name] (see [filename].ext)
------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "pv_audio_type_defs.h"
#include "s_bits.h"
#include "s_elelist.h"
#include "s_tdec_int_file.h"
#include "s_tdec_int_chan.h"
#include "e_progconfigconst.h"
#include "ibstream.h"
#include "get_ele_list.h"
#include "aac_mem_funcs.h"
#include "set_mc_info.h"
#include "get_prog_config.h"
/*----------------------------------------------------------------------------
; MACROS
; Define module specific macros here
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; DEFINES
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL VARIABLE DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; EXTERNAL FUNCTION REFERENCES
; Declare functions defined elsewhere and referenced in this module
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; EXTERNAL VARIABLES REFERENCES
; Declare variables used in this module but defined elsewhere
----------------------------------------------------------------------------*/
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)
{
/* 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(/* LEN_MIX_PRES,*/
pInputStream);
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(/* LEN_MIX_PRES,*/
pInputStream);
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(/* LEN_MIX_PRES,*/
pInputStream);
pScratchPCE->matrix_mix.present = flag;
if (flag != FALSE)
{
temp =
get9_n_lessbits(
LEN_MMIX_IDX,
pInputStream);
pScratchPCE->matrix_mix.ele_tag = temp;
temp =
get1bits(/* LEN_PSUR_ENAB,*/
pInputStream);
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;
} /* 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
* thus far re-sends a PCE, when looking at ADIF files.
*
* Regardless, the temporary PCE will now be copied into the
* the one official program configuration.
*/
pv_memcpy(
&pVars->prog_config,
pScratchPCE,
sizeof(ProgConfig));
/* 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[0],
pVars->prog_config.front.ele_is_cpe[0],
pVars->winmap,
pVars->SFBWidth128);
} /* end if (tag == pVars->current_program) */
return (status);
}