1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 19 #include "aac_dec.h" 20 21 OmxAacDecoder::OmxAacDecoder() 22 { 23 iAacInitFlag = 0; 24 iInputUsedLength = 0; 25 } 26 27 28 OMX_BOOL OmxAacDecoder::AacDecInit(OMX_U32 aDesiredChannels) 29 { 30 Int Status; 31 32 iMemReq = PVMP4AudioDecoderGetMemRequirements(); 33 ipMem = oscl_malloc(iMemReq); 34 35 if (0 == ipMem) 36 { 37 return OMX_FALSE; 38 } 39 40 oscl_memset(&iExt, 0, sizeof(tPVMP4AudioDecoderExternal)); 41 42 iExt.inputBufferCurrentLength = 0; 43 iExt.remainderBits = 0; // Not needed anymore. 44 iExt.inputBufferMaxLength = PVMP4AUDIODECODER_INBUFSIZE; 45 iExt.outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED; 46 iExt.desiredChannels = aDesiredChannels; 47 iExt.aacPlusEnabled = TRUE; 48 iAacInitFlag = 0; 49 iInputUsedLength = 0; 50 //This var is required to do init again inbetween 51 iNumOfChannels = aDesiredChannels; 52 53 54 Status = PVMP4AudioDecoderInitLibrary(&iExt, ipMem); 55 return OMX_TRUE; 56 } 57 58 void OmxAacDecoder::AacDecDeinit() 59 { 60 oscl_free(ipMem); 61 ipMem = NULL; 62 } 63 64 void OmxAacDecoder::ResetDecoder() 65 { 66 67 if (ipMem && (iAacInitFlag != 0)) 68 { 69 PVMP4AudioDecoderResetBuffer(ipMem); 70 } 71 72 } 73 74 Int OmxAacDecoder::AacDecodeFrames(OMX_S16* aOutputBuffer, 75 OMX_U32* aOutputLength, OMX_U8** aInBuffer, 76 OMX_U32* aInBufSize, OMX_S32* aIsFirstBuffer, 77 OMX_AUDIO_PARAM_PCMMODETYPE* aAudioPcmParam, 78 OMX_AUDIO_PARAM_AACPROFILETYPE* aAudioAacParam, 79 OMX_U32* aSamplesPerFrame, 80 OMX_BOOL* aResizeFlag) 81 { 82 Int Status; 83 Int32 StreamType; 84 85 86 *aResizeFlag = OMX_FALSE; 87 88 if (0 == iAacInitFlag) 89 { 90 //Initialization is required again when the client inbetween rewinds the input bitstream 91 //Added to pass khronous conformance tests 92 if (*aIsFirstBuffer != 0) 93 { 94 /* When the input file is reset to the begining by the client, 95 * this module should again be called. 96 */ 97 oscl_memset(ipMem, 0, iMemReq); 98 oscl_memset(&iExt, 0, sizeof(tPVMP4AudioDecoderExternal)); 99 100 iExt.inputBufferCurrentLength = 0; 101 iExt.remainderBits = 0; 102 iExt.inputBufferMaxLength = PVMP4AUDIODECODER_INBUFSIZE; 103 iExt.outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED; 104 iExt.desiredChannels = iNumOfChannels; 105 iExt.aacPlusEnabled = TRUE; 106 iInputUsedLength = 0; 107 108 PVMP4AudioDecoderInitLibrary(&iExt, ipMem); 109 } 110 } 111 112 iExt.pInputBuffer = *aInBuffer + iInputUsedLength; 113 iExt.pOutputBuffer = &aOutputBuffer[0]; 114 115 #ifdef AAC_PLUS 116 iExt.pOutputBuffer_plus = &aOutputBuffer[2048]; 117 #endif 118 119 iExt.inputBufferCurrentLength = *aInBufSize; 120 121 //Decode the config buffer 122 if (0 == iAacInitFlag) 123 { 124 Status = PVMP4AudioDecoderConfig(&iExt, ipMem); 125 if (MP4AUDEC_SUCCESS == Status) 126 { 127 iAacInitFlag = 1; 128 } 129 130 iConfigUpSamplingFactor = iExt.aacPlusUpsamplingFactor; 131 132 if (2 == iExt.aacPlusUpsamplingFactor) 133 { 134 *aSamplesPerFrame = 2 * AACDEC_PCM_FRAME_SAMPLE_SIZE; 135 } 136 else 137 { 138 *aSamplesPerFrame = AACDEC_PCM_FRAME_SAMPLE_SIZE; 139 } 140 141 142 /* 143 * *aInBufSize -= iExt.inputBufferUsedLength; should render *aInBufSize == 0, 144 * If the size of the audio config buffer exceeds the size of the audio config data 145 * the excess bits could be taken as part of next raw aac stream. To avoid that 146 * we force to consume all bits of the audio config buffer, by making *aInBufSize == 0 147 */ 148 *aInBufSize = 0; 149 iInputUsedLength = 0; 150 151 return Status; 152 } 153 154 iExt.inputBufferUsedLength = 0; 155 Status = PVMP4AudioDecodeFrame(&iExt, ipMem); 156 157 if (MP4AUDEC_SUCCESS == Status || SUCCESS == Status) 158 { 159 160 *aInBufSize -= iExt.inputBufferUsedLength; 161 if (0 == *aInBufSize) 162 { 163 iInputUsedLength = 0; 164 } 165 else 166 { 167 iInputUsedLength += iExt.inputBufferUsedLength; 168 } 169 170 *aOutputLength = iExt.frameLength * iExt.desiredChannels; 171 172 #ifdef AAC_PLUS 173 if (2 == iExt.aacPlusUpsamplingFactor) 174 { 175 if (1 == iExt.desiredChannels) 176 { 177 oscl_memcpy(&aOutputBuffer[1024], &aOutputBuffer[2048], (*aOutputLength * 2)); 178 } 179 *aOutputLength *= 2; 180 181 } 182 #endif 183 (*aIsFirstBuffer)++; 184 185 //After decoding the first frame, modify all the input & output port settings 186 if (1 == *aIsFirstBuffer) 187 { 188 StreamType = (Int32) RetrieveDecodedStreamType(); 189 190 if ((0 == StreamType) && (2 == iConfigUpSamplingFactor)) 191 { 192 PVMP4AudioDecoderDisableAacPlus(&iExt, &ipMem); 193 *aSamplesPerFrame = AACDEC_PCM_FRAME_SAMPLE_SIZE; 194 aAudioAacParam->eAACProfile = OMX_AUDIO_AACObjectMain; 195 aAudioAacParam->nFrameLength = AACDEC_PCM_FRAME_SAMPLE_SIZE; 196 } 197 198 //Output Port Parameters 199 aAudioPcmParam->nSamplingRate = iExt.samplingRate; 200 aAudioPcmParam->nChannels = iExt.desiredChannels; 201 202 //Input Port Parameters 203 aAudioAacParam->nSampleRate = iExt.samplingRate; 204 205 //Set the Resize flag to send the port settings changed callback 206 *aResizeFlag = OMX_TRUE; 207 } 208 209 return Status; 210 211 } 212 else if (MP4AUDEC_INCOMPLETE_FRAME == Status) 213 { 214 *aInBuffer += iInputUsedLength; 215 iInputUsedLength = 0; 216 } 217 else 218 { 219 *aInBufSize = 0; 220 iInputUsedLength = 0; 221 } 222 223 return Status; 224 } 225 226 227 //Retrieve the Stream Type of AAC input-bitstream 228 Int OmxAacDecoder::RetrieveDecodedStreamType() 229 { 230 231 if ((iExt.extendedAudioObjectType == MP4AUDIO_AAC_LC) || 232 (iExt.extendedAudioObjectType == MP4AUDIO_LTP)) 233 { 234 return AAC; /* AAC */ 235 } 236 else if (iExt.extendedAudioObjectType == MP4AUDIO_SBR) 237 { 238 return AACPLUS; /* AAC+ */ 239 } 240 else if (iExt.extendedAudioObjectType == MP4AUDIO_PS) 241 { 242 return ENH_AACPLUS; /* AAC++ */ 243 } 244 245 return -1; /* Error evaluating the stream type */ 246 } 247 248 249 //Change the AACEnable flag, according to the AAC profile set by the client in SetParameter API 250 void OmxAacDecoder::UpdateAACPlusEnabled(OMX_BOOL flag) 251 { 252 //Mark this flag as false if client sets any non HE AAC profile in SetParameter call 253 iExt.aacPlusEnabled = (OMX_TRUE == flag) ? true : false; 254 } 255