diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccavcpayloadformat/src/avcpayloadformatread.cpp --- /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 +#include +#include +#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(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( &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( aBuffer )->Data() ); + + iRecvHeader = aRtpHeader; + iBufferToReadExists = ETrue; + + // Get a reference to the data + TDes8& srcData = static_cast( 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