diff -r 826cea16efd9 -r 13a33d82ad98 dvrengine/CommonRecordingEngine/src/CCRRtpFileSource.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dvrengine/CommonRecordingEngine/src/CCRRtpFileSource.cpp Wed Sep 01 12:20:37 2010 +0100 @@ -0,0 +1,521 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: Class that reads RTP packets from propriatary file format.* +*/ + + + + +// INCLUDE FILES +#include "CCRRtpFileSource.h" +#include +#include "CCRPacketBuffer.h" +#include "videoserviceutilsLogger.h" + +// CONSTANTS +const TInt KGroupsCountPoint( 0 ); +const TInt KBufferThesholdCount( 20 ); + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCRRtpFileSource* CCRRtpFileSource::NewL( + const SCRRtpPlayParams& aParams, + CRtpClipHandler*& aClipHandler, + MCRStreamObserver& aSessionObs, + CCRStreamingSession& aOwningSession ) + { + CCRRtpFileSource* self = new( ELeave ) + CCRRtpFileSource( aClipHandler, aSessionObs, aOwningSession ); + CleanupStack::PushL( self ); + self->ConstructL( aParams ); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCRRtpFileSource* CCRRtpFileSource::NewL( + const RFile& aRtpHandle, + CRtpClipHandler*& aClipHandler, + MCRStreamObserver& aSessionObs, + CCRStreamingSession& aOwningSession ) + { + CCRRtpFileSource* self = new( ELeave ) + CCRRtpFileSource( aClipHandler, aSessionObs, aOwningSession ); + CleanupStack::PushL( self ); + self->ConstructL( aRtpHandle ); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::CCRRtpFileSource +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CCRRtpFileSource::CCRRtpFileSource( + CRtpClipHandler*& aClipHandler, + MCRStreamObserver& aSessionObs, + CCRStreamingSession& aOwningSession ) + : CCRPacketSourceBase( aOwningSession, CCRStreamingSession::ECRRtpSourceId ), + iClipHandler( aClipHandler ), + iSessionObs( aSessionObs ), + iInitialTime( KMaxTUint ), + iClipPauseSent( 0 ) + { + // None + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::ConstructL( const SCRRtpPlayParams& aParams ) + { + const TBool timeShift( + aParams.iFileName.Find( KDvrTimeShiftFile ) > KErrNotFound ); + LOG1( "CCRRtpFileSource::ConstructL() in, timeShift: %d", timeShift ); + + // RTP clip handler + User::LeaveIfNull( iClipHandler ); + iClipHandler->RegisterReadObserver( this ); + iClipHandler->StartPlayBackL( aParams, timeShift ); + + LOG( "CCRRtpFileSource::ConstructL() out" ); + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::ConstructL( const RFile& aRtpHandle ) + { + LOG( "CCRRtpFileSource::ConstructL() in" ); + + User::LeaveIfNull( iClipHandler ); + iClipHandler->RegisterReadObserver( this ); + iClipHandler->StartPlayBackL( aRtpHandle ); + + LOG( "CCRRtpFileSource::ConstructL() out" ); + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::~CCRRtpFileSource +// Destructor. +// ----------------------------------------------------------------------------- +// +CCRRtpFileSource::~CCRRtpFileSource() + { + LOG( "CCRRtpFileSource::~CCRRtpFileSource()" ); + + if ( iClipHandler ) + { + iClipHandler->StopPlayBack( KErrNone, 0 ); + } + + delete iSdp; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::GetSdp +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::GetSdp( TPtrC8& aSdp ) + { + if ( iSdp ) + { + aSdp.Set( iSdp->Des() ); + return KErrNone; + } + + return KErrNotReady; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::SetBuffer +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::SetBuffer( CCRPacketBuffer* aBuffer ) + { + iBuffer = aBuffer; + iBuffer->ContinousStream( EFalse ); + iBuffer->MoreComing( EFalse ); + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::PostActionL +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::PostActionL() + { + LOG( "CCRRtpFileSource::PostActionL(), SDP will be handled !" ); + + // SDP + if ( iClipHandler ) + { + iSdp = iClipHandler->GetClipSdpL(); + } + + // Notify that SDP available + iSessionObs.StatusChanged( MCRPacketSource::ERtpStateSdpAvailable ); + delete iSdp; iSdp = NULL; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::Restore +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::Restore() + { + const TInt err( NextClipGroup( ETrue ) ); + if ( err && err != KErrEof ) + { + LOG1( "CCRRtpFileSource::Restore(), NextClipGroup() err: %d", err ); + iSessionObs.StatusChanged( MCRPacketSource::ERtpStateClosing ); + } + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::Play +// +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::Play( const TReal& aStartPos, const TReal& aEndPos ) + { + LOG3( "CCRRtpFileSource::Play(), aStartPos: %f, aEndPos: %f, iClipPauseSent: %d", + aStartPos, aEndPos, iClipPauseSent ); + // Play for player? + if ( aStartPos == KRealZero && aEndPos == KRealZero ) + { + iInitialTime = KMaxTUint; + return NextClipGroup( EFalse ); + } + + // Loading started in player? + if ( aStartPos == KRealMinusOne && aEndPos == KRealMinusOne ) + { + const TBool pauseSent( iClipPauseSent > 0 ); + if ( pauseSent ) + { + iClipPauseSent--; + iBuffer->ResetBuffer(); + } + + // Read more from clip + TInt err( NextClipGroup( EFalse ) ); + if ( !err && pauseSent ) + { + iInitialTime = KMaxTUint; + err = ECRStreamPauseHanling; + LOG( "CCRRtpFileSource::Play(), ECRStreamPauseHanling" ); + } + else + { + if ( err == KErrEof ) + { + err = KErrNone; + if ( iClipHandler ) + { + TRAP( err, iClipHandler->SetSeekPointL( 0 ) ); + } + if ( !err ) + { + err = ECRStreamEndHandling; + LOG( "CCRRtpFileSource::Play(), ECRStreamEndHandling" ); + } + } + } + + return err; + } + + return KErrCompletion; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::Stop +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::Stop() + { + LOG( "CCRRtpFileSource::Stop()" ); + + return RtpPosition( 0 ); + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::SetPosition +// +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::SetPosition( const TInt64 aPosition ) + { + TInt err( RtpPosition( TUint( aPosition / KSiKilo ) ) ); + if ( !err ) + { + err = NextClipGroup( EFalse ); + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::GetPosition +// +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::GetPosition( TInt64& aPosition, TInt64& aDuration ) + { + if ( iBuffer && iClipHandler ) + { + if ( iInitialTime != KMaxTUint ) + { + aPosition += TInt64( iInitialTime ) * KSiKilo; + } + else + { + LOG( "CCRRtpFileSource::GetPosition(), iInitialTime not valid !" ); + } + + aDuration = TInt64( iClipHandler->GetCurrentLength() ) * KSiKilo; +#ifdef CR_ALL_LOGS + LOG2( "CCRRtpFileSource::GetPosition(), aPosition: %u, aDuration: %u", + ( TUint )( aPosition / KSiKilo ), ( TUint )( aDuration / KSiKilo ) ); +#endif // CR_ALL_LOGS + return KErrNone; + } + + return KErrCompletion; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::GroupReadedL +// Adds packets to the buffer when finished asyncronous group reading. +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::GroupReadedL( + const TDesC8& aGroup, + const TUint aGroupTime, + const TBool aLastGroup ) + { + // Group time + if ( iInitialTime == KMaxTUint ) + { + iInitialTime = aGroupTime; + } + + // Data valid? + TInt point( KGroupsCountPoint + KPacketsCountBytes ); + const TInt total( aGroup.Length() ); + if ( point > total ) + { + LOG( "CCRRtpFileSource::GroupReadedL(), No Packets Total Count !" ); + User::Leave( KErrCorrupt ); + } + + // Packets total count (PTC) + const TInt totalCount( CRtpUtil::GetValueL( + aGroup.Mid( KGroupsCountPoint, KPacketsCountBytes ) ) ); + if ( totalCount > 0 ) + { + iBuffer->MoreComing( ETrue ); + } + + // Loop all packets + for ( TInt i( 0 ); i < totalCount; i++ ) + { + // Corrupted? + if ( ( point + KPacketSizeBytesLen ) > total ) + { + LOG( "CCRRtpFileSource::GroupReadedL(), No Packets Size !" ); + User::Leave( KErrCorrupt ); + } + + // Packet total Size (PTS) + TInt packetSize( CRtpUtil::GetValueL( + aGroup.Mid( point, KPacketSizeBytesLen ) ) ); + // Corrupted? + if ( packetSize <= 0 || ( point + packetSize ) > total ) + { + LOG( "CCRRtpFileSource::GroupReadedL(), No Packets Payload !" ); + User::Leave( KErrCorrupt ); + } + + // Packet type + point += KPacketSizeBytesLen; + const MRtpFileWriteObserver::TRtpType type( + ( MRtpFileWriteObserver::TRtpType )( aGroup[point] ) ); + point += KPacketTypeBytesLen; + packetSize -= ( KPacketSizeBytesLen + KPacketTypeBytesLen ); + + // Insert packet to the buffer + const TPtrC8 packet( aGroup.Mid( point, packetSize ) ); + +#ifdef CR_ALL_LOGS + const TUint8* pointer( &packet[2] ); + TInt seq( BigEndian::Get16( pointer ) ); + LOG3( "CCRRtpFileSource::GroupReadedL(), type: %d, packet: %d, seq: %d", + type, packet.Length(), seq ); + //RFileLogger::WriteFormat( _L( "livetv" ), _L( "play.log" ), EFileLoggingModeAppend, + // _L( "GroupReadedL(), type: %d, packet: %d, seq: %d" ), type, packet.Length(), seq ); +#endif // CR_ALL_LOGS + + MCRPacketSource::TCRPacketStreamId stream( MCRPacketSource::EStreamIdCount ); + if ( TypeToStream( type, stream ) ) + { + // Last packet in group? + if ( i >= ( totalCount - 1 ) ) + { + iBuffer->MoreComing( EFalse ); + if ( aLastGroup && stream != MCRPacketSource::EStreamEndTag ) + { + LOG( "CCRRtpFileSource::GroupReadedL(), Misses last group from clip !" ); + stream = MCRPacketSource::EStreamEndTag; + } + } + + // Packet to buffer + iBuffer->AddPacket( stream, packet ); + } + + point+= packetSize; + } + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::ReadStatus +// ----------------------------------------------------------------------------- +// +void CCRRtpFileSource::ReadStatus( TInt aStatus ) + { + LOG1( "CCRRtpFileSource::ReadStatus(), aStatus: %d", aStatus ); + + switch ( aStatus ) + { + case MRtpFileReadObserver::ERtpTimeShifTEnd: + break; + + default: + iSessionObs.StatusChanged( MCRPacketSource::ERtpStateClosing ); + break; + } + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::NextClipGroup +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::NextClipGroup( const TBool aForce ) + { + if ( iBuffer && iClipHandler ) + { + if ( aForce || iBuffer->PacketsMinCount() < KBufferThesholdCount ) + { + TRAPD( err, iClipHandler->NextClipGroupL() ); + return err; + } + + return KErrNone; + } + + return KErrNotReady; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::RtpPosition +// ----------------------------------------------------------------------------- +// +TInt CCRRtpFileSource::RtpPosition( const TUint aPosition ) + { + LOG1( "CCRRtpFileSource::RtpPosition(), aPosition: %d", aPosition ); + + TInt err( KErrCompletion ); + if ( iBuffer && iClipHandler ) + { + TRAP( err, iClipHandler->SetSeekPointL( aPosition ) ); + if ( !err ) + { + iInitialTime = KMaxTUint; + iBuffer->ResetBuffer(); + } + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CCRRtpFileSource::TypeToStream +// ----------------------------------------------------------------------------- +// +TBool CCRRtpFileSource::TypeToStream( + const MRtpFileWriteObserver::TRtpType& aType, + MCRPacketSource::TCRPacketStreamId& aStream ) + { + switch ( aType ) + { + case MRtpFileWriteObserver::ERtpAudio: + aStream = MCRPacketSource::EAudioStream; + break; + + case MRtpFileWriteObserver::ERtcpAudio: + aStream = MCRPacketSource::EAudioControlStream; + break; + + case MRtpFileWriteObserver::ERtpVideo: + aStream = MCRPacketSource::EVideoStream; + break; + + case MRtpFileWriteObserver::ERtcpVideo: + aStream = MCRPacketSource::EVideoControlStream; + break; + + case MRtpFileWriteObserver::ERtpSubTitle: + aStream = MCRPacketSource::ESubTitleStream; + break; + + case MRtpFileWriteObserver::ERtcpSubTitle: + aStream = MCRPacketSource::ESubTitleControlStream; + break; + + case MRtpFileWriteObserver::ERtpClipPause: + LOG( "CCRRtpFileSource::TypeToStream(), ERtpClipPause" ); + iClipPauseSent = ETrue; + aStream = MCRPacketSource::EDisContinousStream; + break; + + case MRtpFileWriteObserver::ERtpClipEnd: + LOG( "CCRRtpFileSource::TypeToStream(), ERtpClipEnd" ); + aStream = MCRPacketSource::EStreamEndTag; + break; + + default: + LOG1( "CCRRtpFileSource::TypeToStream(), Default case, aType: %d", + aType ); + return EFalse; + } + + return ETrue; + } + +// End of File