--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vtprotocolplugins/DisplaySink/src/CDisplaySink.cpp Mon Nov 23 14:47:47 2009 +0200
@@ -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 <mmffourcc.h>
+#include <featmgr.h>
+
+// CONSTANTS
+
+// MACROS
+
+#ifdef _DEBUG
+ #include <e32debug.h>
+ #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<TDesC8* >& 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<TUint8*>( 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
+