camcordermmfplugin/mediarecorder/Src/CCMRAudioInput.cpp
changeset 0 9b3e960ffc8a
child 8 6bc4220d7f67
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camcordermmfplugin/mediarecorder/Src/CCMRAudioInput.cpp	Thu Dec 17 08:51:24 2009 +0200
@@ -0,0 +1,1041 @@
+/*
+* Copyright (c) 2004 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:  Audio input class for handling audio data and giving it to CCMRActiveOutput
+*
+*/
+
+
+// INCLUDES
+#include "CCMRAudioInput.h"
+#include "CCMRAudioInputSW.h"
+#include "CCMRAudioInputHW.h"
+#include "CCMRActiveOutput.h"
+#include "CCMRAudioCodecData.h"
+#include "CCMRFifo.h"
+#include "CCMRVideoHWParams.h"
+#include "CCMRConfigManager.h"
+#include <mmf/server/mmfaudioinput.h>
+#include <AudioInput.h>
+#include <AudioPreference.h>                // For MMF audio preference definitions.
+#include <mmf/common/mmfaudio.h>            // For KMMFEventCategoryAudioLoadingComplete
+
+// CONSTANTS
+// Initial number of buffers allocated
+const TInt KCMRNumAudioBuffers = 10;
+
+// MACROS
+#define AIASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CCMRAUDIOINPUT"), EInternalAssertionFailure))
+
+// Debug print macro
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x
+#else
+#define PRINT(x)
+#endif
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::~CCMRAudioInput
+// -----------------------------------------------------------------------------
+//
+CCMRAudioInput::~CCMRAudioInput()
+    {
+
+    if ( iInputEmpty )
+        {
+        delete iInputEmpty;
+        iInputEmpty = NULL;
+        }
+    if ( iInputFilled )
+        {
+        delete iInputFilled;
+        iInputFilled = NULL;
+        }
+    if ( iOutputFilled )
+        {
+        delete iOutputFilled;
+        iOutputFilled = NULL;
+        }
+    if ( iOutputEmptied )
+        {
+        delete iOutputEmptied;
+        iOutputEmptied = NULL;
+        }
+
+    if ( (!iSrcBufRef) && iDevSoundBuffer )
+        {
+        delete iDevSoundBuffer;
+        iDevSoundBuffer = NULL;
+        }
+    if ( iProcessingBuffer )
+        {
+        // we happen to have the last buffer still in process, must delete it now
+        delete iProcessingBuffer;
+        iProcessingBuffer = NULL;
+        }
+
+    if ( iDecConfigInfo )
+        {
+        delete iDecConfigInfo;
+        iDecConfigInfo = NULL;
+        // iOutputVideoBuffer is not used with decspecinfo
+        }
+
+    if ( iMediaSinkBuffer )
+        {
+        delete iMediaSinkBuffer;
+        iMediaSinkBuffer = NULL;
+        }
+
+    iOutputThreadHandle.Close();
+
+    if ( iMutexCreated )
+        {
+        iMutexObj.Close();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::ConstructL(CCMRActiveOutput* aOutput, TUint aThreadId, CCMRConfigManager* aConfig )
+    {
+    PRINT((_L("CCMRAudioInput::ConstructL() in") ));
+    iConfig = aConfig; // doesn't own
+    iPrioritySettings.iPriority = KAudioPriorityVideoRecording;
+    iPrioritySettings.iPref =  TMdaPriorityPreference( KAudioPrefVideoRecording );
+
+    // Create input fifos
+    // this fifo is for buffers that are available for storing data from MMFAudioInput/DevSound
+    iInputEmpty = CCMRFifo::NewL(KCMRNumAudioBuffers);
+    // this fifo is for buffers that are storing data from MMFAudioInput/DevSound
+    iInputFilled = CCMRFifo::NewL(KCMRNumAudioBuffers);
+    // this fifo is for buffers that contain encoded data and are waiting for sink to retrieve
+    iOutputFilled = CCMRFifo::NewL(KCMRNumAudioBuffers);
+    // this fifo is for buffers that sink has read and are available for reuse in iOutputFilled
+    iOutputEmptied = CCMRFifo::NewL(KCMRNumAudioBuffers);
+
+    iFirstTime = ETrue;
+    iFirstBufferRequested = EFalse;
+    iTimeStampWhenPaused = TTimeIntervalMicroSeconds(0);
+    User::LeaveIfError(iOutputThreadHandle.Open(aThreadId));
+    User::LeaveIfError(iMutexObj.CreateLocal());
+    iMutexCreated = ETrue;
+
+    iMediaSinkBuffer = new (ELeave) CCMRMediaBuffer();
+    iConsumer = aOutput;
+    iConsumer->RegisterSourceL( this );
+
+    PRINT((_L("CCMRAudioInput::ConstructL() out") ));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SetCodecL
+//
+// Set codec
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SetCodecL( CCMRAudioCodecData* aCodecData )
+    {
+    PRINT((_L("CCMRAudioInput::SetCodecL() in")));
+    iCodecData = aCodecData;
+    PRINT((_L("CCMRAudioInput::SetCodecL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SourcePrimeL
+// Primes the source
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SourcePrimeL()
+    {
+    PRINT((_L("CCMRAudioInput::SourcePrimeL()")));
+    iDevSoundBuffer = NULL;
+    iSendBufCount = 0;
+    iFirstTime = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SourceRecordL
+// Start recording
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SourceRecordL()
+    {
+    PRINT((_L("CCMRAudioInput::SourceRecordL() in")));
+    ConfigDevSoundL();
+    iState = EStateRecording;
+    iSamplesUpdatedAfterStart = EFalse;
+    iFirstBufferRequested = EFalse;
+    PRINT((_L("CCMRAudioInput::SourceRecordL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SourcePauseL
+// Pause recording
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SourcePauseL()
+    {
+    PRINT((_L("CCMRAudioInput::SourcePauseL(), calling iDataSource->SourceStopL")));
+    iState = EStateStopping;
+
+    // store the latest timestamp - must do it already here, since sending event may reset it and we should not touch it after reset
+  	MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+    CMMFDevSound* devSound = &audioInput->SoundDevice();
+    TInt sampleRate = iCodecData->GetSampleRate();
+
+	TBool firstPause = EFalse;
+	if (iTimeStampWhenPaused == 0)
+		{
+		firstPause = ETrue;
+		}
+
+    if ( sampleRate )
+        {
+        TTimeIntervalMicroSeconds currentTimeStamp;
+        currentTimeStamp = devSound->SamplesRecorded();
+        currentTimeStamp = currentTimeStamp.Int64() * 1000000;
+        currentTimeStamp = currentTimeStamp.Int64() / sampleRate;
+        iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + currentTimeStamp.Int64();
+        }
+    else
+        {
+        iTimeStampWhenPaused = 0;
+        }
+
+   	TInt initialDelay = 0;
+    // Add A/V sync constant to paused timestamp
+	if ( iConfig && iConfig->IsICMConfigDataAvailable() )
+		{
+		PRINT((_L("CCMRAudioInput::SourcePauseL(), using ICM setting value for AVsync delay")));
+		iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + (iConfig->VideoQualitySettings().iAVSyncResumeDelay*1000);
+		initialDelay = iConfig->VideoQualitySettings().iAVSyncStartDelay;
+		}
+	else
+		{
+		initialDelay = KCMRInitialVideoAudioTimeSyncDC;
+		if ( sampleRate <= KCMRPauseVideoAudioTimeSyncDC_LowSampleRateValue )
+		    {
+		    PRINT((_L("CCMRAudioInput::SourcePauseL(), using LowSampleRateValue")));
+		    iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + (KCMRPauseVideoAudioTimeSyncDC_LowSampleRate*1000);
+		    }
+		else if ( sampleRate <= KCMRPauseVideoAudioTimeSyncDC_MidSampleRateValue )
+			{
+		    PRINT((_L("CCMRAudioInput::SourcePauseL(), using MidSampleRateValue")));
+		    iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + (KCMRPauseVideoAudioTimeSyncDC_MidSampleRate*1000);
+			}
+		else
+		    {
+		    iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + (KCMRPauseVideoAudioTimeSyncDC*1000);
+		    }
+		}
+
+    // Add startdelay if first pause.
+    if ( firstPause )
+	    {
+	    // only add start delay if we haven't been paused. Only add delay after first audio available
+		if ( initialDelay < 0 )
+			{
+			if ( iTimeStampWhenPaused > -(initialDelay*1000) )
+				{
+				iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + (initialDelay*1000);
+				}
+			else
+				{
+				iTimeStampWhenPaused = 0;
+				}
+			}
+		else
+			{
+			iTimeStampWhenPaused = iTimeStampWhenPaused.Int64() + (initialDelay*1000);
+			}
+	    }
+
+    // Stop audio.
+    PRINT((_L("CCMRAudioInput::SourceStopL() DevSound SourceStopL()")));
+    devSound->Stop();
+
+    if ( iOutputFilled->IsEmpty() )
+        {
+        PRINT((_L("CCMRAudioInput::SourcePauseL(), no data buffers queued so no chance to signal end of data; sending an event instead")));
+        TMMFEvent event (KMMFEventCategoryPlaybackComplete, KErrNone);
+    	iEventHandler.SendEventToClient(event);
+        }
+
+    PRINT((_L("CCMRAudioInput::SourcePauseL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SourceStopL
+// Stop playing (recording)
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SourceStopL()
+    {
+    PRINT((_L("CCMRAudioInput::SourceStopL() in")));
+    if ( iState != EStateStopping )
+        {
+        // we came here without pause => there was an error, must stop source
+        PRINT((_L("CCMRAudioInput::SourceStopL() DevSound SourceStopL()")));
+        MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+        CMMFDevSound* devSound = &audioInput->SoundDevice();
+        devSound->Stop();
+        iFirstBufferRequested = EFalse;
+        }
+    // else data source was already stopped in pause
+    iState = EStateStopped;
+    PRINT((_L("CCMRAudioInput::SourceStopL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SetSourcePrioritySettings
+// Set priority settings to source
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SetSourcePrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
+    {
+    iPrioritySettings = aPrioritySettings;
+    MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+    CMMFDevSound* devSound = &audioInput->SoundDevice();
+    devSound->SetPrioritySettings(aPrioritySettings);
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SoundDevice
+// Get reference to DevSound from MMFAudioInput
+// -----------------------------------------------------------------------------
+//
+CMMFDevSound& CCMRAudioInput::SoundDevice()
+    {
+	MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+    return audioInput->SoundDevice();
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::ResetTimeStamp
+//
+// Resets audio timestamp before new recording; can't be reset automatically
+// in stop/play since they are used also in pause/resume when the stamp should
+// not reset
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::ResetTimeStamp()
+    {
+    iTimeStampWhenPaused = TTimeIntervalMicroSeconds(0);
+    iNumFramesReceived = 0;
+    iDecConfigInfoChecked = EFalse;
+    iSamplesUpdatedAfterStart = EFalse;
+    iLatestTimeStamp = 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::SendEventToClient
+// Stop & send event (error) to client
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::SendEventToClient(const TMMFEvent& aEvent)
+	{
+    PRINT((_L("CCMRAudioInput::SendEventToClient() in, event & error, %x & %d"), aEvent.iEventType, aEvent.iErrorCode));
+    TRAPD(error,SourceStopL()); // errors can be ignored, we are already reporting an error here
+    if (error != KErrNone)
+        {
+        PRINT((_L("CCMRAudioInput::SendEventToClient() stop error: %d"), error));
+        }
+	iEventHandler.SendEventToClient(aEvent);
+    PRINT((_L("CCMRAudioInput::SendEventToClient() out")));
+	}
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::NewBufferL
+// Inform sink about new coded buffer, and store it in iOutputCoded unless there
+// aren't any older buffer under processing
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::NewBufferL(CMMFBuffer* aBuffer)
+    {
+    // enter restricted area
+    iMutexObj.Wait();
+
+    CMMFBuffer* storeBuffer = NULL;
+    storeBuffer = aBuffer;
+
+    TInt bufLength = storeBuffer->BufferSize();
+    TInt frameLength = 1;   // set to 1 since nonzero needed as the initial value in the while-loop below
+    TUint8* data = const_cast<TUint8*>((static_cast<CMMFDataBuffer*>(storeBuffer))->Data().Ptr());
+    while ( (bufLength > 0) && (frameLength > 0) )
+        {
+        frameLength = iCodecData->FrameLength( data, bufLength );
+        bufLength -= frameLength;
+        data += frameLength;
+        iNumFramesReceived++;
+        iNumFramesWaiting++;
+        }
+
+    TInt error = KErrNone;
+    if ( iProcessingBuffer )
+        {
+        // there is one under processing, store this one to fifo
+        TRAP(error, iOutputFilled->PutL( reinterpret_cast<TAny*>(storeBuffer) ));
+        PRINT((_L("CCMRAudioInput::NewBufferL() added %x to fifo. Fifo size %d"), storeBuffer, iOutputFilled->NumberOfItems() ));
+        }
+    else
+        {
+        // take it into use immediately
+        iProcessingBuffer = static_cast<CMMFDataBuffer*>(storeBuffer);
+        iProcessingIndex = 0;
+        iSrcNumUnreadBytes = storeBuffer->BufferSize();
+        PRINT((_L("CCMRAudioInput::NewBufferL() taken buffer into iProcessingBuffer %x, size %d"), storeBuffer, iSrcNumUnreadBytes ));
+        }
+
+    // signal to sink
+    if ( ( error == KErrNone ) && iSinkRequestStatus  )
+        {
+        PRINT((_L("CCMRAudioInput::EmptyBufferL() RequestComplete")));
+        iOutputThreadHandle.RequestComplete( iSinkRequestStatus, KErrNone );
+        }
+    else
+        {
+        // else a new request has not been issued yet; this buffer will be handled jointly with previous ones
+        PRINT((_L("CCMRAudioInput::NewBufferL() skipping RequestComplete")));
+        }
+
+    // leave restricted area
+    iMutexObj.Signal();
+
+    if ( error != KErrNone )
+        {
+        // leave postponed here to get out of mutex
+        PRINT((_L("CCMRAudioInput::NewBufferL() leave with error code %d"), error));
+        User::Leave( error );
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::FillBufferL
+// Ask new buffers from devsound.
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::FillBufferL()
+    {
+    PRINT((_L("CCMRAudioInput::FillBufferL() in")));
+    //this is a one-shot "prime" funtion for MMFDevSound as first buffer is uninitialised
+    MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+    CMMFDevSound* devSound = &audioInput->SoundDevice();
+
+    if (!iFirstBufferRequested)
+        {
+        PRINT((_L("CCMRAudioInput::FillBufferL() DevSound RecordInitL")));
+        devSound->RecordInitL();
+        iFirstBufferRequested = ETrue;
+        PRINT((_L("CCMRAudioInput::FillBufferL() out")));
+        return;
+        }
+    PRINT((_L("CCMRAudioInput::FillBufferL() DevSound RecordData")));
+    devSound->RecordData();
+    PRINT((_L("CCMRAudioInput::FillBufferL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::RequestNewData
+// Output active object is ready to accept new data
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::RequestNewData(TRequestStatus& aStatus)
+    {
+	PRINT((_L("CCMRAudioInput::RequestNewData() - START - aStatus: 0x%08x, iSinkRequestStatus: 0x%08x"), &aStatus, iSinkRequestStatus ));
+    // enter restricted area
+    iMutexObj.Wait();
+
+    iSinkRequestStatus = &aStatus;
+    aStatus = KRequestPending;
+
+    // leave restricted area
+    iMutexObj.Signal();
+	PRINT((_L("CCMRAudioInput::RequestNewData() - END - aStatus: 0x%08x, iSinkRequestStatus: 0x%08x"), &aStatus, iSinkRequestStatus ));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::RequestNewDataCancel
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::RequestNewDataCancel(TRequestStatus& aStatus)
+    {
+	PRINT((_L("CCMRAudioInput::RequestNewDataCancel() - START - aStatus: 0x%08x, iSinkRequestStatus: 0x%08x"), &aStatus, iSinkRequestStatus ));
+
+    // enter restricted area
+    iMutexObj.Wait();
+
+	if ( &aStatus == iSinkRequestStatus )
+		{
+		iOutputThreadHandle.RequestComplete( iSinkRequestStatus, KErrCancel );
+		}
+
+    // leave restricted area
+    iMutexObj.Signal();
+
+	PRINT((_L("CCMRAudioInput::RequestNewDataCancel() - END - aStatus: 0x%08x, iSinkRequestStatus: 0x%08x"), &aStatus, iSinkRequestStatus ));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::GetNextBuffer
+// Output active object takes the next output buffer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCMRMediaBuffer* CCMRAudioInput::GetNextBuffer()
+    {
+    PRINT((_L("CCMRAudioInput::GetNextBuffer() in")));
+
+    if ( (!iDecConfigInfoChecked) && (iState == EStateRecording)  )
+        {
+        // check if we have to provide decoder config info first
+
+        iDecConfigInfoChecked = ETrue;
+
+        TRAPD(err,
+            {
+            iDecConfigInfo = iCodecData->GetDecoderConfigInfoLC();
+            if ( iDecConfigInfo != NULL )
+                {
+                // must pop, otherwise TRAPD will panic
+                CleanupStack::Pop(iDecConfigInfo);
+                }
+            }
+            );
+        if ( err != KErrNone )
+            {
+            return NULL;
+            }
+        if ( iDecConfigInfo )
+            {
+            PRINT((_L("CCMRAudioInput::GetNextBuffer() providing decoder config info first")));
+            const TUint8* data = iDecConfigInfo->Ptr();
+            TInt length = iDecConfigInfo->Length();
+            PRINT((_L("CCMRAudioInput::GetNextBuffer() length of the info %d"), length));
+
+            iMediaSinkBuffer->Set( TPtrC8(data,length),
+                CCMRMediaBuffer::EAudioDecSpecInfo,
+                length,
+                EFalse,
+                TTimeIntervalMicroSeconds(0) );
+
+            // can handle only 1 output buffer at a time
+            iOutputBufferInUse = ETrue;
+
+            PRINT((_L("CCMRAudioInput::GetNextBuffer() with DecConfigInfo out")));
+            return iMediaSinkBuffer;
+            }
+        // else the codec doesn't provide it
+        }
+
+
+    // enter restricted area
+    iMutexObj.Wait();
+
+    // take it from fifo
+    if ( iProcessingBuffer && (!iOutputBufferInUse) )
+        {
+
+        // check frame length
+
+        TUint8* data = const_cast<TUint8*>(iProcessingBuffer->Data().Ptr());
+        data += iProcessingIndex;
+
+        AIASSERT( iCodecData );
+
+        TInt frameLength = iCodecData->FrameLength( data, iProcessingBuffer->BufferSize() );
+
+        // associate the next frame from the buffer to mediabuffer
+        iMediaSinkBuffer->Set( TPtrC8(data,frameLength),
+            iCodecData->BufferType(),
+            frameLength,
+            EFalse,
+            TTimeIntervalMicroSeconds((iNumFramesReceived - iNumFramesWaiting)*iCodecData->GetFrameDurationUs()) );
+
+        iNumFramesWaiting--;
+
+        PRINT((_L("CCMRAudioInput::GetNextBuffer() send buf of length %d"),frameLength));
+
+        iProcessingIndex += frameLength;
+        iSrcNumUnreadBytes -= frameLength;
+
+        // leave restricted area
+        iMutexObj.Signal();
+
+        // can handle only 1 output buffer at a time
+        iOutputBufferInUse = ETrue;
+
+        PRINT((_L("CCMRAudioInput::GetNextBuffer() out")));
+        return iMediaSinkBuffer;
+        }
+    else
+        {
+        // leave restricted area
+        iMutexObj.Signal();
+
+        PRINT((_L("CCMRAudioInput::GetNextBuffer() out (no data)")));
+        return NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::NumBuffersWaiting
+// Return the number of buffers in the source
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CCMRAudioInput::NumBuffersWaiting()
+    {
+    return iNumFramesWaiting;
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::LatestTimeStampL
+// Return the latest time stamp from the input stream
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::LatestTimeStampL(TTimeIntervalMicroSeconds& aTimeStamp) const
+    {
+  	// estimate the time since the previous call to devsound's samplesrecorded
+  	if ( iSamplesUpdatedAfterStart )
+  	    {
+        TTime current;
+        current.UniversalTime();
+        aTimeStamp = iLatestTimeStamp.Int64() + current.MicroSecondsFrom(iTimeWhenSamplesUpdated).Int64();
+  	    }
+    else
+        {
+        aTimeStamp = iLatestTimeStamp.Int64();
+        }
+
+    PRINT((_L("CCMRAudioInput::LatestTimeStampL() timestamp %d"), I64INT(aTimeStamp.Int64()) ));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::DurationL
+// Return the duration of the recording
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::DurationL(TTimeIntervalMicroSeconds& aDuration) const
+    {
+    aDuration = TTimeIntervalMicroSeconds(iNumFramesReceived*iCodecData->GetFrameDurationUs());
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::ReturnBuffer
+// Output active object returns an emptied buffer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::ReturnBuffer(CCMRMediaBuffer* aBuffer)
+    {
+    PRINT((_L("CCMRAudioInput::ReturnBuffer() in")));
+    // save it for reuse
+    iMediaSinkBuffer = aBuffer;
+    iOutputBufferInUse = EFalse;
+    if ( iDecConfigInfo )
+        {
+        delete iDecConfigInfo;
+        iDecConfigInfo = NULL;
+        // iOutputVideoBuffer is not used with decspecinfo
+        }
+
+    if ( !iProcessingBuffer )
+        {
+        // we must have stopped due to pausetimer in audiothreadproxysession; no need to save the buffer, it was already saved
+        return;
+        }
+
+    if ( iProcessingBuffer->LastBuffer() )
+        {
+        PRINT((_L("CCMRAudioInput::ReturnBuffer(), last data buffer given to sink; sending an event to inform completion")));
+        TMMFEvent event (KMMFEventCategoryPlaybackComplete, KErrNone);
+    	iEventHandler.SendEventToClient(event);
+        }
+
+    // enter restricted area
+    iMutexObj.Wait();
+    TInt err = KErrNone;
+    if ( iSrcNumUnreadBytes <= 0 )
+        {
+        TRAP(err,iOutputEmptied->PutL( reinterpret_cast<TAny*>(iProcessingBuffer)));
+        if ( err == KErrNone )
+            {
+            PRINT((_L("CCMRAudioInput::ReturnBuffer() save buffer %x to iOutputEmptied"),iProcessingBuffer));
+            // reset
+            iProcessingIndex = 0;
+            iProcessingBuffer = NULL;
+            if (iOutputFilled && !iOutputFilled->IsEmpty())
+                {
+                /* take the next into processing */
+                iProcessingBuffer = reinterpret_cast<CMMFDataBuffer*>(iOutputFilled->Get());
+                iProcessingIndex = 0;
+                iSrcNumUnreadBytes = iProcessingBuffer->BufferSize();
+                PRINT((_L("CCMRAudioInput::ReturnBuffer() started processing a new buffer %x from iOutputFilled"),iProcessingBuffer));
+                }
+            }
+        else
+            {
+            // Can't store in fifo; however, aBuffer was stored to iOutputBuffer already, and iProcessingBuffer is a member
+            // signal the error after got out of mutex
+            PRINT((_L("CCMRAudioInput::ReturnBuffer() putting buffer to fifo failed, deallocate the buffer")));
+            delete iProcessingBuffer;
+            iProcessingBuffer = NULL;
+            }
+        }
+    // leave restricted area
+    iMutexObj.Signal();
+
+    if ( err != KErrNone )
+        {
+        // leave postponed here to get out of mutex
+        PRINT((_L("CCMRAudioInput::ReturnBuffer() report GeneralError event with error code %d"), err));
+        TMMFEvent event(KMMFEventCategoryVideoRecorderGeneralError, err);
+        iEventHandler.SendEventToClient(event);
+        }
+
+    PRINT((_L("CCMRAudioInput::ReturnBuffer() out")));
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::ConfigDevSoundL
+// Check DevSound capabilities before configuring. If sampling rate is not
+// supported by DevSound, select the next highest sampling rate supported.
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::ConfigDevSoundL()
+	{
+    PRINT((_L("CCMRAudioInput::ConfigDevSoundL() in")));
+  	MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+    CMMFDevSound* devSound = &audioInput->SoundDevice();
+
+	// Set Audio Routing API to use default mic only.
+	// Create CAudioInput (errors trapped as this is optional feature from adaptation).
+	PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing in")));
+	CAudioInput* audioRoutingInput = NULL;
+	TRAPD(audioRoutingError, audioRoutingInput = CAudioInput::NewL( *devSound ));
+	CleanupStack::PushL(audioRoutingInput);
+	if ( audioRoutingError == KErrNone )
+		{
+		PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing API created")));
+		RArray<CAudioInput::TAudioInputPreference> inputArray;
+		if ( inputArray.Append( CAudioInput::EDefaultMic ) == KErrNone )
+			{
+			PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing API input array set to default mic.")));
+			// Set Audio Input
+			if ( audioRoutingInput )
+				{
+				TRAP(audioRoutingError, audioRoutingInput->SetAudioInputL( inputArray.Array( ) ));
+				if ( audioRoutingError )
+					{
+					// if KErrNotSupported the devsound implementation probably doesn't support custom interface.
+					PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing API SetAudioInputL failed: %d"), audioRoutingError));
+					}
+				else
+					{
+					PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing API set to default mic.")));
+					}
+				}
+			}
+		else
+			{
+			PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing API input array set to default mic failed.")));
+			}
+		inputArray.Close();
+		PRINT((_L("CCMRAudioInput::ConfigDevSoundL(), Audio Routing out")));
+		}
+	CleanupStack::PopAndDestroy(audioRoutingInput);
+
+	// Query DevSound capabilities and Try to use DevSound sample rate and
+	// mono/stereo capability
+	TMMFCapabilities devSoundCaps = devSound->Capabilities();
+	// get current config
+	TMMFCapabilities devSoundConfig = devSound->Config();
+
+	// Default PCM16
+	devSoundConfig.iEncoding = EMMFSoundEncoding16BitPCM;
+
+	// 1 = Monophonic and 2 == Stereo
+    TInt channels = iCodecData->GetNumChannels();
+    if ((channels == 2) && (devSoundCaps.iChannels & EMMFStereo))
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() stereo recording")));
+        devSoundConfig.iChannels = channels;
+        }
+	else if (devSoundCaps.iChannels & EMMFMono)
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() mono recording")));
+		devSoundConfig.iChannels = 1;
+        }
+    else
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() unsupported channel configuration requested")));
+        User::Leave( KErrNotSupported );
+        }
+
+    if ( iCodecData->GetNumChannels() != devSoundConfig.iChannels )
+	    {
+		iCodecData->SetChannelModeL(devSoundCaps.iChannels);
+    	}
+
+	// Check for std sample rates.
+    TInt sampleRate = iCodecData->GetSampleRate();
+    PRINT((_L("CCMRAudioInput::ConfigDevSoundL() got samplerate: %d from codec"), sampleRate));
+
+    // At the moment only 8 and 16 kHz is supported. If we'll get codecs with other sampling rates, this must be modified
+	if ((sampleRate == 8000) && (devSoundCaps.iRate & EMMFSampleRate8000Hz))
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() using sample rate 8000")));
+		devSoundConfig.iRate = EMMFSampleRate8000Hz;
+        }
+	else if ((sampleRate == 16000) && (devSoundCaps.iRate & EMMFSampleRate16000Hz))
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() using sample rate 16000")));
+		devSoundConfig.iRate = EMMFSampleRate16000Hz;
+        }
+	else if ((sampleRate == 24000) && (devSoundCaps.iRate & EMMFSampleRate24000Hz))
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() using sample rate 24000")));
+		devSoundConfig.iRate = EMMFSampleRate24000Hz;
+        }
+	else if ((sampleRate == 32000) && (devSoundCaps.iRate & EMMFSampleRate32000Hz))
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() using sample rate 32000")));
+		devSoundConfig.iRate = EMMFSampleRate32000Hz;
+        }
+	else if ((sampleRate == 48000) && (devSoundCaps.iRate & EMMFSampleRate48000Hz))
+        {
+        PRINT((_L("CCMRAudioInput::ConfigDevSoundL() using sample rate 48000")));
+		devSoundConfig.iRate = EMMFSampleRate48000Hz;
+        }
+    else
+		{
+        // try to set the codec to 16k samplerate.
+        if ( (sampleRate >= 16000) && (devSoundCaps.iRate & EMMFSampleRate16000Hz) )
+            {
+            // this one leaves if the rate is not supported
+            PRINT((_L("CCMRAudioInput::ConfigDevSoundL() unsupported audio samplerate - trying 16k")));
+            iCodecData->SetBitRateL( 32000 );
+            iCodecData->SetSampleRateL( 16000 );
+    		devSoundConfig.iRate = EMMFSampleRate16000Hz;
+            }
+        else if ( devSoundCaps.iRate & EMMFSampleRate8000Hz)
+            {
+            // this one leaves if the rate is not supported
+            PRINT((_L("CCMRAudioInput::ConfigDevSoundL() unsupported audio samplerate - trying 8k")));
+            iCodecData->SetBitRateL( 16000 );
+            iCodecData->SetSampleRateL( 8000 );
+    		devSoundConfig.iRate = EMMFSampleRate8000Hz;
+            }
+        else
+            {
+            PRINT((_L("CCMRAudioInput::ConfigDevSoundL() unsupported sample rate %d"), sampleRate));
+    		User::Leave( KErrNotSupported );
+            }
+		}
+	devSound->SetConfigL(devSoundConfig);
+    PRINT((_L("CCMRAudioInput::ConfigDevSoundL() out")));
+	}
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::UpdateTimeL
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::UpdateTimeL()
+    {
+    PRINT((_L("CCMRAudioInput::UpdateTimeL() in")));
+    MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+    CMMFDevSound* devSound = &audioInput->SoundDevice();
+    TInt sampleRate = iCodecData->GetSampleRate();
+
+    if ( sampleRate )
+        {
+        TInt64 samples = devSound->SamplesRecorded();
+        PRINT((_L("CCMRAudioInput::UpdateTimeL() samples recorded %d"),I64INT(samples)));
+
+        samples = samples * 1000000;
+        samples = samples / sampleRate;
+        iLatestTimeStamp = samples + iTimeStampWhenPaused.Int64();
+        }
+    else
+        {
+        iLatestTimeStamp = 0;
+        }
+
+    // only add start delay if we haven't been paused. Only add delay after first audio available
+	if ( (iTimeStampWhenPaused == 0) && (iLatestTimeStamp != 0) )
+		{
+		TInt initialDelay = 0;
+	    // Add A/V sync constant to timestamp
+		if ( iConfig && iConfig->IsICMConfigDataAvailable() )
+			{
+			PRINT((_L("CCMRAudioInput::UpdateTimeL(), using ICM setting value for AVsync delay")));
+			initialDelay = iConfig->VideoQualitySettings().iAVSyncStartDelay;
+			}
+		else
+			{
+			PRINT((_L("CCMRAudioInput::UpdateTimeL(), using old setting value for AVsync delay")));
+			initialDelay = KCMRInitialVideoAudioTimeSyncDC;
+			}
+
+		if ( initialDelay < 0 )
+			{
+			if ( iLatestTimeStamp > -( initialDelay*1000) )
+				{
+				iLatestTimeStamp = iLatestTimeStamp.Int64() + ( initialDelay*1000 );
+				}
+			else
+				{
+				iLatestTimeStamp = 0;
+				}
+			}
+		else
+			{
+			iLatestTimeStamp = iLatestTimeStamp.Int64() + ( initialDelay*1000 );
+			}
+		}
+
+	if ( iLatestTimeStamp != 0 )
+		{
+	    iTimeWhenSamplesUpdated.UniversalTime();
+	    iSamplesUpdatedAfterStart = ETrue;
+		}
+    PRINT((_L("CCMRAudioInput::UpdateTimeL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::InitializeComplete
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::InitializeComplete(TInt aError)
+    {
+    PRINT((_L("CCMRAudioInput::InitializeComplete() in, error:%d"), aError));
+    TInt error = aError;
+    if ( error == KErrNone )
+        {
+        MMMFAudioInput* audioInput = static_cast<MMMFAudioInput*>(iMMFDataSource);
+        PRINT((_L("CCMRAudioInput::InitializeComplete() SetPrioritySettings")));
+        audioInput->SoundDevice().SetPrioritySettings(iPrioritySettings);
+        PRINT((_L("CCMRAudioInput::InitializeComplete() ConfigDevSoundL")));
+        TRAP(error, ConfigDevSoundL());
+        if (error == KErrNone)
+            {
+            PRINT((_L("CCMRAudioInput::InitializeComplete() AllocateInputBuffersL")));
+            TRAP(error, AllocateInputBuffersL());
+            }
+        else
+            {
+            PRINT((_L("CCMRAudioInput::InitializeComplete() ConfigDevSoundL, error=%d"), error));
+            }
+        }
+    PRINT((_L("CCMRAudioInput::InitializeComplete() SendEventToClient KMMFEventCategoryAudioLoadingComplete, error: %d"), error));
+    TMMFEvent event(KMMFEventCategoryAudioLoadingComplete, error);
+    iEventHandler.SendEventToClient(event);
+    PRINT((_L("CCMRAudioInput::InitializeComplete() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::ToneFinished
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::ToneFinished(TInt aError)
+    {
+    PRINT((_L("CCMRAudioInput::ToneFinished(), error:%d"), aError));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::BufferToBeFilled
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::BufferToBeFilled(CMMFBuffer* /*aBuffer*/)
+    {
+    PRINT((_L("CCMRAudioInput::BufferToBeFilled()")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::PlayError
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::PlayError(TInt aError)
+    {
+    PRINT((_L("CCMRAudioInput::PlayError(), error:%d"), aError));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::BufferToBeEmptied
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::BufferToBeEmptied(CMMFBuffer* aBuffer)
+    {
+    PRINT((_L("CCMRAudioInput::BufferToBeEmptied()")));
+    TInt error = KErrNone;
+    TRAP(error, BufferFilledL(aBuffer));
+    if (error != KErrNone)
+        {
+        TMMFEvent event (KMMFEventCategoryPlaybackComplete, error);
+        SendEventToClient( event );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::RecordError
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::RecordError(TInt aError)
+    {
+    PRINT((_L("CCMRAudioInput::RecordError(), error=%d"), aError));
+    TMMFEvent event (KMMFEventCategoryPlaybackComplete, aError);
+    iEventHandler.SendEventToClient(event);
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::ConvertError
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::ConvertError(TInt aError)
+    {
+    PRINT((_L("CCMRAudioInput::ConvertError(), error:%d"), aError));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioInput::DeviceMessage
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioInput::DeviceMessage(TUid /*aMessageType*/, const TDesC8& /*aMsg*/)
+    {
+    PRINT((_L("CCMRAudioInput::DeviceMessage()")));
+    }
+
+
+// End of file
+
+