vtprotocolplugins/VideoSource/src/CVSDataSourceImp.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 23 Nov 2009 14:47:47 +0200
changeset 0 ed9695c8bcbe
permissions -rw-r--r--
Revision: 200948

/*
* 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:  Video Source subsystem.
*
*/


// INCLUDE FILES

#include <fbs.h>
#include <e32svr.h>
#include <badesca.h>
#include <mmfdatasourcesink.hrh>

#include "CVSMMFDataBuffer.h"
#include "CVSDataSourceImp.h"
#include "VSPanic.h"

// EXTERNAL FUNCTION PROTOTYPES

// MACROS

#ifdef _DEBUG
#    define __IF_DEBUG(t) {RDebug::t;}
#else
#    define __IF_DEBUG(t)
#endif

// LOCAL CONSTANTS AND MACROS

static const TInt KQcifWidth = 176;
static const TInt KQcifHeight = 144;

 // 4:2:0 planar and 32 bytes extra
 static const TInt KSourceBufferSize =
    ( KQcifWidth * KQcifHeight ) + ( ( KQcifWidth * KQcifHeight ) / 2 ) + 12;

// Granularity for video frame format array
static const TInt KNoOfSupportedFormats = 4;

// How many sequential FillBufferL calls is supported
static const TInt KNoOfSupportedBuffers = 2;

// ============================ MEMBER FUNCTIONS ===============================

// ============================ CVSProviderSwitchAO ============================

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::NewL
// -----------------------------------------------------------------------------
//
CVSProviderSwitchAO* CVSProviderSwitchAO::NewL(
    CVSDataSourceImp* aDataSourceImp )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::NewL() >>"), RThread().Id().operator TUint()));
    CVSProviderSwitchAO* self =
        new ( ELeave ) CVSProviderSwitchAO( aDataSourceImp );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop(); // self
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::NewL() <<"), RThread().Id().operator TUint()));
    return self;
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::ConstructL
// -----------------------------------------------------------------------------
//
void CVSProviderSwitchAO::ConstructL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::ConstructL() >>"), RThread().Id().operator TUint()));
    User::LeaveIfError( iSwitchCs.CreateLocal() );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::ConstructL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::CVSProviderSwitchAO
// -----------------------------------------------------------------------------
//
CVSProviderSwitchAO::CVSProviderSwitchAO( CVSDataSourceImp* aDataSourceImp )
: CActive( EPriorityStandard ), iDataSourceImp( aDataSourceImp )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::CVSProviderSwitchAO() >>"), RThread().Id().operator TUint()));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::CVSProviderSwitchAO() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::~CVSProviderSwitchAO
// -----------------------------------------------------------------------------
//
CVSProviderSwitchAO::~CVSProviderSwitchAO()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::~CVSProviderSwitchAO() >>"), RThread().Id().operator TUint()));
    iSwitchCs.Close();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::~CVSProviderSwitchAO() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::ThreadLogon
