camcordermmfplugin/mediarecorder/Src/CCMRMediaRecorderImp.cpp
changeset 0 9b3e960ffc8a
child 2 c7e61a0077eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camcordermmfplugin/mediarecorder/Src/CCMRMediaRecorderImp.cpp	Thu Dec 17 08:51:24 2009 +0200
@@ -0,0 +1,1594 @@
+/*
+* 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
+
+// ================= 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()
+    {
+    iState = EStateNone;
+
+    // create video recorder
+    iVideoRecorder = CCMRVideoRecorderClient::NewL();
+    // create audio recorder
+    iAudioRecorder = CCMRAudioRecorder::NewL();
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRMediaRecorderImp::~CCMRMediaRecorderImp
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CCMRMediaRecorderImp::~CCMRMediaRecorderImp()
+    {
+    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;
+
+
+    delete iAudioRecorder;
+    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() iAudioRecorder deleted")));
+    delete iPerfMonitor;
+    delete iConfig;
+    delete iVideoRecorder;
+    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() iVideoRecorder deleted")));
+    delete iAudioOutput;
+    delete iVideoOutput;
+
+    if ( iErrorReporter )
+        {
+        iErrorReporter->Cancel();
+        delete iErrorReporter;
+        }
+
+    PRINT((_L("CCMRMediaRecorderImp::~CCMRMediaRecorderImp() out")));
+    //#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)
+
+    {
+    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")));
+    }
+
+
+// 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);
+    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
+        iAudioRecorder->TargetBitRateL(abr);
+        if ( iAudioRecorder && 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()
+    {
+    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
+            }
+        }
+
+
+    }
+
+// -----------------------------------------------------------------------------
+// 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()
+    {
+    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")));
+    }
+
+// -----------------------------------------------------------------------------
+// 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);
+        }
+    iErrors.Append( TCMRError(aError, EErrorFatal) );
+    }
+
+
+// -----------------------------------------------------------------------------
+// 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);
+        }
+    iErrors.Append( TCMRError(aError, EErrorTemp) );
+    }
+
+// -----------------------------------------------------------------------------
+// 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