vtengines/videoteleng/Src/Media/CVtEngDrawNGA.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:53:04 +0200
branchRCL_3
changeset 8 07d1685f0cd4
parent 2 4a81900cd18b
child 16 4e9858fa9559
permissions -rw-r--r--
Revision: 201002 Kit: 201007

/*
* Copyright (c) 2004-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:  Class for NGA Drawer.
*
*/

// INCLUDE FILES

#include "CVtEngDrawNGA.h"
#include "CVtEngEventManager.h"
#include "VtEngPanic.h"
#include "MVtEngFrameObserver.h"
#include "CVtEngSettings.h"
#include "VtEngUtils.h"
#include <videotelephonyvariant.hrh>
#include <tdisplaysinkparamsnga.h>
#include <cvtlogger.h>
#include <graphics/surfaceconfiguration.h>

// Reversed enumeration for the bitmaps.
static const MDisplaySink::TBitmapNo KVtEngBitmapNoReversed[] =
        {
        MDisplaySink::ESecondBitmap,
        MDisplaySink::EFirstBitmap
        };

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVTSurfaceBuffer::TVTSurfaceBuffer
//
// -----------------------------------------------------------------------------
//
TVTSurfaceBuffer::TVTSurfaceBuffer( TUint8* aBuffer, TInt aSurfaceNo )
    : iBuffer( aBuffer ), iSurfaceBufferNo(aSurfaceNo)
    {
    __VTPRINTENTER( "RVD(NGA).TVTSurfaceBuffer.Ctor" )
    __VTPRINTEXIT( "RVD(NGA).TVTSurfaceBuffer.Ctor" )
    }
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVTSurfaceBuffer::Buffer
//
// -----------------------------------------------------------------------------
//
TUint8*& TVTSurfaceBuffer::Buffer()
    {
    return iBuffer;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVTSurfaceBuffer::SurfaceNo
//
// -----------------------------------------------------------------------------
//
TInt TVTSurfaceBuffer::SurfaceNo()
    {
    return iSurfaceBufferNo;
    }
        
void TVTSurfaceBuffer::Set( TUint8* aBuffer, TInt aSurfaceNo )
    {
    iBuffer = aBuffer;
    iSurfaceBufferNo = aSurfaceNo;
    }
    
void TVTSurfaceBuffer::UnSet()
    {
    iBuffer = NULL;
    iSurfaceBufferNo = KErrNotFound;
    }
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::NewL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
CVtEngDrawNGA* CVtEngDrawNGA::NewL(
    MDisplaySinkObserver* aObserver )
    {
    CVtEngDrawNGA* self = new ( ELeave ) CVtEngDrawNGA( aObserver );
    CleanupStack::PushL( self );
    self->ConstructL( );
    CleanupStack::Pop();
    return self;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::~CVtEngDrawNGA
// Destructor. Cannot leave.
// -----------------------------------------------------------------------------
//
CVtEngDrawNGA::~CVtEngDrawNGA()
    {
    __VTPRINTENTER( "RVD(NGA).~" )
    Cancel();   
    
    if(iSurfaceCreated)
        {
        
        if (iSurfaceManager)
            {
            iConfig.iRemoteWindow->RemoveBackgroundSurface(ETrue);
            iConfig.iWsSession->UnregisterSurface(0, iSurfaceId);
            iSurfaceChunk->Close();
            delete iSurfaceChunk;
            iSurfaceChunk = NULL;
            iSurfaceManager->CloseSurface(iSurfaceId);
            iSurfaceUpdateSession.CancelAllUpdateNotifications();
            iSurfaceUpdateSession.Close();
                       
             /* Close the surface manager handle */
            iSurfaceManager->Close();
           
            delete iSurfaceManager;
            iSurfaceManager = 0;
            }
           
        for ( TInt i = KVtEngMaxSurfaceBuffers-1; i >= 0 ; i-- )
            {
            if (iCallBackTable[i])
                {
                iCallBackTable[i]->Cancel();
                delete iCallBackTable[i];
                iCallBackTable[i] = NULL;
                }
            }
    
        iSurfaceBuffers[ 0 ].UnSet();
        iSurfaceBuffers[ 1 ].UnSet();
        iSurfaceBuffer0.UnSet();
        iSurfaceBuffer1.UnSet();
        }
    delete iBufferWaiter;   
    iWaitingBuffers.Reset();
    
    __VTPRINTEXIT( "RVD(NGA).~" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngDrawNGA
// C++ constructor. Cannot leave.
// -----------------------------------------------------------------------------
//
CVtEngDrawNGA::CVtEngDrawNGA( MDisplaySinkObserver* aObserver ) :
    CVtEngDraw( aObserver ),
    iSurfaceFormat( EUidPixelFormatYUV_420Planar )
    
    {
    iConfig.iRemoteWindow = NULL;
    iConfig.iWsSession = NULL;
    iSurfaceCreated = EFalse;
    iWaitingBuffers.Reset();
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseConstructL
// Base construction.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseConstructL( )
    {
    __VTPRINTENTER( "RVD(NGA).BaseConstructL" )
    DoBaseConstructL();
    __VTPRINTEXIT( "RVD(NGA).BaseConstructL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CreateSinkL
// Instantiates display sink.
// -----------------------------------------------------------------------------
//
MDisplaySink* CVtEngDrawNGA::CreateSinkL()
    {
    __VTPRINTENTER( "RVD(NGA).CreateSinkL" )
    TDisplaySinkParamsNGA params;
    GetSinkParams( params );
    MDisplaySink* sink = ::CreateSinkL( params, KNullDesC8 );
    if ( IsFlag( EBaseConstructCalled ) )
        {
        sink->Pause();
        SetFlag( ESinkParamUpdateRequired | ESinkResumeRequired );
        }    
    __VTPRINTEXITR( "RVD(NGA).CreateSinkL flags=%d", params.iFlags )
    return sink;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseRefreshL
// If using scaler, start the scaling otherwise draw a bitmap.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseRefreshL()
    {
    __VTPRINTENTER( "RVD(NGA).BaseRefreshL" )
    __VTPRINTEXIT( "RVD(NGA).BaseRefreshL" )
    }
   
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseRefreshBitmapsL
// Refreshes bitmaps sizes and display mode if needed.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseRefreshBitmapsL()
    {
    __VTPRINTENTER( "RVD(NGA).BaseRefreshBitmapsL" )
    BaseConstructL();
    CreateSurfaceL();
    // set the params for DS
    UpdateSinkParamsL();
    ClearFlag( EFirstFrameReceived );    
    __VTPRINTEXIT( "RVD(NGA).BaseRefreshBitmapsL" )
    }   
    
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseDoCancel
// DoCancel for derived class.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseDoCancel()
    {
    __VTPRINTENTER( "RVD(NGA).BaseDoCancel" )
    __VTPRINTEXIT( "RVD(NGA).BaseDoCancel" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseVerifyConfigL
// Checks current configuration against DSA implementation.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseVerifyConfigL()
    {
    __VTPRINTENTER( "RVD(NGA).BaseVerifyConfigL" )
    __VTPRINTEXIT( "RVD(NGA).BaseVerifyConfigL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseRestartL
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseRestartL()
    {
    __VTPRINTENTER( "RVD(NGA).BaseRestartL" )
    __VTPRINTEXIT( "RVD(NGA).BaseRestartL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseAbortNow
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseAbortNow()
    {
    __VTPRINTENTER( "RVD(NGA).BaseAbortNow" )
    __VTPRINTEXIT( "RVD(NGA).BaseAbortNow" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseStartDrawL
// Starts the drawing.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseStartDrawL()
    {
    __VTPRINTENTER( "RVD(NGA).BaseStartDrawL" )  
    if ( IsFlag( EBaseConstructCalled ) )
        {
        SetFlag( EBaseBaseStartDrawCalled );
        }
    else
        {
        DoBaseStartDrawL();
        }
    __VTPRINTEXIT( "RVD(NGA).BaseStartDrawL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseStopDraw
// Stop the drawing.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseStopDraw()
    {
    // Cancel the timer in any case.
    __VTPRINTENTER( "RVD(NGA).BaseStopDraw" )
    ClearFlag( EBaseBaseStartDrawCalled );
    iWatcher->Cancel();
    iBufferWaiter->Cancel();
    ClearFlag( ERemoteVideoDrawing | EStarted );
    for ( TInt i = KVtEngMaxSurfaceBuffers-1; i >= 0 ; i-- )
        {
        if (iCallBackTable[i])
            {
            iCallBackTable[i]->Cancel();
            }
        }
    Cancel();
    
    __VTPRINTEXIT( "RVD(NGA).BaseStopDraw" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseSetConfigL
// Sets new configuration.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseSetConfigL( const TVtEngRenderConfig& aConfig )
    {
    __VTPRINTENTER( "RVD(NGA).BaseSetConfigL" )
    Mem::FillZ( &iConfig, sizeof( TVtEngRenderConfigNGA ) );
    iConfig = aConfig;
    if ( IsFlag( EBaseConstructCalled ) )
        {
        SetFlag( EBaseSetConfigCalled );
        }
    else
        {
        ConfigUpdatedL();
        }
    __VTPRINTEXIT( "RVD(NGA).BaseSetConfigL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseSetUIForegroundL
// Sets UI foreground status.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseSetUIForegroundL( TBool aForeground )
    {
    __VTPRINTENTER( "RVD(NGA).BaseSetUIForegroundL" )
    __VTPRINTEXIT( "RVD(NGA).BaseSetUIForegroundL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseRequestLastFrame
// Request update last remote video frame through MVtEngFrameObserver::vtSetFrame
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseRequestLastFrame()
    {
    __VTPRINTENTER( "RVD(NGA).BaseRequestLastFrame" )
    __VTPRINTEXIT( "RVD(NGA).BaseRequestLastFrame" )    
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BaseVideoFrameSizeChangedL
// Called when incoming frame buffer size changes.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BaseVideoFrameSizeChangedL( const TSize& /*aTo*/ )
    {
    __VTPRINTENTER( "RVD(NGA).BaseVideoFrameSizeChangedL" )
    BaseConstructL();
    
    TInt err;
    
    iConfig.iRemoteWindow->RemoveBackgroundSurface(ETrue);
    iConfig.iWsSession->UnregisterSurface(0, iSurfaceId);
    
    iSurfaceChunk->Close();
    delete iSurfaceChunk;
    iSurfaceChunk = NULL;
    iSurfaceManager->CloseSurface(iSurfaceId);
    iSurfaceUpdateSession.CancelAllUpdateNotifications();
    iSurfaceUpdateSession.Close();
    
    /* Close the surface manager handle */
    iSurfaceManager->Close();
    delete iSurfaceManager;
    iSurfaceManager = 0;
    
    for ( TInt i = KVtEngMaxSurfaceBuffers-1; i >= 0 ; i-- )
        {
            if (iCallBackTable[i])
                {
                iCallBackTable[i]->Cancel();
                delete iCallBackTable[i];
                iCallBackTable[i] = NULL;
                }
        }
    iSurfaceBuffers[ 0 ].UnSet();
    iSurfaceBuffers[ 1 ].UnSet();
    iSurfaceBuffer0.UnSet();
    iSurfaceBuffer1.UnSet();
    iWaitingBuffers.Reset();
    
    err = iSurfaceUpdateSession.Connect();    
    User::LeaveIfError(err);
    
    iSurfaceManager = new RSurfaceManager();
    
    User::LeaveIfNull(iSurfaceManager); 
    err = iSurfaceManager->Open();
    User::LeaveIfError(err);
    
    RSurfaceManager::TSurfaceCreationAttributesBuf attributes;
    attributes().iPixelFormat           = iSurfaceFormat; 
    attributes().iSize                  = iSourceSize;
    attributes().iBuffers               = KVtEngMaxSurfaceBuffers;
    
    //attributes().iStride                = iSourceSize.iWidth*2;
    attributes().iStride                = iSourceSize.iWidth*3/2;
    
    attributes().iOffsetToFirstBuffer   = 0;
    attributes().iAlignment             = 4;
    attributes().iContiguous            = EFalse;
    attributes().iMappable              = ETrue;
    
    err = iSurfaceManager->CreateSurface(attributes, iSurfaceId);
    User::LeaveIfError(err);  
    
    // Map to chunk
    iSurfaceChunk = new RChunk();
    User::LeaveIfNull(iSurfaceChunk);    
    err = iSurfaceManager->MapSurface(iSurfaceId, *iSurfaceChunk);
    User::LeaveIfError(err);    
    
    // Get the info from the surfaceManager
    RSurfaceManager::TInfoBuf info;
    err = iSurfaceManager->SurfaceInfo(iSurfaceId, info);
    User::LeaveIfError(err);    
    
    TInt offset;
    iSurfaceManager->GetBufferOffset(iSurfaceId, 0, offset);
    iSurfaceBuffer0.Set(iSurfaceChunk->Base() + offset, 0 );
    iSurfaceManager->GetBufferOffset(iSurfaceId, 1, offset);
    iSurfaceBuffer1.Set(iSurfaceChunk->Base() + offset, 1 );
    
    iConfig.iWsSession->RegisterSurface(0, iSurfaceId);   
    iConfig.iRemoteWindow->SetBackgroundSurface(iSurfaceId);
    
    iCallBackTable[0] = new(ELeave) CActiveCallBack(
            TCallBack(SurfaceBuffer0Ready, this), 
            CActive::EPriorityStandard-1);
    CActiveScheduler::Add(iCallBackTable[0]);
    
    iCallBackTable[1] = new(ELeave) CActiveCallBack(
            TCallBack(SurfaceBuffer1Ready, this), 
            CActive::EPriorityStandard-1);
    CActiveScheduler::Add(iCallBackTable[1]);
    
    iSurfaceCreated = ETrue;    
    
    ClearFlag( EInitializePostingSurfaceCalled );   
    
    // set the params for DS
    UpdateSinkParamsL();
    ClearFlag( EFirstFrameReceived );  

    __VTPRINTEXIT( "RVD(NGA).BaseVideoFrameSizeChangedL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawDSA::Config
// Returns current configuration.
// -----------------------------------------------------------------------------
//
TVtEngRenderConfig& CVtEngDrawNGA::Config()
    {
    return iConfig;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::RunL
// CActive heir execution method.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::RunL()
    {
    __VTPRINTENTER( "RVD(NGA).RunL" )
    
    TInt bitmapNo( iStatus.Int() );

    if ( bitmapNo < KErrNone )
        {
        __VTPRINT( DEBUG_MEDIA, "RVD(NGA).RunL notify rvd problem" )
        CVtEngEventManager::NotifyEvent( KVtEngRemoteRenderingProblem );
        return;
        }

    TVtEngBuffer& buffer = iSurfaceBuffers[ bitmapNo ];
    
    if ( !iDSUpdated )
        {
        __VTPRINT( DEBUG_MEDIA, "RVD(NGA).RunL !Updated" )
        __VTPRINTEXIT( "RVD(NGA).RunL" )
        return;
        }
    else if ( buffer.SurfaceBuffer() == NULL )
        {
        __VTPRINT( DEBUG_MEDIA, "RVD(NGA).RunL signalled with NULL buffer" )
        TInt result( iBufferWaiter->FetchBuffer() );
        User::LeaveIfError( result );
        __VTPRINTEXIT( "RVD(NGA).RunL" )
        return;
        }
    
    // Image received, reset counter.
    iCheckpoint = KVtEngWatcherThreshold;

    __VTPRINT2( DEBUG_MEDIA, "RVD(NGA).RunL flags=%d", iFlags )
    TBool firstFrame( !IsFlag ( EFirstFrameReceived ) );
    SetFlag( EFirstFrameReceived );
    if ( firstFrame )
        {
        CVtEngEventManager::NotifyEvent( KVtEngRemoteVideoStarted );
        }

    TInt surfaceno = buffer.SurfaceBuffer()->SurfaceNo();
    __VTPRINT2( DEBUG_MEDIA, "RVD(NGA).RunL received buffer surface id %d", surfaceno )
    if ( iSubmitPending )
        {
        __VTPRINT( DEBUG_MEDIA, "RVD(NGA).RunL submit pending")
        iWaitingBuffers.AddLast(buffer);
        }
    else
        {
        iCallBackTable[surfaceno]->iStatus = KRequestPending;
        iCallBackTable[surfaceno]->SetActive();
        iSurfaceUpdateSession.NotifyWhenDisplayed(iCallBackTable[surfaceno]->iStatus, iTimeStamp);
        iSubmitPending = ETrue;
        iSurfaceUpdateSession.SubmitUpdate(0, iSurfaceId, surfaceno, NULL); 
        buffer.UnSet();
        }
    if ( iSurfaceBuffers[ KVtEngBitmapNoReversed[ bitmapNo ] ].IsSet() )
        {
        __VTPRINT2( DEBUG_MEDIA, "RVD(NGA).RunL reactivating for buffer %d",
            KVtEngBitmapNoReversed[ bitmapNo ] )
        Activate();
        DisplaySink().NextFrame();
        }    
    TInt result = iBufferWaiter->FetchBuffer();
    User::LeaveIfError( result );    
    
    __VTPRINTEXIT( "RVD(NGA).RunL" )
    }


// -----------------------------------------------------------------------------
// CVtEngDrawNGA::BufferReadyL
// BufferReadyL
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::BufferReadyL( TVTSurfaceBuffer* aBuffer )
    {
    __VTPRINTENTER( "RVD(NGA).BufferReadyL" )
    SetAvailableToSink( aBuffer );
    __VTPRINTEXIT( "RVD(NGA).BufferReadyL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::FetchError
// Buffer fetching error
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::FetchError( TInt )
    {
    __VTPRINTENTER( "RVD(NGA).FetchError" )
    CVtEngEventManager::NotifyEvent( KVtEngRemoteRenderingProblem );
    __VTPRINTEXIT( "RVD(NGA).FetchError" )
    }    
   
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::DoBaseConstructL
// Base construction implementation
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::DoBaseConstructL()
    {
    __VTPRINTENTER( "RVD(NGA).DoBaseConstructL" )
    delete iBufferWaiter;
    iBufferWaiter = NULL;

    iBufferWaiter =
        new ( ELeave ) CVtEngBufferWaiter( *this );
        
    for ( TInt i = MDisplaySink::EFirstBitmap;
          i < MDisplaySink::EFirstBitmap + KVtEngMaxSurfaceBuffers; i++ )
        {
        iSurfaceBuffers[ i ].UnSet();
        }     
    ClearFlag( EBaseConstructCalled );          
    __VTPRINTEXIT( "RVD(NGA).DoBaseConstructL" )
    }
          
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::UpdateSinkParamsL
// Updates sink params
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::UpdateSinkParamsL()
    {
    __VTPRINTENTER( "RVD(NGA).UpdateSinkParamsL" )
    if ( IsFlag( EBaseConstructCalled ) )
        {
        SetFlag( ESinkParamUpdateRequired );
        }
    else
        {
        DoUpdateSinkParamsL();
        }
    __VTPRINTEXIT( "RVD(NGA).UpdateSinkParamsL" )
    }

    
 // -----------------------------------------------------------------------------
// CVtEngDrawNGA::DoBaseStartDrawL
//
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::DoBaseStartDrawL()
    {
    __VTPRINTENTER( "RVD(NGA).DoBaseStartDrawL" )
    SetFlag( EReadyInternal );
    if ( !iWatcher->IsActive() )
       {
       iWatcher->Start( KVtEngWatcherTimeout, KVtEngWatcherTimeout,
             iCallback );
       }
    
    DoSurfaceBuffer0Ready();
    DoSurfaceBuffer1Ready();
    
    User::LeaveIfError( iBufferWaiter->FetchBuffer() );
    
        
    SetFlag( ERemoteVideoDrawing );             
    ClearFlag( EBaseBaseStartDrawCalled );
    __VTPRINTEXIT( "RVD(NGA).DoBaseStartDrawL" )
    }
                   
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::DoCreateSurfaceL
// Create surface implementation.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::DoCreateSurfaceL()
    {
    __VTPRINTENTER( "RVD(NGA).DoCreateSurfaceL" )  
    TInt err;
    
    if(iSurfaceCreated)
        {
                
        if (iSurfaceManager)
            {
            /* Change log for recreate surface objects
             * Surface staffs should NOT be recreated once created,
             * but unregister and register needs to be done since the 
             * bounding window change its position and size. At this
             * moment, reset the iWaitingBuffers and reset the callbacks
             * are recommended.
             */
            iConfig.iRemoteWindow->RemoveBackgroundSurface(ETrue);
            iConfig.iWsSession->UnregisterSurface(0, iSurfaceId);
            
            /* Comment out below code to prevent delete the surface objects 
             * at this current stage, code below should NOT be removed due to
             * potential future uses.
             */
            /*
            iSurfaceChunk->Close();
            delete iSurfaceChunk;
            iSurfaceChunk = NULL;
            iSurfaceManager->CloseSurface(iSurfaceId);
            iSurfaceUpdateSession.CancelAllUpdateNotifications();
            iSurfaceUpdateSession.Close();
            */
            
            /* Close the surface manager handle */
            /*
            iSurfaceManager->Close();
            delete iSurfaceManager;
            iSurfaceManager = 0;
            */
            }
        for ( TInt i = KVtEngMaxSurfaceBuffers-1; i >= 0 ; i-- )
            {
                if (iCallBackTable[i])
                    {
                    iCallBackTable[i]->Cancel();
                    delete iCallBackTable[i];
                    iCallBackTable[i] = NULL;
                    }
            }
        /* Comment out below code to prevent delete the surface buffers, 
         * otherwise the last buffer would not store the last frame. 
         * Code below should NOT be removed due to potential future uses.
         */
        /*
        iSurfaceBuffers[ 0 ].UnSet();
        iSurfaceBuffers[ 1 ].UnSet();
        iSurfaceBuffer0.UnSet();
        iSurfaceBuffer1.UnSet();
        */
        iWaitingBuffers.Reset();
        }
    /* Add else branch to escape the recreate of the surface objects, 
     * it could be changed in future.
     */
    else
        {
        err = iSurfaceUpdateSession.Connect();    
        User::LeaveIfError(err);
        
        iSurfaceManager = new RSurfaceManager();
        
        User::LeaveIfNull(iSurfaceManager); 
        err = iSurfaceManager->Open();
        User::LeaveIfError(err);
        
        RSurfaceManager::TSurfaceCreationAttributesBuf attributes;
        attributes().iPixelFormat           = iSurfaceFormat; 
        attributes().iSize                  = iSourceSize;
        attributes().iBuffers               = KVtEngMaxSurfaceBuffers;
        
        //attributes().iStride                = iSourceSize.iWidth*2;
        attributes().iStride                = iSourceSize.iWidth*3/2;
        
        attributes().iOffsetToFirstBuffer   = 0;
        attributes().iAlignment             = 4;
        attributes().iContiguous            = EFalse;
        attributes().iMappable              = ETrue;
        
        err = iSurfaceManager->CreateSurface(attributes, iSurfaceId);
        User::LeaveIfError(err);  
        
        // Map to chunk
        iSurfaceChunk = new RChunk();
        User::LeaveIfNull(iSurfaceChunk);    
        err = iSurfaceManager->MapSurface(iSurfaceId, *iSurfaceChunk);
        User::LeaveIfError(err);    
        
        // Get the info from the surfaceManager
        RSurfaceManager::TInfoBuf info;
        err = iSurfaceManager->SurfaceInfo(iSurfaceId, info);
        User::LeaveIfError(err);    
        
        TInt offset;
        iSurfaceManager->GetBufferOffset(iSurfaceId, 0, offset);
        iSurfaceBuffer0.Set(iSurfaceChunk->Base() + offset, 0 );
        iSurfaceManager->GetBufferOffset(iSurfaceId, 1, offset);
        iSurfaceBuffer1.Set(iSurfaceChunk->Base() + offset, 1 );
        }
    
    iConfig.iWsSession->RegisterSurface(0, iSurfaceId);   
    iConfig.iRemoteWindow->SetBackgroundSurface(iSurfaceId);
    
    iConfig.iRemoteWindow->BeginRedraw();
    iConfig.iRemoteWindow->EndRedraw();
    
    iCallBackTable[0] = new(ELeave) CActiveCallBack(
            TCallBack(SurfaceBuffer0Ready, this), 
            CActive::EPriorityStandard-1);
    CActiveScheduler::Add(iCallBackTable[0]);
    
    iCallBackTable[1] = new(ELeave) CActiveCallBack(
            TCallBack(SurfaceBuffer1Ready, this), 
            CActive::EPriorityStandard-1);
    CActiveScheduler::Add(iCallBackTable[1]);
    
    iSurfaceCreated = ETrue;    
    
    ClearFlag( EInitializePostingSurfaceCalled );
    __VTPRINTEXIT( "RVD(NGA).DoCreateSurfaceL" )
    }
    
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::DoUpdateSinkParamsL
// Updates sink params
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::DoUpdateSinkParamsL()
    {
    __VTPRINTENTER( "RVD(NGA).DoUpdateSinkParamsL" )
    TDisplaySinkParamsNGA params;
    GetSinkParams( params );
    DisplaySink().UpdateSinkParamsL( params, iDSUpdated );
    ClearFlag( ESinkParamUpdateRequired );
    if ( IsFlag( ESinkResumeRequired ) )
        {
        DisplaySink().Resume();
        ClearFlag( ESinkResumeRequired );
        }
    __VTPRINTEXIT( "RVD(DP).DoUpdateSinkParamsL" )
    }
      
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CreateSurfaceL
// Create surface.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::CreateSurfaceL()
    {
    __VTPRINTENTER( "RVD(NGA).CreateSurfaceL" )
    if ( IsFlag( EBaseConstructCalled ) )
        {
        SetFlag( EInitializePostingSurfaceCalled );
        }
    else
        {
        DoCreateSurfaceL();
        }
    __VTPRINTEXIT( "RVD(NGA).CreateSurfaceL" )
    }
           
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::GetSinkParams
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::GetSinkParams( TDisplaySinkParamsNGA& aSinkParams )
    { 
    __VTPRINTENTER( "RVD(NGA).GetSinkParams" )
    Mem::FillZ( &aSinkParams, sizeof( TDisplaySinkParamsNGA ) );
    aSinkParams.iThreadId = RThread().Id();
    aSinkParams.iRequestStatusPtr = &iStatus;
    aSinkParams.iObserver = iObserver;
    aSinkParams.iSurfaceBuffer1 = &iSurfaceBuffers[ 0 ].Buffer();
    aSinkParams.iSurfaceBuffer2 = &iSurfaceBuffers[ 1 ].Buffer();
    aSinkParams.iFrameSize = iSourceSize;
    aSinkParams.iSurfaceFormat = iSurfaceFormat;
    aSinkParams.iFlags = TDisplaySinkParams::EDisplaySinkNGA;
    __VTPRINTEXITR( "RVD(NGA).GetSinkParams flags=%d",
        (TInt) aSinkParams.iFlags )	  
    }
    
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::DisplaySink
// Returns reference to sink.
// -----------------------------------------------------------------------------
//
MDisplaySink& CVtEngDrawNGA::DisplaySink()
    {
    return *iDisplaySink;
    }
     
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::SetToSink
// Sets posting buffer  to sink.
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::SetAvailableToSink( TVTSurfaceBuffer* aBuffer )
    {
    __VTPRINTENTER( "RVD(NGA).SetAvailableToSink" )
    for ( TInt i = MDisplaySink::EFirstBitmap;
          i < MDisplaySink::EFirstBitmap + KVtEngMaxSurfaceBuffers; i++ )
        {
        if ( !iSurfaceBuffers[ i ].IsSet() )
            {
            iSurfaceBuffers[ i ].Set( aBuffer );
            Activate();
            DisplaySink().SetBitmapAvailable(
                static_cast< MDisplaySink::TBitmapNo >( i ) );
            break;
            }
        }
    __VTPRINTEXIT( "RVD(NGA).SetAvailableToSink" )
    }  

TInt CVtEngDrawNGA::SurfaceBuffer0Ready( TAny* aAny )
    {
    __VTPRINTENTER( "RVD(NGA).SurfaceBuffer0Ready" )
    __VTPRINTEXIT( "RVD(NGA).SurfaceBuffer0Ready" )
    return ((CVtEngDrawNGA*)aAny)->DoSurfaceBuffer0Ready();
    }

TBool CVtEngDrawNGA::DoSurfaceBuffer0Ready()
    {
    __VTPRINTENTER( "RVD(NGA).DoSurfaceBuffer0Ready" )
    if ( iSubmitPending )
        {
        iSubmitPending = EFalse;
        }
    if (!iWaitingBuffers.IsEmpty())
        {
        TVtEngBuffer* buffer = iWaitingBuffers.First();
        TInt surfaceno = buffer->SurfaceBuffer()->SurfaceNo();
        __VTPRINT2( DEBUG_MEDIA, "RVD(NGA).DoSurfaceBuffer0Ready, surface buffer %d is in waitingqueue", surfaceno )
        iCallBackTable[surfaceno]->iStatus = KRequestPending;
        iCallBackTable[surfaceno]->SetActive();
        iSurfaceUpdateSession.NotifyWhenDisplayed(iCallBackTable[surfaceno]->iStatus, iTimeStamp);
        iSubmitPending = ETrue;
        iSurfaceUpdateSession.SubmitUpdate(0, iSurfaceId, surfaceno, NULL); 
        iWaitingBuffers.Remove(*buffer);
        buffer->UnSet();
        }
    iBufferWaiter->BufferAvailable(iSurfaceBuffer0);
    __VTPRINTEXIT( "RVD(NGA).DoSurfaceBuffer0Ready" )
    return ETrue;
    }
        
TInt CVtEngDrawNGA::SurfaceBuffer1Ready( TAny* aAny )
    {
    __VTPRINTENTER( "RVD(NGA).SurfaceBuffer1Ready" )
    __VTPRINTEXIT( "RVD(NGA).SurfaceBuffer1Ready" )
    return ((CVtEngDrawNGA*)aAny)->DoSurfaceBuffer1Ready();
    }

TBool CVtEngDrawNGA::DoSurfaceBuffer1Ready()
    {
    __VTPRINTENTER( "RVD(NGA).DoSurfaceBuffer1Ready" )
    if ( iSubmitPending )
        {
        iSubmitPending = EFalse;
        }
    
    if (!iWaitingBuffers.IsEmpty())
        {
        TVtEngBuffer* buffer = iWaitingBuffers.First();
        TInt surfaceno = buffer->SurfaceBuffer()->SurfaceNo();
        __VTPRINT2( DEBUG_MEDIA, "RVD(NGA).DoSurfaceBuffer0Ready, surface buffer %d is in waitingqueue", surfaceno )
        iCallBackTable[surfaceno]->iStatus = KRequestPending;
        iCallBackTable[surfaceno]->SetActive();
        iSurfaceUpdateSession.NotifyWhenDisplayed(iCallBackTable[surfaceno]->iStatus, iTimeStamp);
        iSubmitPending = ETrue;
        iSurfaceUpdateSession.SubmitUpdate(0, iSurfaceId, surfaceno, NULL); 
        iWaitingBuffers.Remove(*buffer);
        buffer->UnSet();
        }
    iBufferWaiter->BufferAvailable(iSurfaceBuffer1);
    __VTPRINTEXIT( "RVD(NGA).DoSurfaceBuffer1Ready" )
    return ETrue;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVtEngBuffer::TVtEngBuffer
//
// -----------------------------------------------------------------------------
//
CVtEngDrawNGA::TVtEngBuffer::TVtEngBuffer()
    : iBuffer( 0 ), iSurfaceBuffer(0)
    {
    __VTPRINTENTER( "RVD(NGA).Buffer.Ctor" )
    __VTPRINTEXIT( "RVD(NGA).Buffer.Ctor" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVtEngBuffer::Set
//
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::TVtEngBuffer::Set( TVTSurfaceBuffer* aBuffer )
    {
    __VTPRINTENTER( "RVD(NGA).Buffer.Set" )
    iSurfaceBuffer = aBuffer;
    iBuffer = aBuffer->Buffer();
    __VTPRINTEXIT( "RVD(NGA).Buffer.Set" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVtEngBuffer::UnSet
//
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::TVtEngBuffer::UnSet()
    {
    __VTPRINTENTER( "RVD(NGA).Buffer.UnSet" )
    iSurfaceBuffer = 0;
    iBuffer = 0;
    __VTPRINTEXIT( "RVD(NGA).Buffer.UnSet" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVtEngBuffer::IsSet
//
// -----------------------------------------------------------------------------
//
TBool CVtEngDrawNGA::TVtEngBuffer::IsSet() const
    {
    return ( iSurfaceBuffer != NULL );
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVtEngBuffer::Buffer
//
// -----------------------------------------------------------------------------
//
TVTSurfaceBuffer* &CVtEngDrawNGA::TVtEngBuffer::SurfaceBuffer()
    {
    return iSurfaceBuffer;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::TVtEngBuffer::Buffer
//
// -----------------------------------------------------------------------------
//
TUint8* &CVtEngDrawNGA::TVtEngBuffer::Buffer()
    {
    return iBuffer;
    }
// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::CVtEngBufferWaiter
// -----------------------------------------------------------------------------
//
CVtEngDrawNGA::CVtEngBufferWaiter::CVtEngBufferWaiter
    //( CVideoRenderer& aVideoRenderer, MVtEngNGABufferWaiterObserver& aObserver )
    ( MVtEngNGABufferWaiterObserver& aObserver )
    : CActive( CActive::EPriorityStandard ),
      iObserver( &aObserver )
    {
    __VTPRINTENTER( "RVD(NGA).BufferWaiter.Ctor" )
    for ( TInt i = 0; i < KVtEngMaxSurfaceBuffers; i++ )
        {
        this->iBuffers[ i ] = NULL;
        }         
    CActiveScheduler::Add( this );
    __VTPRINTEXIT( "RVD(NGA).BufferWaiter.Ctor" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::~CVtEngBufferWaiter
// -----------------------------------------------------------------------------
//
CVtEngDrawNGA::CVtEngBufferWaiter::~CVtEngBufferWaiter()
    {
    __VTPRINTENTER( "RVD(NGA).BufferWaiter.~" )
    Cancel();
    __VTPRINTEXIT( "RVD(NGA).BufferWaiter.~" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::Activate
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::CVtEngBufferWaiter::Activate()
    {
    __VTPRINTENTER( "RVD(NGA).BufferWaiter.Activate" )
    iStatus = KRequestPending;
    SetActive();
    __VTPRINTEXIT( "RVD(NGA).BufferWaiter.Activate" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::FetchBuffer
// -----------------------------------------------------------------------------
//
TInt CVtEngDrawNGA::CVtEngBufferWaiter::FetchBuffer()
    {
    __VTPRINTENTER( "RVD(NGA).BufferWaiter.FetchBuffer" )
    if ( IsActive() )
    {
    	__VTPRINTEXIT( "RVD(NGA).BufferWaiter.FetchBuffer 1" )
      return KErrNone;
    }
    
    Activate();
    if (iStatus == KRequestPending)
        {
        for ( TInt i = 0; i < KVtEngMaxSurfaceBuffers; i++ )
            {
            if(this->iBuffers[ i ] != NULL)
                {
                TRequestStatus* status = &iStatus;
                User::RequestComplete( status, KErrNone );   
                break;  	
                }
            }
        }            
    __VTPRINTEXIT( "RVD(NGA).BufferWaiter.FetchBuffer 2" )    
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::BufferAvailable
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::CVtEngBufferWaiter::BufferAvailable(TVTSurfaceBuffer& aBuffer)
{
	__VTPRINTENTER( "RVD(NGA).BufferWaiter.BufferAvailable" )
    for ( TInt i = 0; i < KVtEngMaxSurfaceBuffers; i++ )
    {
      if(this->iBuffers[ i ] == NULL  )
      {
      this->iBuffers[ i ]= &aBuffer;
      break;  	
      }
    } 
    
    if(iStatus == KRequestPending )
    {
      for ( TInt i = 0; i < KVtEngMaxSurfaceBuffers; i++ )
      {
        if(this->iBuffers[ i ] != NULL)
        {
          TRequestStatus* status = &iStatus;
          User::RequestComplete( status, KErrNone );   
          break;  	
        }
      }
    }    
     	
	__VTPRINTEXIT( "RVD(NGA).BufferWaiter.BufferAvailable" )    
}

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::RunL
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::CVtEngBufferWaiter::RunL()
    {
    __VTPRINTENTER( "RVD(NGA).BufferWaiter.RunL" )
    TInt result( iStatus.Int() );
    if (  result == KErrNone )
    {
      for ( TInt i = 0; i < KVtEngMaxSurfaceBuffers; i++ )
      {
        if(this->iBuffers[ i ] != NULL)
        {   	
          TRAP_IGNORE( iObserver->BufferReadyL( this->iBuffers[ i ] ) );
          this->iBuffers[ i ] = NULL;
          break;
        }
      }
    }
    else
        {
        iObserver->FetchError( result );
        }
    __VTPRINTEXIT( "RVD(NGA).BufferWaiter.RunL" )
    }

// -----------------------------------------------------------------------------
// CVtEngDrawNGA::CVtEngBufferWaiter::DoCancel
// -----------------------------------------------------------------------------
//
void CVtEngDrawNGA::CVtEngBufferWaiter::DoCancel()
    {
    __VTPRINTENTER( "RVD(NGA).BufferWaiter.DoCancel" )    
    
   if ( iStatus == KRequestPending )
       {
       TRequestStatus* status = &iStatus;
       User::RequestComplete(status, KErrCancel);
       }
    
    __VTPRINTEXIT( "RVD(NGA).BufferWaiter.DoCancel" )
    }            
    
//  End of File