// -----------------------------------------------------------------------------
//
TInt CVSProviderSwitchAO::ThreadLogon( MAsyncEventHandler& aEventHandler )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::ThreadLogon() >>"), RThread().Id().operator TUint()));
    iEventHandler = &aEventHandler;
    RThread me;
    iThreadId = me.Id();
    CActiveScheduler::Add( this );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::ThreadLogon() <<"), RThread().Id().operator TUint()));
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::ThreadLogoff
// -----------------------------------------------------------------------------
//
void CVSProviderSwitchAO::ThreadLogoff()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::ThreadLogoff() >>"), RThread().Id().operator TUint()));
    if( RThread().Id().operator TUint() == iThreadId )
        {
        Deque();
        iThreadId = 0;
        iNewProvider = NULL;
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::ThreadLogoff() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::InitiateProviderSwitch
// -----------------------------------------------------------------------------
//
void CVSProviderSwitchAO::InitiateProviderSwitch(
    CVSDataProvider* aNewProvider )
    {
    iSwitchCs.Wait();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::InitiateProviderSwitch() >>"), RThread().Id().operator TUint()));
    iNewProvider = aNewProvider;
    iStatus = KRequestPending;
    SetActive();
    Signal( KErrNone );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::InitiateProviderSwitch() <<"), RThread().Id().operator TUint()));
    iSwitchCs.Signal();
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::RunL
// -----------------------------------------------------------------------------
//
void CVSProviderSwitchAO::RunL()
    {
    iSwitchCs.Wait();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::RunL() >>"), RThread().Id().operator TUint()));
    if( iStatus.Int() == KErrNone )
        {
        if ( iDataSourceImp->SwitchPending() )
            {
            Panic( EVSPanicSwitchAlreadyPending );
            }
        TRAPD(
            leaveCode,
            iDataSourceImp->DoProviderSwitchL( iNewProvider, *iEventHandler ) );
        if ( leaveCode != KErrNone )
            {
            iDataSourceImp->ProviderSwitchError( leaveCode );
            }
        }
    else
        {
        iNewProvider = NULL;
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::RunL() <<"), RThread().Id().operator TUint()));
    iSwitchCs.Signal();
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::DoCancel
// -----------------------------------------------------------------------------
//
void CVSProviderSwitchAO::DoCancel()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::DoCancel() >>"), RThread().Id().operator TUint()));
    // Nothing to do here. This AO is always signalled when it's activated.
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::DoCancel() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSProviderSwitchAO::Signal
// -----------------------------------------------------------------------------
//
void CVSProviderSwitchAO::Signal( TInt aError )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::Signal() >>"), RThread().Id().operator TUint()));
    if( IsActive() )
        {
        TRequestStatus* pStatus = &iStatus;
        RThread me;
        if( me.Id() == iThreadId )
            {
            User::RequestComplete( pStatus, aError );
            }
        else
            {
            if( me.Open( iThreadId ) == KErrNone )
                {
                *pStatus = KRequestPending;
                me.RequestComplete( pStatus, aError );
                me.Close();
                }
            else
                {
                Panic( EVSPanicThreadOpenFailure );
                }
            }
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSProviderSwitchAO::Signal() <<"), RThread().Id().operator TUint()));
    }

// ============================ CVSDataSourceObserverAO ========================

// -----------------------------------------------------------------------------
// CVSDataSourceObserverAO::CVSDataSourceObserverAO
// -----------------------------------------------------------------------------
//
CVSDataSourceObserverAO::CVSDataSourceObserverAO()
: CActive( EPriorityStandard )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::CVSDataSourceObserverAO() >>"), RThread().Id().operator TUint()));
    RThread me;
    iThreadId = me.Id();
    CActiveScheduler::Add( this );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::CVSDataSourceObserverAO() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceObserverAO::~CVSDataSourceObserverA
// -----------------------------------------------------------------------------
//
CVSDataSourceObserverAO::~CVSDataSourceObserverAO()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::~CVSDataSourceObserverAO() >>"), RThread().Id().operator TUint()));
    Cancel();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::~CVSDataSourceObserverAO() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceObserverAO::vsProviderSwitchDone
// -----------------------------------------------------------------------------
//
void CVSDataSourceObserverAO::vsProviderSwitchDone(
    MVSDataSourceObserver& aObserver,
    CVSDataProvider* aOldProvider )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::vsProviderSwitchDone() >>"), RThread().Id().operator TUint()));
    iObserver = &aObserver;
    iOldProvider = aOldProvider;
    iStatus = KRequestPending;
    SetActive();
    Signal( KErrNone );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::vsProviderSwitchDone() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceObserverAO::RunL
// -----------------------------------------------------------------------------
//
void CVSDataSourceObserverAO::RunL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::RunL() >>"), RThread().Id().operator TUint()));
    if( iStatus.Int() == KErrNone )
        {
        iObserver->vsProviderSwitchDone( iOldProvider );
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::RunL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceObserverAO::DoCancel
// -----------------------------------------------------------------------------
//
void CVSDataSourceObserverAO::DoCancel()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::DoCancel() >>"), RThread().Id().operator TUint()));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::DoCancel() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceObserverAO::Signal
// -----------------------------------------------------------------------------
//
void CVSDataSourceObserverAO::Signal( TInt aError )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::Signal() >>"), RThread().Id().operator TUint()));
    TRequestStatus* pStatus = &iStatus;
    RThread me;
    if( me.Id() == iThreadId )
        {
        User::RequestComplete( pStatus, aError );
        }
    else
        {
        if( me.Open( iThreadId ) == KErrNone )
            {
            *pStatus = KRequestPending;
            me.RequestComplete( pStatus, aError );
            me.Close();
            }
        else
            {
            Panic( EVSPanicThreadOpenFailure );
            }
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceObserverAO::Signal() <<"), RThread().Id().operator TUint()));
    }



// =============================== CVSDataSource ===============================

// -----------------------------------------------------------------------------
// CVSDataSource::NewSourceL
// -----------------------------------------------------------------------------
//
CVSDataSource* CVSDataSource::NewSourceL( MVSDataSourceObserver* aObserver )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSource::NewSourceL() >>"), RThread().Id().operator TUint()));
    if ( aObserver == NULL )
        {
        User::Leave( KErrArgument );
        }
    CVSDataSource* self = CVSDataSourceImp::NewSourceL();
    CleanupStack::PushL( self );
    self->ConstructL( aObserver );
    CleanupStack::Pop( self );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSource::NewSourceL() <<"), RThread().Id().operator TUint()));
    return self;
    }

// -----------------------------------------------------------------------------
// CVSDataSource::CVSDataSource
// -----------------------------------------------------------------------------
//
CVSDataSource::CVSDataSource() : MVTVideoSource( KNullUid )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSource::CVSDataSource() >>"), RThread().Id().operator TUint()));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSource::CVSDataSource() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSource::ConstructL
// -----------------------------------------------------------------------------
//
void CVSDataSource::ConstructL( MVSDataSourceObserver* aObserver )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSource::ConstructL() >>"), RThread().Id().operator TUint()));
    iObserver = aObserver;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSource::ConstructL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::NewSourceL
// -----------------------------------------------------------------------------
//
CVSDataSourceImp* CVSDataSourceImp::NewSourceL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::NewSourceL() >>"), RThread().Id().operator TUint()));
    CVSDataSourceImp* self = new (ELeave) CVSDataSourceImp;
    CleanupStack::PushL( self );
    self->ConstructSourceL( KNullDesC8 );
    CleanupStack::Pop( self );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::NewSourceL() <<"), RThread().Id().operator TUint()));
    return self;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SwitchDataProviderL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::SwitchDataProviderL(
    CVSDataProvider* aNewProvider )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SwitchDataProviderL() >>"), RThread().Id().operator TUint()));
    if ( aNewProvider == NULL )
        {
        __IF_DEBUG(Print(_L("SwitchDataProviderL(): NULL argument, leaving.")));
        User::Leave( KErrArgument );
        }
    // Is new provider same as old, then no need to change provider
    if ( aNewProvider == &DataProvider() )
        {
        __IF_DEBUG(Print(_L("SwitchDataProviderL(): New provider same as old: 0x%x"), aNewProvider));
        Observer().vsProviderSwitchDone( aNewProvider );
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SwitchDataProvider() <<"), RThread().Id().operator TUint()));
        return;
        }
    // If Protocol is in the currently initializing itself then complete this switch
    // request when Protocol ready (from SourcePlayL). No need to protect
    // iProtoInitOngoing test with CS.
    if ( iProtoInitOngoing )
        {
        __IF_DEBUG(Print(_L("PROTOCOL INIT ONGOING, PENDING SWITCH FOR A WHILE")));
        iProtoInitCS.Wait();
        iProviderSwitchRequestDuringProtoInit = ETrue;
        iNewProvider = aNewProvider;
        iProtoInitCS.Signal();
        return;
        }
    // Switch provider
    if ( iThreadLogonCalled )
        {
        iProviderSwitchAO->InitiateProviderSwitch( aNewProvider );
        }
    else
        {
        CVSDataProvider* oldProvider = SwitchProvider( aNewProvider );
        Observer().vsProviderSwitchDone( oldProvider );
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SwitchDataProviderL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::PauseSending
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::PauseSending()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::PauseSending() >>"), RThread().Id().operator TUint()));
    iPauseCs.Wait();
    iSendingPaused = ETrue;
    iPauseCs.Signal();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::PauseSending() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::ResumeSending
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::ResumeSending()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::ResumeSending() >>"), RThread().Id().operator TUint()));
    iPauseCs.Wait();
    iSendingPaused = EFalse;
    iPauseCs.Signal();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::ResumeSending() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::~CVSDataSourceImp
// -----------------------------------------------------------------------------
//
CVSDataSourceImp::~CVSDataSourceImp()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::~CVSDataSourceImp() >>"), RThread().Id().operator TUint()));
    delete iDataSourceObserverAO;
    delete iProviderSwitchAO;
    iProtoMimeTypes.Close();
    delete iSupportedVideoFormats;
    iSupportedVideoSizes.Close();
    iSupportedFrameRates.Close();
    // Assuming no need to use critical section here
    iFreeQueue.Close();
    iActiveQueue.Close();
    iAllocatedBuffers.ResetAndDestroy();
    iQueueCs.Close();
    iPauseCs.Close();
    iProtoInitCS.Close();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::~CVSDataSourceImp() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::FillBufferL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::FillBufferL(
    CMMFBuffer* aBuffer,
    MVTVideoSink* aConsumer,
    TMediaId aMediaId )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL() >>"), RThread().Id().operator TUint()));

    if ( aBuffer == NULL || aConsumer == NULL )
        {
        User::Leave( KErrArgument );
        }

    if ( aBuffer->Type() != KUidMmfDataBuffer )
        {
        User::Leave( KErrArgument );
        }

    DataProvider().SetFillBufferParams( aConsumer, aMediaId );

    iPauseCs.Wait();
    const TBool sendingPaused( iSendingPaused );
    iPauseCs.Signal();

    if( iSwitchOngoing )
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL(): Switch ongoing"), RThread().Id().operator TUint()));
        // queues are locked by us -> it's safe to modify queues without
        // locking
        User::LeaveIfError(
            FreeBufferNoWait( static_cast<CVSMMFDataBuffer*>( aBuffer ) ) );
        }
    else if( iSwitchPending )
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL(): Switch pending"), RThread().Id().operator TUint()));
        FreeBufferL( static_cast<CVSMMFDataBuffer*>( aBuffer ) );
        TRAPD(
            err,
            DoProviderSwitchL(
                iProviderSwitchAO->NewDataProvider(),
                iProviderSwitchAO->EventHandler() ) );
        if( err != KErrNone )
            {
            __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL(): Error in switch = %d"), RThread().Id().operator TUint(), err));
            // Not leaving from here (it was provider switch related error),
            // let VT take care of the rest
            ProviderSwitchError( err );
            }
        }
    else if( sendingPaused )
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL(): Sending Paused"), RThread().Id().operator TUint()));
        // queues are locked by us -> it's safe to modify queues without
        // locking
        User::LeaveIfError(
            FreeBufferNoWait( static_cast<CVSMMFDataBuffer*>( aBuffer ) ) );
        }
    else
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL(): No switch -> normal FillBufferL()"), RThread().Id().operator TUint()));
        FreeBufferL( static_cast<CVSMMFDataBuffer*>( aBuffer ) );
        DataProvider().FillBufferL( aBuffer, aConsumer, aMediaId );
        }

    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FillBufferL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::BufferEmptiedL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::BufferEmptiedL() >>"), RThread().Id().operator TUint()));
    User::Leave( KErrNotSupported );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::BufferEmptiedL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::CanCreateSourceBuffer
// -----------------------------------------------------------------------------
//
TBool CVSDataSourceImp::CanCreateSourceBuffer()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CanCreateSourceBuffer() >>"), RThread().Id().operator TUint()));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CanCreateSourceBuffer) <<"), RThread().Id().operator TUint()));
    return ETrue;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::CreateSourceBufferL
