multimediacommscontroller/mmccfilesourcesink/src/mccfilesourceimpl.cpp
changeset 0 1bce908db942
child 18 91f50911ea81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccfilesourcesink/src/mccfilesourceimpl.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1096 @@
+/*
+* 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 FILES
+#include <es_sock.h>
+#include <e32std.h>
+#include "mccfilesourceimpl.h"
+#include "mmcccodecinformation.h"
+#include "mccfilesourcelogs.h"
+#include "mccfileaudio.h"
+#include "mccfilevideo.h"
+#include "mccinternalevents.h"
+#include "mmccinterfacedef.h"
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::NewL
+// Static constructor.
+// -----------------------------------------------------------------------------
+//
+CMccFileSourceImpl* CMccFileSourceImpl::NewL( 
+    TUint32 aEndpointId, 
+    MMccResources* aMccResources )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::NewL" )
+    
+    CMccFileSourceImpl* self = new ( ELeave ) CMccFileSourceImpl( aEndpointId );
+    CleanupStack::PushL(self);
+    self->ConstructL( aMccResources );
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::ConstructL( MMccResources* aMccResources )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::ConstructL" )
+    
+    iFileAudio = CMccFileAudio::NewL( *this );
+    iFileVideo = CMccFileVideo::NewL( *this, aMccResources, iEndpointId );
+    }
+    
+// -----------------------------------------------------------------------------
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CMccFileSourceImpl::CMccFileSourceImpl( TUint32 aEndpointId )
+	: iCurrentState( EConstructed ),
+	  iIsAudio ( EFalse ),
+	  iIsVideo ( EFalse ),
+	  iEndpointId( aEndpointId ),
+	  iDelayAfterStop( 0 ),
+	  iEofTimer( 0 )
+    {
+    }
+        
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::~CMccFileSourceImpl.
+// -----------------------------------------------------------------------------
+//
+CMccFileSourceImpl::~CMccFileSourceImpl()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::~CMccFileSourceImpl" )
+ 
+    StopEofTimer();
+
+    if ( iMP4Handle )
+	    {
+        MP4ParseClose( iMP4Handle );
+	    iMP4Handle = NULL;
+	    }
+
+    delete iFileAudio;
+	delete iFileVideo;  
+
+	iAsyncEventHandler = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::AddDataSink(MCMRMediaSink* aSink)
+//
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::AddDataSink( MCMRMediaSink* /*aSink*/ )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::AddDataSink" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::OpenFileL(TFileName aFileName)
+//
+// Opens a 3gp file for streaming and reads media descriptions into
+// member variables
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::OpenFileL( TFileName aFileName, TBool aFileChangeMode )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::OpenFileL" )
+    
+    TCurrentState oldState = iCurrentState;
+    
+    // Close old file (if exists)
+    CloseFileL( aFileChangeMode );
+  
+    aFileName.ZeroTerminate();
+
+    TRAPD( err, OpenFileForStreamingL( aFileName ) );
+    if ( err )
+        {
+        if ( aFileChangeMode )
+            {
+            // Have to stop timers etc, since old file was closed
+            // and the new file is unusable
+            DoCleanupL( EFalse );
+            }
+        User::Leave( err );
+        }
+		
+	this->SetFileName( aFileName );
+	
+	if ( oldState == EPlaying )
+	    {
+	    // Continue playing with new file
+	    iCurrentState = EPrimed;
+	    SourcePlayL( ETrue, aFileChangeMode );
+	    }
+	else
+	    {
+	    // Keep old state
+	    iCurrentState = oldState;
+	    }
+
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::OpenFile, exit" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::CloseFileL()
+//
+// Closes the 3gp file
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::CloseFileL( TBool aFileChangeMode )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::CloseFileL" )
+    
+    if ( iCurrentState == EPlaying )
+        {
+        SourceStopL( ETrue, aFileChangeMode );
+        }
+    
+    if ( iMP4Handle ) 
+	    {
+	    if ( MP4ParseClose( iMP4Handle ) != MP4_OK )
+	        {
+	        User::Leave( KErrGeneral );
+	        }
+    	iMP4Handle = NULL;
+    	iFileAudio->SetFileHandle( iMP4Handle );
+	    iFileVideo->SetFileHandle( iMP4Handle );		
+	    }
+    
+    iCurrentState = EConstructed;
+    
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::CloseFileL, file closed" )
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::FileNameL()
+// -----------------------------------------------------------------------------
+//   
+TFileName& CMccFileSourceImpl::FileNameL()
+    {
+    return iFileName;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SetPositionL(TTimeIntervalMicroSeconds aPosition)
+// 
+// Sets a new streaming position
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SetPositionL( TTimeIntervalMicroSeconds aPosition )
+    {
+    __FILESOURCE_CONTROLL_INT1( "CMccFileSourceImpl::SetPositionL (us):", 
+                                aPosition.Int64() )
+ 	
+ 	if ( iCurrentState == EStopped ) 
+    	{
+    	return;
+    	}
+
+    TUint32 position = MicroToMilliSeconds( aPosition );
+    
+    if ( VideoInUse() ) 
+	    {
+	    iFileVideo->SetPositionL( position );
+	    
+	    // Position might not end up to what was requested as it is set to
+	    // nearest IFrame.  With audio there's no such limitation and
+	    // therefore it is good to use actual video position for audio.
+	    position = iFileVideo->Position();
+	    
+	    __FILESOURCE_CONTROLL_INT1( "Pos modified to nearest IFrame (ms):", 
+                                    position )
+	    }
+	    
+	if ( AudioInUse() )
+		{
+		iFileAudio->SetPositionL( position );	
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::VideoTypeL()
+// 
+// Returns current video type
+// -----------------------------------------------------------------------------
+//
+CCMRMediaBuffer::TBufferType CMccFileSourceImpl::VideoTypeL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::VideoTypeL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+    
+    return iFileVideo->Type();
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::AudioTypeL()
+// 
+// Returns current audio type
+// -----------------------------------------------------------------------------
+//
+CCMRMediaBuffer::TBufferType CMccFileSourceImpl::AudioTypeL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::AudioTypeL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+
+    return iFileAudio->Type();
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::VideoFrameRateL()
+// 
+// Returns current video frame rate
+// -----------------------------------------------------------------------------
+//
+TReal CMccFileSourceImpl::VideoFrameRateL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::VideoFrameRateL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+        
+    return iFileVideo->VideoFrameRateL();    
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::AudioBitRateL()
+// 
+// Returns current audio bit rate
+// -----------------------------------------------------------------------------
+//
+TUint32 CMccFileSourceImpl::AudioBitRateL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::AudioBitRateL" )
+    
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+
+    TUint32 audioBitRate = iFileAudio->AudioBitRate();
+    
+    __FILESOURCE_CONTROLL_INT1( "CMccFileSourceImpl::AudioBitRateL", audioBitRate )
+    
+    return audioBitRate;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::DurationL()
+// 
+// Returns duration of current media clip
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CMccFileSourceImpl::DurationL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::DurationL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+
+    // Audio and video might have different duration, take longer one
+    //
+    
+    TTimeIntervalMicroSeconds duration = 0;
+    
+    if ( AudioInUse() )
+	    {
+	    duration = MilliToMicroSeconds( iFileAudio->Duration() );
+	    }
+	if ( VideoInUse() )
+		{
+		TTimeIntervalMicroSeconds videoDuration = 
+		    MilliToMicroSeconds( iFileVideo->Duration() );
+		duration = videoDuration > duration ? videoDuration : duration;
+		}
+		
+    __FILESOURCE_CONTROLL_INT1("CMccFileSourceImpl::DurationL in micro=", 
+    	duration.Int64())
+    return duration;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::VideoFrameSizeL()
+// 
+// Returns current video frame size
+// -----------------------------------------------------------------------------
+//
+TSize CMccFileSourceImpl::VideoFrameSizeL()
+    {        
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::VideoFrameSizeL" )
+       
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+    
+    TSize size = iFileVideo->VideoFrameSize();
+    
+    __FILESOURCE_CONTROLL_INT1( "CMccFileSourceImpl::VideoFrameSizeL iWidth", 
+                                size.iWidth )
+	__FILESOURCE_CONTROLL_INT1("CMccFileSourceImpl::VideoFrameSizeL iHeight",
+								size.iHeight )   
+								
+    return size;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::VideoBitRateL()
+// 
+// Returns current video bitrate
+// -----------------------------------------------------------------------------
+//
+TUint32 CMccFileSourceImpl::VideoBitRateL()
+    {    
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::VideoBitRateL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+
+    TUint32 audioBitRate = iFileAudio->AudioBitRate();
+    
+    // Average bitrate is for the whole stream, 
+    // subtract audio average to get video average
+    TUint32 averageBitRate = iFileVideo->StreamAverageBitRate() - audioBitRate;
+    
+    __FILESOURCE_CONTROLL_INT1( "CMccFileSourceImpl::VideoBitRateL, videoBitRate", 
+                               averageBitRate )
+
+    return averageBitRate;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::PositionL()
+// 
+// Returns current streaming position. If other stream is already at end
+// (zero pos) other ones position is used. Otherwise always less progressed
+// streams position is returned.
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMicroSeconds CMccFileSourceImpl::PositionL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::PositionL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+
+    TTimeIntervalMicroSeconds audioPosition = 0;
+    TTimeIntervalMicroSeconds videoPosition = 0;
+ 
+    if ( AudioInUse() )
+	    {
+	    audioPosition = MilliToMicroSeconds( iFileAudio->Position() );
+	    }
+	if ( VideoInUse() )
+		{
+		videoPosition = MilliToMicroSeconds( iFileVideo->Position() );
+		}
+		
+    __FILESOURCE_CONTROLL_INT2( "CMccFileSourceImpl::PositionL in micro, audio:", 
+                                audioPosition.Int64(), 
+                                " video:", videoPosition.Int64() )
+
+    if ( videoPosition.Int64() == 0 || audioPosition.Int64() == 0 )
+        {
+        return Max( videoPosition, audioPosition );
+        }
+    return Min( videoPosition, audioPosition );
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::AudioFourCCL()
+// -----------------------------------------------------------------------------
+//    
+TFourCC CMccFileSourceImpl::AudioFourCCL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::AudioFourCCL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+    
+    return iFileAudio->GetFourCC();
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::VideoFourCCL()
+// -----------------------------------------------------------------------------
+//	    
+TFourCC CMccFileSourceImpl::VideoFourCCL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::VideoFourCCL" )
+
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+    
+    return iFileVideo->GetFourCC();
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::GetConfigKeyL()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::GetConfigKeyL( TDes8& aConfigKey )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::GetConfigKeyL" )
+    
+    __ASSERT_ALWAYS( iMP4Handle && VideoInUse(), User::Leave( KErrNotReady ) );
+    
+    HBufC8* configKey = iFileVideo->GetConfigKeyL();
+    CleanupStack::PushL( configKey );
+    __ASSERT_ALWAYS( configKey, User::Leave( KErrNotFound ) );
+    __ASSERT_ALWAYS( configKey->Length() <= aConfigKey.MaxLength(), 
+                     User::Leave( KErrOverflow ) );
+    aConfigKey.Copy( *configKey );
+    CleanupStack::PopAndDestroy( configKey );
+    
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::GetConfigKeyL, exit" )
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::PlayL()
+// 
+// Starts streaming from 3gp file
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SourcePlayL( TBool aIgnoreEvents, TBool aFileChangeMode )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourcePlayL" )
+    
+    __ASSERT_ALWAYS( iCurrentState != EConstructed, User::Leave( KErrNotReady ) );
+
+    if ( iCurrentState == EPlaying )
+        {
+        return;
+        }
+    
+    // Start decision for both needs to be done before starting either one
+    TBool videoStartNeeded = StartNeededL( *iFileVideo );
+    TBool audioStartNeeded = StartNeededL( *iFileAudio );
+    
+	if ( videoStartNeeded && !aFileChangeMode  )
+    	{
+    	iFileVideo->StartTimerL();
+    	}
+    	
+	if ( audioStartNeeded && !aFileChangeMode )
+	    {
+    	iFileAudio->StartTimerL();	  
+	    }
+	
+	if ( !aIgnoreEvents )
+	    {   
+    	if ( iCurrentState == EPaused )
+    	    {
+    	    SendStreamEventToClient( KMccEventCategoryStream, KMccStreamResumed );
+    	    }
+    	else
+    	    {
+    	    SendStreamEventToClient( KMccEventCategoryStream, KMccStreamStarted );
+    	    }
+	    }
+	    
+    iCurrentState = EPlaying;
+    
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourcePlayL, exit" )
+    }
+        
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SourcePauseL()
+// 
+// Pauses streaming by cancelling timers
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SourcePauseL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourcePauseL" )
+    
+    if ( iCurrentState != EPlaying && iCurrentState != EWaitingPause ) 
+    	{
+    	return;
+    	}
+    	
+ 	if ( VideoInUse() )
+    	{
+    	iFileVideo->StopTimer();	
+    	iFileVideo->Cleanup();
+    	}
+	if ( AudioInUse() )
+	    {
+	    iFileAudio->StopTimer();	
+    	iFileAudio->Cleanup();	    
+	    }
+	    
+    StopEofTimer();	    
+	
+	// If pause was caused by eof, paused event is passed to all filesource users    
+	TUint32 eventNumData = 
+	    ( iCurrentState == EWaitingPause ) ? KMccAutomaticEvent : 0;
+	    
+	SendStreamEventToClient( KMccEventCategoryStream, 
+	                         KMccStreamPaused, 
+	                         KErrNone, 
+	                         eventNumData );
+	
+    iCurrentState = EPaused;
+    
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourcePauseL, exit" )
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::PauseAudioL()
+// 
+// pause audio only
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::PauseAudioL( TInt aError )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::PauseAudio" )
+    
+    if ( iCurrentState != EPlaying ) 
+    	{
+    	return;
+    	}
+    	
+    if ( AudioInUse() )
+	    {
+	    iFileAudio->StopTimer();	
+    	iFileAudio->Cleanup();	    
+	    }
+	    
+	if ( aError )
+        {
+        SendStreamEventToClient( KMccEventCategoryStream, 
+                                 KMccStreamPaused, 
+                                 aError, 
+                                 KMccAutomaticEvent );
+        }
+	else if ( !VideoInUse() || iFileVideo->IsPaused() )
+		{
+		// Initiate pause sequence only if all used media types are paused
+		
+        StartEofTimerL();
+		}
+    else
+        {
+        // NOP
+        }
+		
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::PauseAudio, exit" )
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::PauseVideoL()
+// 
+// pause video only
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::PauseVideoL( TInt aError )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::PauseVideo" )
+    
+    if ( iCurrentState != EPlaying ) 
+    	{
+    	return;
+    	}
+    	
+ 	if ( VideoInUse() )
+    	{
+    	iFileVideo->StopTimer();	
+    	iFileVideo->Cleanup();
+    	}	
+    
+    if ( aError )
+        {
+        SendStreamEventToClient( KMccEventCategoryStream, 
+                                 KMccStreamPaused, 
+                                 aError,
+                                 KMccAutomaticEvent );
+        }
+    else if ( !AudioInUse() || iFileAudio->IsPaused() )
+		{ 
+		// Initiate pause sequence only if all used media types are paused
+		
+        StartEofTimerL();
+		}
+    else
+        {
+        // NOP
+        }
+		
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::PauseVideo, exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::StopL()
+// 
+// Stops streaming
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SourceStopL( TBool aIgnoreEvents, TBool aFileChangeMode )
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourceStopL" )
+  
+    if ( iCurrentState == EConstructed )
+        {
+        return;
+        }
+
+    DoCleanupL( aFileChangeMode );
+	
+	if ( !aIgnoreEvents )
+	    {
+    	SendStreamEventToClient( KMccEventCategoryStream, KMccStreamStopped );
+	    }
+		
+    iCurrentState = EStopped;
+    
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourceStopL, exit" )
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SourceDataTypeCode()
+// -----------------------------------------------------------------------------
+//
+TFourCC CMccFileSourceImpl::SourceDataTypeCode( TMediaId aMediaId )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourceDataTypeCode" )
+
+    if ( KUidMediaTypeVideo == aMediaId.iMediaType &&
+         iFileVideo )
+        {
+        iIsVideo = ETrue;
+        return iFileVideo->GetFourCC(); 
+        }
+    else if ( KUidMediaTypeAudio == aMediaId.iMediaType &&
+        iFileAudio )
+        {
+        iIsAudio = ETrue;
+        return iFileAudio->GetFourCC();
+        }
+    else
+        {
+        return TFourCC( NULL );
+        }
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SetSourceDataTypeCode()
+// -----------------------------------------------------------------------------
+//
+TInt CMccFileSourceImpl::SetSourceDataTypeCode( 
+	TFourCC aCodec, 
+    TMediaId aMediaId )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SetSourceDataTypeCode" )
+	
+    if ( KUidMediaTypeVideo == aMediaId.iMediaType
+    	&& VideoInUse()
+        && aCodec == iFileVideo->GetFourCC() )
+        {   
+        return KErrNone;
+        }
+    else if ( KUidMediaTypeAudio == aMediaId.iMediaType 
+    	&& AudioInUse()
+        && aCodec == iFileAudio->GetFourCC() )
+        {  
+        return KErrNone;
+        }
+    else
+	    {
+	    return KErrNotSupported;
+	    } 
+	}	
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SourcePrimeL()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SourcePrimeL()
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourcePrimeL" )
+   
+   	iCurrentState = EPrimed;	
+	SendStreamEventToClient( KMccEventCategoryStream, KMccStreamPrepared );
+	
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourcePrimeL, exit" )
+	}
+	    
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::FillBufferL()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::FillBufferL( CMMFBuffer* aBuffer,
+						              MDataSink*  aConsumer,
+						              TMediaId    aMediaId )
+	{
+	__FILESOURCE_MEDIA( "CMccFileSourceImpl::FillBufferL" )
+
+	if ( aMediaId.iMediaType == KUidMediaTypeAudio &&
+	     AudioInUse() )
+		{
+    	__FILESOURCE_MEDIA( "CMccFileSourceImpl::FillBufferL, audio" )
+    
+    	iFileAudio->FillBufferL( aBuffer, aConsumer );
+		}
+	else if (aMediaId.iMediaType == KUidMediaTypeVideo &&
+	     VideoInUse() )
+		{
+    	__FILESOURCE_MEDIA( "CMccFileSourceImpl::FillBufferL, video" )    
+       
+		iFileVideo->FillBufferL( aBuffer, aConsumer );
+		}
+	else
+		{
+    	__FILESOURCE_MEDIA( "CMccFileSourceImpl::FillBufferL, unknown media " ) 
+		User::Leave( KErrNotSupported );	
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SourceThreadLogon
+// -----------------------------------------------------------------------------
+//
+TInt CMccFileSourceImpl::SourceThreadLogon( MAsyncEventHandler& aEventHandler )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourceThreadLogon" )
+
+	iAsyncEventHandler = static_cast<MAsyncEventHandler*>( &aEventHandler );
+	return KErrNone;
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SourceThreadLogoff
+// -----------------------------------------------------------------------------
+//		
+void CMccFileSourceImpl::SourceThreadLogoff()
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SourceThreadLogoff" )
+
+	iAsyncEventHandler = NULL;
+	}
+		
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::FileOpenErrorL
+// -----------------------------------------------------------------------------
+//	
+void CMccFileSourceImpl::FileOpenErrorL( MP4Err error )
+	{
+	iMP4Handle = NULL;
+	if ( error == MP4_OUT_OF_MEMORY )
+		{
+		User::Leave( KErrNoMemory );	
+		}
+	else
+		{
+		User::Leave( KErrGeneral );	
+		}
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::MilliToMicroSeconds
+// -----------------------------------------------------------------------------
+//	  	
+TTimeIntervalMicroSeconds CMccFileSourceImpl::MilliToMicroSeconds( 
+    TUint32 aMilliSeconds )
+	{
+	return TTimeIntervalMicroSeconds( (TInt64) aMilliSeconds * KMccMicroToMilliConst );
+	}
+	
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::MicroToMilliSeconds
+// -----------------------------------------------------------------------------
+//	  		
+TUint32 CMccFileSourceImpl::MicroToMilliSeconds( 
+    TTimeIntervalMicroSeconds aMicroSeconds )
+	{
+	return ( aMicroSeconds.Int64() / KMccMicroToMilliConst );
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SetFileName()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SetFileName( const TFileName& aFileName )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::SetFileName" )
+
+	iFileName.Copy( aFileName );
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::OpenFileForStreamingL()
+// -----------------------------------------------------------------------------
+//	
+void CMccFileSourceImpl::OpenFileForStreamingL( TFileName aFileName )
+	{
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::OpenFileForStreamingL" )
+
+    TFileName fullFileName;
+    MP4Err error = MP4_OK;
+    
+    RFs fS;
+    User::LeaveIfError( fS.Connect() );
+	CleanupClosePushL( fS );
+    TParse fp;
+    TInt err = fS.Parse( aFileName, fp );
+    
+    if ( err )
+        {
+        __FILESOURCE_CONTROLL_INT1( 
+            "CMccFileSourceImpl::OpenFileForStreamingL file name parse error:", 
+            err )
+	    User::Leave( err );
+        }
+	
+    fullFileName = fp.FullName();
+  	CleanupStack::PopAndDestroy( &fS ); 
+	
+	this->SetFileName( aFileName );
+	
+	const TInt KMccZeroTerminatorLen = 1;
+	__ASSERT_ALWAYS( 
+	    fullFileName.Length() + KMccZeroTerminatorLen <= fullFileName.MaxLength(),
+	    User::Leave( KErrOverflow ) );
+	
+  	error = MP4ParseOpen( &iMP4Handle, (wchar_t *) fullFileName.PtrZ() );
+
+    if ( error != MP4_OK )
+	    {
+        __FILESOURCE_CONTROLL_INT1( 
+            "CMccFileSourceImpl::OpenFileForStreamingL parse open error:", 
+            error )
+
+	    iMP4Handle = NULL;
+	   	User::Leave( KErrGeneral );
+	    }
+	
+    TBool containAudio = iFileAudio->ParseUpdateAudioDescriptions( iMP4Handle );
+    TBool containVideo = iFileVideo->ParseUpdateVideoDescriptions( iMP4Handle );
+			
+	if ( !containAudio && !containVideo )
+	    {
+	    __FILESOURCE_CONTROLL( 
+	        "CMccFileSourceImpl::OpenFileForStreamingL no audio/video" )
+	    
+	    MP4ParseClose( iMP4Handle );
+	    iMP4Handle = NULL;
+	   	User::Leave( KErrNotSupported );
+	    }
+	    
+	iFileAudio->SetFileHandle( iMP4Handle );
+	iFileVideo->SetFileHandle( iMP4Handle );	
+
+	iFileAudio->ParseUpdateStreamDescription( iMP4Handle );
+	iFileVideo->ParseUpdateStreamDescription( iMP4Handle );
+	
+	// If filecontainers are reused (i.e. filename is changed), 
+	// position has to be zeroed
+	SetPositionL( 0 );
+	
+	__FILESOURCE_CONTROLL( "CMccFileSourceImpl::OpenFileForStreamingL, exit" )
+	}
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SendStreamEventToClient()
+// -----------------------------------------------------------------------------
+//	
+void CMccFileSourceImpl::SendStreamEventToClient( 
+    TMccEventCategory aEventCategory,
+    TMccEventType aEventType,
+    TInt aError,
+    TUint32 aEventNumData )
+    {
+    __FILESOURCE_MEDIA( "CMccFileSourceImpl::SendStreamEventToClient" )
+    
+    if ( iAsyncEventHandler )
+	    {
+	    ClearEvent();
+	    
+	    iMccEvent.iEndpointId = iEndpointId;
+	    iMccEvent.iEventCategory = aEventCategory;
+	    iMccEvent.iEventType = aEventType;
+	    iMccEvent.iErrorCode = aError;
+	    iMccEvent.iEventNumData = aEventNumData;
+
+		TMccInternalEvent internalEvent( KMccFileSourceUid, 
+		                                 EMccInternalEventNone,
+		                                 iMccEvent );
+		                         
+		iAsyncEventHandler->SendEventToClient( internalEvent );
+	    }
+	else
+		{
+		__FILESOURCE_MEDIA( "CMccFileSourceImpl::SendStreamEventToClient, \
+		iAsyncEventHandler=NULL" )
+		}
+    }	
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::AudioInUse()
+// -----------------------------------------------------------------------------
+//
+TBool CMccFileSourceImpl::AudioInUse() const
+    {
+    return ( iFileAudio && iIsAudio );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::VideoInUse()
+// -----------------------------------------------------------------------------
+//
+TBool CMccFileSourceImpl::VideoInUse() const
+    {
+    return ( iFileVideo && iIsVideo );
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::DoCleanupL()
+// -----------------------------------------------------------------------------
+//   
+void CMccFileSourceImpl::DoCleanupL( TBool aFileChangeMode )
+    {
+    if ( VideoInUse() && !aFileChangeMode )
+    	{
+    	iFileVideo->StopTimer();
+    	iFileVideo->ResetTimeL();
+    	// clean the iConsumerBuffer and iConsumer,
+    	// to prevent still send data after Stoped	
+    	iFileVideo->Cleanup();
+    	}
+	if ( AudioInUse() && !aFileChangeMode )
+        {
+	    iFileAudio->StopTimer();
+	    iFileAudio->ResetTimeL();	
+    	iFileAudio->Cleanup();	    
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::StartEofTimerL()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::StartEofTimerL()
+    {
+    StopEofTimer();
+    
+    TInt delayAfterStop( KMccMicroToMilliConst * DelayAfterStop() );
+    
+    __FILESOURCE_CONTROLL_INT1( "CMccFileSourceImpl::StartEofTimerL, microsecs:",
+                                delayAfterStop )
+    
+    iEofTimer = CMccEofTimer::NewL( this );
+    
+    iEofTimer->After( delayAfterStop );
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::EofTimerExpiredL()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::EofTimerExpiredL()
+    {
+    __FILESOURCE_CONTROLL( "CMccFileSourceImpl::EofTimerExpiredL" );
+
+    iCurrentState = EWaitingPause;
+		
+    SendStreamEventToClient( KMccEventCategoryStreamControl, KMccStreamPaused );
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::StopEofTimer()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::StopEofTimer()
+	{
+    if ( iEofTimer )
+        {
+        __FILESOURCE_CONTROLL( 
+            "CMccFileSourceImpl::StopEofTimer, cancel iEofTimer" )
+        iEofTimer->Cancel();
+        delete iEofTimer;
+        iEofTimer = NULL;
+        }
+	}
+	        
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::SetDelayAfterStop()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::SetDelayAfterStop( TInt aDelay )
+    {
+    __FILESOURCE_CONTROLL_INT1( "CMccFileSourceImpl::SetDelayAfterStop aDelay:", 
+                                aDelay )
+    iDelayAfterStop = aDelay;    
+    }
+    
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::DelayAfterStop()
+// -----------------------------------------------------------------------------
+//
+TInt CMccFileSourceImpl::DelayAfterStop( ) const
+    {
+    return iDelayAfterStop;
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::ClearEvent()
+// -----------------------------------------------------------------------------
+//
+void CMccFileSourceImpl::ClearEvent()
+    {
+    iMccEvent = TMccEvent();
+    }
+
+// -----------------------------------------------------------------------------
+// CMccFileSourceImpl::StartNeededL()
+// Checks current file position and determines based on that whether starting
+// of this media type is needed. If this media type is already at end (at zero
+// pos) but other is not yet, this media type does not need starting.
+// -----------------------------------------------------------------------------
+//
+TBool CMccFileSourceImpl::StartNeededL( CMccFileSourceTypeBase& aFileSource )
+    {
+    TBool startNeeded( ETrue );
+    TTimeIntervalMicroSeconds currentPosition = PositionL();
+    
+    if ( aFileSource.MediaType().iMediaType == KUidMediaTypeAudio )
+        {
+        startNeeded = AudioInUse();
+        }
+    if ( aFileSource.MediaType().iMediaType == KUidMediaTypeVideo )
+        {
+        startNeeded = VideoInUse();
+        }
+        
+    if ( startNeeded && 
+         currentPosition.Int64() > 0 && 
+         aFileSource.Position() == 0 )
+        {
+        startNeeded = EFalse;
+        }
+    
+    return startNeeded;
+    }
+    
+#ifndef EKA2
+// DLL interface code
+EXPORT_C TInt E32Dll( TDllReason )
+    {
+    return KErrNone;
+    }
+#endif