mp4asp_dec/arimpeg4aspdechwdevice/src/arimpeg4aspdechwdevice.cpp
author Pat Downey <patd@symbian.org>
Fri, 23 Jul 2010 16:58:44 +0100
changeset 0 bb31fbe78861
permissions -rw-r--r--
Initial commit of Aricent codec contribution.

/*
* 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:
* This is a source file, which is required for Mp4DecHwDevice.
*
*/

//User includes
#include "arimpeg4aspdechwdevice.h"
#include "aristatemachine.h"
#include "ariprint.h"

//manufacturer name
_LIT( KManufacturer, "Aricent" );

_LIT( KIdentifier, "MPEG4/H263 Video Decoder" );

//supported mime types for mp4
_LIT8( KMPEG4SupportedMimeType, "video/mp4v-es" );
// profile level 0
_LIT8( KMPEG4SupportedProfileLevel_0, "video/mp4v-es; profile-level-id=8" );
// profile level 0b / 11
_LIT8( KMPEG4SupportedProfileLevel_0b, "video/mp4v-es; profile-level-id=9" );
// profile level 1
_LIT8( KMPEG4SupportedProfileLevel_1, "video/mp4v-es; profile-level-id=1" );
// profile level 2
_LIT8( KMPEG4SupportedProfileLevel_2, "video/mp4v-es; profile-level-id=2" );
// profile level 3
_LIT8( KMPEG4SupportedProfileLevel_3, "video/mp4v-es; profile-level-id=3" );
// profile level 4
_LIT8( KMPEG4SupportedProfileLevel_4, "video/mp4v-es; profile-level-id=4" );
// profile level 5
_LIT8( KMPEG4SupportedProfileLevel_5, "video/mp4v-es; profile-level-id=5" );

//supported mime types for h263
_LIT8( KH263SupportedMimeType, "video/h263-2000" );
_LIT8( KH26398SupportedMimeType, "video/h263-1998" );

// h263 profile level 10
_LIT8( KH263SupportedProfileLevel_10, "video/h263-2000;profile=0;level=10" );
// h263 profile level 20
_LIT8( KH263SupportedProfileLevel_20, "video/h263-2000;profile=0;level=20" );
// h263 profile level 30
_LIT8( KH263SupportedProfileLevel_30, "video/h263-2000;profile=0;level=30" );
// h263 profile level 45
_LIT8( KH263SupportedProfileLevel_45, "video/h263-2000;profile=0;level=45" );


//---------------------------------------------------------------------------
//1st phase constructor of CAriMpeg4aspdecHwDevice
//---------------------------------------------------------------------------
//
CMMFVideoDecodeHwDevice* CAriMpeg4aspdecHwDevice::NewL()
	{
	PRINT_ENTRY;
	CAriMpeg4aspdecHwDevice* self = new ( ELeave ) CAriMpeg4aspdecHwDevice;
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop( self );
	PRINT_EXIT;
	return self;
	}


//---------------------------------------------------------------------------
//Destructor
//---------------------------------------------------------------------------
//
CAriMpeg4aspdecHwDevice::~CAriMpeg4aspdecHwDevice()
	{
	PRINT_ENTRY;
	delete iInputFormat;
	delete iEngine;
	delete iCodec;
	delete iState;
	
    delete iVideoPictureHeader;

	// This is required becoz user may say exit before start at that point
	// OutputFreeBuffer is not created
	if ( iOutputFreeBuffer )
		{
		for ( TInt i = 0 ; i < KMaxOutputBuffers; i++ )
			{
            if ( ( iOutputFreeBuffer + i )->iHeader )
                {
			    delete ( iOutputFreeBuffer + i )->iHeader;
                }
			if ( ( iOutputFreeBuffer + i )->iData.iRawData )
				{
				delete
				( TUint8* )( iOutputFreeBuffer + i )->iData.iRawData->Ptr();
				}
            if ( ( iOutputFreeBuffer + i )->iData.iRawData )
                {
			    delete ( iOutputFreeBuffer + i )->iData.iRawData;
                }
			}
		delete [] iOutputFreeBuffer;
		}

	if ( iInputFreeBuffers )
		{
		TInt i;
		for ( i = 0 ; i < TInt( iBufferOptions.iMinNumInputBuffers ); i++ )
			{
			delete [] ( TUint8* )iInputFreeBuffers[i].iData.Ptr();
			delete iInputFreeBuffers[i].iUser;
			}
		delete [] iInputFreeBuffers;
		}

	if ( iCustomBufferOptions )
		{
		delete iCustomBufferOptions;
		}
    iOutputFreeBufferQueue.Close();
	iInputFreeBufferQueue.Close();

	iMaxPictureRates.Reset();
	iMaxPictureRates.Close();
	iSupportedFormats.Reset();
	iSupportedFormats.Close();

    iOutputDevice = NULL;
    iMMFDevVideoPlayProxy = NULL;
    iCustomBufferHandle = NULL;
    PRINT_EXIT;
	}
//---------------------------------------------------------------------------
//Retrieves a custom interface to the device.
//---------------------------------------------------------------------------
//
TAny* CAriMpeg4aspdecHwDevice::CustomInterface( TUid /*aInterface*/ )
	{
	PRINT_ENTRY;
	PRINT_EXIT;

	return NULL;
	}


//---------------------------------------------------------------------------
//Retrieves decoder information about this hardware device. The device
//creates a CVideoDecoderInfo structure, fills it with correct data,
//pushes it to the cleanup stack and returns it. The client will delete the
//object when it is no longer needed.
//---------------------------------------------------------------------------
//
CVideoDecoderInfo* CAriMpeg4aspdecHwDevice::VideoDecoderInfoLC()
    {
    PRINT_ENTRY;
    for ( TUint i = 0; i < KDecoderInfoCount; i++ )
		{
		// construct the video types for iVidTypes
		CCompressedVideoFormat* format = NULL;
		TPtrC8 mimeType = KDecoderInfoMimeArray[i];
		format = CCompressedVideoFormat::NewL( mimeType );
		CleanupStack::PushL(format);
		TInt status = iSupportedFormats.Append( format );
		if ( status != KErrNone )
			{
			PRINT_MSG( LEVEL_LOW, ( " Format support is not done, retval of "
					"append = %d \n", status ) );
			}
		CleanupStack::Pop( format );

		// max picture rates
		TPictureRateAndSize pictureRateAndSize;
		pictureRateAndSize.iPictureSize = TSize( KMaxFrameWidth,
				                                KMaxFrameHeight );
		pictureRateAndSize.iPictureRate = KPicRate;
		status = iMaxPictureRates.Append(pictureRateAndSize);
		if ( status != KErrNone )
			{
			PRINT_MSG( LEVEL_LOW, ( " error in appendng picturerates = %d \n",
					status ) );
			}
		}

    TUint maxBitRate = KMaxBitRate;

    CVideoDecoderInfo* videoDecoderInfo = CVideoDecoderInfo::NewL(
        	KUidMp4H263DecoderHwDevice,
        	KManufacturer,
        	KIdentifier,
         	TVersion( 1, 0, 0 ),
        	iSupportedFormats.Array(),
        	EFalse,
        	EFalse,
			TSize( KMaxFrameWidth, KMaxFrameHeight ),
			maxBitRate,
			iMaxPictureRates.Array(),
			ETrue,
			ETrue );

    CleanupStack::PushL( videoDecoderInfo );

    PRINT_MSG( LEVEL_LOW, ( "Closing maxPictureRates&supportedFormats\n" ) );

    PRINT_EXIT;

    return videoDecoderInfo;
}