// -----------------------------------------------------------------------------
//
CMMFBuffer* CVSDataSourceImp::CreateSourceBufferL(
    TMediaId /*aMediaId*/,
    TBool &aReference )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CreateSourceBufferL() >>"), RThread().Id().operator TUint()));
    if ( iRequestedBufferCount >= KNoOfSupportedBuffers )
        {
        User::Leave( KErrOverflow );
        }
    aReference = ETrue;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CreateSourceBufferL(): Returning buffer: %d [0x%08x]"), RThread().Id().operator TUint(), iRequestedBufferCount + 1, iAllocatedBuffers[ iRequestedBufferCount ]));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CreateSourceBufferL() <<"), RThread().Id().operator TUint()));
    return iAllocatedBuffers[ iRequestedBufferCount++ ];
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::CreateSourceBufferL
// -----------------------------------------------------------------------------
//
CMMFBuffer* CVSDataSourceImp::CreateSourceBufferL(
    TMediaId /*aMediaId*/,
    CMMFBuffer& /*aSinkBuffer*/,
    TBool &aReference )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CreateSourceBufferL() >>"), RThread().Id().operator TUint()));
    if ( iRequestedBufferCount >= KNoOfSupportedBuffers )
        {
        User::Leave( KErrOverflow );
        }
    aReference = ETrue;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CreateSourceBufferL(): Returning buffer: %d [0x%08x]"), RThread().Id().operator TUint(), iRequestedBufferCount + 1, iAllocatedBuffers[ iRequestedBufferCount ]));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CreateSourceBufferL() <<"), RThread().Id().operator TUint()));
    return iAllocatedBuffers[ iRequestedBufferCount++ ];
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SourceThreadLogon
// -----------------------------------------------------------------------------
//
TInt CVSDataSourceImp::SourceThreadLogon( MAsyncEventHandler& aEventHandler )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourceThreadLogon() >>"), RThread().Id().operator TUint()));
    __ASSERT_DEBUG( (&DataProvider()) != NULL,
        Panic( EVSPanicProviderNotSet ) );
    TInt err( KErrNone );
    if( !iFbsStarted )
        {
        // Caller does not start the FBS server when compiled on proxy mode
        // so we have to take care of that by ourself.
        err = FbsStartup();
        if( err == KErrNone )
            {
            err = RFbsSession::Connect();
            if( err == KErrNone )
                {
                iFbsStarted = ETrue;
                }
            }
        }
    if( !iThreadLogonCalled && ( err == KErrNone ) )
        {
        err = DataProvider().SourceThreadLogon( aEventHandler );
        if (err != KErrNone)
            {
            return err;
            }
        iProviderSwitchAO->ThreadLogon( aEventHandler );
        iThreadLogonCalled = ETrue;
        iProtoInitOngoing = ETrue;
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourceThreadLogon() <<"), RThread().Id().operator TUint()));
    return err;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SourceThreadLogoff
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::SourceThreadLogoff()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourceThreadLogoff() >>"), RThread().Id().operator TUint()));

    iThreadLogonCalled = EFalse;

    if ( iProviderSwitchRequestDuringProtoInit )
        {
        __IF_DEBUG(Print(_L("PROTOCOL INIT FAILED, NOW COMPLETING THE SWITCH REQUEST WITH ERROR")));
        iProviderSwitchRequestDuringProtoInit = EFalse;
        ProviderSwitchError( KErrAbort );
        }

    if( &DataProvider() )
        {
        DataProvider().SourceThreadLogoff();
        }

    iSwitchOngoing = iSwitchPending = EFalse;

    iProtoInitOngoing = EFalse;

    // If provider switch ongoing complete it
    if ( iProviderSwitchAO->NewDataProvider() != NULL )
        {
        CVSDataProvider* oldProvider =
            SwitchProvider( iProviderSwitchAO->NewDataProvider() );
        Observer().vsProviderSwitchDone( oldProvider );
        }

    iProviderSwitchAO->ThreadLogoff();

    delete iFormat; iFormat = 0;

    iCallFlags = 0;

    // Clear iFreeQueue
    while( iFreeQueue.Count() )
        {
        iFreeQueue.Remove( 0 );
        }

    // Clear iActiveQueue
    while( iActiveQueue.Count() )
        {
        iActiveQueue.Remove( 0 );
        }

    // Set frame buffer to NULL for all buffers
    for( TInt i = 0; i < iRequestedBufferCount; i++ )
        {
        TInt err = KErrNone;
        // Does not leave when framebuffer is set to NULL
        // Both type of buffers needs to be nulled
        TRAP( err, iAllocatedBuffers[i]->SetFrameBufferL( ( MCameraBuffer* )NULL ));
		TRAP( err, iAllocatedBuffers[i]->SetFrameBufferL( ( MFrameBuffer* )NULL ));        }

    // All pre-created buffers are free again
    iRequestedBufferCount = 0;

    if( iFbsStarted )
        {
        RFbsSession::Disconnect();
        iFbsStarted = EFalse;
        }

    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourceThreadLogoff() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SourcePrimeL
// -----------------------------------------------------------------------------
//
TInt CVSDataSourceImp::SourcePrimeL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePrimeL() >>"), RThread().Id().operator TUint()));
    TRAPD( result, DataProvider().SourcePrimeL() );
    if( ( result == KErrNone ) || ( result == KRequestPending ) )
        {
        iDSState = CVSDataSourceImp::EPrimed;
        }
    else
        {
        User::Leave( result );
        }
    iProtoInitOngoing = EFalse;
    // If provider switch was requested when Proto was  initializing itself then
    // fill switch request now
    iProtoInitCS.Wait();
    if ( iProviderSwitchRequestDuringProtoInit )
        {
        __IF_DEBUG(Print(_L("PROTOCOL INIT READY, NOW COMPLETING THE SWITCH REQUEST")));
        iProviderSwitchRequestDuringProtoInit = EFalse;
        iProviderSwitchAO->InitiateProviderSwitch( iNewProvider );
        iNewProvider = NULL;
        }
    iProtoInitCS.Signal();
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePrimeL() <<"), RThread().Id().operator TUint()));
    return result;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SourcePlayL
// -----------------------------------------------------------------------------
//
TInt CVSDataSourceImp::SourcePlayL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePlayL() >>"), RThread().Id().operator TUint()));
    if( !iSwitchOngoing )
        {
        DataProvider().SourcePlayL();
        }
    else
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePlayL(): Switch ongoing -> updating state only, play will be called after switch"), RThread().Id().operator TUint()));
        }
    iDSState = CVSDataSourceImp::EPlaying;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePlayL() <<"), RThread().Id().operator TUint()));
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SourcePauseL
// -----------------------------------------------------------------------------
//
TInt CVSDataSourceImp::SourcePauseL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePauseL() >>"), RThread().Id().operator TUint()));
    if( !iSwitchOngoing )
        {
        DataProvider().SourcePauseL();
        }
    else
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePlayL(): Switch ongoing -> updating state only"), RThread().Id().operator TUint()));
        }
    iDSState = CVSDataSourceImp::EPrimed;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePauseL() <<"), RThread().Id().operator TUint()));
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SourceStopL
// -----------------------------------------------------------------------------
//
TInt CVSDataSourceImp::SourceStopL()
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourceStopL() >>"), RThread().Id().operator TUint()));
    if( !iSwitchOngoing )
        {
        DataProvider().SourceStopL();
        }
    else
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourcePlayL(): Switch ongoing -> updating state only"), RThread().Id().operator TUint()));
        }
    iDSState = CVSDataSourceImp::EStopped;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SourceStopL() <<"), RThread().Id().operator TUint()));
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::ConstructSourceL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::ConstructSourceL( const TDesC8& /*aInitData*/ )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::ConstructSourceL() >>"), RThread().Id().operator TUint()));
    iYuv420PlanarDesc.Zero();
    iYuv420PlanarDesc.Append( KVtVideoMIMETypeYUV420 );
    User::LeaveIfError( iProtoMimeTypes.Append( &iYuv420PlanarDesc ) );
    iProviderSwitchAO = CVSProviderSwitchAO::NewL( this );
    iDataSourceObserverAO = new (ELeave) CVSDataSourceObserverAO();
    iSupportedVideoFormats =
        new (ELeave) CDesC8ArrayFlat( KNoOfSupportedFormats );
    // Get formats supported by all providers
    CVSDataProvider::EnumerateVideoFrameFormatsL( iSupportedVideoFormats );
    // Get video frame sizes for specified format supported by all providers
    TInt i, j;
    i = j = 0;
    for ( i = 0; i < iSupportedVideoFormats->Count(); i++ )
        {
        TPtrC8 format = iSupportedVideoFormats->MdcaPoint( i );
        RArray<TSize> sizeArray;
        CleanupClosePushL( sizeArray );
        CVSDataProvider::EnumerateVideoFrameSizesL( sizeArray, format );
        for ( j = 0; j < sizeArray.Count(); j++ )
            {
            TVSFrameSize sizePerFormat;
            sizePerFormat.iFormat.Set( format );
            sizePerFormat.iSize = sizeArray[j];
            User::LeaveIfError( iSupportedVideoSizes.Append( sizePerFormat ) );
            }
        CleanupStack::PopAndDestroy(); // sizeArray
        }
    // Get video frame rates for specified frame format and size supported
    // by all providers
    for ( i = 0; i < iSupportedVideoSizes.Count(); i++ )
        {
        RArray<TReal32> rateArray;
        CleanupClosePushL( rateArray );
        CVSDataProvider::EnumerateVideoFrameRatesL(
            rateArray,
            iSupportedVideoSizes[i].iFormat,
            iSupportedVideoSizes[i].iSize );
        for ( j = 0; j < rateArray.Count(); j++ )
            {
            TVSFrameRate framePerSizeAndFormat;
            framePerSizeAndFormat.iFormat.Set(
                iSupportedVideoSizes[i].iFormat );
            framePerSizeAndFormat.iSize = iSupportedVideoSizes[i].iSize;
            framePerSizeAndFormat.iRate = rateArray[j];
            User::LeaveIfError( iSupportedFrameRates.Append(
                framePerSizeAndFormat ) );
            }
        CleanupStack::PopAndDestroy(); // rateArray
        }
    // Create queue criticalsection
    User::LeaveIfError( iQueueCs.CreateLocal() );
    // Create VTEng-Protocol guard
    User::LeaveIfError( iPauseCs.CreateLocal() );
    // Pre-create buffers
    for( i = 0; i < KNoOfSupportedBuffers; i++ )
        {
        User::LeaveIfError( iFreeQueue.Append( 0 ) );
        User::LeaveIfError( iActiveQueue.Append( 0 ) );
        CVSMMFDataBuffer* buffer = CVSMMFDataBuffer::NewL( KSourceBufferSize );
        CleanupStack::PushL( buffer );
        User::LeaveIfError( iAllocatedBuffers.Append( buffer ) );
        CleanupStack::Pop(); // buffer
        }
    for( i = 0; i < KNoOfSupportedBuffers; i++ )
        {
        iFreeQueue.Remove( 0 );
        iActiveQueue.Remove( 0 );
        }
    // Init critical sections
    User::LeaveIfError( iProtoInitCS.CreateLocal() );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::ConstructSourceL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::GetMultimediaTypesL
