blob: d2f9926d510730e86cbfb810b6e9dbbc9741d77e [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
#ifndef OSCL_BASE_H_INCLUDED
#include "oscl_base.h"
#endif
#include "mp3_dec.h"
#include "pvmp3decoder_api.h"
Mp3Decoder::Mp3Decoder()
{
iMP3DecExt = NULL;
iAudioMp3Decoder = NULL;
iInputUsedLength = 0;
iInitFlag = 0;
}
OMX_BOOL Mp3Decoder::Mp3DecInit(OMX_AUDIO_CONFIG_EQUALIZERTYPE* aEqualizerType)
{
//Default equalization type
e_equalization EqualizType = (e_equalization) aEqualizerType->sBandIndex.nValue;
iAudioMp3Decoder = CPvMP3_Decoder::NewL();
if (!iAudioMp3Decoder)
{
return OMX_FALSE;
}
// create iMP3DecExt
if (!iMP3DecExt)
{
iMP3DecExt = OSCL_NEW(tPVMP3DecoderExternal, ());
if (!iMP3DecExt)
{
return OMX_FALSE;
}
iMP3DecExt->inputBufferCurrentLength = 0;
}
// Initialize the decoder
//Input/output buffer allocation and CrcEnabler has been kept as false
iAudioMp3Decoder->StartL(iMP3DecExt, false, false, false, EqualizType);
iMP3DecExt->inputBufferMaxLength = 512;
iInitFlag = 0;
iInputUsedLength = 0;
return OMX_TRUE;
}
void Mp3Decoder::ResetDecoder()
{
if (iAudioMp3Decoder)
{
iAudioMp3Decoder->ResetDecoderL();
}
}
void Mp3Decoder::Mp3DecDeinit()
{
if (iAudioMp3Decoder)
{
iAudioMp3Decoder->TerminateDecoderL();
delete iAudioMp3Decoder;
iAudioMp3Decoder = NULL;
if (iMP3DecExt)
{
OSCL_DELETE(iMP3DecExt);
iMP3DecExt = NULL;
}
}
}
Int Mp3Decoder::Mp3DecodeAudio(OMX_S16* aOutBuff,
OMX_U32* aOutputLength, OMX_U8** aInputBuf,
OMX_U32* aInBufSize, OMX_S32* aFrameCount,
OMX_AUDIO_PARAM_PCMMODETYPE* aAudioPcmParam,
OMX_AUDIO_PARAM_MP3TYPE* aAudioMp3Param,
OMX_BOOL aMarkerFlag,
OMX_BOOL* aResizeFlag)
{
int32 Status = MP3DEC_SUCCESS;
*aResizeFlag = OMX_FALSE;
if (iInitFlag == 0)
{
//Initialization is required again when the client inbetween rewinds the input bitstream
//Added to pass khronous conformance tests
if (*aFrameCount != 0)
{
e_equalization EqualizType = iMP3DecExt->equalizerType;
iMP3DecExt->inputBufferCurrentLength = 0;
iInputUsedLength = 0;
iAudioMp3Decoder->StartL(iMP3DecExt, false, false, false, EqualizType);
}
iInitFlag = 1;
}
iMP3DecExt->pInputBuffer = *aInputBuf + iInputUsedLength;
iMP3DecExt->pOutputBuffer = &aOutBuff[0];
iMP3DecExt->inputBufferCurrentLength = *aInBufSize;
iMP3DecExt->inputBufferUsedLength = 0;
if (OMX_FALSE == aMarkerFlag)
{
//If the input buffer has finished off, do not check the frame boundaries just return from here
//This will detect the EOS for without marker test case.
if (0 == iMP3DecExt->inputBufferCurrentLength)
{
iInputUsedLength = 0;
return MP3DEC_INCOMPLETE_FRAME;
}
//If the marker flag is not set, find out the frame boundaries
else
{
Status = iAudioMp3Decoder->SeekMp3Synchronization(iMP3DecExt);
if (1 == Status)
{
if (0 == iMP3DecExt->inputBufferCurrentLength)
{
//This indicates the case of corrupt frame, discard input bytes equal to inputBufferMaxLength
*aInBufSize -= iMP3DecExt->inputBufferMaxLength;
iInputUsedLength += iMP3DecExt->inputBufferMaxLength;
iMP3DecExt->inputBufferUsedLength += iMP3DecExt->inputBufferMaxLength;;
//return sucess so that we can continue decoding with rest of the buffer,
//after discarding the corrupted bit-streams
return MP3DEC_SUCCESS;
}
else
{
*aInputBuf += iInputUsedLength;
iMP3DecExt->inputBufferUsedLength = 0;
iInputUsedLength = 0;
return MP3DEC_INCOMPLETE_FRAME;
}
}
}
}
/*
* inform decoder how much more room is available in the output buffer
*/
iMP3DecExt->outputFrameSize = (*aOutputLength); /* in int16 samples */
Status = iAudioMp3Decoder->ExecuteL(iMP3DecExt);
if (MP3DEC_SUCCESS == Status)
{
*aInBufSize -= iMP3DecExt->inputBufferUsedLength;
if (0 == *aInBufSize)
{
iInputUsedLength = 0;
}
else
{
iInputUsedLength += iMP3DecExt->inputBufferUsedLength;
}
*aOutputLength = iMP3DecExt->outputFrameSize;
//After decoding the first frame, update all the input & output port settings
if (0 == *aFrameCount)
{
//Output Port Parameters
aAudioPcmParam->nSamplingRate = iMP3DecExt->samplingRate;
aAudioPcmParam->nChannels = iMP3DecExt->num_channels;
//Input Port Parameters
aAudioMp3Param->nSampleRate = iMP3DecExt->samplingRate;
//Set the Resize flag to send the port settings changed callback
*aResizeFlag = OMX_TRUE;
}
}
else if (Status == MP3DEC_INVALID_FRAME)
{
*aInBufSize = 0;
iInputUsedLength = 0;
*aOutputLength = 0;
}
else if (Status == MP3DEC_INCOMPLETE_FRAME)
{
*aInputBuf += iInputUsedLength;
iMP3DecExt->inputBufferUsedLength = 0;
iInputUsedLength = 0;
*aOutputLength = 0;
}
else if (Status == MP3DEC_OUTPUT_BUFFER_TOO_SMALL)
{
/*
* This condition is only reached when the mp3 version has changed
* (which is an abnormal condition)
*/
*aInputBuf += iInputUsedLength;
iMP3DecExt->inputBufferUsedLength = 0;
iInputUsedLength = 0;
*aOutputLength = 0;
/*
* Reseting the counter will force to recalculate timing parameters
* ( this will eliminate any silence insertion gap, but may force changing
* audio device parameters ( sampling freq, etc) in the middle of decoding
* If this is allowed, reset the counter.
*/
// (*aFrameCount) = -1;
}
else
{
*aInputBuf += iInputUsedLength;
iInputUsedLength = 0;
*aOutputLength = 0;
}
(*aFrameCount)++;
return Status;
}