//---------------------------------------------------------------------------
//Reads header information from a coded data unit.
//---------------------------------------------------------------------------
//
TVideoPictureHeader* CAriMpeg4aspdecHwDevice::GetHeaderInformationL(
								TVideoDataUnitType /*aDataUnitType*/,
								TVideoDataUnitEncapsulation aEncapsulation,
								TVideoInputBuffer* aDataUnit )
	{
	PRINT_ENTRY;
    if ( !aDataUnit )
	    {
	    PRINT_ERR( "Input argument is not proper, aDataUnit is null \n" );
		User::Leave( KErrArgument );
		}

    if ( aEncapsulation != EDuElementaryStream )
    	{
    	PRINT_ERR( "aEncapsulation is not supported type \n" );
        User::Leave( KErrNotSupported );
    	}

    iVideoPictureHeader = new ( ELeave ) TVideoPictureHeader;

	TRAPD( err, CAriMpeg4aspdecWrapper::GetHeaderInfoL(  *aDataUnit,
												  *iVideoPictureHeader ) );

    if ( err == KErrNone )
		{
		PRINT_EXIT;
        return ( iVideoPictureHeader );
    	}
    delete iVideoPictureHeader;
    iVideoPictureHeader = NULL;

    switch ( err )
        {
        case KErrCorrupt:
        case KErrNoMemory:
        case KErrArgument:
        case KErrNotSupported:
            {
            PRINT_ERR( "GetHeaderInfoL is returned with error \n" );
            User::Leave( err );
            break;
            }
        case KErrUnderflow:
            {
            PRINT_ERR( "GetHeaderInfoL returnd with error KErrUnderflow\n" );
            break;
            }
        default:
            {
            PRINT_ERR( "GetHeaderInfoL is returned with error \n" );
            User::Leave( KErrGeneral );
            }
        };

    PRINT_EXIT;
	return NULL;
	}

