int CProgramConfig_LookupElement( CProgramConfig *pPce, UINT channelConfig, const UINT tag, const UINT channelIdx, UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], UCHAR chIndex[], UCHAR *elMapping, MP4_ELEMENT_ID elList[], MP4_ELEMENT_ID elType ) { if (channelConfig > 0) { /* Constant channel mapping must have been set during initialization. */ if ( elType == ID_SCE || elType == ID_CPE || elType == ID_LFE ) { *elMapping = pPce->elCounter; if (elList[pPce->elCounter] != elType) { /* Not in the list */ if ( (channelConfig == 2) && (elType == ID_SCE) ) { /* This scenario occurs with HE-AAC v2 streams of buggy encoders. Due to other decoder implementations decoding of these kind of streams is desired. */ channelConfig = 1; } else { return 0; } } /* Assume all front channels */ getImplicitAudioChannelTypeAndIndex(&chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); if (elType == ID_CPE) { chType[channelIdx+1] = chType[channelIdx]; chIndex[channelIdx+1] = chIndex[channelIdx]+1; } pPce->elCounter++; } /* Accept all non-channel elements, too. */ return 1; } else { #ifdef TP_PCE_ENABLE if (!pPce->isValid) #endif /* TP_PCE_ENABLE */ { /* Implicit channel mapping. */ if ( elType == ID_SCE || elType == ID_CPE || elType == ID_LFE ) { /* Store all channel element IDs */ elList[pPce->elCounter] = elType; *elMapping = pPce->elCounter++; } } #ifdef TP_PCE_ENABLE else { /* Accept the additional channel(s), only if the tag is in the lists */ int isCpe = 0, i; /* Element counter */ int ec[PC_NUM_HEIGHT_LAYER] = {0}; /* Channel counters */ int cc[PC_NUM_HEIGHT_LAYER] = {0}; int fc[PC_NUM_HEIGHT_LAYER] = {0}; int sc[PC_NUM_HEIGHT_LAYER] = {0}; int bc[PC_NUM_HEIGHT_LAYER] = {0}; int lc = 0;; /* General MPEG (PCE) composition rules: - Over all: <normal height channels><top height channels><bottom height channels> - Within each height layer: <front channels><side channels><back channels> - Exception: The LFE channels have no height info and thus they are arranged at the very end of the normal height layer channels. */ switch (elType) { case ID_CPE: isCpe = 1; case ID_SCE: /* search in front channels */ for (i = 0; i < pPce->NumFrontChannelElements; i++) { int heightLayer = pPce->FrontElementHeightInfo[i]; if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) { int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_FRONT); for (h = heightLayer-1; h >= 0; h-=1) { int el; /* Count front channels/elements */ for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { if (pPce->FrontElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; } } /* Count side channels/elements */ for (el = 0; el < pPce->NumSideChannelElements; el+=1) { if (pPce->SideElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; } } /* Count back channels/elements */ for (el = 0; el < pPce->NumBackChannelElements; el+=1) { if (pPce->BackElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; } } if (h == 0) { /* normal height */ elIdx += pPce->NumLfeChannelElements; chIdx += pPce->NumLfeChannelElements; } } chMapping[chIdx] = channelIdx; chType[chIdx] = aChType; chIndex[chIdx] = fc[heightLayer]; if (isCpe) { chMapping[chIdx+1] = channelIdx+1; chType[chIdx+1] = aChType; chIndex[chIdx+1] = fc[heightLayer]+1; } *elMapping = elIdx; return 1; } ec[heightLayer] += 1; if (pPce->FrontElementIsCpe[i]) { cc[heightLayer] += 2; fc[heightLayer] += 2; } else { cc[heightLayer] += 1; fc[heightLayer] += 1; } } /* search in side channels */ for (i = 0; i < pPce->NumSideChannelElements; i++) { int heightLayer = pPce->SideElementHeightInfo[i]; if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) { int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_SIDE); for (h = heightLayer-1; h >= 0; h-=1) { int el; /* Count front channels/elements */ for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { if (pPce->FrontElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; } } /* Count side channels/elements */ for (el = 0; el < pPce->NumSideChannelElements; el+=1) { if (pPce->SideElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; } } /* Count back channels/elements */ for (el = 0; el < pPce->NumBackChannelElements; el+=1) { if (pPce->BackElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; } } if (h == 0) { /* LFE channels belong to the normal height layer */ elIdx += pPce->NumLfeChannelElements; chIdx += pPce->NumLfeChannelElements; } } chMapping[chIdx] = channelIdx; chType[chIdx] = aChType; chIndex[chIdx] = sc[heightLayer]; if (isCpe) { chMapping[chIdx+1] = channelIdx+1; chType[chIdx+1] = aChType; chIndex[chIdx+1] = sc[heightLayer]+1; } *elMapping = elIdx; return 1; } ec[heightLayer] += 1; if (pPce->SideElementIsCpe[i]) { cc[heightLayer] += 2; sc[heightLayer] += 2; } else { cc[heightLayer] += 1; sc[heightLayer] += 1; } } /* search in back channels */ for (i = 0; i < pPce->NumBackChannelElements; i++) { int heightLayer = pPce->BackElementHeightInfo[i]; if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) { int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_BACK); for (h = heightLayer-1; h >= 0; h-=1) { int el; /* Count front channels/elements */ for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { if (pPce->FrontElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; } } /* Count side channels/elements */ for (el = 0; el < pPce->NumSideChannelElements; el+=1) { if (pPce->SideElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; } } /* Count back channels/elements */ for (el = 0; el < pPce->NumBackChannelElements; el+=1) { if (pPce->BackElementHeightInfo[el] == h) { elIdx += 1; chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; } } if (h == 0) { /* normal height */ elIdx += pPce->NumLfeChannelElements; chIdx += pPce->NumLfeChannelElements; } } chMapping[chIdx] = channelIdx; chType[chIdx] = aChType; chIndex[chIdx] = bc[heightLayer]; if (isCpe) { chMapping[chIdx+1] = channelIdx+1; chType[chIdx+1] = aChType; chIndex[chIdx+1] = bc[heightLayer]+1; } *elMapping = elIdx; return 1; } ec[heightLayer] += 1; if (pPce->BackElementIsCpe[i]) { cc[heightLayer] += 2; bc[heightLayer] += 2; } else { cc[heightLayer] += 1; bc[heightLayer] += 1; } } break; case ID_LFE: { /* Unfortunately we have to go through all normal height layer elements to get the position of the LFE channels. Start with counting the front channels/elements at normal height */ for (i = 0; i < pPce->NumFrontChannelElements; i+=1) { int heightLayer = pPce->FrontElementHeightInfo[i]; ec[heightLayer] += 1; cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1; } /* Count side channels/elements at normal height */ for (i = 0; i < pPce->NumSideChannelElements; i+=1) { int heightLayer = pPce->SideElementHeightInfo[i]; ec[heightLayer] += 1; cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1; } /* Count back channels/elements at normal height */ for (i = 0; i < pPce->NumBackChannelElements; i+=1) { int heightLayer = pPce->BackElementHeightInfo[i]; ec[heightLayer] += 1; cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1; } /* search in lfe channels */ for (i = 0; i < pPce->NumLfeChannelElements; i++) { int elIdx = ec[0]; /* LFE channels belong to the normal height layer */ int chIdx = cc[0]; if ( pPce->LfeElementTagSelect[i] == tag ) { chMapping[chIdx] = channelIdx; *elMapping = elIdx; chType[chIdx] = ACT_LFE; chIndex[chIdx] = lc; return 1; } ec[0] += 1; cc[0] += 1; lc += 1; } } break; /* Non audio elements */ case ID_CCE: /* search in cce channels */ for (i = 0; i < pPce->NumValidCcElements; i++) { if (pPce->ValidCcElementTagSelect[i] == tag) { return 1; } } break; case ID_DSE: /* search associated data elements */ for (i = 0; i < pPce->NumAssocDataElements; i++) { if (pPce->AssocDataElementTagSelect[i] == tag) { return 1; } } break; default: return 0; } return 0; /* not found in any list */ } #endif /* TP_PCE_ENABLE */ } return 1; }
int CProgramConfig_LookupElement( CProgramConfig *pPce, const UINT channelConfig, const UINT tag, const UINT channelIdx, UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], UCHAR chIndex[], UCHAR *elMapping, MP4_ELEMENT_ID elList[], MP4_ELEMENT_ID elType ) { if (channelConfig > 0) { /* Constant channel mapping must have been set during initialization. */ if ( elType == ID_SCE || elType == ID_CPE || elType == ID_LFE ) { *elMapping = pPce->elCounter; if (elList[pPce->elCounter] != elType) { /* Not in the list */ return 0; } /* Assume all front channels */ getImplicitAudioChannelTypeAndIndex(&chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); if (elType == ID_CPE) { chType[channelIdx+1] = chType[channelIdx]; chIndex[channelIdx+1] = chIndex[channelIdx]+1; } pPce->elCounter++; } /* Accept all non-channel elements, too. */ return 1; } else { #ifdef TP_PCE_ENABLE if (!pPce->isValid) #endif /* TP_PCE_ENABLE */ { /* Implicit channel mapping. */ if ( elType == ID_SCE || elType == ID_CPE || elType == ID_LFE ) { /* Store all channel element IDs */ elList[pPce->elCounter] = elType; *elMapping = pPce->elCounter++; } } #ifdef TP_PCE_ENABLE else { /* Accept the additional channel(s), only if the tag is in the lists */ int isCpe = 0, i; int cc = 0, fc = 0, sc = 0, bc = 0, lc = 0, ec = 0; /* Channel and element counters */ switch (elType) { case ID_CPE: isCpe = 1; case ID_SCE: /* search in front channels */ for (i = 0; i < pPce->NumFrontChannelElements; i++) { if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) { chMapping[cc] = channelIdx; chType[cc] = ACT_FRONT; chIndex[cc] = fc; if (isCpe) { chMapping[cc+1] = channelIdx+1; chType[cc+1] = ACT_FRONT; chIndex[cc+1] = fc+1; } *elMapping = ec; return 1; } ec++; if (pPce->FrontElementIsCpe[i]) { cc+=2; fc+=2; } else { cc++; fc++; } } /* search in side channels */ for (i = 0; i < pPce->NumSideChannelElements; i++) { if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) { chMapping[cc] = channelIdx; chType[cc] = ACT_SIDE; chIndex[cc] = sc; if (isCpe) { chMapping[cc+1] = channelIdx+1; chType[cc+1] = ACT_SIDE; chIndex[cc+1] = sc+1; } *elMapping = ec; return 1; } ec++; if (pPce->SideElementIsCpe[i]) { cc+=2; sc+=2; } else { cc++; sc++; } } /* search in back channels */ for (i = 0; i < pPce->NumBackChannelElements; i++) { if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) { chMapping[cc] = channelIdx; chType[cc] = ACT_BACK; chIndex[cc] = bc; if (isCpe) { chMapping[cc+1] = channelIdx+1; chType[cc+1] = ACT_BACK; chIndex[cc+1] = bc+1; } *elMapping = ec; return 1; } ec++; if (pPce->BackElementIsCpe[i]) { cc+=2; bc+=2; } else { cc++; bc++; } } break; case ID_LFE: /* Initialize channel counter and element counter */ cc = pPce->NumEffectiveChannels; ec = pPce->NumFrontChannelElements+ pPce->NumSideChannelElements + pPce->NumBackChannelElements; /* search in lfe channels */ for (i = 0; i < pPce->NumLfeChannelElements; i++) { if ( pPce->LfeElementTagSelect[i] == tag ) { chMapping[cc] = channelIdx; *elMapping = ec; chType[cc] = ACT_LFE; chIndex[cc] = lc; return 1; } ec++; cc++; lc++; } break; /* Non audio elements */ case ID_CCE: /* search in cce channels */ for (i = 0; i < pPce->NumValidCcElements; i++) { if (pPce->ValidCcElementTagSelect[i] == tag) { return 1; } } break; case ID_DSE: /* search associated data elements */ for (i = 0; i < pPce->NumAssocDataElements; i++) { if (pPce->AssocDataElementTagSelect[i] == tag) { return 1; } } break; default: return 0; } return 0; /* not found in any list */ } #endif /* TP_PCE_ENABLE */ } return 1; }