diff -r d9b6a8729acd -r dcbddbbaf8fd vtprotocolplugins/DisplaySink/src/CDisplaySink.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vtprotocolplugins/DisplaySink/src/CDisplaySink.cpp Wed Jun 23 18:14:26 2010 +0300 @@ -0,0 +1,1029 @@ +/* +* Copyright (c) 2006 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: Display Sink subsystem. +* +*/ + + +// INCLUDE FILES + +#include "CDisplaySink.h" +#include "CDisplaySinkDP.h" +#include "CDisplaySinkDSA.h" +#include "CDisplaySinkNGA.h" +#include +#include + +// CONSTANTS + +// MACROS + +#ifdef _DEBUG + #include + #define PRINT RDebug::Print + #define _IFDBG(a) a +#else + #define PRINT + #define _IFDBG(a) +#endif + +// ============================ MEMBER FUNCTIONS =============================== + +// ============================= CVtFrameQueue ================================= + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::CVtFrameQueue +// ----------------------------------------------------------------------------- +// +CVtFrameQueue::CVtFrameQueue() : CActive( EPriorityNormal ) + { + _IFDBG(PRINT( _L( "CVtFrameQueue::CVtFrameQueue<" ) )); + _IFDBG(PRINT( _L( "CVtFrameQueue::CVtFrameQueue>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::ThreadLogon +// ----------------------------------------------------------------------------- +// +TInt CVtFrameQueue::ThreadLogon() + { + _IFDBG(PRINT( _L( "CVtFrameQueue::ThreadLogon<" ) )); + if ( !IsAdded() ) + { + CActiveScheduler::Add( this ); + } + TInt result( iThread.Open( RThread().Id() ) ); + _IFDBG(PRINT( _L( "CVtFrameQueue::ThreadLogon %d >" ), result )); + return result; + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::SinkStoppedL +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::SinkStoppedL() + { + _IFDBG(PRINT( _L( "CVtFrameQueue::SinkStoppedL<" ) )); + DoReleaseBufferL( iBuffer ); + DoReleaseBufferL( iReleaseBuffer ); + _IFDBG(PRINT( _L( "CVtFrameQueue::SinkStoppedL>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::ThreadLogoff +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::ThreadLogoff() + { + _IFDBG(PRINT( _L( "CVtFrameQueue::ThreadLogoff<" ) )); + if ( IsAdded() ) + { + Deque(); + } + _IFDBG(PRINT( _L( "CVtFrameQueue::ThreadLogoff>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::Store +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::Store( MVTVideoSource& aSupplier, + CMMFDataBuffer* aBuffer, + TSize aFrameSize, + TPtr8& aPtr ) + { + _IFDBG(PRINT( _L( "CVtFrameQueue::Store<" ) )); + iSupplier = &aSupplier; + iBuffer = aBuffer; + iFrameSize = aFrameSize; + iPtr = &aPtr; + _IFDBG(PRINT( _L( "CVtFrameQueue::Store>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::IsStored +// ----------------------------------------------------------------------------- +// +TBool CVtFrameQueue::IsStored() const + { + _IFDBG(PRINT( _L( "CVtFrameQueue::IsStored<" ) )); + _IFDBG(PRINT( _L( "CVtFrameQueue::IsStored %d>" ), + ( iBuffer != NULL ) )); + return ( iBuffer != NULL ); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::Buffer +// ----------------------------------------------------------------------------- +// +TVtMMFDataBuffer CVtFrameQueue::Buffer() + { + _IFDBG(PRINT( _L( "CVtFrameQueue::Buffer<" ) )); + _IFDBG(PRINT( _L( "CVtFrameQueue::Buffer %d>" ), + reinterpret_cast< TUint >( iBuffer ) )); + return TVtMMFDataBuffer(iBuffer, iFrameSize, *iPtr); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::Release +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::Release() + { + _IFDBG(PRINT( _L( "CVtFrameQueue::Release<" ) )); + if ( !IsActive() && IsStored() ) + { + iReleaseBuffer = iBuffer; + iBuffer = NULL; + iStatus = KRequestPending; + TRequestStatus* pStatus = &iStatus; + SetActive(); + iThread.RequestComplete( pStatus, KErrNone ); + _IFDBG(PRINT( _L( "CVtFrameQueue::Release -done-" ) )); + } + _IFDBG(PRINT( _L( "CVtFrameQueue::Release>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::RunL +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::RunL() + { + _IFDBG(PRINT( _L( "CVtFrameQueue::RunL<" ) )); + DoReleaseBufferL( iReleaseBuffer ); + _IFDBG(PRINT( _L( "CVtFrameQueue::RunL>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::DoReleaseBufferL +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::DoReleaseBufferL( CMMFDataBuffer*& aBuffer ) + { + _IFDBG(PRINT( _L( "CVtFrameQueue::DoReleaseBufferL<" ) )); + if ( aBuffer && iSupplier ) + { + iSupplier->BufferEmptiedL( aBuffer ); + aBuffer = NULL; + } + _IFDBG(PRINT( _L( "CVtFrameQueue::DoReleaseBufferL>" ) )); + } + +// ----------------------------------------------------------------------------- +// CVtFrameQueue::DoCancel +// ----------------------------------------------------------------------------- +// +void CVtFrameQueue::DoCancel() + { + // nothing to do + } + +// ============================ CVtCallback ================================= + +// ----------------------------------------------------------------------------- +// CVtCallback::CVtCallback( MDisplaySinkObserver& aObserver ) +// ----------------------------------------------------------------------------- +// +CVtCallback::CVtCallback( MDisplaySinkObserver& aObserver ) +: CActive( EPriorityStandard ), iObserver( &aObserver ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::CVtCallback()<"), RThread().Id().operator TUint())); + CActiveScheduler::Add( this ); + iOwnThreadId = RThread().Id(); + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::CVtCallback()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CVtCallback::~CVtCallback() +// ----------------------------------------------------------------------------- +// +CVtCallback::~CVtCallback() + { + Cancel(); + } + +// ----------------------------------------------------------------------------- +// CVtCallback::VideoFrameSizeChangedL( const TSize& aFrom, const TSize& aTo ) +// ----------------------------------------------------------------------------- +// +void CVtCallback::VideoFrameSizeChangedL( const TSize& aFrom, const TSize& aTo ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::VideoFrameSizeChangedL()<"), RThread().Id().operator TUint())); + iCallBackType = EVideoFrameSizeChanged; + iFrom = aFrom; + iTo = aTo; + IssueCallbackL(); + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::VideoFrameSizeChangedL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CVtCallback::Result() const +// ----------------------------------------------------------------------------- +// +TInt CVtCallback::Result() const + { + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::Result()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::Result()>"), RThread().Id().operator TUint())); + return iResult; + } + +// ----------------------------------------------------------------------------- +// CVtCallback::Completed() const +// ----------------------------------------------------------------------------- +// +TBool CVtCallback::Completed() const + { + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::Completed()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::Completed()>"), RThread().Id().operator TUint())); + return iCompleted; + } + +// ----------------------------------------------------------------------------- +// CVtCallback::IssueCallbackL() +// ----------------------------------------------------------------------------- +// +void CVtCallback::IssueCallbackL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::IssueCallbackL()<"), RThread().Id().operator TUint())); + iCompleted = EFalse; + TRequestStatus* pStatus = &iStatus; + RThread thread; + if( thread.Id() == iOwnThreadId ) + { + SetActive(); + User::RequestComplete( pStatus, KErrNone ); + } + else + { + User::LeaveIfError( thread.Open( iOwnThreadId ) ); + SetActive(); + *pStatus = KRequestPending; + thread.RequestComplete( pStatus, KErrNone ); + thread.Close(); + } + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::IssueCallbackL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CVtCallback::RunL() +// ----------------------------------------------------------------------------- +// +void CVtCallback::RunL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::RunL()<"), RThread().Id().operator TUint())); + + iResult = KErrNone; + + switch( iCallBackType ) + { + case EVideoFrameSizeChanged: + iObserver->VideoFrameSizeChangedL( iFrom, iTo ); + break; + + default: + User::Leave( KErrArgument ); + } + + iCompleted = ETrue; + + _IFDBG(PRINT(_L("VideoSource[%d]: CVtCallback::RunL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CVtCallback::DoCancel() +// ----------------------------------------------------------------------------- +// +void CVtCallback::DoCancel() + { + // do nothing! + } + +// ----------------------------------------------------------------------------- +// CVtCallback::RunError( TInt aError ) +// ----------------------------------------------------------------------------- +// +TInt CVtCallback::RunError( TInt aError ) + { + iCompleted = ETrue; + iResult = aError; + return KErrNone; + } + +// ========================== TDisplaySinkParams =============================== + +// ----------------------------------------------------------------------------- +// TDisplaySinkParams::TDisplaySinkParams +// ----------------------------------------------------------------------------- +// +EXPORT_C TDisplaySinkParams::TDisplaySinkParams() : + iFrameRateLimit( EFrameRateLimitNone ) + { + } + + +// ============================ CDisplaySink =================================== + +// ----------------------------------------------------------------------------- +// CDisplaySink::~CDisplaySink +// ----------------------------------------------------------------------------- +// +CDisplaySink::~CDisplaySink() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::~CDisplaySink()<"), RThread().Id().operator TUint())); + delete iVideoFrameQueue; + iBitmapCS.Close(); + delete iVTSignaller; + iVTMimeTypes.Reset(); + iVTMimeTypes.Close(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::~CDisplaySink()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::ConstructL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::ConstructL( TDisplaySinkParams& aParams, + const TDesC8& aInitData ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ConstructL()<"), RThread().Id().operator TUint())); + iDSFlags = aParams.iFlags; + iYuv420PlanarDesc.Delete( 0, iYuv420PlanarDesc.Length() ); + iYuv420PlanarDesc.Append( KVtVideoMIMETypeYUV420 ); + User::LeaveIfError( iVTMimeTypes.Append( &iYuv420PlanarDesc ) ); + iVideoFrameQueue = new ( ELeave ) CVtFrameQueue(); + iVTSignaller = new ( ELeave ) CVtCallback( *aParams.iObserver ); + BitmapEntry( EFirstBitmap ).iIsFree = EFalse; + BitmapEntry( ESecondBitmap ).iIsFree = EFalse; + iThreadId = aParams.iThreadId; + iRequestStatusPtr = aParams.iRequestStatusPtr; + iFrameSize = QCIF; + SetFrameRateLimit( aParams.iFrameRateLimit ); + User::LeaveIfError( iBitmapCS.CreateLocal() ); + BaseConstructL( aParams, aInitData ); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ConstructL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::Destroy +// ----------------------------------------------------------------------------- +// +void CDisplaySink::Destroy() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::Destroy()<"), RThread().Id().operator TUint())); + delete this; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::Destroy()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SetBitmapAvailable( TBitmapNo aBitmapNo ) +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SetBitmapAvailable( TBitmapNo aBitmapNo ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetBitmapAvailable()<"), RThread().Id().operator TUint())); + iBitmapCS.Wait(); + BitmapEntry( aBitmapNo ).iIsFree = ETrue; + BaseSetBitmapAvailable( aBitmapNo ); + iBitmapCS.Signal(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetBitmapAvailable()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::Release +// ----------------------------------------------------------------------------- +// +void CDisplaySink::Release() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::Release()<"), RThread().Id().operator TUint())); + iBitmapCS.Wait(); + if( !iReleased ) + { + iReleased = ETrue; + if( iRequestStatusPtr != NULL && + (*iRequestStatusPtr) == KRequestPending ) + { + RThread thread; + TInt err = thread.Open( iThreadId ); + if( err == KErrNone ) + { + *iRequestStatusPtr = KRequestPending; + TRequestStatus* statusP = iRequestStatusPtr; + thread.RequestComplete( statusP, KErrCancel ); + thread.Close(); + } + } + } + iVideoFrameQueue->Release(); + iBitmapCS.Signal(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::Release()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::UpdateSinkParamsL( const TDisplaySinkParams& aParams, +// TBool& aUpdated ) +// ----------------------------------------------------------------------------- +// +void CDisplaySink::UpdateSinkParamsL( + const TDisplaySinkParams& aParams, TBool& aUpdated ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::UpdateSinkParamsL()<"), RThread().Id().operator TUint())); + // This modification was requested by the VT engine team + iReleased = EFalse; + // This modification was requested by the VT engine team + iBitmapCS.Wait(); + BaseUpdateSinkParamsL( aParams ); + aUpdated = EFalse; + iParamsUpdated = &aUpdated; + iDSFlags = aParams.iFlags; + BitmapEntry( EFirstBitmap ).iIsFree = EFalse; + BitmapEntry( ESecondBitmap ).iIsFree = EFalse; + iVideoFrameQueue->Release(); + iBitmapCS.Signal(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::UpdateSinkParamsL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::Pause() +// ----------------------------------------------------------------------------- +// +void CDisplaySink::Pause() + { + iBitmapCS.Wait(); + iPaused = ETrue; + iVideoFrameQueue->Release(); + iBitmapCS.Signal(); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::Resume() +// ----------------------------------------------------------------------------- +// +void CDisplaySink::Resume() + { + iBitmapCS.Wait(); + iPaused = EFalse; + iBitmapCS.Signal(); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::operator MVTVideoSink&() +// ----------------------------------------------------------------------------- +// +CDisplaySink::operator MVTVideoSink&() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::operator MVTVideoSink&()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::operator MVTVideoSink&()>"), RThread().Id().operator TUint())); + return *this; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::NextFrame +// ----------------------------------------------------------------------------- +// +void CDisplaySink::NextFrame() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::NextFrame()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::NextFrame()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::GetMultimediaTypesL() const +// ----------------------------------------------------------------------------- +// +const RArray& CDisplaySink::GetMultimediaTypesL() const + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::GetMultimediaTypeL()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::GetMultimediaTypeL()>"), RThread().Id().operator TUint())); + return iVTMimeTypes; + } + + + +// ----------------------------------------------------------------------------- +// CDisplaySink::SetFormatL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SetFormatL( const TDesC8& aFormat ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetFormatL()<"), RThread().Id().operator TUint())); + if ( aFormat != KVtVideoMIMETypeYUV420 ) + { + User::Leave( KErrNotSupported ); + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetFormatL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SetVideoFrameSizeL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SetVideoFrameSizeL( const TSize& aSize ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetVideoFrameSizeL()<"), RThread().Id().operator TUint())); + if ( iInitFlags & ESinkThreadLogonCalled ) + { + SinkThreadLogonL(); + } + if ( iInitFlags & EFbsSessionConnected ) + { + TSize size( aSize ); + BaseSetVideoFrameSizeL( aSize ); + iFrameSize = aSize; + } + else + { + User::Leave( KErrNotReady ); + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetVideoFrameSizeL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::GetVideoFrameSizeL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::GetVideoFrameSizeL( TSize& aSize ) const + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::GetVideoFrameSizeL()<"), RThread().Id().operator TUint())); + aSize = iFrameSize; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::GetVideoFrameSizeL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::EmptyBufferL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::EmptyBufferL( + TVtMMFDataBuffer aDataBuffer, + MVTVideoSource* aSupplier, + TMediaId /*aMediaId*/ ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL()<"), RThread().Id().operator TUint())); + if ( aDataBuffer.GetMMFBuffer() == NULL || aSupplier == NULL ) + { + User::Leave( KErrArgument ); + } + if ( iReleased ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL(): sink released, just return buffer"), RThread().Id().operator TUint())); + aSupplier->BufferEmptiedL( aDataBuffer.GetMMFBuffer() ); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL()>"), RThread().Id().operator TUint())); + return; + } + else if ( iInitFlags & ESinkThreadLogonCalled ) + { + TRAPD( result, SinkThreadLogonL() ); + if ( result != KErrNone ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL(): SinkThreadLogonL failed %d"), RThread().Id().operator TUint(), result)); + aSupplier->BufferEmptiedL( aDataBuffer.GetMMFBuffer() ); + User::Leave( result ); + } + } + if ( aDataBuffer.GetMMFBuffer()->Type() != KVTUidYUVFrameBuffer ) + { + User::Leave( KErrArgument ); + } + if ( iState != EPlaying ) + { + User::Leave( KErrNotReady ); + } + iBitmapCS.Wait(); + + CleanupSignalPushL( iBitmapCS ); + iBuffer = aDataBuffer.GetMMFBuffer(); + iSupplier = aSupplier; + if ( IsOkToSendFrame() ) + { + // Waiting for frame size update? + if ( iWaitingForUpdate ) + { + // Update completed? + if ( iVTSignaller->Completed() ) + { + // YES: If it failed then Leave + if ( iVTSignaller->Result() != KErrNone ) + { + iSupplier->BufferEmptiedL( iBuffer ); + User::Leave( iVTSignaller->Result() ); + } + } + else + { + // NO: Report buffer emptied and return + iSupplier->BufferEmptiedL( iBuffer ); + CleanupStack::PopAndDestroy(); // iBitmapCS.Signal(); + return; + } + } + + // Is param update pending? + if ( iParamsUpdated ) + { + // YES: set new params + BaseDoUpdateParamsL(); + *iParamsUpdated = ETrue; + iParamsUpdated = 0; + iWaitingForUpdate = EFalse; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL(): params update finished"), RThread().Id().operator TUint())); + } + + // Update YUV data descriptor size based on resolution info. + TSize size( aDataBuffer.GetFrameSize() ); + TInt length( ( size.iWidth * size.iHeight * 12 ) / 8 ); + aDataBuffer.Data().Set( const_cast( aDataBuffer.Data().Ptr() ), length, length ); + // Expected frame size same as received size? + if ( !BaseSizesMatch( size ) ) + { + if ( !iWaitingForUpdate ) + { + iVTSignaller->VideoFrameSizeChangedL( iExpectedFrameSize, + aDataBuffer.GetFrameSize() ); + BaseVideoFrameSizeChangedL( aDataBuffer.GetFrameSize() ); + iWaitingForUpdate = ETrue; + } + CleanupStack::PopAndDestroy(); // iBitmapCS.Signal(); + iSupplier->BufferEmptiedL( iBuffer ); + return; + } + // All validation done, now it is ok to do implementation specific + // empty buffer. + BaseEmptyBufferL( aDataBuffer ); + +// debugging +// debugging +// debugging + + //iFC.PrintStatus(); + +// debugging +// debugging +// debugging + + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL()>"), RThread().Id().operator TUint())); + // No CleanupStack::PopAndDestroy() here, because cleanup is done in + // BaseEmptyBufferL(). Reason behind this decission is that certain + // things have to be handled either before or after cleanup and thus + // single cleanup here is not enough. + return; + } + else + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL(): dropping frame %d < %d"), RThread().Id().operator TUint(), iMilliSecondsSinceLastFrame, iFrameRateInterval )); + iSupplier->BufferEmptiedL( iBuffer ); + } + CleanupStack::PopAndDestroy(); // iBitmapCS.Signal() + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::EmptyBufferL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::BufferFilledL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::BufferFilledL( CMMFBuffer* /*aBuffer*/ ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::BufferFilledL()<"), RThread().Id().operator TUint())); + User::Leave( KErrNotSupported ); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::BufferFilledL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::CanCreateSinkBuffer +// ----------------------------------------------------------------------------- +// +TBool CDisplaySink::CanCreateSinkBuffer() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::CanCreateSinkBuffer()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::CanCreateSinkBuffer()>"), RThread().Id().operator TUint())); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::CreateSinkBufferL +// ----------------------------------------------------------------------------- +// +CMMFBuffer* CDisplaySink::CreateSinkBufferL( + TMediaId /*aMediaId*/, + TBool& /*aReference*/ ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::CreateSinkBufferL()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::CreateSinkBufferL()>"), RThread().Id().operator TUint())); + return NULL; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkThreadLogon +// ----------------------------------------------------------------------------- +// +TInt CDisplaySink::SinkThreadLogon( MAsyncEventHandler& /*aEventHandler*/ ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogon()<"), RThread().Id().operator TUint())); + iInitFlags |= ESinkThreadLogonCalled; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogon()>"), RThread().Id().operator TUint())); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkThreadLogonL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SinkThreadLogonL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogonL()<"), RThread().Id().operator TUint())); + TInt result( FbsStartup() ); + if ( result == KErrNone ) + { + CleanupStack::PushL( TCleanupItem( &SinkThreadLogonCleanup, this ) ); + FbsConnectL(); + ThreadOpenL(); + User::LeaveIfError( iVideoFrameQueue->ThreadLogon() ); + BaseSinkThreadLogonL(); + iInitFlags &= ~ESinkThreadLogonCalled; + CleanupStack::Pop(); // TCleanupItem( &SinkThreadLogonCleanup, this ) + } + User::LeaveIfError( result ); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogonL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkThreadLogoff +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SinkThreadLogoff() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogoff()<"), RThread().Id().operator TUint())); + BaseSinkThreadLogoff(); + iVideoFrameQueue->ThreadLogoff(); + ThreadClose(); + FbsDisconnect(); + iInitFlags = 0; + iExpectedFrameSize = TSize(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogoff()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkPrimeL +// ----------------------------------------------------------------------------- +// +TInt CDisplaySink::SinkPrimeL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkPrimeL()<"), RThread().Id().operator TUint())); + if ( iState != EStopped ) + { + return KErrNone; + } + iState = EPrimed; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkPrimeL()>"), RThread().Id().operator TUint())); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkPlayL +// ----------------------------------------------------------------------------- +// +TInt CDisplaySink::SinkPlayL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkPlayL()<"), RThread().Id().operator TUint())); + if ( iState != EPrimed ) + { + User::Leave( KErrNotReady ); + } + ResetFrameRateLimitter(); + iState = EPlaying; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkPlayL()>"), RThread().Id().operator TUint())); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkPauseL +// ----------------------------------------------------------------------------- +// +TInt CDisplaySink::SinkPauseL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkPauseL()<"), RThread().Id().operator TUint())); + if ( iState != EPlaying ) + { + return KErrNone; + } + iState = EPrimed; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkPauseL()>"), RThread().Id().operator TUint())); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkStopL +// ----------------------------------------------------------------------------- +// +TInt CDisplaySink::SinkStopL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkStopL()<"), RThread().Id().operator TUint())); + if ( iState == EStopped ) + { + return KErrNone; + } + iBitmapCS.Wait(); + iVideoFrameQueue->SinkStoppedL(); + iBitmapCS.Signal(); + iState = EStopped; + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkStopL()>"), RThread().Id().operator TUint())); + return KErrNone; + } + + +// ----------------------------------------------------------------------------- +// CDisplaySink::CDisplaySink +// ----------------------------------------------------------------------------- +// +CDisplaySink::CDisplaySink() : MVTVideoSink( KNullUid ), + iSinkFourCC( 0 ), iState( EStopped ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::Ctor()<"), RThread().Id().operator TUint())); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::Ctor()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SetFrameRateLimit( +// TDisplaySinkParams::TFrameRateLimit aFrameRateLimit ) +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SetFrameRateLimit( + TDisplaySinkParams::TFrameRateLimit aFrameRateLimit ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetFrameRateLimit()<"), RThread().Id().operator TUint())); + iFrameRateInterval = TInt( aFrameRateLimit ); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SetFrameRateLimit()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::ResetFrameRateLimitter() +// ----------------------------------------------------------------------------- +// +void CDisplaySink::ResetFrameRateLimitter() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ResetFrameRateLimitter()<"), RThread().Id().operator TUint())); + iMilliSecondsSinceLastFrame = 0; + iLastFrameTime = Time::NullTTime(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ResetFrameRateLimitter()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::BufferFilledL +// ----------------------------------------------------------------------------- +// +TBool CDisplaySink::IsOkToSendFrame() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::IsOkToSendFrame()<"), RThread().Id().operator TUint())); + TBool isOkToSendFrame( EFalse ); + if( iPaused ) + { + // nothing to do here because okToSendFrame defaults to EFalse + } + else if( iFrameRateInterval == TDisplaySinkParams::EFrameRateLimitNone ) + { + // If no limitation is set -> send frame + isOkToSendFrame = ETrue; + } + else if( iLastFrameTime == Time::NullTTime() ) + { + // EmptyBufferL() is being called the first time after SinkPlayL() -> + // send frame + iLastFrameTime.HomeTime(); + isOkToSendFrame = ETrue; + } + else + { + // Check if enough time has passed since previous frame sent + TTime now; + now.HomeTime(); + TTimeIntervalMicroSeconds interval( + now.MicroSecondsFrom( iLastFrameTime ) ); + iMilliSecondsSinceLastFrame += I64INT( interval.Int64() ) / 1000; + iLastFrameTime = now; + if( iMilliSecondsSinceLastFrame >= iFrameRateInterval ) + { + // Enough time passed -> send frame + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::IsOkToSendFrame(): sending frame %d >= %d"), RThread().Id().operator TUint(), iMilliSecondsSinceLastFrame, iFrameRateInterval )); + isOkToSendFrame = ETrue; + while( iMilliSecondsSinceLastFrame >= iFrameRateInterval ) + { + iMilliSecondsSinceLastFrame -= iFrameRateInterval; + } + } + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::IsOkToSendFrame() %d>"), RThread().Id().operator TUint(), isOkToSendFrame)); + return isOkToSendFrame; + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::FbsConnectL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::FbsConnectL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::FbsConnectL()<"), RThread().Id().operator TUint())); + if ( !( iInitFlags & EFbsSessionConnected ) ) + { + User::LeaveIfError( RFbsSession::Connect() ); + iInitFlags |= EFbsSessionConnected; + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::FbsConnectL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::ThreadOpenL +// ----------------------------------------------------------------------------- +// +void CDisplaySink::ThreadOpenL() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ThreadOpenL()<"), RThread().Id().operator TUint())); + if ( !( iInitFlags & EThreadOpened ) ) + { + User::LeaveIfError( iThread.Open( iThreadId ) ); + iInitFlags |= EThreadOpened; + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ThreadOpenL()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::FbsDisconnect +// ----------------------------------------------------------------------------- +// +void CDisplaySink::FbsDisconnect() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::FbsDisconnect()<"), RThread().Id().operator TUint())); + if ( iInitFlags & EFbsSessionConnected ) + { + RFbsSession::Disconnect(); + iInitFlags &= ~EFbsSessionConnected; + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::FbsDisconnect()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::ThreadClose +// ----------------------------------------------------------------------------- +// +void CDisplaySink::ThreadClose() + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ThreadClose()<"), RThread().Id().operator TUint())); + if ( iInitFlags & EThreadOpened ) + { + iThread.Close(); + iInitFlags &= ~EThreadOpened; + } + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::ThreadClose()>"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CDisplaySink::SinkThreadLogonCleanup +// ----------------------------------------------------------------------------- +// +void CDisplaySink::SinkThreadLogonCleanup( TAny* aPtr ) + { + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogonCleanup()<"), RThread().Id().operator TUint())); + CDisplaySink* self = reinterpret_cast< CDisplaySink* >( aPtr ); + self->iVideoFrameQueue->ThreadLogoff(); + self->ThreadClose(); + self->FbsDisconnect(); + _IFDBG(PRINT(_L("VideoSource[%d]: CDisplaySink::SinkThreadLogonCleanup()>"), RThread().Id().operator TUint())); + } + +// ================= OTHER EXPORTED FUNCTIONS ============== + +// ----------------------------------------------------------------------------- +// CreateSinkL +// ----------------------------------------------------------------------------- +// +EXPORT_C MDisplaySink* CreateSinkL( TDisplaySinkParams& aParams, + const TDesC8& aInitData ) + { + MDisplaySink* sink = NULL; + if (aParams.iFlags & TDisplaySinkParams::EDisplaySinkNGA) + { + sink = CDisplaySinkNGA::NewL( aParams, aInitData ); + } + else if ( FeatureManager::FeatureSupported( KFeatureIdDisplayPost ) && + ( aParams.iFlags & TDisplaySinkParams::EDisplaySinkDP ) ) + { + sink = CDisplaySinkDP::NewL( aParams, aInitData ); + } + else + { + sink = CDisplaySinkDSA::NewL( aParams, aInitData ); + } + return sink; + } + +// End of File +