//---------------------------------------------------------------------------
//Returns a header from GetHeaderInformationL() back to the decoder so that
//the memory can be freed.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::ReturnHeader( TVideoPictureHeader* aHeader )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		if ( iVideoPictureHeader == aHeader )
			{
			delete iVideoPictureHeader;
            iVideoPictureHeader = NULL;
			}
		else
			{
			iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrArgument );
			}
		}
	else
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Sets the device input format to a compressed video format.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetInputFormatL(
								   const CCompressedVideoFormat& aFormat,
								   TVideoDataUnitType aDataUnitType,
								   TVideoDataUnitEncapsulation aEncapsulation,
								   TBool aDataInOrder )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		if ( ( !aDataInOrder ) ||
             ( aEncapsulation == EDuGenericPayload ) ||
             ( aEncapsulation == EDuRtpPayload ) ||
             ( aDataUnitType == EDuArbitraryStreamSection ) )
             User::Leave( KErrNotSupported );

		if ( ( aFormat.MimeType().FindF( KMPEG4SupportedMimeType ) !=
															KErrNotFound ) ||
			( aFormat.MimeType().FindF( KH263SupportedMimeType ) !=
														    KErrNotFound ) ||
			( aFormat.MimeType().FindF( KH26398SupportedMimeType ) !=
														    KErrNotFound ) )

			{
			iInputFormat = CCompressedVideoFormat::NewL( aFormat );
			iDataUnitType  = aDataUnitType;
			iEncapsulation = aEncapsulation;
			}
		else
			{
			PRINT_ERR( "aFormat is not supported \n" );
			User::Leave( KErrNotSupported );
			}
		}
	else
		{
		PRINT_ERR( "istate is not initialized yet\n" );
		User::Leave( KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Sets whether decoding should be synchronized to the current clock source,
//if any, or if pictures should instead be decoded as soon as possible.
//If decoding is synchronized, decoding timestamps are used if available,
//presentation timestamps are used if not. When decoding is not synchronized,
//pictures are decoded as soon as source data is available for them, and the
//decoder has a free output buffer. If a clock source is not available,
//decoding will not be synchronized.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SynchronizeDecoding( TBool /*aSynchronize*/ )
	{
	PRINT_ENTRY;
	PRINT_EXIT;
	return;
	}


//---------------------------------------------------------------------------
//Sets the Buffer Options as specified by the client.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetBufferOptionsL(
						const CMMFDevVideoPlay::TBufferOptions& aOptions )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		TTimeIntervalMicroSeconds zerotime( 0 );
        if ( ( aOptions.iMinNumInputBuffers < KMinInputBuffers ) ||
             ( aOptions.iPreDecodeBufferSize != 0 ) ||
             ( aOptions.iMaxPostDecodeBufferSize != 0 ) ||
             ( aOptions.iPreDecoderBufferPeriod != zerotime ) ||
             ( aOptions.iPostDecoderBufferPeriod != zerotime ) )
        	{
            User::Leave( KErrArgument );
        	}

		if ( ( aOptions.iMinNumInputBuffers > KMaxInputBuffers ) ||
               ( aOptions.iMaxInputBufferSize > KMaxInputBufferSize ) )
			{
		    User::Leave( KErrNotSupported );
			}

		iBufferOptions = aOptions;
		}
	else
		{
		PRINT_ERR( "istate is not initialized yet\n" );
		User::Leave( KErrNotReady );
		}

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Gets the video decoder buffer options actually in use.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetBufferOptions(
								CMMFDevVideoPlay::TBufferOptions& aOptions )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		aOptions = iBufferOptions;
		}
	else
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Indicates which HRD/VBV specification is fulfilled in the input stream and
//any related parameters.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetHrdVbvSpec(
								THrdVbvSpecification /*aHrdVbvSpec*/,
								const TDesC8& /*aHrdVbvParams*/ )
	{
	PRINT_ENTRY;
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Sets the output post-processor device to use.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetOutputDevice(
										CMMFVideoPostProcHwDevice* aDevice )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		if ( !aDevice )
			{
			iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrArgument );
			}
		else
			{
			iOutputDevice = aDevice;

			// checks whether customBuffer supported by o/p device
            iCustomBufferHandle =
             ( MMmfVideoBufferManagement* )( iOutputDevice->CustomInterface(
										KMmfVideoBuffermanagementUid ) );
			}
		}
	else
		{
		PRINT_ERR( "istate is not initialized yet, "
				"calling MdvppFatalError on iMMFDevVideoPlayProxy\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Returns the current decoding position, i.e.
//the timestamp for the most recently decoded picture.
//---------------------------------------------------------------------------
//
TTimeIntervalMicroSeconds CAriMpeg4aspdecHwDevice::DecodingPosition()
	{
	PRINT_ENTRY;
	if ( iState->IsInitialized() )
		{
		PRINT_EXIT;
		return iDecodingPosition;
		}
	else
		{
		PRINT_ERR( "iState is not initialised, calling  MdvppFatalError\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		PRINT_EXIT;
		return ( TTimeIntervalMicroSeconds( 0 ) );
		}
	}

//---------------------------------------------------------------------------
//Returns the current pre-decoder buffer size.
//---------------------------------------------------------------------------
//
TUint CAriMpeg4aspdecHwDevice::PreDecoderBufferBytes()
	{
	PRINT_ENTRY;
    if ( !( iState->IsInitialized() ) )
        {
        iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
        PRINT_EXIT;
		return ( 0 );
        }

    PRINT_EXIT;
    return 0;
	}

//---------------------------------------------------------------------------
//Reads various counters related to the received input bitstream
//and coded data units.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetBitstreamCounters(
							CMMFDevVideoPlay::TBitstreamCounters& aCounters )
	{
	PRINT_ENTRY;
	if ( iState->IsInitialized() )
		{
		aCounters = iBitstreamCounters;
		//Reset the counters to Zero
		iBitstreamCounters.iLostPackets = 0;
		iBitstreamCounters.iTotalPackets = 0;
		}
	else
		{
		PRINT_ERR( "iState is not initialised, calling  MdvppFatalError\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Retrieves the number of free input buffers the decoder has available
//---------------------------------------------------------------------------
//
TUint CAriMpeg4aspdecHwDevice::NumFreeBuffers()
	{
	PRINT_ENTRY;
	if ( iState->IsInitialized() )
		{
		if ( iNumberOfInputBuffersAllocated == 0 )
		    {
		    PRINT_EXIT;
		    return ( iBufferOptions.iMinNumInputBuffers );
		    }
		else
		    {
		    PRINT_EXIT;
		    return  ( iInputFreeBufferQueue.Count() );
		    }
		}
	else
		{
		PRINT_ERR( "iState is not initialised, calling  MdvppFatalError\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		PRINT_EXIT;
		return( KErrNone );
		}
	}

//---------------------------------------------------------------------------
//Returns an input buffer of size aBufferSize. If no buffer is available
//then NULL is returned.
//---------------------------------------------------------------------------
//
TVideoInputBuffer* CAriMpeg4aspdecHwDevice::GetBufferL( TUint aBufferSize )
	{
	PRINT_ENTRY;
	if ( !( iState->IsInitialized() ) )
        {
        PRINT_ERR( "istate is not initialized yet\n" );
        User::Leave( KErrNotReady );
        }

    if ( iState->IsInputEndPending() )
	    {
	    PRINT_ERR( "input is pending\n" );
		User::Leave( KErrNotReady );
	    }

    if ( aBufferSize > iBufferOptions.iMaxInputBufferSize )
        {
        PRINT_ERR( "aBufferSize is more than the allowed size\n" );
    	PRINT_MSG( LEVEL_HIGH, ( "reqBufSize = %d, maxAllowedBufSize = %d",
    			aBufferSize, iBufferOptions.iMaxInputBufferSize ) );
        User::Leave( KErrArgument );
        }

	TVideoInputBuffer *inBuffer = NULL;

    if ( iNumberOfInputBuffersAllocated ==
								iBufferOptions.iMinNumInputBuffers )
        {
        if ( iInputFreeBufferQueue.Count() )
            {
            // Reallocate the input buffer if needed
            PRINT_MSG( LEVEL_HIGH, ( "Reallocate input buffer if needed" ) );
			CreateInputBufferL( aBufferSize, ETrue );
			inBuffer = iInputFreeBufferQueue[0];
			iInputFreeBufferQueue.Remove( 0 );
            }
        else
            {
            PRINT_ERR( "No input free buffers available \n" );
            return NULL;
            }
        }
    else if ( iNumberOfInputBuffersAllocated <
									iBufferOptions.iMinNumInputBuffers )
        {
        // Allocate new buffer of the requested size
        //PRINT_ERR( "CreateInputBufferL returned EFALSE\n" );
        CreateInputBufferL( aBufferSize, EFalse );

        // remove the last created buffer
        inBuffer = iInputFreeBufferQueue[ iInputFreeBufferQueue.Count() - 1];

        iInputFreeBufferQueue.Remove( iInputFreeBufferQueue.Count() - 1 );
        }
    else
        {
        PRINT_ERR( "iNumberOfInputBuffersAllocated is less "
        		"			iBufferOptions.iMinNumInputBuffers\n" );
        User::Leave( KErrGeneral );
        }

    PRINT_EXIT;
	return inBuffer;
	}

//---------------------------------------------------------------------------
//Called by DevVideoPlay to write the coded data.
//Writes a piece of coded video data to the decoder. The data buffer must
//be retrieved from the decoder with GetBufferL()..
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::WriteCodedDataL( TVideoInputBuffer* aBuffer )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		PRINT_ERR( "istate is not initialized yet \n" );
		User::Leave( KErrNotReady );
		}

    if ( !aBuffer )
		{
		PRINT_ERR( "aBuffer is null \n" );
		User::Leave( KErrArgument );
		}

    if ( aBuffer->iData.Length() == 0 )
	    {
	    PRINT_ERR( "length of aBuffer is zero \n" );
		User::Leave( KErrArgument );
	    }

	if ( iState->IsInputEndPending() )
		{
		PRINT_ERR( "IsInputEndPending is true \n" );
		User::Leave( KErrEof );
		}

	if ( ( iDataUnitType == EDuSeveralSegments ) ||
			( iDataUnitType == EDuVideoSegment ) )
	    {
		iBitstreamCounters.iTotalPackets++;
	    }

	// if custom interface is supported by o/p device get all the buffers
	// and add it to Engine
	if ( !iOutputBuffersCreated )
		{
		// Set Stream information
		if ( !iDecoderConfigured )
			{
    		iCodec->ConfigDecoderL( &( aBuffer->iData ) );
			// set input & output formats to Codec
			iCodec->SetFormatsL( iDataUnitType, iOutputFormat );
            iDecoderConfigured = ETrue;
			}

    	if ( !iCustomBufferHandle )
    		{
			// Get o/p buffer length for creation
			iOutputBufferSize = iCodec->GetOutputBufferLength();
			CreateOutputBuffersL();
    		}
		iOutputBuffersCreated = ETrue;
		}

	// add all the o/p buffers to engine
	if ( !iBufferAdded )
		{
		if ( iCustomBufferHandle )
			{
			TVideoPicture* videoPicture = NULL;
			for ( TInt i = 0;
				  i < TInt( iCustomBufferOptions->iNumInputBuffers );
				  i++ )
				{
				videoPicture = iCustomBufferHandle->MmvbmGetBufferL(
										iCustomBufferOptions->iBufferSize );
				if ( videoPicture )
					{
					TRAPD( lErr, videoPicture->iHeader =
									new ( ELeave ) TVideoPictureHeader ) ;
					if ( lErr != KErrNone )
                    	{
                    	iCustomBufferHandle->MmvbmReleaseBuffer(
															  videoPicture );
                    	iMMFDevVideoPlayProxy->MdvppFatalError( this,
															  KErrArgument );
                    	}
                    else
                    	{
					    iEngine->AddOutput( videoPicture );
                    	}
					}
				else
					{
					break;
					}
				}
			}
		else
			{
			for ( TInt i = 0; i < iOutputFreeBufferQueue.Count(); i++ )
				{
				iEngine->AddOutput( iOutputFreeBufferQueue[0] );
				iOutputFreeBufferQueue.Remove( 0 );
				}
			}
		iBufferAdded = ETrue;
		}

	iPictureCounters.iTotalPictures++;
	iFilledBufferCounter++;
	TInt err = iEngine->AddInput( aBuffer );
	PRINT_MSG( LEVEL_LOW, ( "WriteCodedDataL, addinput err = %d", err ) );
	PRINT_EXIT;
	}


#ifdef SYMBIAN_MDF_API_V2
//---------------------------------------------------------------------------
//Configures the Mpeg4/H263 decoder by passing the required header
//information for the stream that is getting decoded. The header
//structurespecific  to the Decoder is passed as iOptional member.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::ConfigureDecoderL(
							const TVideoPictureHeader& aVideoPictureHeader )
    {
    PRINT_ENTRY;
	if ( iState->IsInitialized() )
		{
		PRINT_ERR( "iState is already initialised \n" );
		User::Leave( KErrNotReady );
		}

    TInt level = aVideoPictureHeader.iLevel;
    PRINT_MSG( LEVEL_LOW, ( "ConfigureDecoderL,level = %d \n", level ) );
    if ( aVideoPictureHeader.iOptional )
        {
        // Mpeg-4
        switch ( level )
            {
			case 0:
			case KMP4Level11: //level 0b
			case KMP4Level1:
			case KMP4Level2:
			case KMP4Level3:
			case KMP4Level4:
			case KMP4Level5:
			case -1:
				break;
			default:
				{
				PRINT_ERR( "level is not supported \n" );
				User::Leave( KErrNotSupported );
				}
            }
        }
    else
        {
        // H.263
        switch ( level )
            {
			case KH263Level10:
			case KH263Level20:
			case KH263Level30:
			case KH263Level45:
			case -1:
				break;
			default:
				{
				PRINT_ERR( "level is not supported \n" );
				User::Leave( KErrNotSupported );
				}
            }
        }

	// Create Codec and configure the decoder
	iCodec = CAriMpeg4aspdecWrapper::NewL( this );

	// configure the decoder in case of mpeg-4 otherwise ie in
	// case of h.263 wait till the first call of WriteCodedDataL()
    if ( aVideoPictureHeader.iOptional )
        {
	    iCodec->ConfigDecoderL( aVideoPictureHeader.iOptional );
    	iDecoderConfigured = ETrue;
        }
    iConfigureDecoderCalled = ETrue;

    PRINT_EXIT;
    }
#endif

//---------------------------------------------------------------------------
//Retrieves post-processing information about this hardware device.
//The device creates a CPostProcessorInfo structure, fills it with correct
//data, pushes it to the cleanup stack and returns it. The client will
//delete the object when it is no longer needed.
//---------------------------------------------------------------------------
//
CPostProcessorInfo* CAriMpeg4aspdecHwDevice::PostProcessorInfoLC()
	{
	PRINT_ENTRY;
	//Aricent decoder does not support any post processing functionality
	RArray<TUncompressedVideoFormat> supportedFormats;
	CleanupClosePushL( supportedFormats );

	RArray<TUint32> supportedCombinations;
	CleanupClosePushL( supportedCombinations );

	TYuvToRgbCapabilities yuvToRgbCapabilities;
	RArray<TScaleFactor> supportedScaleFactors;
	CleanupClosePushL( supportedScaleFactors );

	yuvToRgbCapabilities.iSamplingPatterns = 0;
	yuvToRgbCapabilities.iCoefficients = 0;
	yuvToRgbCapabilities.iRgbFormats = 0;
	yuvToRgbCapabilities.iLightnessControl = EFalse;
	yuvToRgbCapabilities.iSaturationControl = EFalse;
	yuvToRgbCapabilities.iContrastControl = EFalse;
	yuvToRgbCapabilities.iGammaCorrection = EFalse;
	yuvToRgbCapabilities.iDitherTypes = 0;


	CPostProcessorInfo* info = CPostProcessorInfo::NewL(
		KUidMp4H263DecoderHwDevice,
		KManufacturer,
		KIdentifier,
		TVersion( 1, 0, 0 ),
		supportedFormats.Array(),
		supportedCombinations.Array(),
		//Accelerated or not
		EFalse,
		//supports DSA
		EFalse,
		yuvToRgbCapabilities,
		//supported rotations
		ERotateNone,
		//supports Arbitrary scaling
		EFalse,
		supportedScaleFactors.Array(),
		//supports antialiased scaling
		EFalse );

	CleanupStack::PushL( info );
	CleanupStack::Pop( &supportedScaleFactors );
	supportedScaleFactors.Close();
	CleanupStack::Pop( &supportedCombinations );
	supportedCombinations.Close();
	CleanupStack::Pop( &supportedFormats );
	supportedFormats.Close();

	PRINT_EXIT;
	return info;
	}

//---------------------------------------------------------------------------
//Retrieves the list of the output formats that the device supports.
//The list can depend on the device source format, and therefore
//SetSourceFormatL() must be called before calling this method.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetOutputFormatListL(
								RArray<TUncompressedVideoFormat>& aFormats )
	{
	PRINT_ENTRY;
    if ( iState->IsInitialized() )
    	{
    	PRINT_ERR( "iState is already initialised \n" );
        User::Leave( KErrNotReady );
    	}

    if ( !iInputFormat )
	    {
		//Input format should be set before calling this function, as output
        // format is decided based on input format
	    PRINT_ERR( "iInputFormat is not set yet \n" );
		User::Leave( KErrNotReady );
	    }

	TUncompressedVideoFormat format;
	format.iDataFormat = EYuvRawData;
	format.iYuvFormat.iYuv2RgbMatrix = NULL;
	format.iYuvFormat.iRgb2YuvMatrix = NULL;
	format.iYuvFormat.iAspectRatioNum = 1;
	format.iYuvFormat.iAspectRatioDenom = 1;

	aFormats.Reset();

    //The following formats are supported by both H.263 and Mpeg-4

	//YUV 420 Chroma0 Planar
	format.iYuvFormat.iCoefficients = EYuvBt601Range0;
	format.iYuvFormat.iPattern      = EYuv420Chroma1;
	format.iYuvFormat.iDataLayout   = EYuvDataPlanar;
	aFormats.Append( format );

    //YUV 422 Chroma LE Interleaved
    format.iYuvFormat.iPattern      = EYuv422Chroma1;
	format.iYuvFormat.iDataLayout   = EYuvDataInterleavedLE;
    aFormats.Append( format );

    //YUV 422 Chroma BE Interleaved
    format.iYuvFormat.iDataLayout   = EYuvDataInterleavedBE;
    aFormats.Append( format );

    //The following formats are only supported by Mpeg-4
    if ( iInputFormat->MimeType().FindF( KMPEG4SupportedMimeType ) !=
															   KErrNotFound )
        {
        //BT 601.5 Full Range
        // YUV 420 Chroma0 Planar
        format.iYuvFormat.iCoefficients = EYuvBt601Range1;
	    format.iYuvFormat.iPattern      = EYuv420Chroma1;
	    format.iYuvFormat.iDataLayout   = EYuvDataPlanar;
        aFormats.Append( format );

        //YUV 422 Chroma LE Interleaved
        format.iYuvFormat.iPattern      = EYuv422Chroma1;
	    format.iYuvFormat.iDataLayout   = EYuvDataInterleavedLE;
        aFormats.Append( format );

        //YUV 422 Chroma BE Interleaved
        format.iYuvFormat.iDataLayout   = EYuvDataInterleavedBE;
        aFormats.Append( format );

        //BT 709 Reduced Range
	    // YUV 420 Chroma0 Planar
	    format.iYuvFormat.iCoefficients = EYuvBt709Range0;
	    format.iYuvFormat.iPattern      = EYuv420Chroma1;
	    format.iYuvFormat.iDataLayout   = EYuvDataPlanar;
	    aFormats.Append( format );

        //YUV 422 Chroma LE Interleaved
        format.iYuvFormat.iPattern      = EYuv422Chroma1;
	    format.iYuvFormat.iDataLayout   = EYuvDataInterleavedLE;
        aFormats.Append( format );

        //YUV 422 Chroma BE Interleaved
        format.iYuvFormat.iDataLayout   = EYuvDataInterleavedBE;
        aFormats.Append( format );

        //BT 709 Full Range
        // YUV 420 Chroma0 Planar
	    format.iYuvFormat.iCoefficients = EYuvBt709Range1;
	    format.iYuvFormat.iPattern      = EYuv420Chroma1;
	    format.iYuvFormat.iDataLayout   = EYuvDataPlanar;
	    aFormats.Append( format );

        //YUV 422 Chroma LE Interleaved
        format.iYuvFormat.iPattern      = EYuv422Chroma1;
	    format.iYuvFormat.iDataLayout   = EYuvDataInterleavedLE;
        aFormats.Append( format );

        //YUV 422 Chroma BE Interleaved
        format.iYuvFormat.iDataLayout   = EYuvDataInterleavedBE;
        aFormats.Append( format );
	    }
    PRINT_EXIT;
    }

//---------------------------------------------------------------------------
// Sets the device output format.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetOutputFormatL(
									const TUncompressedVideoFormat &aFormat )
	{
	PRINT_ENTRY;
    if ( iState->IsInitialized() )
    	{
    	PRINT_ERR( "istate is already initialised \n" );
        User::Leave( KErrNotReady );
    	}

    if ( !iInputFormat )
	    {
		//Input format should be set before calling this function, as output
        // format is decided based on input format
	    PRINT_ERR( "iInputFormat is not set yet \n" );
		User::Leave( KErrNotReady );
	    }

	// check whether output format is supported or not.if not supported leave
	RArray<TUncompressedVideoFormat> formats;
	CleanupClosePushL( formats );
	GetOutputFormatListL( formats );

	TBool flag = EFalse;

	for ( TInt i = 0; i < formats.Count(); i++ )
		{
		if ( aFormat == formats[i] )
			{
			flag = ETrue;
			break;
			}
		}
	CleanupStack::Pop ( &formats );
    formats.Close();

	if ( !flag )
		{
		PRINT_ERR( "outputformat is not supported \n" );
        User::Leave( KErrNotSupported );
		}

    iOutputFormat = aFormat;
    PRINT_EXIT;
	}

//---------------------------------------------------------------------------
// Sets the clock source to use for video timing.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetClockSource( MMMFClockSource* /*aClock*/ )
	{
	PRINT_ENTRY;
    if ( iState->IsInitialized() )
    	{
    	PRINT_ERR( "iState is initialised,calling MdvppFatalError \n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
    	}

    PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
// Sets the device video output destination.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetVideoDestScreenL( TBool aScreen )
	{
	PRINT_ENTRY;
	if ( !iState->IsInitialized() )
		{
		if ( aScreen )
			{
			PRINT_ERR( "KErrNotSupported \n" );
			User::Leave( KErrNotSupported );
			}
		}
	else
		{
		PRINT_ERR( "KErrNotSupported \n" );
		User::Leave( KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
// Sets the post-processing types to be used.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetPostProcessTypesL(
										TUint32 /*aPostProcCombination*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
// Sets post-processing options for input (pan-scan ) cropping.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetInputCropOptionsL( const TRect& /*aRect*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
// Sets post-processing options for YUV to RGB color space conversion
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetYuvToRgbOptionsL(
								    const TYuvToRgbOptions& /*aOptions*/,
									const TYuvFormat& /*aYuvFormat*/,
									TRgbFormat /*aRgbFormat*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
// Sets post-processing options for YUV to RGB color space conversion. Uses
//the device input and output formats.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetYuvToRgbOptionsL(
									const TYuvToRgbOptions& /*aOptions*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
// Sets post-processing options for rotation. SetPostProcessTypesL() must be
//called before this method is used.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetRotateOptionsL(
											TRotationType /*aRotationType*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Sets post-processing options for scaling. SetPostProcessTypesL() must be
//called before this method is used.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetScaleOptionsL( const TSize& /*aTargetSize*/,
											 TBool /*aAntiAliasFiltering*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Sets post-processing options for output cropping.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetOutputCropOptionsL( const TRect& /*aRect*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Sets post-processing plug-in specific options.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetPostProcSpecificOptionsL(
												const TDesC8& /*aOptions*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "KErrNotSupported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Initializes the device. This method is asynchronous, the device calls
//MdvppInitializeComplete() of MMFVideoPlayProxy after initialization has
//completed. After this method has successfully completed, further
//configuration changes are not possible except where separately noted.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Initialize()
	{
	PRINT_ENTRY;
    if ( !iState->IsTransitionValid( CStateMachine::EInitializeCommand ) )
		{
		PRINT_ERR( "state is not valid in statemachine \n" );
		iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, KErrNotReady );
        return;
		}

    TRAPD( err, iInputFreeBuffers	=
	  new ( ELeave ) TVideoInputBuffer[iBufferOptions.iMinNumInputBuffers] );
    if ( err )
        {
        iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
        PRINT_ERR( "creation of iInputFreeBuffers returned error\n" );
		return;
		}

	iPictureCounters.iPicturesDisplayed = 0;
	iPictureCounters.iPicturesSkipped = 0;
	iPictureCounters.iTotalPictures = 0;
	iPictureCounters.iPicturesDecoded = 0;

	iBitstreamCounters.iLostPackets = 0;
	iBitstreamCounters.iTotalPackets = 0;

	// if custom interface is supported then enable the interface
	if ( iCustomBufferHandle )
		{

		TRAP( err, iCustomBufferOptions =
		          new ( ELeave ) MMmfVideoBufferManagement::TBufferOptions );

		if ( err != KErrNone )
			{
			iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
			PRINT_ERR( "creation of iCustomBuffeOptions returned error \n" );
			return;
			}

		iCustomBufferOptions->iNumInputBuffers = KMaxOutputBuffers + 1;
		iCustomBufferOptions->iBufferSize = TSize( KMaxFrameWidth,
												   KMaxFrameHeight );

		iCustomBufferHandle->MmvbmSetObserver(
							( MMmfVideoBufferManagementObserver * )this );

		iCustomBufferHandle->MmvbmEnable( ETrue );

		TRAP( err,
		iCustomBufferHandle->MmvbmSetBufferOptionsL(
											       *iCustomBufferOptions ) );

		if ( err != KErrNone )
			{
			PRINT_ERR( "iCustomBufferHandle->MmvbmSetBufferOptionsL \n" );
			iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
			return;
			}
		}

	if ( !iConfigureDecoderCalled )
		{
        TRAP( err, iCodec = CAriMpeg4aspdecWrapper::NewL( this ) );
        if ( err != KErrNone )
            {
		    iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
		    PRINT_ERR( "CCodecInterface::NewL returned error \n" );
		    return;
            }
		}

	// Engine Creation
	TRAP( err, iEngine = CBaseEngine::NewL(
								     this, ( MBaseCodec* )iCodec, EFalse ) );
	if ( err != KErrNone )
		{
		iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
		PRINT_ERR( "CBaseEngine::NewL returned error \n" );
		return;
		}

	// set input & output formats to Codec
	if ( iConfigureDecoderCalled )
		{
		TRAP( err, iCodec->SetFormatsL(  iDataUnitType, iOutputFormat ) );
        if ( err != KErrNone )
            {
		    iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
		    PRINT_ERR( "iCodec->SetFormatsL returned error \n" );
		    return;
            }
		}

	err = iState->Transit( CStateMachine::EInitializeCommand );
	if ( err )
		{
		iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, err );
		PRINT_ERR( "state is not set to initialised \n" );
		return;
		}

	iMMFDevVideoPlayProxy->MdvppInitializeComplete( this, KErrNone );

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Commit all changes since the last CommitL(), Revert() or Initialize()
//to the hardware device. This only applies to methods which can be called
//both before AND after DevVideoPlay has been initialized.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::CommitL()
	{
	PRINT_ENTRY;
    if ( !( iState->IsInitialized() ) )
	    {
	    PRINT_ERR( "istate is not initialised yet \n" );
		User::Leave( KErrNotReady );
	    }
	PRINT_EXIT;
    return;
	}

//---------------------------------------------------------------------------
//Revert all changes since the last CommitL(), Revert() or Initialize() back
//to their previous settings. This only applies to methods which can be
//called both before AND after DevVideoPlay has been initialized..
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Revert()
	{
	PRINT_ENTRY;
    if ( !( iState->IsInitialized() ) )
	    {
	    PRINT_ERR( "istate is not initialised yet \n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	    }
    PRINT_EXIT;
    return;
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::StartDirectScreenAccessL(
										const TRect& /*aVideoRect*/,
										CFbsScreenDevice& /*aScreenDevice*/,
										const TRegion& /*aClipRegion*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "Not supported API \n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetScreenClipRegion( const TRegion& /*aRegion*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "Not supported API \n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetPauseOnClipFail( TBool /*aPause*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "Not supported API \n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::AbortDirectScreenAccess()
	{
	PRINT_ENTRY;
	PRINT_ERR( "Not supported API \n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
//Indicates whether playback is proceeding. This method can be used to check
//whether playback was paused or not in response to a new clipping region
//or DSA abort
//---------------------------------------------------------------------------
//
TBool CAriMpeg4aspdecHwDevice::IsPlaying()
	{
	PRINT_ENTRY;
	if ( !( iState->IsInitialized() ) )
		{
		 PRINT_ERR( "istate is not initialised yet \n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	return ( iState->IsStarted() );
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Redraw()
	{
	PRINT_ENTRY;
	PRINT_ERR( "Not supported API \n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
//Starts video playback, including decoding, post-processing, and rendering.
//Playback will proceed until it has been stopped or paused, or the end of
//the bitstream is reached.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Start()
	{
	PRINT_ENTRY;
    if ( iState->IsPlaying() )
		{
		PRINT_EXIT;
		PRINT_ERR( "already in playing state \n" );
		return;
		}
	if ( !iState->IsTransitionValid( CStateMachine::EStartCommand ) )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	iDecodingPosition = TTimeIntervalMicroSeconds( 0 );
	iEngine->Start();

	TInt error = iState->Transit( CStateMachine::EStartCommand );
	if ( error != KErrNone )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Stops video playback. No new pictures will be decoded, post-processed,
//or rendered.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Stop()
	{
	PRINT_ENTRY;
    if ( iState->IsStopped() )
        {
        PRINT_EXIT;
        PRINT_ERR( "already in stopped state \n" );
        return;
		}
	if ( !iState->IsTransitionValid( CStateMachine::EStopCommand ) )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	iPictureNumber = 0;
	// Stop & Reset the Engine
	iEngine->Stop();
	iEngine->Reset();
	iBufferAdded			= EFalse;
	iFilledBufferCounter	= 0;
	iInputEndCalled			= EFalse;
	iNoLastOut				= EFalse;
	iInputBufferConsumedCounter = 0;
	TInt error = iState->Transit( CStateMachine::EStopCommand );
	if ( error != KErrNone )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Pauses video playback, including decoding, post-processing, and rendering.
//No pictures will be decoded, post-processed, or rendered until playback has
//been resumed.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Pause()
	{
	PRINT_ENTRY;
    if ( iState->IsPaused() )
        {
        PRINT_EXIT;
        PRINT_ERR( "already in paused state \n" );
        return;
		}

	if ( !iState->IsTransitionValid( CStateMachine::EPauseCommand ) )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	//Stop the Engine
	iEngine->Stop();

	TInt error = iState->Transit( CStateMachine::EPauseCommand );
	if ( error != KErrNone )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Resumes video playback after a pause.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::Resume()
	{
	PRINT_ENTRY;
    if ( iState->IsPlaying() )
        {
        PRINT_EXIT;
        PRINT_ERR( "already in playing state \n" );
        return;
		}

	if ( !iState->IsTransitionValid( CStateMachine::EResumeCommand ) )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	// Start The Engine
	iEngine->Start();

	TInt error = iState->Transit( CStateMachine::EResumeCommand );
	if ( error != KErrNone )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Changes to a new decoding and playback position,used for randomly accessing
//(seeking)the input stream. The position change flushes all input and output
//buffers. Pre-decoder and post-decoder buffering are handled as if a new
//bitstream was being decoded. If the device still has buffered pictures that
//precede the new playback position, they will be discarded. If playback is
//synchronized to a clock source, the client is responsible for setting the
//clock source to the new position..
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetPosition(
						const TTimeIntervalMicroSeconds& aPlaybackPosition )
	{
	PRINT_ENTRY;
	//Start Decoding from new position
	if ( iState->IsInitialized() )
		{
		iEngine->Stop();
		iEngine->Reset();
        iDecodingPosition = aPlaybackPosition;
		iBufferAdded = EFalse;
		iEngine->Start();
		}
	else
		{
		PRINT_ERR( "istate is not initialised yet\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::FreezePicture(
							const TTimeIntervalMicroSeconds& /*aTimestamp*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API \n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
//Not Supported.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::ReleaseFreeze(
							const TTimeIntervalMicroSeconds& /*aTimestamp*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API \n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}

//---------------------------------------------------------------------------
//Returns the current playback position, i.e. the timestamp for the most
//recently displayed or virtually displayed picture. If the device output
//is written to another device, the most recent output picture is used
//---------------------------------------------------------------------------
//
TTimeIntervalMicroSeconds CAriMpeg4aspdecHwDevice::PlaybackPosition()
	{
	PRINT_ENTRY;
	// In Decoder case decoding position is same as playback position
	if ( !( iState->IsInitialized() ) )
		{
		PRINT_ERR( "iState is not initialised \n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	return iDecodingPosition;
	}

//---------------------------------------------------------------------------
//Returns the total amount of memory allocated for uncompressed pictures.
//---------------------------------------------------------------------------
//
TUint CAriMpeg4aspdecHwDevice::PictureBufferBytes()
	{
	PRINT_ENTRY;
	if ( !( iState->IsInitialized() ) )
		{
		PRINT_ERR( "iState is not initialised yet \n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}
	PRINT_EXIT;
	return( KMaxOutputBuffers * iOutputBufferSize );
	}

//---------------------------------------------------------------------------
//Reads various counters related to decoded pictures.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetPictureCounters(
							CMMFDevVideoPlay::TPictureCounters& aCounters )
	{
	PRINT_ENTRY;
    if ( !( iState->IsInitialized() ) )
    	{
		PRINT_ERR( "iState is not initialised yet\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
    	}

	aCounters = iPictureCounters;

	//Reset the counters to Zero
	iPictureCounters.iPicturesDisplayed = 0;
	iPictureCounters.iPicturesSkipped = 0;
	iPictureCounters.iTotalPictures = 0;
	iPictureCounters.iPicturesDecoded = 0;

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetComplexityLevel( TUint /*aLevel*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
TUint CAriMpeg4aspdecHwDevice::NumComplexityLevels()
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return 0;
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetComplexityLevelInfo( TUint /*aLevel*/,
						CMMFDevVideoPlay::TComplexityLevelInfo& /*aInfo*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Called by the Post Proc hwdevice when a picture is displayed on the screen.
//Returns a picture back to the device.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::ReturnPicture( TVideoPicture* aPicture )
	{
	PRINT_ENTRY;
    if ( !( iState->IsInitialized() ) )
    	{
    	PRINT_ERR( "iState is not initialised yet\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
    	}

    if ( iCustomBufferHandle )
		{
	    delete aPicture->iHeader ;
	    aPicture->iHeader = NULL ;
		}
	else
		{
		// add to engine if state is not stopped
		if ( iState->IsStopped() )
			{
			iOutputFreeBufferQueue.Append( aPicture );
			}
		else
			{
			iEngine->AddOutput( aPicture );
			}
        }
    PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
TBool CAriMpeg4aspdecHwDevice::GetSnapshotL( TPictureData& /*aPictureData*/,
								const TUncompressedVideoFormat& /*aFormat*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	return( KErrNone );
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetTimedSnapshotL( TPictureData* /*aPictureData*/,
				const TUncompressedVideoFormat& /*aFormat*/,
				const TTimeIntervalMicroSeconds& /*aPresentationTimestamp*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	PRINT_EXIT;
	//Should take it from Post Proc HwDevice
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetTimedSnapshotL( TPictureData* /*aPictureData*/,
								const TUncompressedVideoFormat& /*aFormat*/,
								const TPictureId& /*aPictureId*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	PRINT_EXIT;
	//Should take it from Post Proc HwDevice
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::CancelTimedSnapshot()
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotSupported );
	PRINT_EXIT;
	return;
	}


//---------------------------------------------------------------------------
//Not supported API.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetSupportedSnapshotFormatsL(
							RArray<TUncompressedVideoFormat>& /*aFormats*/ )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	PRINT_EXIT;
	User::Leave( KErrNotSupported );
	}

//---------------------------------------------------------------------------
//sets the Flag iInputEndCalled to ETrue
//Notifies the hardware device that the end of input data has been reached
//and no more input data will be written
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::InputEnd()
	{
	PRINT_ENTRY;
	if ( !( iState->IsTransitionValid( CStateMachine::EInputEndCommand ) ) )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	iInputEndCalled = ETrue;

	if ( ( iFilledBufferCounter - iInputBufferConsumedCounter ) == 1 )
		{
		GetLastFrame();
		Stop();
		iMMFDevVideoPlayProxy->MdvppStreamEnd();
		PRINT_EXIT;
        return;
		}

	TInt error = iState->Transit( CStateMachine::EInputEndCommand );

	if ( error != KErrNone )
		{
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
		}

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Notifies the Hw Device that input buffer is free
//---------------------------------------------------------------------------
//
TInt CAriMpeg4aspdecHwDevice::InputBufferConsumed ( TAny* aInp, TInt aError )
	{
	PRINT_ENTRY;

	if ( aInp )
		{
		 iInputFreeBufferQueue.Append( REINTERPRET_CAST( TVideoInputBuffer*,
														 aInp ) );

		 //call back to clinet
		 if ( ( aError != KErrCancel ) && ( !iInputEndCalled ) )
			iMMFDevVideoPlayProxy->MdvppNewBuffers();
		}
	if ( iInputEndCalled && iNoLastOut )
		{
		HandleInputEndInStopping();
		iMMFDevVideoPlayProxy->MdvppStreamEnd();
		}

	PRINT_EXIT;
	return ( KErrNone );
	}

//---------------------------------------------------------------------------
//Notifies the Hw Device that out buffer has decoded data
//---------------------------------------------------------------------------
//
TInt CAriMpeg4aspdecHwDevice::OutputBufferReady ( TAny* aOut, TInt aError )
	{
	PRINT_ENTRY;
    if ( aError == KErrNone )
        {
        iPictureNumber++;
        // call back information regarding slice and picture loss

        SliceAndPictureLoss();

        //Decoded Buffer is available
        TVideoPicture* videoPicture = REINTERPRET_CAST( TVideoPicture*,
														aOut );
        
        videoPicture->iHeader->iPictureNumber = iPictureNumber;
        
        iFilledBufferCounter--;

        iPictureCounters.iPicturesDecoded++;
        iPictureCounters.iPicturesDisplayed++;

        iDecodingPosition = videoPicture->iTimestamp;

		if ( !iOutputDevice )
			{
			iMMFDevVideoPlayProxy->MdvppNewPicture( videoPicture );

			if ( iInputEndCalled &&
				 ( ( iFilledBufferCounter - iInputBufferConsumedCounter )
					== 1 )
				)
				{
				GetLastFrame();
				Stop();
				PRINT_ERR( "calling streamend\n" );
				iMMFDevVideoPlayProxy->MdvppStreamEnd();
				}
			PRINT_EXIT;
			return( KErrNone );
			}
		else
			{
			TRAPD( error, iOutputDevice->WritePictureL( videoPicture ) );

			if ( error == KErrNone )
				{
				if ( iInputEndCalled &&
					 ( ( iFilledBufferCounter - iInputBufferConsumedCounter )
							 == 1 ) )
					{
					GetLastFrame();
					HandleInputEndInStopping();
					PRINT_ERR( "calling streamend\n" );
					iMMFDevVideoPlayProxy->MdvppStreamEnd();
					}
				}
	            else if ( error ) // KErrArgument, KErrNotReady
	               {
	                iPictureCounters.iPicturesDisplayed--;
	                // Currently not handled
	               }
            }
        }

    else if ( aError == KErrCancel )
		{
		 // Add buffers to output free buffer queue if cutombuffer is not set
		if ( !iCustomBufferHandle )
			{
			iOutputFreeBufferQueue.Append( REINTERPRET_CAST( TVideoPicture*,
																	aOut ) );
			}
		else
			{

			delete ( ( TVideoPicture* )aOut )->iHeader;
			( ( TVideoPicture* )aOut )->iHeader = NULL;

			// release the buffer
			iCustomBufferHandle->MmvbmReleaseBuffer( REINTERPRET_CAST(
												    TVideoPicture*, aOut ) );
			}

		}

    else // other errors
        {
        // currently not handled
        }

    PRINT_EXIT;
	return ( KErrNone );
	}

//---------------------------------------------------------------------------
//Notifies the hw devcie that Error has occured in PE
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::FatalErrorFromProcessEngine ( TInt aError )
	{
	PRINT_ENTRY;
	PRINT_ERR( "not supported API\n" );
	iMMFDevVideoPlayProxy->MdvppFatalError( this, aError );
	PRINT_EXIT;
	}
//---------------------------------------------------------------------------
//Callback to indicate the command has been processed
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::CommandProcessed ( TInt aCmd, TAny* aCmdData,
												TInt aError )
	{
	PRINT_ENTRY;
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Call back from output device, indicates buffers availability
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::MmvbmoNewBuffers()
	{
	PRINT_ENTRY;
	TVideoPicture* videoPicture = NULL;

	TRAPD( err, videoPicture = iCustomBufferHandle->MmvbmGetBufferL(
									iCustomBufferOptions->iBufferSize ) );

	if ( err != KErrNone )
		{
		PRINT_ERR( "iCustomBufferHandle->MmvbmGetBufferL returned error\n" );
		iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrArgument );
		}
	if (  videoPicture )
		{
		if ( videoPicture->iHeader )
			{
			delete videoPicture->iHeader;
			videoPicture->iHeader = NULL;
			}

        TRAPD(  err1, videoPicture->iHeader =
									   new ( ELeave ) TVideoPictureHeader ) ;

        if ( err1 != KErrNone )
        	{
        	iCustomBufferHandle->MmvbmReleaseBuffer( videoPicture ) ;
        	iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrArgument );
        	}
        else
        	{
		    iEngine->AddOutput( videoPicture );
        	}
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Callback from output device.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::MmvbmoReleaseBuffers()
	{
	PRINT_ENTRY;
	iEngine->Stop();
	iEngine->Reset();
	PRINT_EXIT;
	}



//---------------------------------------------------------------------------
//Call back from the codec wrapper when there is new config information.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::NewConfigFound()
	{
	PRINT_ENTRY;

    /* Reset the all the output buffers added to the ProcessEngine.
	 * Create them again if custom buffers are not used.
	 */
	while ( iEngine->NumOutputBuffers() )
		  OutputBufferReady ( iEngine->FetchOutputBuffer(), KErrCancel );

	iOutputBuffersCreated = EFalse;
	iBufferAdded          = EFalse;

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Call back from the codec wrapper when EInputConsumed for Not yet get I frame
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::EInputConsumed()
	{
	PRINT_ENTRY;

	iInputBufferConsumedCounter++;

	if ( iInputEndCalled && ( iFilledBufferCounter ==
							  ( iInputBufferConsumedCounter + 1 ) ) )
		{
		iNoLastOut = ETrue;
		}

	PRINT_EXIT;
	}
//---------------------------------------------------------------------------
//Set the proxy implementation to be used. Called just
//after the object is constructed
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SetProxy( MMMFDevVideoPlayProxy& aProxy )
	{
	PRINT_ENTRY;
	iMMFDevVideoPlayProxy = &aProxy;
	PRINT_EXIT;
	}


//---------------------------------------------------------------------------
//Default constructor of CAriMpeg4aspdecHwDevice
//---------------------------------------------------------------------------
//
CAriMpeg4aspdecHwDevice::CAriMpeg4aspdecHwDevice()
    :iInputFreeBuffers( NULL ),
     iOutputDevice( NULL ),
     iMMFDevVideoPlayProxy( NULL ),
	 iState( NULL ),
     iVideoPictureHeader( NULL ),
	 iDecodingPosition( TTimeIntervalMicroSeconds( 0 ) ),
     iInputFormat( NULL ),
     iCodec( NULL ),
     iEngine( NULL ),
     iInputEndCalled( EFalse ),
     iOutputFreeBuffer( NULL ),
     iFilledBufferCounter( 0 ),
     iDataUnitType( EDuCodedPicture ),
     iEncapsulation( EDuElementaryStream ),
     iOutputBufferSize( 0 ),
     iOutputBuffersCreated( EFalse ),
     iPictureNumber( 0 ),
     iNumberOfInputBuffersAllocated( 0 ),
	 iCustomBufferHandle( NULL ),
	 iCustomBufferOptions( NULL ),
	 iBufferAdded( EFalse ),
     iConfigureDecoderCalled( EFalse ),
	 iDecoderConfigured( EFalse ),
	 iInputBufferConsumedCounter( 0 ),
	 iNoLastOut( EFalse )
    {
    PRINT_ENTRY;
	iBufferOptions.iPreDecodeBufferSize 		= 0;
	iBufferOptions.iMaxPostDecodeBufferSize   	= 0;
	iBufferOptions.iPreDecoderBufferPeriod 		= 0;
	iBufferOptions.iPostDecoderBufferPeriod 	= 0;
	iBufferOptions.iMinNumInputBuffers 			= KMaxInputBuffers;
	iBufferOptions.iMaxInputBufferSize 			= KMaxInputBufferSize;


    // Initializing iOutputFormat with one of the combination supported by
    // Mpeg-4/H.263 hwdevice

	iOutputFormat.iDataFormat					= EYuvRawData;
    // For H.263 it is always Bt 601.5 reduced range
    // For Mpeg-4 input stream contains this information
	iOutputFormat.iYuvFormat.iCoefficients		= EYuvBt601Range0;
    // The input stream format ( H.263 & Mpeg-4 ) comes in Chroma1 format and
	//so output is also decoded into Chroma1 format
	iOutputFormat.iYuvFormat.iPattern			= EYuv420Chroma1;
	iOutputFormat.iYuvFormat.iDataLayout		= EYuvDataPlanar;
	iOutputFormat.iYuvFormat.iYuv2RgbMatrix		= NULL;
	iOutputFormat.iYuvFormat.iRgb2YuvMatrix		= NULL;
	iOutputFormat.iYuvFormat.iAspectRatioNum	= 1;
	iOutputFormat.iYuvFormat.iAspectRatioDenom	= 1;
	PRINT_EXIT;
    }


//---------------------------------------------------------------------------
//This is the 2nd phase constructor
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::ConstructL()
	{
	PRINT_ENTRY;
	iState = CStateMachine::NewL();
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Module to create output data
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::CreateOutputBuffersL()
	{
	PRINT_ENTRY;
	if ( iOutputFreeBuffer )
		{
		for ( TInt i = 0 ; i < KMaxOutputBuffers; i++ )
			{
			if ( ( iOutputFreeBuffer + i )->iHeader )
				{
				delete ( iOutputFreeBuffer + i )->iHeader;
				}
			if ( ( iOutputFreeBuffer + i )->iData.iRawData )
				{
				delete
				( TUint8* )( iOutputFreeBuffer + i )->iData.iRawData->Ptr();
				}
			if ( ( iOutputFreeBuffer + i )->iData.iRawData )
				{
				delete ( iOutputFreeBuffer + i )->iData.iRawData;
				}
			}
		delete [] iOutputFreeBuffer;
		}
	for ( TInt i = 0; i < iOutputFreeBufferQueue.Count(); i++ )
		{
		iOutputFreeBufferQueue.Remove( 0 );
		}
	// Create the output Buffer( s ) and buffers to engine
	iOutputFreeBuffer = new ( ELeave ) TVideoPicture[KMaxOutputBuffers];
	TInt i;
    for ( i = 0 ; i < KMaxOutputBuffers; i++ )
		{
        ( iOutputFreeBuffer + i )->iData.iRawData = NULL;
		( iOutputFreeBuffer + i )->iHeader = NULL;
        }

	for ( i = 0 ; i < KMaxOutputBuffers; i++ )
		{
		TUint8* ptr;
		TPtr8*  temp;

		ptr = new ( ELeave ) TUint8[iOutputBufferSize];
		CleanupStack::PushL( ptr );
		temp = new ( ELeave ) TPtr8( ptr, 0, iOutputBufferSize );
		CleanupStack::Pop( ptr );

		( iOutputFreeBuffer + i )->iData.iRawData = temp;
		( iOutputFreeBuffer + i )->iHeader =
									    new ( ELeave ) TVideoPictureHeader;

		//Add o/p buffer( s ) to the Queue
		iEngine->AddOutput( ( iOutputFreeBuffer + i ) );
		}
    iBufferAdded = ETrue;
    PRINT_EXIT;
	}


//---------------------------------------------------------------------------
//Gives callbacks to client regarding slice and picture loss
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::SliceAndPictureLoss()
	{
	PRINT_ENTRY;
	TUint firstMacroblock;
	TUint numMacroblocks;
	TPictureId pictureId;
	pictureId.iIdType = TPictureId::EPictureNumber;

	// call back to client regading picture loss
	if ( ( iCodec->GetPictureLossInfo() ) >= KMaxAllowPicLoss )
		{
	  	PRINT_MSG( LEVEL_LOW, ( "Mpeg4aspdecHwDevice::SliceAndPictureLoss, "
	  			"				calling callback regading picture loss" ) );
		iMMFDevVideoPlayProxy->MdvppPictureLoss();
		}

   	PRINT_MSG( LEVEL_LOW, ( "CAriMpeg4aspdecHwDevice::SliceAndPictureLoss, "
   			"				calling callback regarding slice loss" ) );
	 // call back to clinet regarding slice loss
	 iCodec->GetSliceLossInfo( firstMacroblock, numMacroblocks );

	if ( ( firstMacroblock != 0 ) || ( numMacroblocks != 0 ) )
	 	iMMFDevVideoPlayProxy->MdvppSliceLoss( firstMacroblock,
											   numMacroblocks,
											   pictureId );

	PRINT_EXIT;
	}


//---------------------------------------------------------------------------
//Creates one input Buffer
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::CreateInputBufferL( TUint aBufferSize,
											   TBool aReallocate )
	{
	PRINT_ENTRY;

	if ( !aReallocate )
		{
	   	PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 1++" ) );
		// Create the Buffer and add it to Queue
		TUint8* ptr = new ( ELeave ) TUint8[aBufferSize];
	   	PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 2++" ) );
		TInt* lastBufferFlag  = new ( ELeave ) TInt[sizeof( TInt )];
	   	PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 3++" ) );
		iInputFreeBuffers[iNumberOfInputBuffersAllocated].iData.Set( ptr,
													0,
													TInt( aBufferSize ) );
		iInputFreeBuffers[iNumberOfInputBuffersAllocated].iUser =
								   REINTERPRET_CAST( TAny*, lastBufferFlag );
		iInputFreeBufferQueue.Append(
				        iInputFreeBuffers + iNumberOfInputBuffersAllocated );
		iNumberOfInputBuffersAllocated++;
	   	PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 4++" ) );
		}

	else // input buffers are already created and do reallocation here
		{
		PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 5++" ) );
		TVideoInputBuffer* inBuffer = iInputFreeBufferQueue[0];
		// check the size of the current with the size
		//of the buffer present in i/p Q
		if ( aBufferSize > TUint( inBuffer->iData.MaxLength() ) )
			{
			PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 6++" ) );
			// delete the previous buffer
			delete [] ( TUint8* )inBuffer->iData.Ptr();
			PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 7++" ) );
			delete inBuffer->iUser;

			// reallocate the buffer
			TUint8* ptr = new ( ELeave ) TUint8[aBufferSize];
			PRINT_MSG( LEVEL_LOW, ( "CreateInputBufferL 8++" ) );
			//delete inBuffer->iUser;
			TInt* lastBufferFlag  = new ( ELeave ) TInt[sizeof( TInt )];
			inBuffer->iData.Set( ptr, 0, TInt( aBufferSize ) );
			inBuffer->iUser = REINTERPRET_CAST( TAny*, lastBufferFlag );
			}
		}

	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//When InputEnd is called while the hw device in Stopping State.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::HandleInputEndInStopping()
	{
	PRINT_ENTRY;
	if ( iState->IsInputEndPending() )
		{
		iPictureNumber = 0;
		// Stop & Reset the Engine
		iEngine->Stop();
		iBufferAdded			= EFalse;
		iFilledBufferCounter	= 0;
		iInputEndCalled			= EFalse;
		iInputBufferConsumedCounter = 0;
		iNoLastOut				= EFalse;
		TInt error = iState->Transit( CStateMachine::EStopCommand );
		if ( error != KErrNone )
			{
			iMMFDevVideoPlayProxy->MdvppFatalError( this, KErrNotReady );
			}
		}
	PRINT_EXIT;
	}

//---------------------------------------------------------------------------
//Gets the last frame of the sequence.
//---------------------------------------------------------------------------
//
void CAriMpeg4aspdecHwDevice::GetLastFrame()
	{
	PRINT_ENTRY;
	TInt err = KErrNone;

	if ( ( iEngine->NumOutputBuffers() ) > 0 )
		{
		TVideoPicture* lVideoPicture =
						( TVideoPicture* )( iEngine->FetchOutputBuffer() );
		err = iCodec->GetLastFrame( lVideoPicture );

		if ( err == KErrNone )
			{
			lVideoPicture->iHeader->iPictureNumber = iPictureNumber;

			iPictureCounters.iPicturesDecoded++;
			iPictureCounters.iPicturesDisplayed++;

			iDecodingPosition = lVideoPicture->iTimestamp;

			if ( !iOutputDevice )
				{
				iMMFDevVideoPlayProxy->MdvppNewPicture( lVideoPicture );
				}
			else
				{
				TRAPD( error,
					   iOutputDevice->WritePictureL( lVideoPicture ) );
				if ( error != KErrNone )
					{
					iPictureCounters.iPicturesDisplayed--;
					// Currently not handled
		           	}
				}
			}
		else
			{
			//Add the output buffer back to ProcessEngine
			iEngine->AddOutput( lVideoPicture );
			}
		}
	PRINT_EXIT;
	}

const TImplementationProxy ImplementationTable[] =
	{
    IMPLEMENTATION_PROXY_ENTRY( KUidMp4DecoderHwDeviceImplUid,
								CAriMpeg4aspdecHwDevice::NewL )
	};


EXPORT_C const TImplementationProxy* ImplementationGroupProxy(
														TInt& aTableCount )
	{
	PRINT_ENTRY;
	aTableCount =
			sizeof( ImplementationTable ) / sizeof( TImplementationProxy );
	PRINT_EXIT;
	return ImplementationTable;
	}