multimediacommscontroller/mmccfilesourcesink/src/mccfileaudio.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccfilesourcesink/src/mccfileaudio.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,506 @@
+/*
+* Copyright (c) 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:  
+*
+*/
+
+
+
+
+#include "mccfileaudio.h"
+#include "mmcccodecinformation.h"
+#include "mccperiodicrunner.h"
+#include "mccfilesourcelogs.h"
+#include "mccinternaldef.h"
+
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::NewL
+// -----------------------------------------------------------------------------
+//
+CMccFileAudio* CMccFileAudio::NewL( CMccFileSourceImpl& aSource )
+	{
+	CMccFileAudio* self = new (ELeave) CMccFileAudio ( aSource );
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMccFileAudio::ConstructL()
+	{
+	CMccFileSourceTypeBase::ConstructL();	
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::CMccFileAudio
+// -----------------------------------------------------------------------------
+//
+CMccFileAudio::CMccFileAudio( CMccFileSourceImpl& aSource )
+	: CMccFileSourceTypeBase ( aSource, KUidMediaTypeAudio ),
+	  iBufferType ( CCMRMediaBuffer::EAudioAMRNB )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::~CMccFileAudio
+// -----------------------------------------------------------------------------
+//
+CMccFileAudio::~CMccFileAudio( )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::FillBufferL
+// -----------------------------------------------------------------------------
+//
+void CMccFileAudio::FillBufferL( 
+    CMMFBuffer* aBuffer,
+    MDataSink* aConsumer )
+	{
+	CMccFileSourceTypeBase::FillBufferL( aBuffer, aConsumer );
+	
+	// There might be pending audio frames, read the oldest one immediately
+	WriteBufferL();
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::ParseUpdateAudioDescriptions
+// -----------------------------------------------------------------------------
+//
+TBool CMccFileAudio::ParseUpdateAudioDescriptions( MP4Handle aMP4Handle )
+	{
+	TBool isAudio = EFalse;
+	
+	mp4_u32 timeScale = 0;
+	if ( MP4ParseRequestAudioDescription( aMP4Handle,
+         ( mp4_u32* ) &iLength, ( mp4_u32* ) &iType,
+         ( mp4_u8* ) &iFramesPerSample, ( mp4_u32* ) &timeScale,
+         ( mp4_u32* ) &iAverageBitRate )
+         == MP4_OK )
+	    {
+        if ( iType == MP4_TYPE_AMR_NB )
+	        {
+	        __FILESOURCE_CONTROLL( "CMccFileAudio:ParseUpdateAudioDescriptions \
+MP4_TYPE_AMR_NB!" )
+
+	        iBufferType = CCMRMediaBuffer::EAudioAMRNB;
+	        isAudio = ETrue;
+	        iFourCC = TFourCC( KMccFourCCIdAMRNB );
+	        }
+	    else if ( iType != MP4_TYPE_NONE )
+	        {
+	        __FILESOURCE_CONTROLL( "CMccFileAudio:ParseUpdateAudioDescriptions \
+contains unsupported audio" )
+
+		    iFourCC = TFourCC( KMccFourCCUnsupported );
+	        }
+	    else
+	        {
+	        // NOP
+	        }
+	    }
+	return isAudio;	
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::DoSetPositionL
+// -----------------------------------------------------------------------------
+//
+void CMccFileAudio::DoSetPositionL( TUint32 aPosition )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileAudio::DoSetPositionL" )
+
+    __ASSERT_ALWAYS( aPosition <= iLength, User::Leave( KErrArgument ) );
+
+    mp4_u32 videoPos = 0;
+    if ( MP4ParseSeek( iMP4Handle, ( mp4_u32 ) aPosition,
+         ( mp4_u32* ) &iPosition, ( mp4_u32* ) &videoPos, MP4TRUE )
+         != MP4_OK )
+        {   
+        User::Leave( KErrGeneral );
+        }	
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::Type
+// -----------------------------------------------------------------------------
+//
+CCMRMediaBuffer::TBufferType CMccFileAudio::Type()
+	{
+	return iBufferType;
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::GetFourCC
+// -----------------------------------------------------------------------------
+//
+TFourCC CMccFileAudio::GetFourCC()
+	{
+	return iFourCC;
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::TickCallBack
+// -----------------------------------------------------------------------------
+//
+TCallBack CMccFileAudio::TickCallBack()
+    {
+    return TCallBack( TickAudioL, this );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccFileAudio::PositionL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMccFileAudio::Position()
+	{
+	return iPosition;	
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::DurationL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMccFileAudio::Duration()
+	{
+	return iLength;	
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::AudioBitRateL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMccFileAudio::AudioBitRate()
+	{
+	return iAverageBitRate;	
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::VideoFrameSizeL
+// -----------------------------------------------------------------------------
+//
+TSize CMccFileAudio::VideoFrameSize()
+	{
+	TSize size;
+    return size;
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileAudio::VideoFrameRateL
+// -----------------------------------------------------------------------------
+//
+TReal CMccFileAudio::VideoFrameRateL()
+	{
+	return 0;	
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::StartTimerL
+// -----------------------------------------------------------------------------
+//
+void CMccFileAudio::StartTimerL()
+	{
+	__FILESOURCE_CONTROLL( "CMccFileAudio::StartTimerL" )
+	
+	if ( IsPaused() )
+	    {
+	    SetPaused( EFalse );
+	    
+	    SetPositionL( iPosition, ETrue );
+	    }
+	else
+	    {
+	    SetStartTime();
+	    }
+	
+	const TInt KMccFileIntervalMinInterval = 60000;       
+	const TInt KMccFileAudioPTime = 20000;
+	TInt tickIntervalAudio = 0;
+	iReadsPerInterval = 0;
+	
+	__ASSERT_ALWAYS( iFramesPerSample > 0, User::Leave( KErrArgument ) );
+	
+	while ( tickIntervalAudio < KMccFileIntervalMinInterval )
+        {
+        tickIntervalAudio += KMccFileAudioPTime * iFramesPerSample;
+        iReadsPerInterval++;
+        }
+    
+   	__FILESOURCE_CONTROLL_INT1( "CMccFileAudio::StartTimer (timer):", 
+                            tickIntervalAudio )
+                            
+    iTimerInterval = tickIntervalAudio;
+    iCorrectionInterval = iTimerInterval;
+    
+	iPeriodicRunner->Start( tickIntervalAudio, TCallBack( TickAudioL, this ) );	
+ 
+	__FILESOURCE_CONTROLL( "CMccFileAudio::StartTimerL, exit" )	
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::TickAudioL
+// -----------------------------------------------------------------------------
+//
+TInt CMccFileAudio::TickAudioL( TAny* aObject )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileAudio::TickAudioL" )
+	
+	CMccFileAudio* self = static_cast<CMccFileAudio*>( aObject );
+
+    TBool read( ETrue );
+    TInt readsPerInterval( self->iReadsPerInterval );
+    for ( TInt i = 0; i < readsPerInterval && read; i++ )
+        {
+        // Do timing correction only after everything within this cycle has
+        // been read
+        TBool doTimingCorrection( ( i + 1 ) == readsPerInterval );
+        read = self->ReadFrameL( doTimingCorrection );
+        }
+   
+    return KErrNone;	
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::ReadFrameL
+// -----------------------------------------------------------------------------
+//
+TBool CMccFileAudio::ReadFrameL( TBool aDoTimingCorrection )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileAudio::ReadFrameL" )	    
+	   
+
+	if ( MP4ParseIsFrameAvailable( iMP4Handle, MP4_TYPE_AMR_NB ) != MP4_OK )
+        {	
+        __FILESOURCE_CONTROLL( "CMccFileAudio::ReadFrameL, no audio" ) 
+
+		SetPaused( ETrue );
+		TRAPD( positionErr, SetPositionL( 0 ) );
+		iSource.PauseAudioL( positionErr );	
+        return EFalse;	
+        }
+    
+	MP4ParseNextFrameSize( iMP4Handle, MP4_TYPE_AMR_NB,
+        ( mp4_u32* ) &iBufferSize );
+
+    HBufC8* mediaBuffer = HBufC8::NewLC( iBufferSize );
+    TPtr8 mediaSinkBuffer = mediaBuffer->Des();
+    mediaSinkBuffer.SetLength( iBufferSize );
+    TUint8* bufPtr = CONST_CAST(TUint8*, mediaSinkBuffer.Ptr());
+
+    TUint32 oldPosition = iPosition;
+    if ( MP4ParseReadAudioFrames( iMP4Handle,
+        ( mp4_u8* )  bufPtr,
+        ( mp4_u32 ) iBufferSize, ( mp4_u32* ) &iAudioSize,
+        ( mp4_u32* ) &iPosition, ( mp4_u32* ) &iReturnedFrames,
+		NULL ) == MP4_OK )
+		{
+		__FILESOURCE_CONTROLL_INT1( ":ReadFrameL:ReadAudioFrameL, \
+read, time position", iPosition ) 	
+        __FILESOURCE_CONTROLL_INT1( ":ReadFrameL:ReadAudioFrameL, \
+read, returned frames", iReturnedFrames ) 	
+
+        if ( aDoTimingCorrection )
+            {
+            DoTimingCorrection( iPosition );
+            }
+	
+	    // Update read interval (how much position changes on each frame read)
+        iReadInterval = iPosition - oldPosition;
+    				
+		// Calculate real frame size from sample size
+        TInt frameSize = iBufferSize / iReturnedFrames;
+        TUint counter = 0;
+        TInt addToTimeStamp = 0;
+        TInt startPosition = 0;
+        TInt mediaBufferLen = mediaBuffer->Length();
+        
+        while ( ( counter < iReturnedFrames ) && 
+                ( startPosition < mediaBufferLen ) )
+            {
+            counter++;
+	
+			frameSize = GetFrameLength( mediaBuffer->Mid( startPosition ) );
+		    if ( frameSize != 0 && ( startPosition + frameSize <= mediaBufferLen ) )
+			    {
+			    TTimeIntervalMicroSeconds timeStamp = 
+            	    GetTimeStamp( addToTimeStamp );
+            	
+                CMccFrameItem* item = new (ELeave) CMccFrameItem();
+                CleanupStack::PushL( item );
+                item->iFrame = HBufC8::NewL( frameSize );
+                item->iFrame->Des().Copy( 
+                    mediaBuffer->Mid( startPosition, frameSize ) );
+                item->iTimeStamp = timeStamp;
+                User::LeaveIfError( iFrames.Append( item ) );
+                CleanupStack::Pop( item );
+			    }
+	   	    addToTimeStamp += 20000;
+            startPosition += frameSize;				
+            }    
+		}
+	else
+		{
+		__FILESOURCE_CONTROLL( ":ReadFrameL:ReadAudioFrameL, \
+reading frames failed" )
+		}
+    CleanupStack::PopAndDestroy(mediaBuffer);
+	mediaBuffer = NULL; 
+
+	__FILESOURCE_CONTROLL( ":ReadFrameL:ReadAudioFrameL, \
+writing buffer, copying" )
+
+    WriteBufferL();
+    
+    return ETrue;
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::WriteBufferL
+// -----------------------------------------------------------------------------
+//
+void CMccFileAudio::WriteBufferL()
+	{
+	__FILESOURCE_CONTROLL("CMccFileAudio::WriteBufferL")
+	
+    if ( iFrames.Count() && iConsumer && iConsumerBuffer )
+	    {
+	    CMMFDataBuffer* buf = static_cast<CMMFDataBuffer*>(iConsumerBuffer); 
+	    
+	    HBufC8* audioFrame = (iFrames[0])->iFrame;
+	    // to be sure the source buffer length is greater or equal
+	    if ( buf->Data().MaxLength() >= audioFrame->Des().Length() )
+		    {   
+			buf->Data().Copy( *audioFrame );
+			iConsumerBuffer->SetTimeToPlay((iFrames[0])->iTimeStamp);
+			iConsumerBuffer->SetLastBuffer(EFalse);
+			iConsumerBuffer->SetFrameNumber( iSequenceNum );
+			delete iFrames[0];
+			iFrames.Remove(0);
+			audioFrame = NULL;
+			iConsumer->BufferFilledL( iConsumerBuffer );
+			iConsumer = NULL;
+			iConsumerBuffer = NULL;
+			iSequenceNum++;
+			__FILESOURCE_CONTROLL("CMccFileAudio::WriteBufferL, done")	
+		    }
+		else
+			{
+			__FILESOURCE_CONTROLL("CMccFileAudio::WriteBufferL, frame dropped")
+			
+			delete iFrames[0];
+			iFrames.Remove(0);
+			audioFrame = NULL;
+			}
+	    }
+	else
+		{
+		__FILESOURCE_CONTROLL("CMccFileAudio::WriteBufferL, writing ignored")
+		}	
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::GetFrameLength
+// -----------------------------------------------------------------------------
+//	
+TUint32 CMccFileAudio::GetFrameLength( TPtrC8 aData )
+	{
+	const TUint8 *ptrData=aData.Ptr();
+	//read FT from data
+	TUint8 fT = (TUint8) ( *ptrData & 0x78 );
+	fT = TUint8 ( fT >> 3 );
+	//return frame length
+	switch ( fT )
+		{
+		case 0: //amr 4.75
+			{
+			const TUint32 number13 = 13;
+	        return number13;
+	        }
+        case 1: //amr 5.15
+			{
+			const TUint32 number14 = 14;
+	        return number14;
+	        }
+		case 2: //amr 5.9
+			{
+			const TUint32 number16 = 16;
+
+			return number16;
+	        }
+		case 3: //amr 6.7
+	        {
+	       	const TUint32 number18 = 18;
+			return number18;
+	        }
+		case 4: //amr 7.4
+			{
+			const TUint32 number20 = 20;
+			return number20;
+	        }
+        case 5: //amr 7.95
+	        {
+	        const TUint32 number21 = 21;
+			return number21;
+	        }
+        case 6: //amr 10.2
+			{
+			const TUint32 number27 = 27;
+	        return number27;
+	        }
+        case 7: //amr 12.2
+	        {
+	       	const TUint32 number32 = 32;
+	        return number32;
+	        }
+		case 8: //amr SID
+			{
+	       	const TUint32 number6 = 6;
+			return number6;
+			}
+		case 15: //no data
+			{
+	       	const TUint32 number1 = 1;
+			return number1;
+			}
+        default: //not arm narrowband
+	        {
+	        const TUint32 number0 = 0;
+			return number0;
+	        }
+        }	 
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileAudio::GetTimeStamp
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CMccFileAudio::GetTimeStamp( TUint32 aAddToTimeStamp )
+	{                       
+	TInt64 position = iPosition + iPositionModifier;
+	TUint32 position2 = ( position < 0 ) ? 0 : (TUint32)position;
+	TTimeIntervalMicroSeconds timeStamp = 
+	    TTimeIntervalMicroSeconds( ( (TInt64) position2 * KMccMicroToMilliConst ) + aAddToTimeStamp );
+
+   	__FILESOURCE_CONTROLL_INT1( "CMccFileAudio::GetTimeStamp timestamp (without clock frequency):", 
+                                timeStamp.Int64() )
+                                
+	return timeStamp;
+	}
+