// -----------------------------------------------------------------------------
//
const RArray<TDesC8*>& CVSDataSourceImp::GetMultimediaTypesL() const
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetMultimediaTypeL() >>"), RThread().Id().operator TUint()));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetMultimediaTypeL() <<"), RThread().Id().operator TUint()));
    return iProtoMimeTypes;
    }


// -----------------------------------------------------------------------------
// CVSDataSourceImp::SetFormatL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::SetFormatL( const TDesC8& aFormat )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SetFormatL() >>"), RThread().Id().operator TUint()));
    if ( &DataProvider() == NULL )
        {
        User::Leave( KErrBadHandle );
        }
    TBool supported = EFalse;
    for ( TInt i = 0; i < iSupportedVideoFormats->Count(); i++ )
        {
        TPtrC8 format = iSupportedVideoFormats->MdcaPoint( i );
        if ( aFormat == format )
            {
            supported = ETrue;
            break;
            }
        }
    if ( !supported )
        {
        User::Leave( KErrNotSupported );
        }
    DataProvider().SetFormatL( aFormat );
    delete iFormat; iFormat = 0;
    iFormat = aFormat.AllocL();
    iCallFlags |= ESetFormatCalled;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SetFormatL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SetFrameRateL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::SetFrameRateL( TReal32 aFrameRate )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SetFrameRateL() >>"), RThread().Id().operator TUint()));
    if ( &DataProvider() == NULL )
        {
        User::Leave( KErrBadHandle );
        }
    TBool supported = EFalse;
    for ( TInt i = 0; i < iSupportedFrameRates.Count(); i++ )
        {
        TVSFrameRate rate = iSupportedFrameRates[i];
        if ( rate.iFormat == iFormat->Des() && rate.iSize == iSize)
            {
            if ( aFrameRate == rate.iRate )
                {
                supported = ETrue;
                break;
                }
            }
        }
    if ( !supported )
        {
        User::Leave( KErrNotSupported );
        }
    DataProvider().SetFrameRateL( aFrameRate );
    iFrameRate = aFrameRate;
    iCallFlags |= ESetFrameRateCalled;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SetFrameRateL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::SetVideoFrameSizeL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::SetVideoFrameSizeL( const TSize& aSize )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SetVideoFrameSizeL() >>"), RThread().Id().operator TUint()));
    if ( &DataProvider() == NULL )
        {
        User::Leave( KErrBadHandle );
        }
    TBool supported = EFalse;
    for ( TInt i = 0; i < iSupportedVideoSizes.Count(); i++ )
        {
        TVSFrameSize size = iSupportedVideoSizes[i];
        if ( size.iFormat == iFormat->Des() )
            {
            if ( aSize == size.iSize )
                {
                supported = ETrue;
                break;
                }
            }
        }
    if ( !supported )
        {
        User::Leave( KErrNotSupported );
        }
    DataProvider().SetVideoFrameSizeL( aSize );
    iSize = aSize;
    iCallFlags |= ESetSizeCalled;
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::SetVideoFrameSizeL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::GetVideoFrameSizeL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::GetVideoFrameSizeL( TSize& aSize ) const
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetVideoFrameSizeL() >>"), RThread().Id().operator TUint()));
    if ( &DataProvider() == NULL )
        {
        User::Leave( KErrBadHandle );
        }
    DataProvider().GetVideoFrameSizeL( aSize );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetVideoFrameSizeL() <<"), RThread().Id().operator TUint()));
    }


