diff -r 000000000000 -r bb31fbe78861 mp3_dec/arimp3decmmfcodec/src/arimp3decmmfcodec.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mp3_dec/arimp3decmmfcodec/src/arimp3decmmfcodec.cpp Fri Jul 23 16:58:44 2010 +0100 @@ -0,0 +1,751 @@ +/* +* Copyright (c) 2009 Aricent and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Aricent - initial contribution. +* +* Contributors: +* +* Description: +* Implementation of member functions of Plugin class (CAriMp3DecMmfCodec). +* +*/ + +// System includes +#include +#include +// User includes +#include "arimp3decwrapper.h" +#include "arimp3decmmfcodec.h" +#include "arimp3decmmfcodec_uid.hrh" +#include "ariprint.h" + +//Maximum size of a single input frame in an Mp3 stream +const TInt KMinBytesInput = 1440; + + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// Creates an instance of CAriMp3DecMmfCodec. +// Instance is not left on cleanup stack. +// --------------------------------------------------------------------------- +// + +CMMFCodec* CAriMp3DecMmfCodec::NewL() + { + PRINT_ENTRY; + CAriMp3DecMmfCodec* self = new ( ELeave ) CAriMp3DecMmfCodec(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + PRINT_EXIT; + return ( CMMFCodec* )self; + } + +// --------------------------------------------------------------------------- +// Destructor;Destroys the decoder instance and any internal buffers +// --------------------------------------------------------------------------- +// + +CAriMp3DecMmfCodec::~CAriMp3DecMmfCodec() + { + PRINT_ENTRY; + if ( iInternalInputBuffer ) + { + delete iInternalInputBuffer; + iInternalInputBuffer = NULL; + } + if ( iInternalOutputBuffer ) + { + delete iInternalOutputBuffer; + iInternalOutputBuffer = NULL; + } + + if ( iCodec ) + { + delete iCodec; + iCodec = NULL; + } + PRINT_EXIT; + } + +// --------------------------------------------------------------------------- +// From class CMMFCodec. +// The function Sets codec configuration. +// The value used for aConfigType must be KUidMmfCodecAudioSettings +// (defined in include\mmf\plugins\mmfCodecImplementationUIDs.hrh) +// --------------------------------------------------------------------------- +// + + void CAriMp3DecMmfCodec::ConfigureL( TUid /*aConfigType*/, + const TDesC8& /*aParam*/ ) + { + PRINT_ENTRY; + PRINT_EXIT; + } + + // -------------------------------------------------------------------------- + // From class CMMFCodec. + // This function is used to flush out status information when a + // reposition occurs. + // This is used if the codec requires resetting prior to use. + // -------------------------------------------------------------------------- + // + + void CAriMp3DecMmfCodec::ResetL() + { + PRINT_ENTRY; + iInternalInputBufferResidueLen = 0; + iInternalOutputBufferPos = 0; + iInternalOutputBufferResidueLen = 0; + PRINT_EXIT; + } + + //--------------------------------------------------------------------------- + // From class CMMFCodec. + // This function is used to decode the given source and fill the + // destination buffer with the decode data. + // The buffers can be of any size. Since the buffers can be of any size + // there is no guarantee that all the source buffer can be processed to + // fill the destination buffer or that the all the source buffer may be + // processed before the destination is full. Therefore the ProcessL needs + // to return a TCodecProcessResult returing the number of source bytes + // processed and the number of destination bytes processed along with a + // process result code defined thus: + // - EProcessComplete: the codec processed all the source data into the + // sink buffer + // - EProcessIncomplete: the codec filled sink buffer before all the source + // buffer was processed + // - EDstNotFilled: the codec processed the source buffer but the sink + // buffer was not filled + // - EEndOfData: the codec detected the end data - all source data in + // processed but sink may not be full + // - EProcessError: the codec process error condition + // + // The ProcessL should start processing the source buffer from the iPosition + // data member of the source data and start filling the destination buffer + // from its iPosition. + //--------------------------------------------------------------------------- + // + +TCodecProcessResult CAriMp3DecMmfCodec::ProcessL( const CMMFBuffer& aSrc, + CMMFBuffer& aDst ) + { + PRINT_ENTRY; + // total decoded bytes added to the dst buffer + TInt totalDstBytesAdded = 0; + // total src bytes added to the internal src buffer + TInt totalSrcBytesCopied = 0; + // temporary variable to use for copying the sorce or destination data + TInt numberOfBytesCopied; + // Flag for finding valid sync + TBool syncFound = EFalse; + + /** + * Process the dst buffer, update the dstBufferPos and check + * whether dst buffer is NULL or not. + */ + CMMFDataBuffer* dst = static_cast( &aDst ); + + const TInt dstMaxLen = dst->Data().MaxLength(); + TUint8* dstPtr = const_cast( dst->Data().Ptr() ); + TInt dstBufferPos = dst->Position(); + + /** + * Process the src buffer, update srcbuffer length, position and + * flag for last frame. check whether src buffer is NULL or not + * and check src buffer contains any data + */ + const CMMFDataBuffer* src = static_cast( &aSrc ); + + TUint8* srcPtr = const_cast ( src->Data().Ptr() ); + TInt srcBufferLen = src->Data().Length(); + TInt srcBufferPos = src->Position(); + TBool lastFrame = src->LastBuffer(); + + if ( srcBufferLen == 0 && iInternalInputBufferResidueLen == 0 ) + { + PRINT_ERR( "source buffer length is zero" ); + User::Leave( KErrArgument ); + } + + /** + * if any destination bytes from internal destination buffer is not + * given to the dst buffer from the previous call, give it to the + * dst buffer. After this block, it ensures that no bytes are remaining + * in the internal destination buffer. + */ + if ( iInternalOutputBufferResidueLen - iInternalOutputBufferPos > 0 ) + { + numberOfBytesCopied = CopyToDstBuffer( dst, totalDstBytesAdded ); + + if ( iInternalOutputBufferResidueLen - iInternalOutputBufferPos > 0 ) + { + PRINT_EXIT; + return Result( TCodecProcessResult::EProcessIncomplete, + totalSrcBytesCopied, totalDstBytesAdded ); + } + else + { + if ( ( lastFrame ) && ( srcBufferLen - srcBufferPos == 0 )&& + ( iInternalInputBufferResidueLen == 0 ) ) + { + iInternalOutputBufferResidueLen = 0; + iInternalInputBufferResidueLen = 0; + iInternalOutputBufferPos = 0; + PRINT_EXIT; + return Result( TCodecProcessResult::EEndOfData, + totalSrcBytesCopied, totalDstBytesAdded ); + } + iInternalOutputBufferPos = 0; + iInternalOutputBufferResidueLen = 0; + } + } + + /** + * copy the src buffer data into the internal buffer till internal buffer + * holds minimum bytes to process i.e KMinBytesInput. After this block, it + * ensures that internal source buffer holds KMinBytesInput. + * if it is a last frame, treat remaining residual buffer as internal + * buffer. + */ + if ( ( KMinBytesInput - iInternalInputBufferResidueLen > 0 ) + && ( srcBufferLen - srcBufferPos > 0 ) ) + { + numberOfBytesCopied = CopyFromSrcBuffer( src, totalSrcBytesCopied ); + } + + if ( ( KMinBytesInput > iInternalInputBufferResidueLen ) + && ( !lastFrame ) ) + { + PRINT_EXIT; + return Result( TCodecProcessResult::EDstNotFilled, + srcBufferLen - srcBufferPos, totalDstBytesAdded ); + } + + /** + * process the src buffer till destination buffer or source buffer + * or both buffers are exhausted. + */ + do + { + /** + * call seeksync to find the valid fram start offset i.e syncpos. + * update internal buffer position to that offset position if it is + * success.if it is failed then there is no valid frame start in + * the available buffer. Go for new src buffer. all bytes present + * in the internal buffer are discarded. + */ + TInt syncpos; + TInt srcBufferRemainingBytes = srcBufferLen + - srcBufferPos + - totalSrcBytesCopied; + TInt dstBufferRemainingBytes = dstMaxLen + - dstBufferPos + - totalDstBytesAdded; + TInt internalInputBufferPos = 0; + + if ( KErrNone != iCodec->SeekSync( + &iInternalInputBuffer[internalInputBufferPos], + ( iInternalInputBufferResidueLen - internalInputBufferPos ), + syncpos ) ) + { + TCodecProcessResult result = GetNewData( src, totalSrcBytesCopied, + totalDstBytesAdded ); + + if ( result.iStatus == TCodecProcessResult::EDstNotFilled || + result.iStatus == TCodecProcessResult::EEndOfData ) + { + return result; + } + } + else + { + syncFound = ETrue; + internalInputBufferPos += syncpos; + } + /** + * call GetFrameInfo to find whether valid frame is present in the + * availabel buffer.if it is success and framelength is 0 then + * there is no valid frame is present, discard the present buffer + * till sync position and add new buffer. + */ + if ( syncFound ) + { + TInt frameLen; + TMp3FrameInfo frameInfo; + if ( KErrNone != iCodec->GetFrameInfo( + &iInternalInputBuffer[internalInputBufferPos], + ( iInternalInputBufferResidueLen - internalInputBufferPos ), + frameLen, frameInfo ) ) + { + PRINT_ERR( "Decoder Getframeinfo failed" ); + User::Leave( KErrGeneral ); + } + if ( frameLen == 0 ) + { + TCodecProcessResult result = GetNewData( src, + totalSrcBytesCopied, totalDstBytesAdded ); + + if ( result.iStatus == TCodecProcessResult::EDstNotFilled || + result.iStatus == TCodecProcessResult::EEndOfData ) + { + return result; + } + } + + /** + * if the buffer has less than framelen then fill the internal + * sorce buffer with KMinBytesInput bytes. + */ + if ( frameLen > ( iInternalInputBufferResidueLen + - internalInputBufferPos ) ) + { + if( lastFrame ) + { + iInternalInputBufferResidueLen = 0; + iInternalOutputBufferResidueLen = 0; + iInternalOutputBufferPos = 0; + PRINT_EXIT; + return Result( + TCodecProcessResult::EEndOfData, + totalSrcBytesCopied, totalDstBytesAdded ); + } + + ShiftData( internalInputBufferPos, 0 ); + numberOfBytesCopied = CopyFromSrcBuffer( src, + totalSrcBytesCopied ); + internalInputBufferPos = 0; + + if ( iInternalInputBufferResidueLen < KMinBytesInput ) + { + PRINT_EXIT; + return Result( + TCodecProcessResult::EDstNotFilled, + totalSrcBytesCopied, totalDstBytesAdded ); + } + } + + /** + * initialize the variables like srcUsed and dstLen accordingly. + * call Decode. + */ + + TInt srcUsed = iInternalInputBufferResidueLen + - internalInputBufferPos; + TInt dstLen = iOutFrameSize; + + TInt error = iCodec->Decode( + &iInternalInputBuffer[internalInputBufferPos], + srcUsed, iInternalOutputBuffer, dstLen ); + + if ( KErrNone != error ) + { + iInternalInputBufferResidueLen = 0; + PRINT_ERR( error ); + return Result( + TCodecProcessResult::EProcessError, + totalSrcBytesCopied, totalDstBytesAdded ); + } + + /** + * Fill Destination Buffer + */ + + iInternalOutputBufferResidueLen = dstLen; + numberOfBytesCopied = CopyToDstBuffer( dst, totalDstBytesAdded ); + dstBufferRemainingBytes -= numberOfBytesCopied; + + /*** + * Fill Sorce Buffer + */ + + internalInputBufferPos += srcUsed ; + ShiftData( internalInputBufferPos, 0 ); + numberOfBytesCopied = CopyFromSrcBuffer( src, + totalSrcBytesCopied ); + srcBufferRemainingBytes -= numberOfBytesCopied; + internalInputBufferPos = 0; + + /*** + * check four conditions if else for src and if else for dst + */ + + // src buffer has available bytes to decode + if ( srcBufferRemainingBytes > 0 ) + { + if ( dstBufferRemainingBytes == 0 ) + { + PRINT_EXIT; + return Result( TCodecProcessResult::EProcessIncomplete, + totalSrcBytesCopied, totalDstBytesAdded ); + } + } + + else + { + // dst buffer has availabe space for decoded bytes + if ( dstBufferRemainingBytes > 0 ) + { + // last frame of the input stream + if ( lastFrame ) + { + if ( iInternalInputBufferResidueLen == 0 ) + { + PRINT_EXIT; + return Result( TCodecProcessResult::EEndOfData, + totalSrcBytesCopied, totalDstBytesAdded ); + } + } + else + { + PRINT_EXIT; + return Result( TCodecProcessResult::EDstNotFilled, + totalSrcBytesCopied, totalDstBytesAdded ); + } + } + else + { + /** + *internal output buffer has decoded bytes which is not + *given to dst buffer. + */ + if ( iInternalOutputBufferResidueLen + - iInternalOutputBufferPos > 0 ) + { + PRINT_EXIT; + return Result( + TCodecProcessResult::EProcessIncomplete, + totalSrcBytesCopied, totalDstBytesAdded ); + } + // last frame of the input stream + else if ( lastFrame ) + { + // if internal buffer has available bytes to decode + if ( iInternalInputBufferResidueLen > 0 ) + { + PRINT_EXIT; + return Result( + TCodecProcessResult::EProcessIncomplete, + totalSrcBytesCopied, totalDstBytesAdded ); + } + else + { + iInternalInputBufferResidueLen = 0; + PRINT_EXIT; + return Result( + TCodecProcessResult::EEndOfData, + totalSrcBytesCopied, totalDstBytesAdded ); + } + } + else + { + PRINT_EXIT; + return Result( + TCodecProcessResult::EProcessComplete, + totalSrcBytesCopied, totalDstBytesAdded ); + } + } + } + } + }while ( 1 ); + } + +//---------------------------------------------------------------------------- +// Default constructor for performing 1st stage construction. +// Should not contain any code that could leave. +//---------------------------------------------------------------------------- +// + +CAriMp3DecMmfCodec::CAriMp3DecMmfCodec(): +iCodec( NULL ), iInternalInputBufferResidueLen( 0 ), +iInternalOutputBufferResidueLen( 0 ), iOutFrameSize( 0 ), +iInternalInputBuffer( NULL ), iInternalOutputBuffer( NULL ), +iInternalOutputBufferPos( 0 ) + { + PRINT_ENTRY; + PRINT_EXIT; + } + +//---------------------------------------------------------------------------- +// Second phase of the two-phased constructor. +// Creates an instance of decoder +//---------------------------------------------------------------------------- +// + +void CAriMp3DecMmfCodec::ConstructL() + { + PRINT_ENTRY; + TMp3FrameInfo frameInfo; + + TRAPD( creatErr,iCodec = CAriMp3DecWrapper::NewL() ); + if( KErrNone != creatErr ) + { + PRINT_ERR( creatErr ); + User::Leave( creatErr ); + } + + User::LeaveIfError( iCodec->Reset() ); + + TInt frameLength; + + User::LeaveIfError( iCodec->GetMaxFrameInfo( frameLength, frameInfo ) ); + + iOutFrameSize = frameInfo.iBufferSize; + + iInternalInputBuffer = new( ELeave ) TUint8[KMinBytesInput]; + if ( !iInternalInputBuffer ) + { + PRINT_ERR( "iInternalInputBuffer is not created" ); + User::Leave( KErrNoMemory ); + } + + iInternalOutputBuffer = new( ELeave ) TUint8[iOutFrameSize]; + if ( !iInternalOutputBuffer ) + { + PRINT_ERR( "iInternalOutputBuffer is not created" ); + User::Leave( KErrNoMemory ); + } + } + +//---------------------------------------------------------------------------- +// Updates the result of the processing +//---------------------------------------------------------------------------- +// +TCodecProcessResult CAriMp3DecMmfCodec::Result( + TCodecProcessResult::TCodecProcessResultStatus aStatus, + TInt aSrcBytesConsumed, TInt aDstBytesAdded ) + + { + PRINT_ENTRY; + TCodecProcessResult result; + // update destination bytes + result.iDstBytesAdded = aDstBytesAdded; + // update source bytes + result.iSrcBytesProcessed = aSrcBytesConsumed; + + // update status + switch ( aStatus ) + { + case TCodecProcessResult::EProcessComplete: + result.iStatus = TCodecProcessResult::EProcessComplete; + break; + case TCodecProcessResult::EProcessIncomplete: + result.iStatus = TCodecProcessResult::EProcessIncomplete; + break; + case TCodecProcessResult::EEndOfData: + result.iStatus = TCodecProcessResult::EEndOfData; + break; + case TCodecProcessResult::EDstNotFilled: + result.iStatus = TCodecProcessResult::EDstNotFilled; + break; + case TCodecProcessResult::EProcessError: + result.iStatus = TCodecProcessResult::EProcessError; + break; + default: + result.iStatus = TCodecProcessResult::EProcessError; + break; + } + PRINT_MSG( LEVEL_HIGH, ( "result.iSrcBytesProcessed = %d", + result.iSrcBytesProcessed ) ); + PRINT_MSG( LEVEL_HIGH, ( "result.iDstBytesAdded = %d", + result.iDstBytesAdded ) ); + PRINT_MSG( LEVEL_HIGH, ( "result.iStatus = %d", + result.iStatus ) ); + PRINT_EXIT; + return result; + } + +//---------------------------------------------------------------------------- +// Copy the bytes to destination buffer from the internal buffer +// first checks whether the number of bytes to be copied is lesser of the +// destination buffer reamining bytes and internal input internal remaining +// remaining bytes and then copies that many bytes. +//---------------------------------------------------------------------------- +// + TInt CAriMp3DecMmfCodec::CopyToDstBuffer( CMMFDataBuffer* aDst, + TInt &aDstBytesConsumed ) + { + PRINT_ENTRY; + TInt numberOfBytesToBeCopied; + const TInt dstMaxLen = aDst->Data().MaxLength(); + TUint8* dstPtr = const_cast( aDst->Data().Ptr() ); + TInt dstBufferPos = aDst->Position(); + + // destination buffer remaining bytes + TInt dstBufferRemainingBytes = dstMaxLen + - dstBufferPos + - aDstBytesConsumed; + // internal output buffer remaining bytes + TInt internalOutputBufferRemainingBytes = + iInternalOutputBufferResidueLen + - iInternalOutputBufferPos; + + if ( internalOutputBufferRemainingBytes > dstBufferRemainingBytes ) + { + numberOfBytesToBeCopied = dstBufferRemainingBytes; + } + else + { + numberOfBytesToBeCopied = internalOutputBufferRemainingBytes; + iInternalOutputBufferResidueLen = 0; + } + + // copy data to destination buffer from internal ouput buffer + Mem::Copy( dstPtr + dstBufferPos + aDstBytesConsumed, + iInternalOutputBuffer + iInternalOutputBufferPos, + numberOfBytesToBeCopied ); + + // update internal output buffer position + if( iInternalOutputBufferResidueLen ) + { + iInternalOutputBufferPos += dstBufferRemainingBytes; + } + else + { + iInternalOutputBufferPos = 0; + } + + aDstBytesConsumed += numberOfBytesToBeCopied; + aDst->Data().SetLength( dstBufferPos + aDstBytesConsumed ); + PRINT_EXIT; + return numberOfBytesToBeCopied; + } + +//--------------------------------------------------------------------------- +// Copy the bytes from the source buffer to the internal input buffer. +// first it checks number of bytes to be copied is lesser of the source buffer +// remaining bytes or internal input buffer remaining bytes and then copies +// that many bytes. +//--------------------------------------------------------------------------- +// + TInt CAriMp3DecMmfCodec::CopyFromSrcBuffer( const CMMFDataBuffer* aSrc, + TInt &aSrcBytesConsumed ) + { + PRINT_ENTRY; + TInt numberOfBytesToBeCopied; + TUint8* srcPtr = const_cast ( aSrc->Data().Ptr() ); + TInt srcBufferLen = aSrc->Data().Length(); + TInt srcBufferPos = aSrc->Position(); + + // calculate the source buffer remaining bytes + TInt srcBufferRemainingBytes = srcBufferLen - srcBufferPos + - aSrcBytesConsumed; + + // calculate internal input buffer remaining bytes + TInt internalInputBufferRemaingBytes = KMinBytesInput + - iInternalInputBufferResidueLen; + + if ( internalInputBufferRemaingBytes > srcBufferRemainingBytes ) + { + numberOfBytesToBeCopied = srcBufferRemainingBytes; + } + else + { + numberOfBytesToBeCopied = internalInputBufferRemaingBytes; + } + + // copy data from source buffer to internal input buffer + Mem::Copy( iInternalInputBuffer + iInternalInputBufferResidueLen, + srcPtr + srcBufferPos + aSrcBytesConsumed, + numberOfBytesToBeCopied ); + + // update internal input buffer residue length + iInternalInputBufferResidueLen += numberOfBytesToBeCopied; + aSrcBytesConsumed += numberOfBytesToBeCopied; + PRINT_EXIT; + return numberOfBytesToBeCopied; + } +//--------------------------------------------------------------------------- +// Moves the data of the internal input buffer to the start position +//--------------------------------------------------------------------------- +// +void CAriMp3DecMmfCodec::ShiftData( TInt aFromPos, TInt aToPos ) + { + PRINT_ENTRY; + for ( TInt i = aToPos; i < ( iInternalInputBufferResidueLen - aFromPos ); + i++ ) + { + iInternalInputBuffer[i] = iInternalInputBuffer[i + aFromPos]; + } + iInternalInputBufferResidueLen -= aFromPos; + PRINT_EXIT; + } +//--------------------------------------------------------------------------- +// Gets the new data from the source buffer. +// checks whether it is last buffer from the source buffer and copies the data +// and then checks if source buffer remianing bytes are not and returns the +// result of the processing. +//--------------------------------------------------------------------------- +// +TCodecProcessResult CAriMp3DecMmfCodec::GetNewData( + const CMMFDataBuffer* aSrc, + TInt &aSrcBytesConsumed, TInt &aDstBytesConsumed ) + { + PRINT_ENTRY; + TUint8* srcPtr = const_cast ( aSrc->Data().Ptr() ); + TInt srcBufferLen = aSrc->Data().Length(); + TInt srcBufferPos = aSrc->Position(); + TBool lastFrame = aSrc->LastBuffer(); + // calculate source buffer remaining bytes + TInt srcBufferRemainingBytes = srcBufferLen - srcBufferPos + - aSrcBytesConsumed; + + TCodecProcessResult result; + result.iStatus = TCodecProcessResult::EProcessError; + + // if it is last frame return end of data + if ( ( lastFrame ) && ( srcBufferRemainingBytes == 0 ) ) + { + iInternalInputBufferResidueLen = 0; + iInternalOutputBufferResidueLen = 0; + iInternalOutputBufferPos = 0; + PRINT_EXIT; + return Result( TCodecProcessResult::EEndOfData, + aSrcBytesConsumed, aDstBytesConsumed ); + } + else + { + iInternalInputBufferResidueLen = 0; + TInt numberOfBytesToBeCopied = CopyFromSrcBuffer( aSrc, + aSrcBytesConsumed ); + + if ( iInternalInputBufferResidueLen < KMinBytesInput ) + { + PRINT_EXIT; + return Result( TCodecProcessResult::EDstNotFilled, + aSrcBytesConsumed, aDstBytesConsumed ); + } + } + PRINT_EXIT; + return result; + } +/* __________________________________________________________________________ +* Exported proxy for instantiation method resolution +* Define the interface UIDs +*/ + +const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY( KUidMp3DecCodecImplUid, + CAriMp3DecMmfCodec::NewL ) + }; + +EXPORT_C const TImplementationProxy* ImplementationGroupProxy( + TInt& aTableCount ) +{ + PRINT_ENTRY; + aTableCount = sizeof( ImplementationTable ) + / sizeof( TImplementationProxy ); + PRINT_EXIT; + return ImplementationTable; +} + +//--------------------------------------------------------------------------- +// End of File +//---------------------------------------------------------------------------