status_t AACDecoder::initCheck() { memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal)); mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED; mConfig->aacPlusEnabled = 1; // The software decoder doesn't properly support mono output on // AACplus files. Always output stereo. mConfig->desiredChannels = 2; UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements(); mDecoderBuf = malloc(memRequirements); status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf); if (err != MP4AUDEC_SUCCESS) { ALOGE("Failed to initialize MP4 audio decoder"); return UNKNOWN_ERROR; } uint32_t type; const void *data; size_t size; sp<MetaData> meta = mSource->getFormat(); if (meta->findData(kKeyESDS, &type, &data, &size)) { ESDS esds((const char *)data, size); CHECK_EQ(esds.InitCheck(), (status_t)OK); const void *codec_specific_data; size_t codec_specific_data_size; esds.getCodecSpecificInfo( &codec_specific_data, &codec_specific_data_size); mConfig->pInputBuffer = (UChar *)codec_specific_data; mConfig->inputBufferCurrentLength = codec_specific_data_size; mConfig->inputBufferMaxLength = 0; UChar * spec = (UChar *)codec_specific_data; for(int i = 0; i < codec_specific_data_size; i++) { ALOGE("spec[%d] = 0x%x",i+1,spec[i]); } if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf) != MP4AUDEC_SUCCESS) { return ERROR_UNSUPPORTED; } }else if(meta->findData(kKeyAacInfo,&type,&data,&size)){ mConfig->pInputBuffer = (UChar *)data; mConfig->inputBufferCurrentLength = size; mConfig->inputBufferMaxLength = 0; if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf) != MP4AUDEC_SUCCESS) { return ERROR_UNSUPPORTED; } } return OK; }
OSCL_EXPORT_REF int32 CDecoder_AAC::ExecuteL(tPVMP4AudioDecoderExternal * pExt) { int32 nResult = FALSE; if (iFirstFrame == false) { nResult = PVMP4AudioDecodeFrame(pExt, pMem); } else { if (PVMP4AudioDecoderInitLibrary(pExt, pMem) != 0) { return(KCAI_CODEC_INIT_FAILURE); } // set samples/frame to default value (right now this is the only one supported) if (PVMP4AudioDecoderConfig(pExt, pMem) != SUCCESS) { nResult = PVMP4AudioDecodeFrame(pExt, pMem); /* could be ADIF type */ } iNumSamplesPerFrame = KAAC_NUM_SAMPLES_PER_FRAME; pExt->desiredChannels = pExt->encodedChannels; iFirstFrame = false; } return nResult; }
static long aacd_opencore_start( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size) { AACD_TRACE( "start() buffer=%x size=%d", (*(unsigned long*)buffer), buffer_size ); AACDOpenCore *oc = (AACDOpenCore*) info->ext; tPVMP4AudioDecoderExternal *pExt = oc->pExt; pExt->remainderBits = 0; pExt->frameLength = 0; // prepare the first samples buffer: //pExt->pOutputBuffer = malloc(4096 * sizeof(int16_t)); //pExt->pOutputBuffer_plus = pExt->pOutputBuffer + 2048; pExt->pOutputBuffer = aacd_prepare_samples( info, 4096 ); pExt->pOutputBuffer_plus = pExt->pOutputBuffer + 2048; int32_t status; int frameDecoded = 0; int attempts = 16; /* pre-init search adts sync */ while (pExt->frameLength == 0 && attempts--) { pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; status = PVMP4AudioDecoderConfig(pExt, oc->pMem); AACD_DEBUG( "start() Status[0]: %d", status ); if (status != MP4AUDEC_SUCCESS) { status = PVMP4AudioDecodeFrame(pExt, oc->pMem); AACD_DEBUG( "start() Status[1]: %d", status ); buffer -= pExt->inputBufferUsedLength; buffer_size -= pExt->inputBufferUsedLength; if (MP4AUDEC_SUCCESS == status) { AACD_DEBUG( "start() frameLength: %d\n", pExt->frameLength); frameDecoded = 1; continue; } } if (buffer_size <= PVMP4AUDIODECODER_INBUFSIZE) break; } if (!frameDecoded) { AACD_INFO( "start() No stream info available - trying to decode a frame" ); if (buffer_size >= PVMP4AUDIODECODER_INBUFSIZE) status = PVMP4AudioDecodeFrame(pExt, oc->pMem); else AACD_WARN( "start() Input buffer too small" ); } //free( pExt->pOutputBuffer ); if (status != MP4AUDEC_SUCCESS) { AACD_ERROR( "start() init failed status=%d", status ); return -1; } AACD_DEBUG( "start() bytesconsumed=%d", pExt->inputBufferUsedLength ); int streamType = -1; if ((pExt->extendedAudioObjectType == MP4AUDIO_AAC_LC) || (pExt->extendedAudioObjectType == MP4AUDIO_LTP)) { streamType = AAC; } else if (pExt->extendedAudioObjectType == MP4AUDIO_SBR) { streamType = AACPLUS; } else if (pExt->extendedAudioObjectType == MP4AUDIO_PS) { streamType = ENH_AACPLUS; } AACD_DEBUG( "start() streamType=%d", streamType ); if ((AAC == streamType) && (2 == pExt->aacPlusUpsamplingFactor)) { AACD_INFO( "start() DisableAacPlus" ); PVMP4AudioDecoderDisableAacPlus(pExt, oc->pMem); } info->samplerate = pExt->samplingRate; info->channels = pExt->desiredChannels; oc->frameSamplesFactor = pExt->desiredChannels; if (2 == pExt->aacPlusUpsamplingFactor) oc->frameSamplesFactor *= 2; info->frame_bytesconsumed = pExt->inputBufferUsedLength; info->frame_samples = pExt->frameLength * oc->frameSamplesFactor; return pExt->inputBufferUsedLength; }
Int OmxAacDecoder::AacDecodeFrames(OMX_S16* aOutputBuffer, OMX_U32* aOutputLength, OMX_U8** aInBuffer, OMX_U32* aInBufSize, OMX_S32* aIsFirstBuffer, OMX_AUDIO_PARAM_PCMMODETYPE* aAudioPcmParam, OMX_AUDIO_PARAM_AACPROFILETYPE* aAudioAacParam, OMX_U32* aSamplesPerFrame, OMX_BOOL* aResizeFlag) { Int Status; Int32 StreamType; *aResizeFlag = OMX_FALSE; if (0 == iAacInitFlag) { //Initialization is required again when the client inbetween rewinds the input bitstream //Added to pass khronous conformance tests if (*aIsFirstBuffer != 0) { /* When the input file is reset to the begining by the client, * this module should again be called. */ oscl_memset(ipMem, 0, iMemReq); oscl_memset(&iExt, 0, sizeof(tPVMP4AudioDecoderExternal)); iExt.inputBufferCurrentLength = 0; iExt.remainderBits = 0; iExt.inputBufferMaxLength = PVMP4AUDIODECODER_INBUFSIZE; iExt.outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED; iExt.desiredChannels = iNumOfChannels; iExt.aacPlusEnabled = TRUE; iInputUsedLength = 0; PVMP4AudioDecoderInitLibrary(&iExt, ipMem); } } iExt.pInputBuffer = *aInBuffer + iInputUsedLength; iExt.pOutputBuffer = &aOutputBuffer[0]; #ifdef AAC_PLUS iExt.pOutputBuffer_plus = &aOutputBuffer[2048]; #endif iExt.inputBufferCurrentLength = *aInBufSize; //Decode the config buffer if (0 == iAacInitFlag) { #if PROFILING_ON OMX_U32 StartTime = OsclTickCount::TickCount(); #endif Status = PVMP4AudioDecoderConfig(&iExt, ipMem); #if PROFILING_ON OMX_U32 EndTime = OsclTickCount::TickCount(); iTotalTicks += (EndTime - StartTime); #endif if (MP4AUDEC_SUCCESS == Status) { iAacInitFlag = 1; } iConfigUpSamplingFactor = iExt.aacPlusUpsamplingFactor; if (2 == iExt.aacPlusUpsamplingFactor) { *aSamplesPerFrame = 2 * AACDEC_PCM_FRAME_SAMPLE_SIZE; } else { *aSamplesPerFrame = AACDEC_PCM_FRAME_SAMPLE_SIZE; } /* * *aInBufSize -= iExt.inputBufferUsedLength; should render *aInBufSize == 0, * If the size of the audio config buffer exceeds the size of the audio config data * the excess bits could be taken as part of next raw aac stream. To avoid that * we force to consume all bits of the audio config buffer, by making *aInBufSize == 0 */ *aInBufSize = 0; iInputUsedLength = 0; return Status; } iExt.inputBufferUsedLength = 0; #if PROFILING_ON OMX_U32 StartTime = OsclTickCount::TickCount(); #endif Status = PVMP4AudioDecodeFrame(&iExt, ipMem); #if PROFILING_ON OMX_U32 EndTime = OsclTickCount::TickCount(); iTotalTicks += (EndTime - StartTime); #endif if (MP4AUDEC_SUCCESS == Status || SUCCESS == Status) { *aInBufSize -= iExt.inputBufferUsedLength; if (0 == *aInBufSize) { iInputUsedLength = 0; } else { iInputUsedLength += iExt.inputBufferUsedLength; } *aOutputLength = iExt.frameLength * iExt.desiredChannels; #ifdef AAC_PLUS if (2 == iExt.aacPlusUpsamplingFactor) { if (1 == iExt.desiredChannels) { oscl_memcpy(&aOutputBuffer[1024], &aOutputBuffer[2048], (*aOutputLength * 2)); } *aOutputLength *= 2; } #endif (*aIsFirstBuffer)++; //After decoding the first frame, modify all the input & output port settings if (1 == *aIsFirstBuffer) { StreamType = (Int32) RetrieveDecodedStreamType(); if ((0 == StreamType) && (2 == iConfigUpSamplingFactor)) { PVMP4AudioDecoderDisableAacPlus(&iExt, &ipMem); *aSamplesPerFrame = AACDEC_PCM_FRAME_SAMPLE_SIZE; aAudioAacParam->eAACProfile = OMX_AUDIO_AACObjectMain; aAudioAacParam->nFrameLength = AACDEC_PCM_FRAME_SAMPLE_SIZE; } //Output Port Parameters aAudioPcmParam->nSamplingRate = iExt.samplingRate; aAudioPcmParam->nChannels = iExt.desiredChannels; //Input Port Parameters aAudioAacParam->nSampleRate = iExt.samplingRate; //Set the Resize flag to send the port settings changed callback *aResizeFlag = OMX_TRUE; } #if PROFILING_ON iNumOutputSamples += *aSamplesPerFrame; #endif return Status; } else if (MP4AUDEC_INCOMPLETE_FRAME == Status) { *aInBuffer += iInputUsedLength; iInputUsedLength = 0; } else { *aInBufSize = 0; iInputUsedLength = 0; } return Status; }
int aac_decode(char *outbuf, const char *inbuf, int len) { int Status; /* seek to first adts sync */ if( !dec_sync ) { uint8_t *inp = (uint8_t *)inbuf; if( (inp[0] == 0xFF) && ((inp[1] & 0xF6) == 0xF0) ) { dec_sync = 1; } else return 0; } append_inbuf(inbuf, len); /* needed for some stream encoded on neon. */ if( pExt->inputBufferCurrentLength - pExt->inputBufferUsedLength < 256 ) { return 0; } //pExt->pInputBuffer = (uint8_t *)inbuf; pExt->pOutputBuffer = (short *)outbuf; pExt->pOutputBuffer_plus = (short *)(outbuf+4096); //pExt->inputBufferUsedLength=0; //pExt->inputBufferCurrentLength = len; if( !dec_configed ) { Status = PVMP4AudioDecoderConfig(pExt, pMem); /*fprintf(stderr, "config %d. used %d, current %d\n", Status, pExt->inputBufferUsedLength, pExt->inputBufferCurrentLength);*/ } Status = PVMP4AudioDecodeFrame(pExt, pMem); if (MP4AUDEC_SUCCESS == Status || SUCCESS == Status) { /*fprintf(stderr, "[SUCCESS] Status: SUCCESS " "inputBufferUsedLength: %u, " "inputBufferCurrentLength: %u, " "remainderBits: %u, " "frameLength: %u\n", pExt->inputBufferUsedLength, pExt->inputBufferCurrentLength, pExt->remainderBits, pExt->frameLength);*/ if( pExt->frameLength > 0 && !dec_configed ) { dec_configed = 1; } } else { fprintf(stderr, "aac decode error %d\n", Status); fprintf(stderr, "used %d, current %d\n", pExt->inputBufferUsedLength, pExt->inputBufferCurrentLength); #if 1 if( pExt->inputBufferUsedLength > pExt->inputBufferCurrentLength ) { /* this is ridiculous, but does happen.. * try to re-init the decoder. */ dec_sync = 0; dec_configed = 0; pExt->inputBufferUsedLength=0; pExt->inputBufferCurrentLength = 0; PVMP4AudioDecoderResetBuffer(pMem); PVMP4AudioDecoderInitLibrary(pExt, pMem); } #endif return -1; } return pExt->frameLength*4; }