diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccfilesourcesink/src/mccfilesourceimpl.cpp --- /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 +#include +#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( &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