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_opencoremp3_start( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size) { AACD_TRACE( "start() buffer=%x size=%d", (*(unsigned long*)buffer), buffer_size ); AACDOpenCoreMP3 *oc = (AACDOpenCoreMP3*) info->ext; tPVMP3DecoderExternal *pExt = oc->pExt; // prepare the first samples buffer: pExt->pOutputBuffer = malloc(4096 * sizeof(int16_t)); pExt->outputFrameSize = 4096; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->crcEnabled = 0; pExt->equalizerType = flat; pvmp3_InitDecoder( oc->pExt, oc->pMem ); int32_t status; int frameDecoded = 0; pExt->outputFrameSize = 0; /* pre-init search adts sync */ while (pExt->outputFrameSize == 0) { pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->outputFrameSize = 4096; status = pvmp3_framedecoder(pExt, oc->pMem); AACD_DEBUG( "start() Status[0]: %d - cosumed %d bytes", status, pExt->inputBufferUsedLength ); if (status != NO_DECODING_ERROR) { buffer -= pExt->inputBufferUsedLength; buffer_size -= pExt->inputBufferUsedLength; } else frameDecoded = 1; if (buffer_size <= 64) break; } free(pExt->pOutputBuffer); pExt->pOutputBuffer = NULL; if (status != NO_DECODING_ERROR) { AACD_ERROR( "start() init failed status=%d", status ); return -1; } AACD_DEBUG( "start() bytesconsumed=%d", pExt->inputBufferUsedLength ); info->samplerate = pExt->samplingRate; info->channels = pExt->num_channels; return pExt->inputBufferUsedLength; }
static int aacd_opencoremp3_decode( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size, jshort *jsamples, jint outLen ) { AACDOpenCoreMP3 *oc = (AACDOpenCoreMP3*) info->ext; tPVMP3DecoderExternal *pExt = oc->pExt; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->pOutputBuffer = jsamples; pExt->outputFrameSize = outLen; int32_t status = pvmp3_framedecoder( pExt, oc->pMem ); if (status != NO_DECODING_ERROR) { AACD_ERROR( "decode() bytesleft=%d, status=%d", buffer_size, status ); return -1; } info->frame_bytesconsumed = pExt->inputBufferUsedLength; info->frame_samples = pExt->outputFrameSize; return 0; }
static long aacd_opencoremp3_start( AACDInfo *info, unsigned char *buffer, unsigned long buffer_size) { AACD_TRACE( "start() buffer=%x size=%d", (*(unsigned long*)buffer), buffer_size ); AACDOpenCoreMP3 *oc = (AACDOpenCoreMP3*) info->ext; tPVMP3DecoderExternal *pExt = oc->pExt; // prepare the first samples buffer: //pExt->pOutputBuffer = malloc(4096 * sizeof(int16_t)); pExt->pOutputBuffer = aacd_prepare_samples( info, 4096 ); pExt->outputFrameSize = 4096; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->crcEnabled = 0; pExt->equalizerType = flat; pvmp3_InitDecoder( oc->pExt, oc->pMem ); int32_t status; int frameDecoded = 0; int attempts = 16; int totalConsumed = 0; pExt->outputFrameSize = 0; /* pre-init search adts sync */ while (!frameDecoded && attempts--) { pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; pExt->inputBufferUsedLength = 0; pExt->outputFrameSize = 4096; status = pvmp3_framedecoder(pExt, oc->pMem); AACD_DEBUG( "start() Status[0]: %d - consumed %d bytes", status, pExt->inputBufferUsedLength ); totalConsumed += pExt->inputBufferUsedLength; if (status != NO_DECODING_ERROR) { AACD_ERROR( "start() frame decode error=%d", status ); if (!pExt->inputBufferUsedLength) { AACD_ERROR( "start() first frame cannot be decoded - trying to sync again" ); int move = buffer_size < 2048 ? (buffer_size >> 1) : 1024; buffer += move; buffer_size -= move; totalConsumed += move; pExt->pInputBuffer = buffer; pExt->inputBufferMaxLength = buffer_size; pExt->inputBufferCurrentLength = buffer_size; ERROR_CODE err = pvmp3_frame_synch( oc->pExt, oc->pMem ); if (err == SYNCH_LOST_ERROR) { AACD_ERROR( "start() cannot re-sync the stream after next %d bytes, status=%d", move, err ); } else if (err != NO_DECODING_ERROR) { AACD_ERROR( "start() cannot sync the stream status=%d", err ); break; } else { totalConsumed += pExt->inputBufferUsedLength; AACD_INFO( "start() sync was successful - used bytes=%d", totalConsumed ); } } buffer -= pExt->inputBufferUsedLength; buffer_size -= pExt->inputBufferUsedLength; }
void SoftMP3::onQueueFilled(OMX_U32 portIndex) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); while (!inQueue.empty() && !outQueue.empty()) { BufferInfo *inInfo = *inQueue.begin(); OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; BufferInfo *outInfo = *outQueue.begin(); OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { inQueue.erase(inQueue.begin()); inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); // pad the end of the stream with 529 samples, since that many samples // were trimmed off the beginning when decoding started outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); memset(outHeader->pBuffer, 0, outHeader->nFilledLen); outHeader->nFlags = OMX_BUFFERFLAG_EOS; outQueue.erase(outQueue.begin()); outInfo->mOwnedByUs = false; notifyFillBufferDone(outHeader); return; } if (inHeader->nOffset == 0) { mAnchorTimeUs = inHeader->nTimeStamp; mNumFramesOutput = 0; } mConfig->pInputBuffer = inHeader->pBuffer + inHeader->nOffset; mConfig->inputBufferCurrentLength = inHeader->nFilledLen; mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); mConfig->pOutputBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer); ERROR_CODE decoderErr; if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf)) != NO_DECODING_ERROR) { ALOGV("mp3 decoder returned error %d", decoderErr); if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR && decoderErr != SIDE_INFO_ERROR) { ALOGE("mp3 decoder returned error %d", decoderErr); notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); mSignalledError = true; return; } if (mConfig->outputFrameSize == 0) { mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); } // This is recoverable, just ignore the current frame and // play silence instead. memset(outHeader->pBuffer, 0, mConfig->outputFrameSize * sizeof(int16_t)); mConfig->inputBufferUsedLength = inHeader->nFilledLen; } else if (mConfig->samplingRate != mSamplingRate || mConfig->num_channels != mNumChannels) { mSamplingRate = mConfig->samplingRate; mNumChannels = mConfig->num_channels; notify(OMX_EventPortSettingsChanged, 1, 0, NULL); mOutputPortSettingsChange = AWAITING_DISABLED; return; } if (mIsFirst) { mIsFirst = false; // The decoder delay is 529 samples, so trim that many samples off // the start of the first output buffer. This essentially makes this // decoder have zero delay, which the rest of the pipeline assumes. outHeader->nOffset = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset; } else { outHeader->nOffset = 0; outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t); } outHeader->nTimeStamp = mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate; outHeader->nFlags = 0; CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); inHeader->nOffset += mConfig->inputBufferUsedLength; inHeader->nFilledLen -= mConfig->inputBufferUsedLength; mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; if (inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; notifyFillBufferDone(outHeader); outHeader = NULL; } }
void SoftMP3::onQueueFilled(OMX_U32 portIndex) { if (mSignalledError || mOutputPortSettingsChange != NONE) { return; } List<BufferInfo *> &inQueue = getPortQueue(0); List<BufferInfo *> &outQueue = getPortQueue(1); while (!inQueue.empty() && !outQueue.empty()) { BufferInfo *inInfo = *inQueue.begin(); OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; BufferInfo *outInfo = *outQueue.begin(); OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { inQueue.erase(inQueue.begin()); inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); outHeader->nFilledLen = 0; outHeader->nFlags = OMX_BUFFERFLAG_EOS; outQueue.erase(outQueue.begin()); outInfo->mOwnedByUs = false; notifyFillBufferDone(outHeader); return; } if (inHeader->nOffset == 0) { /*a@nufront start*/ if (inHeader->nTimeStamp != INVALID_TIMESTAMP) /*a@nufront end*/ mAnchorTimeUs = inHeader->nTimeStamp; mNumFramesOutput = 0; } mConfig->pInputBuffer = inHeader->pBuffer + inHeader->nOffset; mConfig->inputBufferCurrentLength = inHeader->nFilledLen; mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); mConfig->pOutputBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer); ERROR_CODE decoderErr; if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf)) != NO_DECODING_ERROR) { LOGV("mp3 decoder returned error %d", decoderErr); if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR || mConfig->outputFrameSize == 0) { LOGE("mp3 decoder returned error %d", decoderErr); if (mConfig->outputFrameSize == 0) { LOGE("Output frame size is 0"); } notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); mSignalledError = true; return; } // This is recoverable, just ignore the current frame and // play silence instead. memset(outHeader->pBuffer, 0, mConfig->outputFrameSize * sizeof(int16_t)); mConfig->inputBufferUsedLength = inHeader->nFilledLen; } else if (mConfig->samplingRate != mSamplingRate || mConfig->num_channels != mNumChannels) { mSamplingRate = mConfig->samplingRate; mNumChannels = mConfig->num_channels; notify(OMX_EventPortSettingsChanged, 1, 0, NULL); mOutputPortSettingsChange = AWAITING_DISABLED; return; } outHeader->nOffset = 0; outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t); outHeader->nTimeStamp = mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate; outHeader->nFlags = 0; CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); inHeader->nOffset += mConfig->inputBufferUsedLength; inHeader->nFilledLen -= mConfig->inputBufferUsedLength; mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; /*a@nufront start*/ mAnchorTimeUs += (mNumFramesOutput * 1000000ll) / mConfig->samplingRate; /*a@nufront end*/ if (inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; inQueue.erase(inQueue.begin()); inInfo = NULL; notifyEmptyBufferDone(inHeader); inHeader = NULL; } outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; notifyFillBufferDone(outHeader); outHeader = NULL; } }