// -----------------------------------------------------------------------------
// CVSDataSourceImp::DoProviderSwitchL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::DoProviderSwitchL(
    CVSDataProvider* aNewProvider,
    MAsyncEventHandler& aEventHandler )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::DoProviderSwitchL() >>"), RThread().Id().operator TUint()));

    iQueueCs.Wait();

    // If there are entries in iActiveQueue wait until they are freed by Protocol
    if ( iActiveQueue.Count() > 0 )
        {
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::DoProviderSwitchL(): activequeue count > 0, <<"), RThread().Id().operator TUint()));
        iSwitchPending = ETrue;
        iQueueCs.Signal();
        return;
        }
    else
        {
        iSwitchPending = EFalse;
        }

    iSwitchOngoing = ETrue;

    /*
     * THE FOLLOWING CALLS USE CActiveSchedulerWait WHICH MEANS SOME OTHER
     * OBJECT MAY RUN IN BETWEEN THE FOLLOWING CALLS I.E. THESE CALLS ARE NOT
     * SYNCHRONOUS.
     */

    User::LeaveIfError( aNewProvider->SourceThreadLogon( aEventHandler ) );

    // Is format set by the Protocol
    if ( iCallFlags & ESetFormatCalled )
        {
        aNewProvider->SetFormatL( *iFormat );
        }
    // Is size set by the Protocol
    if ( iCallFlags & ESetSizeCalled )
        {
        aNewProvider->SetVideoFrameSizeL( iSize );
        }
    // Is framerate set by the Protocol
    if ( iCallFlags & ESetFrameRateCalled )
        {
        aNewProvider->SetFrameRateL( iFrameRate );
        }
    // Stop old provider
    if ( &DataProvider() != NULL )
        {
        switch( iDSState )
            {
        case EPlaying:
            DataProvider().SourcePauseL();
            DataProvider().SourceStopL();
            break;

        case EPrimed:
            DataProvider().SourceStopL();
            break;

        default:
            break;
            };
        DataProvider().SourceThreadLogoff();
        }

    // Set new provider state according to current state
    switch ( iDSState )
        {
        case EStopped:
            break;

        case EPrimed:
        case EPlaying:
            aNewProvider->PrimeL();

            // check if SourcePlayL() was called during prime
            if( iDSState == EPlaying )
                {
                aNewProvider->SourcePlayL();
                aNewProvider->SwitchFrom( DataProvider() );
                }
            // or SourceStopL()
            else if( iDSState == EStopped )
                {
                aNewProvider->SourceStopL();
                }
            break;
        }
    /*
     * THE FOLLOWING CALLS ARE SUPPOSED TO BE SYNCHRONOUS IN THAT THEY DO NOT
     * LET ACTIVE SCHEDULER RUN SOME OTHER OBJECT.
     */

    // Complete switch
    CVSDataProvider* oldProvider = SwitchProvider( aNewProvider );

    // Set consumer and media id
    DataProvider().SetFillBufferParams(
        oldProvider->Consumer(),
        oldProvider->MediaId() );

    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::DoProviderSwitchL(): iFreeQueue.Count() = %d, iActiveQueue.Count() = %d"), RThread().Id().operator TUint(), iFreeQueue.Count(), iActiveQueue.Count() ));

    // If old provider has pending FillBufferL() calls -> call FillBufferL()
    // for new provider if it is in Playing state.
	if( iDSState == EPlaying )
		{
        for ( TInt i = 0; i < iFreeQueue.Count(); i++ )
            {
            iFreeQueue[ i ]->Reset();
            DataProvider().FillBufferL(
                iFreeQueue[i],
                DataProvider().Consumer(),
                DataProvider().MediaId() );
    		}
        }

    // Buffers that are being used by Protocol are set to be needing a reset
    for ( TInt i = 0; i < iActiveQueue.Count(); i++ )
        {
        iActiveQueue[ i ]->SetNeedsReset( ETrue );
        }

    iSwitchOngoing = EFalse;

    iQueueCs.Signal();

    iDataSourceObserverAO->vsProviderSwitchDone( Observer(), oldProvider );
    iProviderSwitchAO->NewDataProvider() = NULL;

    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::DoProviderSwitchL() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::CVSDataSourceImp
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::ProviderSwitchError( TInt aError )
    {
    DataProvider().NotifyError( aError );
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::CVSDataSourceImp
// -----------------------------------------------------------------------------
//
CVSDataSourceImp::CVSDataSourceImp()
: iFreeQueue( KNoOfSupportedBuffers ), iActiveQueue( KNoOfSupportedBuffers )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CVSDataSourceImp() >>"), RThread().Id().operator TUint()));
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::CVSDataSourceImp() <<"), RThread().Id().operator TUint()));
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::GetBufferL
// -----------------------------------------------------------------------------
//
CVSMMFDataBuffer* CVSDataSourceImp::GetBufferL( TBool aRemove )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetBufferL() >>"), RThread().Id().operator TUint()));
    if( !iQueueCs.IsBlocked() )
        {
        iPauseCs.Wait();
        const TBool sendingPaused( iSendingPaused );
        iPauseCs.Signal();

        iQueueCs.Wait();

        // while switch is pending, always return NULL we don't want to let
        // buffer float around
        if( iSwitchPending || sendingPaused )
            {
            iQueueCs.Signal();
            __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetBufferL(): Switch pending or sending paused -> returning NULL"), RThread().Id().operator TUint()));
            return 0;
            }

        // If no buffers in free (FillBufferL is called) queue -> return NULL
        if( !iFreeQueue.Count() )
            {
            iQueueCs.Signal();
            __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetBufferL(): NO free buffers -> returning NULL"), RThread().Id().operator TUint()));
            return 0;
            }
        // Otherwise get first buffer
        CVSMMFDataBuffer* temp = iFreeQueue[ 0 ];
        // Move to active (BufferFilledL is called) queue if requested
        if( aRemove )
            {
            iFreeQueue.Remove( 0 );
            TInt err = iActiveQueue.Append( temp );
            if ( err != KErrNone )
                {
                iQueueCs.Signal();
                User::Leave( err );
                }
            }
        iQueueCs.Signal();
        __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetBufferL() returning [$%x]"), RThread().Id().operator TUint(), temp));
        return temp;
        }
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::GetBufferL(): blocked, returning [$%08x]"), RThread().Id().operator TUint(), 0));
    return 0;
    }

