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 int aacd_opencore_decode( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size, jshort *jsamples, jint outLen ) { AACDOpenCore *oc = (AACDOpenCore*) info->ext; tPVMP4AudioDecoderExternal *pExt = oc->pExt; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->pOutputBuffer = jsamples; pExt->pOutputBuffer_plus = jsamples+2048; int32_t status = PVMP4AudioDecodeFrame( pExt, oc->pMem ); if (status != MP4AUDEC_SUCCESS && status != SUCCESS) { AACD_ERROR( "decode() bytesleft=%lu, status=%d", buffer_size, status ); return -1; } info->frame_bytesconsumed = pExt->inputBufferUsedLength; info->frame_samples = pExt->frameLength * oc->frameSamplesFactor; return 0; }
int _frame_decoder(audio_decoder_p decoder, pcm_data_p pcm) { switch (decoder->audio_type) { case AUDIO_TYPE_MP3: { tPVMP3DecoderExternal tmp_ext = *((tPVMP3DecoderExternal *) decoder->dec_ext); tPVMP3DecoderExternal *mp3_ext = &tmp_ext; mp3_ext->inputBufferUsedLength = 0; ERROR_CODE errorCode = pvmp3_framedecoder(mp3_ext, decoder->dec_mem); medvdbg("[%s] Line %d, pvmp3_framedecoder, errorCode %d\n", __FUNCTION__, __LINE__, errorCode); RETURN_VAL_IF_FAIL((errorCode == NO_DECODING_ERROR), AUDIO_DECODER_ERROR); pcm->length = mp3_ext->outputFrameSize; pcm->samples = mp3_ext->pOutputBuffer; pcm->channels = mp3_ext->num_channels; pcm->samplerate = mp3_ext->samplingRate; break; } case AUDIO_TYPE_AAC: { tPVMP4AudioDecoderExternal *aac_ext = (tPVMP4AudioDecoderExternal *) decoder->dec_ext; aac_ext->inputBufferUsedLength = 0; aac_ext->remainderBits = 0; Int decoderErr = PVMP4AudioDecodeFrame(aac_ext, decoder->dec_mem); medvdbg("[%s] Line %d, PVMP4AudioDecodeFrame, decoderErr %d\n", __FUNCTION__, __LINE__, decoderErr); RETURN_VAL_IF_FAIL((decoderErr == MP4AUDEC_SUCCESS), AUDIO_DECODER_ERROR); pcm->length = aac_ext->frameLength * aac_ext->desiredChannels; pcm->samples = aac_ext->pOutputBuffer; pcm->channels = aac_ext->desiredChannels; pcm->samplerate = aac_ext->samplingRate; break; } #ifdef CONFIG_CODEC_LIBOPUS case AUDIO_TYPE_OPUS: { opus_dec_external_t *opus_ext = (opus_dec_external_t *) decoder->dec_ext; Int err = opus_frameDecode(opus_ext, decoder->dec_mem); medvdbg("[%s] Line %d, opus_frameDecode, err %d\n", __FUNCTION__, __LINE__, err); RETURN_VAL_IF_FAIL((err == OPUS_OK), AUDIO_DECODER_ERROR); pcm->length = opus_ext->outputFrameSize * opus_ext->desiredChannels; pcm->samples = opus_ext->pOutputBuffer; pcm->channels = opus_ext->desiredChannels; pcm->samplerate = opus_ext->desiredSampleRate; break; } #endif default: // No decoding, return failure. return AUDIO_DECODER_ERROR; } return AUDIO_DECODER_OK; }
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; }
status_t AACDecoder::read( MediaBuffer **out, const ReadOptions *options) { /* ** end of aac audio stream in the case of initCheck is not OK, ** avoid abnormal playing later. @Jun 16, 2011. by hbb */ if(mInitCheck != OK) { ALOGE("mInitCheck is not OK, so end aac audio stream"); return ERROR_END_OF_STREAM; } status_t err; *out = NULL; int64_t seekTimeUs; ReadOptions::SeekMode mode; if (options && options->getSeekTo(&seekTimeUs, &mode)) { CHECK(seekTimeUs >= 0); mNumSamplesOutput = 0; if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } // Make sure that the next buffer output does not still // depend on fragments from the last one decoded. PVMP4AudioDecoderResetBuffer(mDecoderBuf); } else { seekTimeUs = -1; } repeat: if (mInputBuffer == NULL) { err = mSource->read(&mInputBuffer, options); if (err != OK) { return err; } int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { if(mAnchorTimeUs != timeUs) { mAnchorTimeUs = timeUs; mNumSamplesOutput = 0; } } else { // We must have a new timestamp after seeking. CHECK(seekTimeUs < 0); } } MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK); mConfig->pInputBuffer = (UChar *)mInputBuffer->data() + mInputBuffer->range_offset(); mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->remainderBits = 0; mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data()); mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048]; #if WRITE_FILE if(aacFp) fwrite(mConfig->pInputBuffer,1, mConfig->inputBufferCurrentLength,aacFp); #endif //ALOGE("inputlen %d input[0] = %x input[1]%x", mConfig->inputBufferCurrentLength,(mConfig->pInputBuffer)[0],(mConfig->pInputBuffer)[1]); Int decoderErr = MP4AUDEC_SUCCESS; if(mConfig->isMutilChannle) { decoderErr = PVMP4AudioDecodeFrameSixChannel(mConfig, mDecoderBuf); } else { decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf); } if (mInputBuffer != NULL) { mInputBuffer->set_range( mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, mInputBuffer->range_length() - mConfig->inputBufferUsedLength); if (mInputBuffer->range_length() <= 3) { mInputBuffer->release(); mInputBuffer = NULL; } } //if the input data no enough,will drop this frame inputdata. get the next frame data. if(decoderErr != MP4AUDEC_SUCCESS) { if(mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } if(buffer) { buffer->release(); buffer = NULL; } goto repeat; } /* * AAC+/eAAC+ streams can be signalled in two ways: either explicitly * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual * rate system and the sampling rate in the final output is actually * doubled compared with the core AAC decoder sampling rate. * * Explicit signalling is done by explicitly defining SBR audio object * type in the bitstream. Implicit signalling is done by embedding * SBR content in AAC extension payload specific to SBR, and hence * requires an AAC decoder to perform pre-checks on actual audio frames. * * Thus, we could not say for sure whether a stream is * AAC+/eAAC+ until the first data frame is decoded. */ if (++mNumDecodedBuffers <= 2) { ALOGV("audio/extended audio object type: %d + %d", mConfig->audioObjectType, mConfig->extendedAudioObjectType); ALOGV("aac+ upsampling factor: %d desired channels: %d", mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels); CHECK(mNumDecodedBuffers > 0); if (mNumDecodedBuffers == 1) { mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor; // Check on the sampling rate to see whether it is changed. int32_t sampleRate; CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate)); ALOGV("--->aac samplerae %d",sampleRate); if (mConfig->samplingRate != sampleRate) { mMeta->setInt32(kKeySampleRate, mConfig->samplingRate); ALOGV("Sample rate was %d Hz, but now is %d Hz", sampleRate, mConfig->samplingRate); buffer->release(); // mInputBuffer->release(); // mInputBuffer = NULL; return INFO_FORMAT_CHANGED; } } else { // mNumDecodedBuffers == 2 if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC || mConfig->extendedAudioObjectType == MP4AUDIO_LTP) { if (mUpsamplingFactor == 2) { // The stream turns out to be not aacPlus mode anyway ALOGV("Disable AAC+/eAAC+ since extended audio object type is %d", mConfig->extendedAudioObjectType); mConfig->aacPlusEnabled = 0; } } else { if (mUpsamplingFactor == 1) { // aacPlus mode does not buy us anything, but to cause // 1. CPU load to increase, and // 2. a half speed of decoding ALOGV("Disable AAC+/eAAC+ since upsampling factor is 1"); mConfig->aacPlusEnabled = 0; } } } } size_t numOutBytes = mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels; if (mUpsamplingFactor == 2) { if (mConfig->desiredChannels == 1) { memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2); } numOutBytes *= 2; } if (decoderErr != MP4AUDEC_SUCCESS) { ALOGW("AAC decoder returned error %d, substituting silence", decoderErr); memset(buffer->data(), 0, numOutBytes); // Discard input buffer. if(mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } // fall through } buffer->set_range(0, numOutBytes); buffer->meta_data()->setInt64( kKeyTime, mAnchorTimeUs + (mNumSamplesOutput * 1000000) / mConfig->samplingRate); mNumSamplesOutput += mConfig->frameLength; *out = buffer; return OK; }