camcordermmfplugin/mediarecorder/Src/CCMRMediaRecorderImp.cpp
author hgs
Wed, 06 Oct 2010 14:52:34 +0300
changeset 42 605672cc2a86
parent 15 50d5061ee01e
permissions -rw-r--r--
201039

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



// INCLUDE FILES
#include "CCMRVideoRecorderClient.h"
#include "CCMRMediaRecorderImp.h"
#include "CCMRPerfMonitor.h"
#include "CCMRVideoHWParams.h"
#include "CCMRVideoCodecs.h"
#include "CCMRSupportedCodecs.h"
#include "CCMRConfigManager.h"
#include <mmf/common/mmfvideo.h>


// MACROS

// Assertion macro wrapper for code cleanup
#define MRASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CCMRMEDIARECORDER"), 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 "CCMRMediaRecorderImpTraces.h"
#endif

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


// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRMediaRecorderImp
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CCMRMediaRecorderImp::CCMRMediaRecorderImp()
    {

    iObserver = NULL;
    iSink = NULL;
    iVideoRecorder = NULL;
    iAudioRecorder = NULL;
    iVideoRecorderPreparing = EFalse;
    iAudioRecorderPreparing = EFalse;
    iAudioEnabled = ETrue;
    iState = EStateNone;
    iErrorCode = KErrNone;

    iMaxTargetBitRate = KMMFVariableVideoBitRate; //here this means: not set (=> won't be checked when setting A/V bitrates)

    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMRMediaRecorder* CCMRMediaRecorder::NewL()
    {

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

    return self;

    }


// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::ConstructL()
    {
    OstTrace0( CAMERASRV_PERFORMANCE, CCMRMEDIARECORDERIMP_CONSTRUCTL, "e_CCMRMediaRecorderImp::ConstructL 1" );
    iState = EStateNone;

    // create video recorder
    iVideoRecorder = CCMRVideoRecorderClient::NewL();
    // create audio recorder
    iAudioRecorder = CCMRAudioRecorder::NewL();
    OstTrace0( CAMERASRV_PERFORMANCE, DUP1_CCMRMEDIARECORDERIMP_CONSTRUCTL, "e_CCMRMediaRecorderImp::ConstructL 0" );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::~CCMRMediaRecorderImp
// Destructor.
// -----------------------------------------------------------------------------
//
CCMRMediaRecorderImp::~CCMRMediaRecorderImp()
    {
    OstTrace0( CAMERASRV_PERFORMANCE, CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp 1" );
    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() in")));
    // note, adding "this->" below disabled a PC Lint warning since it makes State explicitly to refer to this class
    if ( (this->State() == EStateRecording) || (this->State() == EStatePaused) )
        {
        // recorder must be stopped first
        PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() must stop first")));
        TRAPD(err, this->StopL());
        if ( err ) {}
        // we are destructing, ignore the error; error can't be KErrNotReady since our state is not stopping
        }
    // we can't enter here when in stopping-state since stop is blocking controller thread to wait
    // for audio & video threads to complete stop
    // Note that pausing & destructing can't happen at the same time since neither of them can be executed internally,
    // so we don't need to check pausing state here

    // zeroed to make PC Lint happy
    iObserver = NULL;
    iSink = NULL;
    iAudioSource = NULL;


    OstTrace0( CAMERASRV_PERFORMANCE, DUP2_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_AudioRecorder 1" );
    delete iAudioRecorder;
    OstTrace0( CAMERASRV_PERFORMANCE, DUP3_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_AudioRecorder 0" );
    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() iAudioRecorder deleted")));
    delete iPerfMonitor;
    delete iConfig;
    OstTrace0( CAMERASRV_PERFORMANCE, DUP4_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_VideoRecorder 1" );
    delete iVideoRecorder;
    OstTrace0( CAMERASRV_PERFORMANCE, DUP5_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_VideoRecorder 0" );
    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() iVideoRecorder deleted")));
    OstTrace0( CAMERASRV_PERFORMANCE, DUP6_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_AudioOutput 1" );
    delete iAudioOutput;
    OstTrace0( CAMERASRV_PERFORMANCE, DUP7_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_AudioOutput 0" );
    OstTrace0( CAMERASRV_PERFORMANCE, DUP8_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_VideoOutput 1" );
    delete iVideoOutput;
    OstTrace0( CAMERASRV_PERFORMANCE, DUP9_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp_delete_VideoOutput 0" );

    if ( iErrorReporter )
        {
        iErrorReporter->Cancel();
        delete iErrorReporter;
        }

    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() out")));
    OstTrace0( CAMERASRV_PERFORMANCE, DUP1_CCMRMEDIARECORDERIMP_CCMRMEDIARECORDERIMP, "e_CCMRMediaRecorderImp::~CCMRMediaRecorderImp 0" );
    //#pragma attol insert _ATCPQ_DUMP(0);
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::OpenL
// Opens media recorder
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::OpenL(MCMRMediaRecorderObserver *aObserver,
                                 MDataSource *aAudioSource,
                                 MCMRMediaSink *aSink, TInt aCameraHandle,
                                 const TDesC8& aVideoMimeType,
                                 TFourCC aAudioType)

    {
    OstTrace0( CAMERASRV_PERFORMANCE, CCMRMEDIARECORDERIMP_OPENL, "e_CCMRMediaRecorderImp::OpenL 1" );
    PRINT((_L("CCMRMediaRecorderImp::OpenL() in, thread id %x"),TInt(RThread().Id())));
    if ( State() != EStateNone )
        {
        PRINT((_L("CCMRMediaRecorderImp::OpenL() already exists")));
        User::Leave( KErrAlreadyExists );
        }

    MRASSERT(aObserver);
    iObserver = aObserver;

    MRASSERT(aSink);
    iSink = aSink;

    if ( aAudioSource == NULL )
        {
        iAudioEnabled = EFalse;
        }
    iAudioSource = aAudioSource;

    // create active output objects; must be created here so that they all are in the same thread
    iAudioOutput = CCMRActiveOutput::NewL( iSink, this );
    iVideoOutput = CCMRActiveOutput::NewL( iSink, this );

    iPerfMonitor = CCMRPerfMonitor::NewL( iAudioOutput, iVideoOutput, iVideoRecorder, this );
    iConfig = CCMRConfigManager::NewL();

    // open video recorder
    TRAPD( err, iVideoRecorder->OpenL(this, iVideoOutput, aCameraHandle, aVideoMimeType, iPerfMonitor, iConfig) );
    if ( err != KErrNone )
        {
        PRINT((_L("CCMRMediaRecorderImp::OpenL() video open failed")));
        User::Leave( err );
        }
    // Inform sink about average bit-rate
    TInt br = 0;
    TRAP( err, iVideoRecorder->TargetBitRateL(br));
    if ( err == KErrNone )
        {
        TReal videoBitrateScaler = 0;
        if ( iConfig )
        	{
             videoBitrateScaler = iConfig->PluginSettings().iCMRAvgVideoBitRateScaler;
         	}
         // make sure we never get scaler value 0 (ends up Div0 error)
        if ( videoBitrateScaler == 0 )
         	{
         	videoBitrateScaler = KCMRAvgVideoBitRateScaler;
         	}

         //inform the estimated average bitrate to sink; use a HW-specific scaler to estimate the average
        br = static_cast<TInt>( br*videoBitrateScaler );
        iSink->SetAverageVideoBitRate( br );

        // open audio recorder
        TRAP( err, iAudioRecorder->OpenL(this, iAudioSource, iAudioOutput, aAudioType, iConfig) );
        }

    if ( err != KErrNone )
        {
        PRINT((_L("CCMRMediaRecorderImp::OpenL() audio open failed")));
        User::Leave( err );
        }

    TRAP( err, iAudioRecorder->TargetBitRateL(br));
    if ( err == KErrNone )
        {
        // Inform sink about the default average bit-rate
        iSink->SetAverageAudioBitRate( br );
        }
    else
        {
        PRINT((_L("CCMRMediaRecorderImp::OpenL() audio bitrate check failed")));
        User::Leave( err );
        }

    iErrorReporter = new (ELeave) CCMRErrorReporter(aObserver);

    iState = EStateOpen;
    PRINT((_L("CCMRMediaRecorderImp::OpenL() out")));
    OstTrace0( CAMERASRV_PERFORMANCE, DUP1_CCMRMEDIARECORDERIMP_OPENL, "e_CCMRMediaRecorderImp::OpenL 0" );
    }


// Settings

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetVideoCodecL
// Sets video codec (overrides the codec given in OpenL).
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetVideoCodecL( const TDesC8& aVideoMimeType )
    {
    PRINT((_L("CCMRMediaRecorderImp::SetVideoCodecL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetVideoCodecL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->SetVideoCodecL( aVideoMimeType );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GetVideoCodecL
// Gets the currently used video codec
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::GetVideoCodecL( TDes8& aVideoMimeType )
    {
    PRINT((_L("CCMRMediaRecorderImp::GetVideoCodecL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::GetVideoCodecL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->GetVideoCodecL( aVideoMimeType );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GetSupportedVideoCodecsL
// Gets the supported & installed video codecs. This can be called also before opened
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::GetSupportedVideoCodecsL( CDesC8Array& aVideoMimeTypes )
    {
    PRINT((_L("CCMRMediaRecorderImp::GetSupportedVideoCodecsL()")));

    iVideoRecorder->GetSupportedVideoCodecsL( aVideoMimeTypes );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetAudioCodecL
// Sets audio codec (overrides the codec given in OpenL).
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetAudioCodecL( const TFourCC& aAudioType )
    {
    PRINT((_L("CCMRMediaRecorderImp::SetAudioCodecL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetAudioCodecL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iAudioRecorder->SetAudioCodecL( aAudioType );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GetAudioCodecL
// Gets the currently used audio codec
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::GetAudioCodecL( TFourCC& aAudioType )
    {
    PRINT((_L("CCMRMediaRecorderImp::GetAudioCodecL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::GetAudioCodecL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iAudioRecorder->GetAudioCodecL( aAudioType );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GetSupportedAudioCodecsL
// Gets the supported & installed audio codecs. This can be called also before opened
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::GetSupportedAudioCodecsL( RArray<TFourCC>& aAudioTypes )
    {
    PRINT((_L("CCMRMediaRecorderImp::GetSupportedAudioCodecsL()")));
    iAudioRecorder->GetSupportedAudioCodecsL( aAudioTypes );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetVideoFrameRateL
// Sets video frame rate (capture rate & encoding target rate.
// This can be changed also while recording, but then affects only to encoding frame rate
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetVideoFrameRateL(TReal32 aFrameRate)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameRateL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameRateL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->SetFrameRateL(aFrameRate);
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::VideoFrameRateL
// Gets video (encoding) frame rate (capture rate is the same or higher).
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TReal32 CCMRMediaRecorderImp::VideoFrameRateL()
    {
    PRINT((_L("CCMRMediaRecorderImp::VideoFrameRateL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::VideoFrameRateL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->FrameRateL(iFrameRate);
    return iFrameRate;
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetVideoFrameSizeL
// Sets video frame size.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetVideoFrameSizeL(const TSize& aSize)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameSizeL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameSizeL() wrong state")));
        User::Leave( KErrNotReady );
        }
    // this can't be changed while recording; video recorder is supposed to notice if in wrong state
    // state is changed based on mvroStateChange()
    iVideoRecorder->SetFrameSizeL(aSize);
    if ( iConfig != NULL )
        {
        iConfig->SetVideoFrameSize(aSize);
        }

    // Change audio samplerate based on framesize
    TSize framesize;
    TInt samplerate = 0;
    TInt channelmode = 0;
    iVideoRecorder->FrameSizeL(framesize);


	if ( iConfig && iConfig->IsICMConfigDataAvailable() )
		{
		samplerate = iConfig->VideoQualitySettings().iAudioSamplingRate;
		channelmode = iConfig->VideoQualitySettings().iAudioChannels;
		PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameSizeL() setting audio settings using ICM samplerate: %d, channels: %d"), samplerate, channelmode));
		}
	else
		{
	    if ( (framesize.iHeight >= KCMRVGAHeight) && (framesize.iWidth >= KCMRVGAWidth) )
	        {
	        samplerate = KCMRAACAudioSampleRateWithVGA;
	        channelmode = KCMRAACAudioChannelModeWithVGA;
	        PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameSizeL() >=VGA Default audio to samplerate:%d channels:%d"), samplerate, channelmode));
	        }
	    else if ( (framesize.iHeight >= KCMRCIFHeight) && (framesize.iWidth >= KCMRCIFWidth) )
	        {
	        samplerate = KCMRAACAudioSampleRateWithCIF;
	        channelmode = KCMRAACAudioChannelModeWithCIF;
	        PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameSizeL() CIF Default audio to samplerate:%d channels:%d"), samplerate, channelmode));
	        }
	    else if ( (framesize.iHeight >= KCMRQVGAHeight) && (framesize.iWidth >= KCMRQVGAWidth) )
	        {
	        samplerate = KCMRAACAudioSampleRateWithQVGA;
	        channelmode = KCMRAACAudioChannelModeWithQVGA;
	        PRINT((_L("CCMRMediaRecorderImp::SetVideoFrameSizeL() QVGA Default audio to samplerate:%d channels:%d"), samplerate, channelmode));
	        }
	     else
	        {
	        // AAC is not used for lower resolutions.
	        }
		}

    TFourCC currentAudioCodec;
    iAudioRecorder->GetAudioCodecL(currentAudioCodec);
    if ( currentAudioCodec == KCMRFourCCIdMPEG4AAC )
	    {
    	if ( samplerate )
        	{
        	iAudioRecorder->SetTargetSampleRateL( samplerate );
        	}
	    if ( channelmode )
	        {
	        iAudioRecorder->SetChannelModeL( channelmode );
	        }
	    }
    }


// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GetVideoFrameSizeL
// Gets video frame size.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::GetVideoFrameSizeL(TSize& aSize) const
    {
    PRINT((_L("CCMRMediaRecorderImp::GetVideoFrameSizeL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::GetVideoFrameSizeL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->FrameSizeL(aSize);
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetVideoBitRateL
// Sets video bitrate (or KMMFVariableVideoBitRate)
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetVideoBitRateL(TInt aBitRate)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetVideoBitRateL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetVideoBitRateL() wrong state")));
        User::Leave( KErrNotReady );
        }

    if ( ( iMaxTargetBitRate != KMMFVariableVideoBitRate ) && ( aBitRate != KMMFVariableVideoBitRate ) )
        {
        TInt abr;
        // check that the total bit-rate (audio+video) does not exceed a given limit
        if ( iAudioRecorder != NULL )
            {
            iAudioRecorder->TargetBitRateL(abr);
            if ( iAudioEnabled && ( abr > 0 ) &&
                 ( abr + aBitRate > iMaxTargetBitRate ) )
                {
                PRINT((_L("CCMRMediaRecorderImp::SetVideoBitRateL() too high combined bitrate")));
                User::Leave(KErrArgument);
                }
            }
        }

    // this can be changed also while recording
    iVideoRecorder->SetTargetBitRateL(aBitRate);
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::VideoBitRateL
// Gets video bitrate.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CCMRMediaRecorderImp::VideoBitRateL()
    {
    PRINT((_L("CCMRMediaRecorderImp::VideoBitRateL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::VideoBitRateL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->TargetBitRateL(iTargetBitRate);
    return iTargetBitRate;
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetVideoCodingOptionsL
// Set misc video coding options
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetVideoCodingOptionsL(const TCCMRVideoCodingOptions& aOptions)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetVideoCodingOptionsL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetVideoCodingOptionsL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->SetVideoCodingOptionsL( aOptions );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetVideoRateControlOptionsL
// Set video rate control options
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetVideoRateControlOptionsL(const TRateControlOptions& aOptions)
	{
    PRINT((_L("CCMRMediaRecorderImp::SetVideoCodingOptionsL() in")));
    if ( (iState == EStateNone) ||
    	 (iState == EStateOpen) ||
    	 (iState == EStatePreparing) )
    	{
        // not prepared / recording yet
        PRINT((_L("CCMRMediaRecorderImp::SetVideoRateControlOptionsL() wrong state")));
        User::Leave( KErrNotReady );
    	}
    iVideoRecorder->SetVideoRateControlOptionsL( aOptions );
    PRINT((_L("CCMRMediaRecorderImp::SetVideoCodingOptionsL() out")));
	}

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GetVideoRateControlOptionsL
// Get video rate control options
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::GetVideoRateControlOptionsL(TRateControlOptions& aOptions)
    {
    PRINT((_L("CCMRMediaRecorderImp::GetVideoRateControlOptionsL() in")));
    if ( (iState == EStateNone) ||
         (iState == EStateOpen) ||
         (iState == EStatePreparing) )
        {
        // not prepared / recording yet
        PRINT((_L("CCMRMediaRecorderImp::GetVideoRateControlOptionsL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->GetVideoRateControlOptionsL( aOptions );
    PRINT((_L("CCMRMediaRecorderImp::GetVideoRateControlOptionsL() out")));
    }


// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetAudioBitRateL
// Sets audio bitrate
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetAudioBitRateL(TInt aBitRate)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetAudioBitRateL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetAudioBitRateL() wrong state")));
        User::Leave( KErrNotReady );
        }

    if ( ( iMaxTargetBitRate != KMMFVariableVideoBitRate ) && ( aBitRate > 0 ) )
        {
        TInt vbr;
        // check that the total bit-rate (audio+video) does not exceed a given limit
        iVideoRecorder->TargetBitRateL(vbr);
        if ( ( vbr != KMMFVariableVideoBitRate ) &&
             (vbr + aBitRate > iMaxTargetBitRate ) )
            {
            PRINT((_L("CCMRMediaRecorderImp::SetAudioBitRateL() too high combined bitrate")));
            User::Leave(KErrArgument);
            }
        }

    iAudioRecorder->SetTargetBitRateL(aBitRate);
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::AudioBitRateL
// Gets audio bitrate
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CCMRMediaRecorderImp::AudioBitRateL()
    {
    PRINT((_L("CCMRMediaRecorderImp::AudioBitRateL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::AudioBitRateL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iAudioRecorder->TargetBitRateL(iTargetBitRate);
    return iTargetBitRate;
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetAudioEnabledL
// Sets audio enabled / disabled for the next recording.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetAudioEnabledL(TBool aEnabled)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetAudioEnabledL(), aEnabled: %d"),aEnabled));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetAudioEnabledL() wrong state")));
        User::Leave( KErrNotReady );
        }

    if ( (State() == EStateRecording) || (State() == EStatePaused) )
        {
        // can't change this parameter when recording or paused.
        PRINT((_L("CCMRMediaRecorderImp::SetAudioEnabledL(), leaves, state: %d"),State()));
        User::Leave(KErrNotReady);
        }
    else
        {
        if ( iAudioEnabled && (!aEnabled) )
            {
            // audio recorder was used but should not be used any more
            iAudioRecorderPreparing = EFalse; //this should be redundant, but repeated to ensure prepare to complete

            if ( iSink )
                {
                // Inform sink about the bit-rate which is now 0
                iSink->SetAverageAudioBitRate( 0 );
                }
            }
        else if ( aEnabled )
            {
            // Enable possibly disabled audio
            TInt bitrate;
            iAudioRecorder->TargetBitRateL( bitrate );
            if ( iSink )
                {
                // Inform sink about the average bit-rate.
                iSink->SetAverageAudioBitRate( bitrate );
                }
            }

        if ( iAudioEnabled != aEnabled )
            {
            // state is changed
            iAudioEnabled = aEnabled;
            // force prepare
            iState = EStateOpen;
            // inform controller
            iObserver->MmroStateChange( iState, KErrNone );
            }
        else
            {
            // redundant call
            }

        }

    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::AudioEnabledL
// Checks if audio is enabled / disabled.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CCMRMediaRecorderImp::AudioEnabledL() const
    {
    PRINT((_L("CCMRMediaRecorderImp::AudioEnabledL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::AudioEnabledL() wrong state")));
        User::Leave( KErrNotReady );
        }
    return iAudioEnabled;
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetGainL
// Sets audio recording gain.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetGainL(TInt aGain)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetGainL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetGainL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iAudioRecorder->SetGainL( aGain );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::GainL
// Gets audio recording gain.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CCMRMediaRecorderImp::GainL() const
    {
    PRINT((_L("CCMRMediaRecorderImp::GainL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::GainL() wrong state")));
        User::Leave( KErrNotReady );
        }
    return iAudioRecorder->GainL();
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::MaxGainL
// Gets max audio recording gain.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CCMRMediaRecorderImp::MaxGainL() const
    {
    PRINT((_L("CCMRMediaRecorderImp::MaxGainL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::MaxGainL() wrong state")));
        User::Leave( KErrNotReady );
        }
    return iAudioRecorder->MaxGainL();
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetAudioPriorityL
// Set audio priority settings.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetAudioPriorityL(const TMMFPrioritySettings& aPrioritySettings)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetAudioPriorityL()")));
    if ( iState == EStateNone )
        {
        // not opened yet
        PRINT((_L("CCMRMediaRecorderImp::SetAudioPriorityL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iAudioRecorder->SetPriorityL( aPrioritySettings );
    }


// Recording control

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::PrepareL
// Prepares audio & video recorders for recording.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::PrepareL()
    {
    OstTrace0( CAMERASRV_PERFORMANCE, CCMRMEDIARECORDERIMP_PREPAREL, "e_CCMRMediaRecorderImp::PrepareL 1" );
    PRINT((_L("CCMRMediaRecorderImp::PrepareL()")));

    if ( (State() != EStateOpen) && (State() != EStateReadyToRecord) )
        {
        // prepare possible only when open or prepared
        PRINT((_L("CCMRMediaRecorderImp::PrepareL() wrong state")));
        User::Leave( KErrNotReady );
        }

    iState = EStatePreparing;

    TThreadPriority audioThreadPriority = EPriorityNormal;
    // since we don't know the order of preparecomplete callbacks, both flags must be ETrue
    // before any preparations are started.
    if ( iAudioEnabled )
        {
        iAudioRecorderPreparing = ETrue;
        audioThreadPriority = iAudioRecorder->GetThreadPriority();
        }
    else
        {
        iAudioRecorderPreparing = EFalse;
        }

    iVideoRecorder->SetThreadPriorityL( audioThreadPriority );

    // start preparing video recorder, then wait for MvroStateChange
    iVideoRecorderPreparing = ETrue;
    TRAPD( err, iVideoRecorder->PrepareL() );
    if ( err != KErrNone )
        {
        // As we know the implementation of iVideoRecorder, it can leave only before any async calls.
        // Hence we can restore the previous state & leave here and there is no need to return the observer call
        iVideoRecorderPreparing = EFalse;
        PRINT((_L("CCMRMediaRecorderImp::PrepareL() video prepare failed %d"), err));
        User::Leave( err );
        }


    if ( iAudioEnabled )
        {
        // Prepare audio recorder

        TRAP(err, iAudioRecorder->PrepareL());

        if ( err == KErrNotSupported )
            {
            // No suitable audio codec found => disable audio but don't let this trouble video recording
            PRINT((_L("CCMRMediaRecorderImp::PrepareL() - iAudioRecorder->PrepareL didn't find a suitable audio codec, error code %d"),err));
            iAudioEnabled = EFalse;
            iAudioRecorderPreparing = EFalse;
            // Inform sink about the bit-rate which is now 0
            iSink->SetAverageAudioBitRate( 0 );
            }
        else if ( err != KErrNone )
            {
            // Some more serious problem => preparation of media recorder is not successful.
            // However, we cannot leave here since video recorder is preparing and hence
            // media recorder state can not be restored => error is informed in callback
            PRINT((_L("CCMRMediaRecorderImp::PrepareL() - iAudioRecorder->PrepareL failed with error code %d"),err));
            iErrorCode = err;
            iAudioRecorderPreparing = EFalse;
            }
        else
            {
            // ok
            }
        }

    OstTrace0( CAMERASRV_PERFORMANCE, DUP1_CCMRMEDIARECORDERIMP_PREPAREL, "e_CCMRMediaRecorderImp::PrepareL 0" );

    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::RecordL
// Starts recording.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::RecordL()
    {
    PRINT((_L("CCMRMediaRecorderImp::RecordL() in")));
    if ( ( State() == EStateStopping ) || ( State() == EStatePausing ) )
        {
        PRINT((_L("CCMRMediaRecorderImp::RecordL() wrong state")));
        User::Leave( KErrNotReady );
        }

    if ( (State() == EStateRecording) || (State() == EStatePaused) )
        {
        // ignore, recording already going on
        PRINT((_L("CCMRMediaRecorderImp::RecordL() ignore, recording already")));
        return;
        }

    if ( iState != EStateReadyToRecord )
        {
        PRINT((_L("CCMRMediaRecorderImp::RecordL() wrong state")));
        User::Leave(KErrNotReady);
        }

    iVideoOutput->Start();

    iVideoStopped = EFalse;
    TRAPD(err,iVideoRecorder->RecordL());

    if ( err == KErrNone )
        {
        if ( iAudioEnabled )
            {
            iAudioStopped = EFalse;
            iAudioOutput->Start();
            TRAP(err,iAudioRecorder->RecordL());

            if ( err != KErrNone )
                {
                // if audio leaved, video should be stopped
                StopL();
                }
            }
        else
            {
            // audio not recording
            iAudioStopped = ETrue;
            }
        }
    else
        {
        // Leave only now when both components are stopped (can't let audio->recordL leave)
        PRINT((_L("CCMRMediaRecorderImp::RecordL() video's recordl failed %d"), err));
        User::Leave( err );
        }

    // Start performance monitor
    iPerfMonitor->StartL();

    if ( iAudioEnabled )
        {
        // set initial lipsync adjustment
        iVideoRecorder->AdjustTimeStampsL( iAudioRecorder->AVSyncAdjustmentStart() );
        }

    //successful
    iState = EStateRecording;

    PRINT((_L("CCMRMediaRecorderImp::RecordL() out")));
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::StopL
// Stop recording.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::StopL()
    {
    OstTrace0( CAMERASRV_PERFORMANCE, CCMRMEDIARECORDERIMP_STOPL, "e_CCMRMediaRecorderImp::StopL 1" );
    PRINT((_L("CCMRMediaRecorderImp::StopL() in")));
    if ( (State() == EStateRecording) || (State() == EStatePaused) )
        {
        TInt errVideo;
        TInt errVideoStop;        
        TInt errAudio;

        iState = EStateStopping;

        // try to free as many buffers as possible for stop / EOS marker
        iVideoOutput->Flush();
        
        if ( iAudioEnabled && (!iAudioStopped) )
            {
            // start stopping of audio (async)
            TRAP(errAudio,iAudioRecorder->StopL());
            }
        else
            {
            errAudio = KErrNone;
            }

        // try to free as many buffers for video thread as possible.
        iVideoOutput->Flush();
        
        // stop video (sync)
        TRAP(errVideo, iVideoRecorder->StopL());        

        iVideoEOSReached = EFalse;
        TTimeIntervalMicroSeconds32 sleeptime = 15000; // 15ms roughly 1 or ½ frame duration
        PRINT((_L("CCMRMediaRecorderImp::StopL() EOS sleeptime: %d"), sleeptime.Int() ));        
        while ( !iVideoEOSReached )
            {
            PRINT((_L("CCMRMediaRecorderImp::StopL() Waiting EOS / streamend, flushing controller thread buffers:")));            
            iVideoOutput->Flush();
            PRINT((_L("CCMRMediaRecorderImp::StopL() Waiting EOS / streamend, returning to video thread to return buffers to encoder:")));            
            TRAP(errVideoStop, iVideoRecorder->RequestBuffersAndWaitEOSL(iVideoEOSReached));
            if (!iVideoEOSReached)
                {
                PRINT((_L("CCMRMediaRecorderImp::StopL() sleeping %d microsecs waiting for EOS"), sleeptime.Int() ));                
                User::After(sleeptime); // wait 1 frame duration until asking again for StreamEnd again;
                }
            }
        
        iVideoStopped = ETrue;

        if ( iAudioEnabled && (!iAudioStopped) && (errAudio == KErrNone) )
            {
            // Start waiting until audiorecorder indicates it has stopped
            PRINT((_L("CCMRMediaRecorderImp::StopL() ensure that audio recorder has stopped")));
            TRAP(errAudio,iAudioRecorder->WaitUntilStoppedL());
            iAudioStopped = ETrue;
            }
        iAudioOutput->Stop();
        iAudioOutput->Flush();

        // final cleanup for video buffers.
        iVideoOutput->Stop();
        iVideoOutput->Flush();
        
        iPerfMonitor->StopL();

        iState = EStateReadyToRecord;

        if ( errVideo != KErrNone )
            {
            PRINT((_L("CCMRMediaRecorderImp::StopL() leaves, video error %d"),errVideo));
            User::Leave( errVideo );
            }
        if ( errVideoStop != KErrNone )
            {
            PRINT((_L("CCMRMediaRecorderImp::StopL() leaves, videostop error %d"),errVideoStop));
            User::Leave( errVideo );
            }
        if ( errAudio != KErrNone )
            {
            PRINT((_L("CCMRMediaRecorderImp::StopL() leaves, audio error %d"),errAudio));
            User::Leave( errAudio );
            }
        }
    else
        {
        PRINT((_L("CCMRMediaRecorderImp::StopL() already stopped, ignoring")));
        }
    PRINT((_L("CCMRMediaRecorderImp::StopL() out")));
    OstTrace0( CAMERASRV_PERFORMANCE, DUP1_CCMRMEDIARECORDERIMP_STOPL, "e_CCMRMediaRecorderImp::StopL 0" );
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::PauseL
// Pause recording.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::PauseL()
    {
    PRINT((_L("CCMRMediaRecorderImp::PauseL() in")));
    if ( State() != EStateRecording )
        {
        return;
        }

    TInt err;

    // sync call
    TRAP( err, iVideoRecorder->PauseL() );

    if ( err != KErrNone )
        {
        //Stop both
        StopL();
        PRINT((_L("CCMRMediaRecorderImp::PauseL() video's recordl failed %d"),err));
        User::Leave( err );

        }
    else if ( iAudioEnabled )
        {
        iState = EStatePausing;

        // sync call
        TRAP( err, iAudioRecorder->PauseL());

        if ( err != KErrNone )
            {
            // stop both
            iState = EStateRecording;
            StopL();
            PRINT((_L("CCMRMediaRecorderImp::PauseL() audio's recordl failed %d"),err));
            User::Leave( err );
            }
        }
    else
        {
        // ok
        }

    iPerfMonitor->PauseL();

    //successful
    iState = EStatePaused;
    PRINT((_L("CCMRMediaRecorderImp::PauseL() out")));

    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::ResumeL
// Resume recording.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::ResumeL()
    {
    PRINT((_L("CCMRMediaRecorderImp::ResumeL() in")));
    if ( State() == EStatePausing )
        {
        PRINT((_L("CCMRMediaRecorderImp::Resume() wrong state")));
        User::Leave( KErrNotReady );
        }

    if ( State() != EStatePaused )
        {
        return;
        }

    TInt err = KErrNone;

    if ( iAudioEnabled )
        {
        TRAP(err,iAudioRecorder->ResumeL());
        if ( err != KErrNone )
            {
            // stop both
            StopL();
            PRINT((_L("CCMRMediaRecorderImp::ResumeL() audio's resumel failed %d"),err));
            User::Leave( err );
            }

        }


    TRAP( err, iVideoRecorder->ResumeL() );
    if ( err != KErrNone )
        {
        //Stop both
        StopL();
        PRINT((_L("CCMRMediaRecorderImp::ResumeL() video's resumel failed %d"),err));
        User::Leave( err );
        }
    else
        {
        // ok
        }

    iPerfMonitor->StartL();

    if ( iAudioEnabled )
        {
        // set lipsync adjustment after pause
        iVideoRecorder->AdjustTimeStampsL( iAudioRecorder->AVSyncAdjustmentResume() );
        }

    //successful
    iState = EStateRecording;
    PRINT((_L("CCMRMediaRecorderImp::ResumeL() out")));

    }

// Observer methods

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::MvroStateChange
// Video recorder state change callback
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::MvroStateChange(CCMRRecorderBase::TRecorderState aState)
    {
    PRINT((_L("CCMRMediaRecorderImp::MvroStateChange(), aState %d, iState %d"),aState,iState));

    switch ( State() )
        {
        case EStatePreparing:

            if ( iErrorCode != KErrNone )
                {
                // audio preparation was completed with an error
                iVideoRecorderPreparing = EFalse;
                iState = EStateOpen;
                iObserver->MmroPrepareComplete( iErrorCode );
                PRINT((_L("CCMRMediaRecorderImp::MvroStateChange(), called preparecomplete with audio errorcode %d"),iErrorCode));
                iErrorCode = KErrNone;
                }
            else if ( aState == CCMRRecorderBase::EStateReadyToRecord )
                {
                iVideoRecorderPreparing = EFalse;

                // call prepare complete -callback if both recorders are prepared
                if ( !iAudioRecorderPreparing )
                    {
                    iState = EStateReadyToRecord;
                    iObserver->MmroPrepareComplete(KErrNone);
                    }
                //else have to wait until audio is prepared
                }
            else
                {
                PRINT((_L("CCMRMediaRecorderImp::MvroStateChange() unexpected state change")));
                MRASSERT( 0 );
                }
            break;

        case EStateReadyToRecord:
            if ( aState == CCMRRecorderBase::EStateOpen )
                {
                // a setting changed video recorder to not-readytorecord state => new prepare needed
                iState = EStateOpen;
                // inform controller
                iObserver->MmroStateChange( iState, KErrNone );
                }
            // else by default state change is to record => no actions needed

            break;

        case EStateStopping:
            {
            PRINT((_L("CCMRMediaRecorderImp::MvroStateChange(), video stopped either normally by receiving EOS or by fatal error.")));            
            iVideoStopped = ETrue;
            break;
            }
        default:
            {
            if ( (aState == CCMRRecorderBase::EStateReadyToRecord)
                || (aState == CCMRRecorderBase::EStateNone) )     // none is signalled if thread was terminated
                {
                // recording stopped
                PRINT((_L("CCMRMediaRecorderImp::MvroStateChange(), video stopped unexpectedly while recording")));
                iVideoStopped = ETrue;
                }
            break;
            }
        }

    PRINT((_L("CCMRMediaRecorderImp::MvroStateChange() out")));
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::MvroError
// Video recorder error callback
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::MvroError(TInt aError)
    {
    PRINT((_L("CCMRMediaRecorderImp::MvroError(), aError %d"),aError));

    switch ( State() )
        {
        case EStatePreparing:

            iVideoRecorderPreparing = EFalse;
            if ( !iAudioRecorderPreparing )
                {
                // Some problem happened with either in camera API or devvr initialisation.
                iObserver->MmroPrepareComplete( aError );
                iState = EStateOpen;
                }
            else
                {
                // have to wait until audio is prepared, don't send any error code yet
                iErrorCode = aError;
                }
            break;

        case EStateStopping:
            // error occurred while stopping, must wait until stop is complete before signaling the error
            PRINT((_L("CCMRMediaRecorderImp::MvroError(), error occurred while stopping, must wait until stop is complete before signaling the error")));
            iErrorCode = aError;
            break;


        default:
            {
            // all the errors are considered fatal, and the fatality is interpreted by application/user based on error code.
            PRINT((_L("CCMRMediaRecorderImp::MvroError(), forwarding error to iErrorReporter")));
            iErrorReporter->FatalError(aError);
            // assumes the controller will stop us
            }
        }

    PRINT((_L("CCMRMediaRecorderImp::MvroError() out")));
    }




// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::MaroStateChange
// Audio recorder state change callback
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::MaroStateChange(CCMRRecorderBase::TRecorderState aState)
    {
    PRINT((_L("CCMRMediaRecorderImp::MaroStateChange(), aState %d, iState %d"),aState,iState));

    switch ( State() )
        {
        case EStatePreparing:

            if ( iErrorCode != KErrNone )
                {
                // preparation was completed with error
                iState = EStateOpen;
                iObserver->MmroPrepareComplete( iErrorCode );
                iErrorCode = KErrNone;
                iAudioRecorderPreparing = EFalse;
                }
            else if ( aState == CCMRRecorderBase::EStateReadyToRecord )
                {

                iAudioRecorderPreparing = EFalse;
                // call prepare complete -callback if both recorders are prepared
                if ( !iVideoRecorderPreparing )
                    {
                    iState = EStateReadyToRecord;
                    iObserver->MmroPrepareComplete(KErrNone);
                    }
                //else have to wait until video is prepared
                }
            else
                {
                PRINT((_L("CCMRMediaRecorderImp::MaroStateChange() unexpected state change")));
                MRASSERT( 0 );
                }

            break;

        case EStateReadyToRecord:
            if ( aState == CCMRRecorderBase::EStateOpen )
                {
                // a setting changed audio recorder to not-readytorecord state => new prepare needed
                iState = EStateOpen;
                // inform controller
                iObserver->MmroStateChange( iState, KErrNone );
                }
            // else by default state change is to record => no actions needed

            break;

        case EStatePausing:
            // waiting for audio to pause, pausing is sync and no extra actions needed here
            break;

        case EStateStopping:
            // waiting for audio to stop; should not come here
            iAudioStopped = ETrue;
            break;

        default:
            {
            if ( (aState == CCMRRecorderBase::EStateReadyToRecord)
                || (aState == CCMRRecorderBase::EStateNone) )     // none is signalled if thread was terminated
                {
                PRINT((_L("CCMRMediaRecorderImp::MaroStateChange(), audio stopped unexpectedly while recording")));
                iAudioStopped = ETrue;
                }
            break;
            }

        }

    PRINT((_L("CCMRMediaRecorderImp::MaroStateChange() out")));

    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::MaroError
// Audio recorder error callback
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::MaroError(TInt aError)
    {
    PRINT((_L("CCMRMediaRecorderImp::MaroError(), aError %d"),aError));

    switch ( State() )
        {
        case EStatePreparing:
            {
            iAudioRecorderPreparing = EFalse;
            if ( !iVideoRecorderPreparing )
                {
                // Some problem happened with audio initialisation.
                iObserver->MmroPrepareComplete( aError );
                iState = EStateOpen;
                }
            else
                {
                // have to wait until video is prepared => don't call any observer callbacks yet
                iErrorCode = aError;
                }
            break;
            }

        default:
            {
            PRINT((_L("CCMRMediaRecorderImp::MaroError(), forwarding error to iErrorReporter")));
            // all the errors are considered fatal, and the fatality is interpreted by application/user based on error code.
            // audio recorder always changes its state before signalling error
            iErrorReporter->FatalError(aError);
            }
        }
    PRINT((_L("CCMRMediaRecorderImp::MaroError() out")));
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::MaooError
// Active output error callback
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::MaooError(TInt aError)
    {
    PRINT((_L("CCMRMediaRecorderImp::MaooError(), error %d, forwarding error to iErrorReporter"),aError));
    iErrorReporter->FatalError( aError );
    // assumes the controller will stop us
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetPreferredVideoEncoderL
// Set video encoder using its UID. Usage optional.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetPreferredVideoEncoderL(TUid& aEncoder)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetPreferredVideoEncoderL() in, UID: %d"), aEncoder.iUid));
    if ( (iState == EStateNone) )
        {
        // not prepared / recording yet
        PRINT((_L("CCMRMediaRecorderImp::SetPreferredVideoEncoderL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->SetPreferredVideoEncoderL( aEncoder );
    PRINT((_L("CCMRMediaRecorderImp::SetPreferredVideoEncoderL() out")));
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::SetPreferredVideoEncapsulationL
// Set video encoder output format encapsulation. Usage optional.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::SetPreferredVideoEncapsulationL(TVideoDataUnitEncapsulation aCapsulation)
    {
    PRINT((_L("CCMRMediaRecorderImp::SetPreferredVideoEncapsulationL() in, encapsulation: %d"), (TInt)aCapsulation));
    if ( (iState == EStateNone) )
        {
        // not prepared / recording yet
        PRINT((_L("CCMRMediaRecorderImp::SetPreferredVideoEncapsulationL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->SetPreferredVideoEncapsulationL( aCapsulation );
    PRINT((_L("CCMRMediaRecorderImp::SetPreferredVideoEncapsulationL() out")));
    }

// ---------------------------------------------------------
// CCMRMediaRecorderImp::SetSegmentTargetSizeL
// Set video encoder target segment size. Usage optional.
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRMediaRecorderImp::SetSegmentTargetSizeL(TUint aLayer, TUint aSizeBytes, TUint aSizeMacroblocks )
    {
    PRINT((_L("CCMRMediaRecorderImp::SetSegmentTargetSizeL() in")));
    if ( (iState == EStateNone) )
        {
        // not prepared / recording yet
        PRINT((_L("CCMRMediaRecorderImp::SetSegmentTargetSizeL() wrong state")));
        User::Leave( KErrNotReady );
        }
    iVideoRecorder->SetSegmentTargetSizeL( aLayer,  aSizeBytes, aSizeMacroblocks);
    PRINT((_L("CCMRMediaRecorderImp::SetSegmentTargetSizeL() out")));
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRErrorReporter::CCMRErrorReporter
// Default constructor
// -----------------------------------------------------------------------------
//
CCMRMediaRecorderImp::CCMRErrorReporter::CCMRErrorReporter(MCMRMediaRecorderObserver *aObserver) : CActive(EPriorityNormal), iObserver(aObserver)
    {
    CActiveScheduler::Add(this);
    iRunning = EFalse;
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRErrorReporter::~CCMRErrorReporter
// Destructor
// -----------------------------------------------------------------------------
//
CCMRMediaRecorderImp::CCMRErrorReporter::~CCMRErrorReporter()
    {
    PRINT((_L("CCMRErrorReporter::~CCMRErrorReporter")));
    Cancel();
    iErrors.Close();
    }


// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRErrorReporter::FatalError
// Report fatal error
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::CCMRErrorReporter::FatalError(TInt aError)
    {
    if ( !IsActive() )
        {
 		iStatus=KRequestPending;
		SetActive();
		TRequestStatus *tmp=(&iStatus);
		User::RequestComplete(tmp,0);
        }
    TInt error = iErrors.Append( TCMRError(aError, EErrorFatal) );
    if ( error != KErrNone )
        {
        PRINT((_L("CCMRMediaRecorderImp::CCMRErrorReporter::FatalError() OOM error in storing error code.")));
        MRASSERT( 0 );        
        }    
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRErrorReporter::TemporaryError
// Report temporary error
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::CCMRErrorReporter::TemporaryError(TInt aError)
    {
    if ( !IsActive() )
        {
 		iStatus=KRequestPending;
		SetActive();
		TRequestStatus *tmp=(&iStatus);
		User::RequestComplete(tmp,0);
        }
    TInt error = iErrors.Append( TCMRError(aError, EErrorTemp) );
    if ( error != KErrNone )
        {
        PRINT((_L("CCMRMediaRecorderImp::CCMRErrorReporter::TemporaryError() OOM error in storing error code.")));
        MRASSERT( 0 );        
        }
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRErrorReporter::RunL
// Serve error reporting requests
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::CCMRErrorReporter::RunL()
    {
    PRINT((_L("CCMRMediaRecorderImp::CCMRErrorReporter::RunL() in")));
    if ( !iRunning )
        {
        // this may be called again while observer callback is running, since callback calls MR::StopL which sets activescheduler running
        iRunning = ETrue;

        while ( iErrors.Count() > 0 )
            {
            TCMRError tmp = iErrors[0];
            if ( tmp.iErrorType == EErrorFatal )
                {
                iObserver->MmroFatalError(tmp.iErrorCode);
                }
            else
                {
                iObserver->MmroTemporaryError(tmp.iErrorCode);
                }
            iErrors.Remove(0);
            }

        iErrors.Reset();
        iRunning = EFalse;
        }
    PRINT((_L("CCMRMediaRecorderImp::CCMRErrorReporter::RunL() out")));
    }

// -----------------------------------------------------------------------------
// CCMRMediaRecorderImp::CCMRErrorReporter::DoCancel
// Cancel pending requests
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCMRMediaRecorderImp::CCMRErrorReporter::DoCancel()
    {
    // activation & request are set at the same time => nothing to cancel
    }



// End of file