// -----------------------------------------------------------------------------
// CVSDataSourceImp::FreeBufferL
// -----------------------------------------------------------------------------
//
void CVSDataSourceImp::FreeBufferL( CVSMMFDataBuffer* aBuffer )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FreeBufferL() >>"), RThread().Id().operator TUint()));
    iQueueCs.Wait();
    TInt err = FreeBufferNoWait( aBuffer );
    iQueueCs.Signal();
    User::LeaveIfError( err );
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FreeBufferL() <<"), RThread().Id().operator TUint()));
    }


// -----------------------------------------------------------------------------
// CVSDataSourceImp::FreeBufferNoWait( CVSMMFDataBuffer* aBuffer )
// -----------------------------------------------------------------------------
//
TInt CVSDataSourceImp::FreeBufferNoWait( CVSMMFDataBuffer* aBuffer )
    {
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FreeBufferNoWait() >>"), RThread().Id().operator TUint()));

    // Append buffer into free (FillBufferL is called) queue
    TInt err( KErrNone );

    // Try finding buffer from active (BufferFilledL is called) queue
    TInt actIdx = iActiveQueue.Find( aBuffer );

    // If it is found, remove it from there
    if( actIdx != KErrNotFound )
        {
        iActiveQueue.Remove( actIdx );
        TRAP( err, aBuffer->ReleaseL() );
        if( err != KErrNone )
            {
            return err;
            }
        }

    if( iFreeQueue.Find( aBuffer ) == KErrNotFound )
        {
        err = iFreeQueue.Append( aBuffer );
        }

#ifdef _DEBUG
    TBuf<256> b;
    TInt i;
    b = _L("Active: ");
    for( i = 0; i < iActiveQueue.Count(); i++ )
        {
        if( i > 0 )
            {
            b.Append( _L(", ") );
            }
        TBuf<16> b1;
        b1.Format( _L("[$%08x]"), iActiveQueue[i] );
        b.Append( b1 );
        }
    RDebug::Print( b );

    b = _L("Free  : ");
    for( i = 0; i < iFreeQueue.Count(); i++ )
        {
        if( i > 0 )
            {
            b.Append( _L(", ") );
            }
        TBuf<16> b1;
        b1.Format( _L("[$%08x]"), iFreeQueue[i] );
        b.Append( b1 );
        }
    RDebug::Print( b );
#endif
    __IF_DEBUG(Print(_L("VideoSource[%d]: CVSDataSourceImp::FreeBufferNoWait() <<"), RThread().Id().operator TUint()));

    return err;
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================

//  End of File