--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccavcpayloadformat/src/avcpayloadformatread.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,716 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: AVC Payload Format Read .. DePayloadizes incoming RTP packets
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <mmf/common/mmffourcc.h>
+#include <Sysutil.h>
+#include "MccRtpDataSource.h"
+#include "avcpayloadformatread.h"
+#include "avcrtpstruct.h"
+#include "MccInternalDef.h"
+
+_LIT8(AVCPSC, "\x0\x0\x0\x1");
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::CAvcPayloadFormatRead
+//
+// CAvcPayloadFormatRead default constructor, can NOT contain any code,
+// that might leave
+// Phase #1 of 2-phase constructor
+// -----------------------------------------------------------------------------
+//
+CAvcPayloadFormatRead::CAvcPayloadFormatRead ( ) :
+ iDecoder( NULL )
+ {
+ iFourCC.Set( TFourCC( 'H','2','6','4' ) );
+ iUsingJitterBufferExtension = ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::ConstructL
+//
+// Symbian 2nd phase constructor can leave.
+// Phase #2 of 2-phase constructor
+// Initializes the State machine and rest of the members.
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::ConstructL ( MDataSource* aSource )
+ {
+ iRtpDataSource = aSource;
+ iBufferToReadExists = EFalse;
+
+ iFourCC.Set( TFourCC( 'H','2','6','4' ) );
+
+ // Initialize decoding state machine
+ iStateMachine = CFormatDecodeStateMachine::NewL( this );
+ iStateMachine->ChangeState( EDecodeIdle );
+
+ iPayloadBuffer = CMMFDataBuffer::NewL(KAvcMaxRxPacketSize);
+ iFrameBuffer = CMMFDataBuffer::NewL(KAvcMaxRxPacketSize + sizeof(TRTPInfo));
+
+ iCounter = 0;
+ iCurDataSource = aSource;
+ iUsingJitterBufferExtension = ETrue;
+ iNalSent = 0;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::NewL
+//
+// Two-phased constructor.
+// Static function for creating and constructing an instance of the AVC format.
+//
+// Returns: CAvcPayloadFormatRead* : pointer to created instance
+// -----------------------------------------------------------------------------
+//
+CAvcPayloadFormatRead* CAvcPayloadFormatRead::NewL ( MDataSource* aSource )
+ {
+
+ if ( NULL == aSource )
+ {
+ User::Leave ( KErrArgument );
+ }
+
+ if ( KRtpSourceUID != aSource->DataSourceType( ) )
+ {
+ User::Leave ( KErrNotSupported );
+ }
+
+ CAvcPayloadFormatRead* self = new ( ELeave ) CAvcPayloadFormatRead();
+ CleanupStack::PushL ( self );
+ self->ConstructL ( aSource );
+ CleanupStack::Pop ( );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::~CAvcPayloadFormatRead
+//
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CAvcPayloadFormatRead::~CAvcPayloadFormatRead ( )
+ {
+ // commented out CreateSourceBufferL now sets aReference to ETrue.
+ // datapath doesn't clean this buffer any longer.
+ if ( iFrameBuffer )
+ {
+ delete iFrameBuffer;
+ }
+ if ( iPayloadBuffer)
+ delete iPayloadBuffer;
+ if ( iStateMachine )
+ {
+ iStateMachine->Cancel( );
+ delete iStateMachine;
+ }
+
+ delete iDecoder;
+ iRtpDataSource = NULL;
+ iSink = NULL;
+ iCurDataSource = NULL;
+
+ iPayloadTypes.Close();
+ }
+
+// Virtual functions from CMMFFormatDecode
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::FrameTimeInterval
+//
+// Return the frame time interval for the given media
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CAvcPayloadFormatRead::FrameTimeInterval( TMediaId aMediaId ) const
+ {
+ if ( aMediaId.iMediaType == KUidMediaTypeVideo)
+ {
+ return TTimeIntervalMicroSeconds( 0 ); // return some correct value as required
+ }
+ else
+ {
+ return TTimeIntervalMicroSeconds( 0 );
+ }
+ }
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::Streams
+//
+// Return the frame time interval for the given media
+// -----------------------------------------------------------------------------
+//
+TUint CAvcPayloadFormatRead::Streams(TUid /*aMediaType*/) const
+ {
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::Duration
+//
+// Return the clip duration for the given media.
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CAvcPayloadFormatRead::Duration( TMediaId /*aMediaType*/ ) const
+ {
+ return TTimeIntervalMicroSeconds( 1000000000 );
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::Initialize
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::InitializeL( )
+ {
+
+ if(!iDecoder)
+ iDecoder = CRFC3984Decode::NewL();
+
+ }
+
+// The following functions are virtual function implementation from MDataSource
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::FillBufferL
+// Fill Buffer
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::FillBufferL( CMMFBuffer* aBuffer,
+ MDataSink* aConsumer,
+ TMediaId aMediaId )
+ {
+
+ if ( aMediaId.iMediaType != KUidMediaTypeVideo )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ if ( aBuffer->Type( ) != KUidMmfDataBuffer )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ iSink = aConsumer;
+ iMediaId = aMediaId;
+
+ iFillRequested = ETrue;
+
+
+ if(iNalSent < iNalCount)
+ {
+ CAvcRtpStruct * ptr = NULL;
+ TBufC8<4> buf(AVCPSC);
+
+ ptr = NULL;
+ // while((ptr = iDecoder->GetNalUnit(iNalSent++)) != NULL && iCounter < 2)
+ {
+ ptr = iDecoder->GetNalUnit(iNalSent++);
+ if(ptr)
+ {
+ iCounter++;
+ TDes8& dataDes = STATIC_CAST( CMMFDataBuffer*, iFrameBuffer )->Data( );
+ TPtr8 pDes = ptr->iDes->Des( );
+
+
+ if(iUsingJitterBufferExtension)
+ {
+ TRTPInfo info;
+ info.TS = (ptr->iTimeStamp*1000)/90;
+ info.SN = ptr->iSeqNo;
+ info.DON = ptr->iDon;
+ info.PT = ptr->iPacketType;
+ info.FUH = ptr->iFUHeader; // copying FU-Header
+ dataDes.Copy((TUint8*)&info, sizeof(TRTPInfo));
+ if(ptr->iPacketType != PACKET_FU_A && ptr->iPacketType != PACKET_FU_B)
+ dataDes.Append(AVCPSC);
+ dataDes.Append(pDes.Ptr( ), pDes.Length( ));
+ }
+ else
+ {
+ dataDes.Copy(pDes.Ptr( ), pDes.Length( ));
+ if(ptr->iPacketType != PACKET_FU_A && ptr->iPacketType != PACKET_FU_B)
+ dataDes.Insert(0, AVCPSC);//Add PSC to each packet
+ }
+
+
+ iFrameBuffer->SetTimeToPlay(TTimeIntervalMicroSeconds((ptr->iTimeStamp*1000)/90));//us
+ iFrameBuffer->SetFrameNumber(ptr->iSeqNo);
+
+ // sending first NAL unit to the jitter buffer
+ iSink->BufferFilledL(iFrameBuffer);
+ }
+ // else
+ // break;
+
+ if(iNalSent == iNalCount)
+ {
+ iNalSent++;
+ iDecoder->ClearBuffer();
+ iNalCount = 0;
+ iStateMachine->ChangeState( EWaitSourceData ); // No payload ask for it
+ }
+ }
+ iCounter = 0;
+ }
+
+
+
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::FillSourceBufferL
+//
+// Send fill buffer request to RTP Data Soure
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::FillSourceBufferL( )
+ {
+// iRtpDataSource->FillBufferL( iPayloadBuffer, this, iMediaId ); // RtpSourceSink doesn't really need the Media Id.
+ // RTP will fill buffer when it receives a packet
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourceThreadLogon
+//
+// Log in to the source thread
+// -----------------------------------------------------------------------------
+//
+TInt CAvcPayloadFormatRead::SourceThreadLogon( MAsyncEventHandler& aEventHandler )
+ {
+ static_cast<CMCCRtpDataSource*>(iRtpDataSource)->SetPayloadSize( 1500 );
+
+ iCurDataSource->SourceThreadLogon( aEventHandler );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::NegotiateSourceL( MDataSink& aDataSink )
+//
+// Negotiate source settings to match data sink object.
+// Re-size frame buffers if needed
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::NegotiateSourceL( MDataSink& aDataSink )
+ {
+ iSink = static_cast<MDataSink*>( &aDataSink );//aDataSink;
+
+ iCurDataSource->NegotiateSourceL( *this );
+
+
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourceThreadLogoff
+//
+// Log out of the source thread.
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::SourceThreadLogoff( )
+ {
+ iCurDataSource->SourceThreadLogoff( );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::BufferFilledL
+//
+// Called after the data buffer is filled. Update the number of bytes read
+// and the current read position for the next read operation.
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::BufferFilledL( CMMFBuffer* aBuffer,
+ const TRtpRecvHeader& aRtpHeader )
+ {
+
+ User::LeaveIfNull( aBuffer );
+
+ if ( KUidMmfDataBuffer != aBuffer->Type() )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ //#ifdef TRACE_AVC_PAYLOAD_FORMAT_READ
+ // RDebug::Print ( _L ( "start CMMFAmrWbFormatRead::BufferFilledL" ) );
+ // RDebug::Print ( _L ( "M = %d, R = %d, CSI = %d, SIT = %d, PT = %d, SN = %d, CS = %d" ),
+ // aRtpHeader.iMarker, aRtpHeader.reserved, aRtpHeader.iChecksumInd,
+ // aRtpHeader.iSpeechItemToggle, aRtpHeader.iPayloadType,
+ // aRtpHeader.iSeqNum, aRtpHeader.iChecksum );
+ //#endif
+
+
+ // Copy received buffer
+ iPayloadBuffer->Data().Copy( static_cast<CMMFDataBuffer*>( aBuffer )->Data() );
+
+ iRecvHeader = aRtpHeader;
+ iBufferToReadExists = ETrue;
+
+ // Get a reference to the data
+ TDes8& srcData = static_cast<CMMFDataBuffer*>( iPayloadBuffer )->Data();
+
+
+
+ // Decode the payload
+ iNalCount = 0;
+ iDecoder->DePayloadizeFrameL(srcData, iRecvHeader.iTimestamp, iRecvHeader.iTimestamp, iRecvHeader.iSeqNum
+ , iRecvHeader.iMarker, iNalCount);
+
+
+ // Whenever BufferFilledL is called from RtpSourceSink
+ // Data has been depayloadized, now read the data and send it to the sink (DataPath)
+ iStateMachine->ChangeState( EEmptyDataToSink );
+ SendDataToSinkL(); // sending data to sink
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SendDataToSinkL
+//
+// Send full frame buffer to Data Path
+// -----------------------------------------------------------------------------
+//
+
+void CAvcPayloadFormatRead::SendDataToSinkL( )
+ {
+ TInt count = 0;
+ CAvcRtpStruct * ptr = NULL;
+ TBufC8<4> buf(AVCPSC);
+
+ #ifdef TRACE_AVC_PAYLOAD_FORMAT_READ
+ RDebug::Print ( _L ( "CAvcPayloadFormatRead::SendDataToSinkL( ) - START" ) );
+ #endif
+
+ iFillRequested = EFalse;
+
+
+ // We give data to jitter buffer through the iSink->BufferFilledL() function below. Now when the jitter
+ // buffer has handled the data, it calls back FillBufferL() and there we check if all the data is given
+ // and if so, delete the buffers. Otherwise give data back to it again.
+
+ iNalSent = 0; // starting from 0 and going to iNalCount (in FillBuffer)
+
+
+ ptr = NULL;
+ ptr = iDecoder->GetNalUnit(iNalSent++);
+ if(ptr)
+ {
+ TDes8& dataDes = STATIC_CAST( CMMFDataBuffer*, iFrameBuffer )->Data( );
+ TPtr8 pDes = ptr->iDes->Des( );
+
+
+ if(iUsingJitterBufferExtension)
+ {
+ TRTPInfo info;
+ info.TS = (ptr->iTimeStamp*1000)/90;
+ info.SN = ptr->iSeqNo;
+ info.DON = ptr->iDon;
+ info.PT = ptr->iPacketType;
+ info.FUH = ptr->iFUHeader; // copying FU-Header
+ dataDes.Copy((TUint8*)&info, sizeof(TRTPInfo));
+ if(ptr->iPacketType != PACKET_FU_A && ptr->iPacketType != PACKET_FU_B)
+ dataDes.Append(AVCPSC);
+ dataDes.Append(pDes.Ptr( ), pDes.Length( ));
+ }
+ else
+ {
+ dataDes.Copy(pDes.Ptr( ), pDes.Length( ));
+ if(ptr->iPacketType != PACKET_FU_A && ptr->iPacketType != PACKET_FU_B)
+ dataDes.Insert(0, AVCPSC);//Add PSC to each packet
+ }
+
+
+ iFrameBuffer->SetTimeToPlay(TTimeIntervalMicroSeconds((ptr->iTimeStamp*1000)/90));//us
+ iFrameBuffer->SetFrameNumber(ptr->iSeqNo);
+
+ // sending first NAL unit to the jitter buffer
+ iSink->BufferFilledL(iFrameBuffer);
+ }
+
+
+ // Clear buffers and then reset iNalCount
+ //iDecoder->ClearBuffer();
+ //iNalCount = 0;
+
+
+ #ifdef TRACE_AVC_PAYLOAD_FORMAT_READ
+ RDebug::Print ( _L ( "CAvcPayloadFormatRead::SendDataToSinkL( ) - DONE" ) );
+ #endif
+ }
+
+/*void CAvcPayloadFormatRead::SendDataToSinkL( )
+ {
+ TInt count = 0;
+ CAvcRtpStruct * ptr = NULL;
+ TBufC8<4> buf(AVCPSC);
+
+ #ifdef TRACE_AVC_PAYLOAD_FORMAT_READ
+ RDebug::Print ( _L ( "CAvcPayloadFormatRead::SendDataToSinkL( ) - START" ) );
+ #endif
+
+ iFillRequested = EFalse;
+
+
+ for(count = 0; count < iNalCount; count++)
+ {
+ ptr = NULL;
+ ptr = iDecoder->GetNalUnit(count);
+ if(ptr)
+ {
+ TDes8& dataDes = STATIC_CAST( CMMFDataBuffer*, iFrameBuffer )->Data( );
+ TPtr8 pDes = ptr->iDes->Des( );
+
+
+ if(iUsingJitterBufferExtension)
+ {
+ TRTPInfo info;
+ info.TS = (ptr->iTimeStamp*1000)/90;
+ info.SN = ptr->iSeqNo;
+ info.DON = ptr->iDon;
+ dataDes.Copy((TUint8*)&info, sizeof(TRTPInfo));
+ dataDes.Append(AVCPSC);
+ dataDes.Append(pDes.Ptr( ), pDes.Length( ));
+ }
+ else
+ {
+ dataDes.Copy(pDes.Ptr( ), pDes.Length( ));
+ dataDes.Insert(0, AVCPSC);//Add PSC to each packet
+ }
+
+
+ iFrameBuffer->SetTimeToPlay(TTimeIntervalMicroSeconds((ptr->iTimeStamp*1000)/90));//us
+ iFrameBuffer->SetFrameNumber(ptr->iSeqNo);
+
+ iSink->BufferFilledL(iFrameBuffer);
+ }
+
+ }
+
+
+
+ // Clear buffers and then reset iNalCount
+ iDecoder->ClearBuffer();
+ iNalCount = 0;
+
+
+ #ifdef TRACE_AVC_PAYLOAD_FORMAT_READ
+ RDebug::Print ( _L ( "CAvcPayloadFormatRead::SendDataToSinkL( ) - DONE" ) );
+ #endif
+ }
+
+*/
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourceDataTypeCode
+//
+// Return the source data type ( four CC code ) for the given media
+// -----------------------------------------------------------------------------
+//
+TFourCC CAvcPayloadFormatRead::SourceDataTypeCode( TMediaId aMediaId )
+ {
+ if ( aMediaId.iMediaType == KUidMediaTypeVideo )
+ {
+ return iFourCC;
+ }
+ else
+ {
+ return TFourCC( ); //defaults to 'NULL' fourCC
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SetSourceDataTypeCode
+//
+// Set the source data type to the given four CC code for the given media
+// -----------------------------------------------------------------------------
+//
+TInt CAvcPayloadFormatRead::SetSourceDataTypeCode( TFourCC aSourceFourCC,
+ TMediaId aMediaId )
+ {
+ if ( KUidMediaTypeVideo != aMediaId.iMediaType )
+ {
+ return KErrNotSupported;
+ }
+
+ iFourCC = aSourceFourCC;
+ iMediaId = aMediaId;
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::CreateSourceBufferL
+//
+// Create a source buffer for the given media and indicate in aReference if buffer
+// is created.
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CAvcPayloadFormatRead::CreateSourceBufferNowL( TMediaId aMediaId,
+ TBool &aReference )
+ {
+ if ( aMediaId.iMediaType != KUidMediaTypeVideo )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ // the source buffers belong to AmrPayloadFormatRead not to datapath
+ // aference should be set to ETrue and destried by AmrPayloadFormatRead itself.
+ aReference = ETrue;
+ return iFrameBuffer;
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::CreateSourceBufferL
+//
+// Create a source buffer for the given media, setting frame size to match
+// the given sink buffer
+// -----------------------------------------------------------------------------
+//
+CMMFBuffer* CAvcPayloadFormatRead::CreateSourceBufferL( TMediaId aMediaId,
+ //CMMFBuffer& /*aSinkBuffer*/,
+ TBool &aReference )
+ {
+ if ( aMediaId.iMediaType != KUidMediaTypeVideo )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ return CreateSourceBufferNowL( aMediaId, aReference );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SinkDataTypeCode()
+// Returns the datatype code for this Format Decoder
+// -----------------------------------------------------------------------------
+//
+TFourCC CAvcPayloadFormatRead::SinkDataTypeCode( TMediaId aMediaId )
+ {
+ if( KUidMediaTypeVideo == aMediaId.iMediaType )
+ {
+ return iFourCC;
+ }
+ else
+ {
+ return TFourCC();
+ }
+ };
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::CancelDlRequest( )
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::CancelDlRequest( )
+ {
+
+ iStateMachine->Cancel( );
+ iStateMachine->ChangeState( EDecodeIdle );
+
+
+ iBufferToReadExists = EFalse;
+ iFillRequested = EFalse;
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourcePrimeL( )
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::SourcePrimeL( )
+ {
+ iCurDataSource->SourcePrimeL();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourcePlayL( )
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::SourcePlayL( )
+ {
+ iCurDataSource->SourcePlayL();
+ }
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourcePauseL( )
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::SourcePauseL( )
+ {
+ iCurDataSource->SourcePauseL( );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SourceStopL( )
+//
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::SourceStopL( )
+ {
+ //CancelDlRequest( );
+
+
+ iCurDataSource->SourceStopL( );
+ }
+
+// ---------------------------------------------------------------------------
+// CAvcPayloadFormatRead::SetPayloadType
+// Sets the payloadtype to be accepted.
+// -----------------------------------------------------------------------------
+//
+void CAvcPayloadFormatRead::SetPayloadType( TUint8 aPayloadType )
+ {
+ iPayloadTypes.Reset();
+ iPayloadTypes.Append( aPayloadType );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CAvcPayloadFormatRead::FillSinkBufferL
+// Fill the sink buffer, not needed, currently sendDataToSinkL fills the sink buffers before sending.
+// -----------------------------------------------------------------------------
+//
+
+void CAvcPayloadFormatRead::FillSinkBufferL( )
+{
+ TFourCC();
+}
+
+
+void CAvcPayloadFormatRead::UseRTPInfoExtension()
+{
+ iUsingJitterBufferExtension = EFalse;
+}
+
+// ---------------------------------------------------------------------------
+
+void CAvcPayloadFormatRead::ConfigurePayloadFormatL( const TDesC8& /*aConfigParams*/ )
+{
+ // Fill this function when integrating AVC decoder
+}
\ No newline at end of file