camcordermmfplugin/mediarecorder/Src/CCMRVideoRecorderClient.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 12 Mar 2010 15:43:25 +0200
branchRCL_3
changeset 10 6bc4220d7f67
parent 0 9b3e960ffc8a
permissions -rw-r--r--
Revision: 201007 Kit: 201008

/*
* Copyright (c) 2003 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:  Implementation for video recorder client class
*
*/



// INCLUDE FILES
#include "CCMRRecorderBase.h"
#include "CCMRVideoSettings.h"  // default video settings
#include "CCMRSupportedCodecs.h"
#include "CCMRVideoRecorderClient.h"
#include "CCMRVideoCodecs.h"

#include <mmf/common/mmfvideo.h>
#include <badesca.h>

// Assertion macro wrapper for code cleanup
#define VRCASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CCMRVIDEORECORDER"), EInternalAssertionFailure)) 

// Debug print macro
#ifdef _DEBUG
#include <e32svr.h>
#define PRINT(x) RDebug::Print x
#else
#define PRINT(x)
#endif

#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "CCMRVideoRecorderClientTraces.h"
#endif


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

// ---------------------------------------------------------
// CCMRVideoRecorderClient::NewL
// Standard Symbian OS two-phased constructor
// Returns: CCMRVideoRecorderClient*: Pointer to the newly-created 
//                              video recorder
// ---------------------------------------------------------
//
CCMRVideoRecorderClient* CCMRVideoRecorderClient::NewL()
    {

    PRINT((_L("CCMRVideoRecorderClient::NewL()"))); 

    CCMRVideoRecorderClient* self = new (ELeave) CCMRVideoRecorderClient;    
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();

    return self;    

    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::ConstructL()
// Symbian OS Constructor
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::ConstructL()
    {

    PRINT((_L("CCMRVideoRecorderClient::ConstructL()")));    

    iVideoCodecs = CCMRVideoCodecs::NewL();

    SetState(EStateNone);

    }



// ---------------------------------------------------------
// CCMRVideoRecorderClient::~CCMRVideoRecorderClient()
// Destructor
// ---------------------------------------------------------
//
CCMRVideoRecorderClient::~CCMRVideoRecorderClient()
    {
    OstTrace0( CAMERASRV_PERFORMANCE, CCMRVIDEORECORDERCLIENT_CCMRVIDEORECORDERCLIENT, "e_CCMRVideoRecorderClient::~CCMRVideoRecorderClient 1" );

    PRINT((_L("CCMRVideoRecorderClient::~CCMRVideoRecorderClient() in")));

    // This is the counterpart to NewL & OpenL, e.g. Close & Delete

    // free all memory allocated and uninitalize & delete objects created

    delete iThreadEventMonitor;
    iThreadEventMonitor = NULL;
    // close thread
    if ( iThreadCreated )
        {
        iThreadProxy.Close();
        }

    delete iVideoCodecs;
    iVideoCodecs = NULL;

    iObserver = NULL;

    SetState(EStateNone);

    // enable for RTRT code coverage
    //#pragma attol insert _ATCPQ_DUMP(0);
    PRINT((_L("CCMRVideoRecorderClient::~CCMRVideoRecorderClient() out")));
    OstTrace0( CAMERASRV_PERFORMANCE, DUP1_CCMRVIDEORECORDERCLIENT_CCMRVIDEORECORDERCLIENT, "e_CCMRVideoRecorderClient::~CCMRVideoRecorderClient 0" );
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::OpenL
// Opens the video recorder instance, creates submodules
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::OpenL(MCMRVideoRecorderObserver* aObserver, 
                              CCMRActiveOutput* aOutput,
                              TInt aCameraHandle, 
                              const TDesC8& aVideoMimeType,
                              MMMFClockSource* aClockSource,
                              CCMRConfigManager* aConfig  )
    {
    PRINT((_L("CCMRVideoRecorderClient::OpenL()")));

    if ( State() != EStateNone ) 
        {
        PRINT((_L("CCMRVideoRecorderClient::OpenL() already exists")));
        User::Leave( KErrAlreadyExists );
        }

    User::LeaveIfError(iThreadProxy.CreateSubThread(iThreadCreated, aConfig));

    iThreadEventMonitor = CCMRSubThreadEventMonitor::NewL(*this, iThreadProxy); 
    iThreadEventMonitor->Start();

    VRCASSERT( aObserver );
    iObserver = aObserver;

    // set output AO to thread
    VRCASSERT( aOutput );
    User::LeaveIfError(iThreadProxy.SetOutput( aOutput ));
    
    // set clocksource
    User::LeaveIfError(iThreadProxy.SetClockSource( aClockSource));

    // set camera handle to thread
    User::LeaveIfError(iThreadProxy.SetCameraHandle( aCameraHandle ));

    // check that it is supported
    if ( iVideoCodecs->DoWeSupportThisL( aVideoMimeType ) )
        {
        User::LeaveIfError(iThreadProxy.SetCodec( aVideoMimeType ));
        //Event is signaled if state change is needed
        }
    else
        {
        // codec doesn't exist in the system
        PRINT((_L("CCMRVideoRecorderClient::OpenL() unsupported codec")));
        User::Leave( KErrNotSupported );
        }

    SetState(EStateOpen);
    iObserver->MvroStateChange( State() );

    }



// ---------------------------------------------------------
// CCMRVideoRecorderClient::PrepareL
// Prepares the recorder for recording
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::PrepareL()
    {

    PRINT((_L("CCMRVideoRecorderClient::PrepareL() in")));

    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    SetState(EStatePreparing);
    // prepare thread
    User::LeaveIfError(iThreadProxy.Prepare());

                              
    PRINT((_L("CCMRVideoRecorderClient::PrepareL() out")));
    }


// ---------------------------------------------------------
// CCMRVideoRecorderClient::RecordL
// Starts recording
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::RecordL()
    {

    PRINT((_L("CCMRVideoRecorderClient::Record()           ")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    // start recording
    User::LeaveIfError(iThreadProxy.Record());

    SetState(EStateRecording);
    PRINT((_L("CCMRVideoRecorderClient::Record() complete           ")));
    }


// ---------------------------------------------------------
// CCMRVideoRecorderClient::StopL
// Stops recording
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::StopL()
    {
    PRINT((_L("CCMRVideoRecorderClient::Stop() in")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
            
    SetState(EStateStopping);
    // Stop thread
    User::LeaveIfError(iThreadProxy.Stop());
    PRINT((_L("CCMRVideoRecorderClient::Stop() out, must wait for state change before stop completed")));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::RequestBuffersAndWaitEOSL
// Waits until video thread stops recording and receives EOS (end of stream) marker
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::RequestBuffersAndWaitEOSL(TInt& aVideoEOSReached)
    {
    PRINT((_L("CCMRVideoRecorderClient::RequestBuffersAndWaitEOSL() in")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
            
    User::LeaveIfError(iThreadProxy.RequestBuffersAndWaitEOSL(aVideoEOSReached));
    PRINT((_L("CCMRVideoRecorderClient::RequestBuffersAndWaitEOSL() out, stop completed")));
    }


// ---------------------------------------------------------
// CCMRVideoRecorderClient::PauseL
// Pauses recording
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::PauseL()
    {

    PRINT((_L("CCMRVideoRecorderClient::Pause() in")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    // pause thread
    User::LeaveIfError(iThreadProxy.Pause());
    
    SetState(EStatePaused);
               
    PRINT((_L("CCMRVideoRecorderClient::Pause() out")));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::ResumeL
// Resumes recording
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::ResumeL()
    {

    PRINT((_L("CCMRVideoRecorderClient::Resume() in")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    // resume thread
    User::LeaveIfError(iThreadProxy.Resume());

    SetState(EStateRecording);
    PRINT((_L("CCMRVideoRecorderClient::Resume() out")));

    }



// Setters & Getters

// -----------------------------------------------------------------------------
// CCMRVideoRecorderClient::SetVideoCodecL
// Set video codec.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRVideoRecorderClient::SetVideoCodecL(const TDesC8& aMimeType) const
    {
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    // check that it is supported
    if ( iVideoCodecs->DoWeSupportThisL( aMimeType ) )
        {
        User::LeaveIfError(iThreadProxy.SetCodec( aMimeType ));
        //Event is signaled if state change is needed
        }
    else
        {
        // codec doesn't exist in the system
        PRINT((_L("CCMRVideoRecorderClient::OpenL() unsupported codec")));
        User::Leave( KErrNotSupported );
        }
    }

// -----------------------------------------------------------------------------
// CCMRVideoRecorderClient::GetVideoCodecL
// Get the used video codec.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRVideoRecorderClient::GetVideoCodecL( TDes8& aVideoMimeType ) const
    {
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    User::LeaveIfError(iThreadProxy.GetCodec( aVideoMimeType ));
    }


// -----------------------------------------------------------------------------
// CCMRVideoRecorderClient::GetSupportedVideoCodecsL
// Get list of supported video codecs.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRVideoRecorderClient::GetSupportedVideoCodecsL( CDesC8Array& aVideoMimeTypes ) const
    {
    if ( iVideoCodecs )
        {
        iVideoCodecs->GetSupportedVideoCodecsL( aVideoMimeTypes );
        }
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetTargetBitRateL
// Sets new target bitrate
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetTargetBitRateL(TInt aBitRate) 
    {
    PRINT((_L("CCMRVideoRecorderClient::SetTargetBitRate, aBitrate = % d"),aBitRate));

    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    User::LeaveIfError(iThreadProxy.SetBitRate( aBitRate ));

    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::TargetBitrateL
// Gets current target bitrate
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::TargetBitRateL(TInt& aBitRate)
    {
    PRINT((_L("CCMRVideoRecorderClient::TargetBitRate")));

    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    User::LeaveIfError(iThreadProxy.GetBitRate(aBitRate));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetFrameSizeL
// Sets new input & output frame size
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetFrameSizeL(const TSize& aSize) const
    {

    PRINT((_L("CCMRVideoRecorderClient::SetFrameSize")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
    

    User::LeaveIfError(iThreadProxy.SetFrameSize( aSize ));
    //Event is signaled if state change is needed

    }



// ---------------------------------------------------------
// CCMRVideoRecorderClient::FrameSizeL
// Gets current frame size
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::FrameSizeL(TSize& aSize) const
    {
    PRINT((_L("CCMRVideoRecorderClient::FrameSizeL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
                
    User::LeaveIfError(iThreadProxy.GetFrameSize( aSize )); 
                
    }


// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetFrameRateL
// Sets new target frame rate
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetFrameRateL(TReal32 aFrameRate) const
    {

    PRINT((_L("CCMRVideoRecorderClient::SetFrameRate")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );


    User::LeaveIfError(iThreadProxy.SetFrameRate( aFrameRate ));

    //Event is signaled if state change is needed
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::FrameRateL
// Get the used encoding frame rate
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::FrameRateL(TReal32& aFrameRate) const
    {
    PRINT((_L("CCMRVideoRecorderClient::FrameRateL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
                
    User::LeaveIfError(iThreadProxy.GetFrameRate(aFrameRate));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetVideoCodingOptionsL
// Set misc video coding options
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetVideoCodingOptionsL(const TCCMRVideoCodingOptions& aOptions) const
    {
    PRINT((_L("CCMRVideoRecorderClient::SetVideoCodingOptionsL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    User::LeaveIfError(iThreadProxy.SetMiscOptions(aOptions));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetVideoRateControlOptionsL
// Set video rate control options
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetVideoRateControlOptionsL(const TRateControlOptions& aOptions) const
    {
    PRINT((_L("CCMRVideoRecorderClient::SetVideoRateControlOptionsL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    User::LeaveIfError(iThreadProxy.SetVideoRateControlOptions(aOptions));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::GetVideoRateControlOptionsL
// Get video rate control options
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::GetVideoRateControlOptionsL(TRateControlOptions& aOptions) const
    {
    PRINT((_L("CCMRVideoRecorderClient::GetVideoRateControlOptionsL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );

    User::LeaveIfError( iThreadProxy.GetVideoRateControlOptions(aOptions) );
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetPreferredVideoEncoderL
// Set video encoder using its UID. Usage optional.
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetPreferredVideoEncoderL(TUid& aEncoder)
    {
    PRINT((_L("CCMRVideoRecorderClient::SetPreferredVideoEncoderL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
    User::LeaveIfError(iThreadProxy.SetPreferredVideoEncoder(aEncoder));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetPreferredVideoEncapsulationL
// Set video encoder output format encapsulation. Usage optional.
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetPreferredVideoEncapsulationL(TVideoDataUnitEncapsulation aCapsulation)
    {
    PRINT((_L("CCMRVideoRecorderClient::SetPreferredVideoEncapsulationL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
    User::LeaveIfError(iThreadProxy.SetPreferredVideoEncapsulation(aCapsulation));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetSegmentTargetSizeL
// Set video encoder target segment size. Usage optional.
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetSegmentTargetSizeL(TUint aLayer, TUint aSizeBytes, TUint aSizeMacroblocks )
    {
    PRINT((_L("CCMRVideoRecorderClient::SetSegmentTargetSizeL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
    User::LeaveIfError(iThreadProxy.SetSegmentTargetSize(aLayer, aSizeBytes, aSizeMacroblocks));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::AdjustTimeStampsL
// Adjust time stamps of video
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::AdjustTimeStampsL(const TInt aAdjustmentMs) const
    {
    PRINT((_L("CCMRVideoRecorderClient::AdjustTimeStampsL()")));
    // other state checks handled in the thread, but in this state there is no thread
    VRCASSERT( State() != EStateNone );
                
    User::LeaveIfError(iThreadProxy.AdjustTimeStamps(aAdjustmentMs));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::SetThreadPriorityL
// Set video thread priority, based on audio thread priority
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::SetThreadPriorityL(const TThreadPriority& aAudioThreadPriority) const
    {
    User::LeaveIfError(iThreadProxy.SetThreadPriority( aAudioThreadPriority ));
    }

// ---------------------------------------------------------
// CCMRVideoRecorderClient::HandleEvent
// Handle events from video recorder thread
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoRecorderClient::HandleEvent(const TMMFEvent& aEvent)
    {
    PRINT((_L("CCMRVideoRecorderClient::HandleEvent(), aEvent.iEventType %d"),aEvent.iEventType.iUid));
    // note: can't use switch here since it can't compare Uids
    if ( aEvent.iEventType == KCMRCameraPrepareError )
        {
        SetState( EStateOpen );// no need to call state change
        iObserver->MvroError( aEvent.iErrorCode );
        }
    else if ( aEvent.iEventType == KCMRCameraReserveError )
        {
        SetState( EStateOpen );// no need to call state change
        iObserver->MvroError( aEvent.iErrorCode );
        }
    else if ( aEvent.iEventType == KCMRCameraCaptureError )
        {
        // assume the client will stop us
        iObserver->MvroError( aEvent.iErrorCode );
        }
    else if ( aEvent.iEventType == KCMREncoderInitError )
        {
        SetState( EStateOpen );// no need to call state change
        iObserver->MvroError( aEvent.iErrorCode );
        }
    else if ( aEvent.iEventType == KCMRRunTimeError )
        {
        // assume the client will stop us
        iObserver->MvroError( aEvent.iErrorCode );
        }
    else if ( aEvent.iEventType == KCMRPrepareComplete )
        {
        SetState( EStateReadyToRecord );
        iObserver->MvroStateChange( EStateReadyToRecord );
        }
    else if ( aEvent.iEventType == KCMRRecordingComplete )
        {
        SetState( EStateReadyToRecord );
        iObserver->MvroStateChange( EStateReadyToRecord );
        }
    else if ( aEvent.iEventType == KCMRPrepareNeeded )
        {
        if ( State() == EStateReadyToRecord )
            {
            SetState( EStateOpen );
            iObserver->MvroStateChange( EStateOpen );
            }
        }
    else if ( aEvent.iErrorCode == KErrServerTerminated )
        {
        // thread was terminated, can't use it any more
        SetState( EStateNone );
        iObserver->MvroStateChange( EStateNone );
        iObserver->MvroError( aEvent.iErrorCode );
        }
    else
        {
        // something unknown, perhaps from the system
        PRINT((_L("CCMRVideoRecorderClient::HandleEvent() unknown event")));
        iObserver->MvroError( aEvent.iErrorCode );
        }

    }