--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpToFile.cpp Thu Dec 17 09:14:38 2009 +0200
@@ -0,0 +1,712 @@
+/*
+* 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: Implementation of the Common Recording Engine RTP save format class.*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "CRtpToFile.h"
+#include <ipvideo/CRtpMetaHeader.h>
+#include <e32math.h>
+#include <bsp.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+const TUint KMaxValidDelta( 500 ); // 0.5 s
+const TUint8 KDummyFullQuality( 100 ); // 100%
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::NewL
+// Static two-phased constructor. Leaves object to cleanup stack.
+// -----------------------------------------------------------------------------
+//
+CRtpToFile* CRtpToFile::NewL(
+ MRtpFileObserver& aFileObs,
+ MRtpFileWriteObserver& aWriteObs )
+ {
+ CRtpToFile* self = new( ELeave ) CRtpToFile( aFileObs, aWriteObs );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::CRtpToFile
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CRtpToFile::CRtpToFile(
+ MRtpFileObserver& aFileObs,
+ MRtpFileWriteObserver& aWriteObs )
+ : CRtpFileBase(),
+ iFileObs( aFileObs ),
+ iWriteObs( aWriteObs ),
+ iCurrentTime( 0 ),
+ iPreviousTime( 0 ),
+ iPreviousDelta( 0 ),
+ iReferenceTime( 0 ),
+ iRecordEndTime( 0 ),
+ iSeekArrayReference( 0 ),
+ iGroupReUse( KErrNotFound ),
+ iAction( MRtpFileWriteObserver::ESaveEnd )
+ {
+ // None
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::ConstructL()
+ {
+ LOG( "CRtpToFile::ConstructL()" );
+
+ CRtpFileBase::ConstructL();
+ iCurrentPath = HBufC::NewL( 0 );
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+//
+CRtpToFile::~CRtpToFile()
+// -----------------------------------------------------------------------------
+ {
+ LOG( "CRtpToFile::~CRtpToFile()" );
+
+ Cancel();
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::InitRtpSaveL
+// Sets path of RTP file and initiates variables.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::InitRtpSaveL(
+ const MRtpFileWriteObserver::SRtpRecParams& aParams,
+ const MRtpFileWriteObserver::TRtpSaveAction& aAction )
+ {
+ LOG1( "CRtpToFile::InitRtpSaveL() in, ClipPath: %S", &aParams.iClipPath );
+ User::LeaveIfError( ( iMode != EModeNone ) * KErrInUse );
+
+ // Mode
+ switch ( aAction )
+ {
+ case MRtpFileWriteObserver::ESaveTimeShift:
+ iMode = EModeTimeShift;
+ break;
+
+ default:
+ iMode = EModeNormal;
+ break;
+ }
+
+ // File server
+ if ( !iFs.Handle() )
+ {
+ User::LeaveIfError( iFs.Connect() );
+ }
+
+ // Create clip
+ CreateNewClipL( aParams );
+
+ // Real clip's end time
+ iPreviousTime = 0;
+ iReferenceTime = iGroupTime * KSiKilo;
+ UpdateCurrentTimeL();
+ TInt64 duration( aParams.iEndTime.Int64() -
+ aParams.iStartTime.Int64() );
+ iRecordEndTime = iCurrentTime.Int64() + duration;
+
+ // Prepare variables
+ iSeekArrayReference = iGroupTime;
+ iStartGroupTime = iGroupTime;
+
+ LOG( "CRtpToFile::InitRtpSaveL() out" );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::ActivateGroupsReuseL
+// Starts reuse packet groups for live record when they are played.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::ActivateGroupsReuseL()
+ {
+ LOG2( "CRtpToFile::ActivateGroupsReuseL(), iMode: %d, iGroupReUse: %d",
+ iMode, iGroupReUse );
+ if ( iGroupReUse != KErrNotFound || iMode != EModeTimeShift )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ iGroupReUse = KErrInUse;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::SwapClipL
+// Sets new path of RTP file and initiates variables.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::SwapClipL( const MRtpFileWriteObserver::SRtpRecParams& aParams )
+ {
+ LOG1( "CRtpToFile::SwapClipL(), aClipPath: %S", &aParams.iClipPath );
+
+ User::LeaveIfError( ( iMode != EModeTimeShift ) * KErrGeneral );
+
+ // Update old clip
+ WriteSeekHeaderL();
+ iGroupReUse = KErrNotFound;
+
+ // Open new clip
+ CreateNewClipL( aParams );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::SaveNextRtpGroupL
+// Saves one RTP packet group to a specified file.
+// -----------------------------------------------------------------------------
+//
+TInt CRtpToFile::SaveNextGroupL(
+ TPtr8& aGroup,
+ TUint& aGroupLength,
+ const MRtpFileWriteObserver::TRtpSaveAction& aAction )
+ {
+ // Verify data and mode
+ User::LeaveIfError( iMode );
+
+ // Group
+ iDataPtr.Set( aGroup );
+
+ // Set group variables
+ AddGroupL();
+ GroupTimeL( aGroupLength );
+ AddGroupHeaderL();
+
+ // Write to file
+ iAction = aAction;
+ iFile.Write( iThisGroup, iDataPtr, iGroupTotalLen, iStatus );
+ SetActive();
+
+ LOG2( "CRtpToFile::SaveNextGroupL(), iThisGroup: %d, iGroupTime: %u",
+ iThisGroup, iGroupTime );
+#ifdef CR_ALL_LOGS
+ LogVariables( _L( "SaveNextGroupL()" ) );
+#endif // CR_ALL_LOGS
+
+ return iThisGroup;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::UpdatePreviousTimeL
+// Updates previous time after pause.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::UpdatePreviousTimeL()
+ {
+ UpdateCurrentTimeL();
+ iPreviousTime = iCurrentTime.Int64();
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::StopRtpSave
+// Stops file saving and finalizes header.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::StopRtpSave( const TInt aError )
+ {
+ Cancel();
+ const TRtpFileMode mode( iMode );
+
+ // If active
+ if ( mode != EModeNone )
+ {
+#ifdef CR_ALL_LOGS
+ LogVariables( _L( "StopRtpSave()" ) );
+#endif // CR_ALL_LOGS
+ iMode = EModeNone;
+
+ // Update clip headers
+ if ( mode != EModeTimeShift )
+ {
+ TRAP_IGNORE( WriteFinalMetaHeaderL( aError ) );
+ }
+ else
+ {
+ iLastSeekAddr = KMaxTInt;
+ TRAP_IGNORE( WriteSeekHeaderL() );
+ }
+
+ // Close file
+ iFile.Flush();
+ iFile.Close();
+
+ if ( aError == KErrNoMemory && !iGroupsTotalCount )
+ {
+ // Failed due to insufficient disk space, and couldn't save any
+ // packets to clip. Happens when recording is started with disk
+ // space already below threshold, and failed to free any space.
+ // Delete the clip completely, otherwise we are just consuming
+ // space below threshold(s).
+ LOG( "CRtpToFile::StopRtpSave(), deleting file without packets !" );
+ iFs.Delete( *iCurrentPath );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::GetClipPath
+// Getter for full path of currently recorded clip.
+// -----------------------------------------------------------------------------
+//
+HBufC* CRtpToFile::ClipPath()
+ {
+ return iCurrentPath;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpFromFile::GetCurrentLength
+// Gets the current length of the clip during recording.
+// -----------------------------------------------------------------------------
+//
+TUint CRtpToFile::GetCurrentLength()
+ {
+ return iGroupTime;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpFromFile::UpdateRecordEndTime
+// Uppdates the current recording end time.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::UpdateRecordEndTime( const TTime& aEndTime )
+ {
+ if ( aEndTime > iCurrentTime )
+ {
+ iRecordEndTime = aEndTime.Int64();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::UpdatePlayAttL
+// Updates clip's playback count and spot attributes after watching.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::UpdatePlayAttL( const TInt aNewSpot )
+ {
+ CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
+ iFile, CRtpMetaHeader::EMetaUpdate );
+ CRtpMetaHeader::SAttributes att;
+ metaheader->ReadAttributesL( att );
+
+ // Step playback counter by one
+ att.iPlayCount++;
+ // Update playback spot
+ att.iPlaySpot = ( aNewSpot > 0 && aNewSpot < iLastSeekAddr )? aNewSpot:
+ KErrNone;
+ metaheader->WriteAttributesL( att );
+ CleanupStack::PopAndDestroy( metaheader );
+ LOG2( "CRtpToFile::UpdatePlayAttL(), New playback count: %d, spot: %d",
+ att.iPlayCount, att.iPlaySpot );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::RunL
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::RunL()
+ {
+ User::LeaveIfError( iStatus.Int() );
+ User::LeaveIfError( iFile.Flush() );
+
+ // Start packets re-use?
+ if ( iGroupReUse == KErrInUse )
+ {
+ const TInt point( iFileObs.CurrentFileReadPoint( 0 ) );
+ if ( point > ( iSeekHeaderPoint + KSeekHeaderBytes ) )
+ {
+ iGroupReUse = KErrNone;
+ }
+ }
+
+ // Stop recording if time shift too close to live
+ if ( iGroupReUse > KErrNone &&
+ iFileObs.CurrentFileReadPoint( 1 ) < KErrNone )
+ {
+ iAction = MRtpFileWriteObserver::ESaveEnd;
+ LOG( "CRtpToFile::RunL(), Time shift play too close to record !" );
+ }
+
+ // Stop recording if end time reached
+ if ( iCurrentTime.Int64() > iRecordEndTime )
+ {
+ iAction = MRtpFileWriteObserver::ESaveEnd;
+ LOG( "CRtpToFile::RunL(), Record end time reached !" );
+ }
+
+ iFileObs.RtpGroupSaved( iAction );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CRtpToFile::RunError( TInt aError )
+ {
+ LOG1( "CRtpToFile::RunError(), RunL Leaved: %d", aError );
+
+ if ( &iWriteObs )
+ {
+ iWriteObs.WriteStatus( aError );
+ }
+
+ StopRtpSave( aError );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::DoCancel()
+ {
+ LOG( "CRtpToFile::DoCancel()" );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::CreateNewClipL
+// Opens new clip and creates initial headers.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::CreateNewClipL(
+ const MRtpFileWriteObserver::SRtpRecParams& aParams )
+ {
+ // Open file
+ iFile.Close();
+ User::LeaveIfError( iFile.Replace( iFs, aParams.iClipPath,
+ EFileShareAny | EFileStream | EFileWrite ) );
+ // Headers
+ WriteInitialMetaHeaderL( aParams );
+ WriteSeekHeaderL();
+ const TInt firstGroup( iSeekHeaderPoint + KSeekHeaderBytes );
+
+ // Variables
+ iGroupTime = 0;
+ iGroupsTotalCount = 0;
+ iFirstSeekAddr = firstGroup;
+ iLastSeekAddr = firstGroup;
+ iNextGroupPoint = firstGroup;
+ delete iCurrentPath; iCurrentPath = NULL;
+ iCurrentPath = aParams.iClipPath.AllocL();
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::AddGroupL
+// Updates file and packet group header variables for a new group.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::AddGroupL()
+ {
+ // New group
+ iThisGroup = iNextGroupPoint;
+
+ // Group header
+ // Note ! KGroupHeaderBytes size is allocated to incoming group in
+ // CCRRtpRecordSink::ResetGroupVariables(), but data does not exits
+ // before CRtpToFile::AddGroupHeaderL() method is called.
+ iGroupTotalLen = KGroupHeaderBytes + iDataPtr.Length();
+ iNextGroupPoint = iThisGroup + iGroupTotalLen;
+ const TInt prevGroup( iLastSeekAddr );
+
+ // Time shift handling
+ if ( iGroupReUse > KErrNone )
+ {
+ iGroupReUse--;
+ }
+ else
+ {
+ iGroupsTotalCount++;
+ iLastSeekAddr = ( iMode != EModeTimeShift )? iThisGroup: 0;
+ }
+
+ // Start write to the beginning of the clip?
+ if ( iGroupReUse == KErrNone )
+ {
+ iGroupReUse = iGroupsTotalCount;
+ iNextGroupPoint = iSeekHeaderPoint + KSeekHeaderBytes;
+ LOG2( "CRtpToFile::AddGroupL(), iGroupReUse: %d, iNextGroupPoint: %d",
+ iGroupReUse, iNextGroupPoint );
+ }
+
+ // First group in clip?
+ if ( iGroupsTotalCount == 1 )
+ {
+ iPrevGroupPoint = 0;
+ WriteSeekHeaderL();
+ iSeekArrayReference = iGroupTime;
+ }
+ else
+ {
+ iPrevGroupPoint = prevGroup;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::GroupTimeL
+// Generates group time from group length reported by ring buffer and actual
+// network time difference to previous group. Reference time is used to avoid
+// running time error caused by network burst.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::GroupTimeL( TUint& aGroupLength )
+ {
+ UpdateCurrentTimeL();
+ TUint syncLength( 0 );
+
+ // previous time initiated?
+ if ( iPreviousTime > 0 )
+ {
+ const TInt64 delta( iCurrentTime.Int64() - iPreviousTime );
+ iReferenceTime+= delta;
+ const TInt timeDelta( delta / KSiKilo );
+ const TInt burstDelta( Abs( timeDelta - iPreviousDelta ) );
+#ifdef CR_ALL_LOGS
+ LOG3( "CRtpToFile::GroupTimeL(), aGroupLength: %u, burstDelta: %d, timeDelta: %d",
+ aGroupLength, burstDelta, timeDelta );
+#endif // CR_ALL_LOGS
+
+ // Use reference time?
+ if ( timeDelta > KNormalRecGroupLength &&
+ Abs( burstDelta - aGroupLength ) < KMaxValidDelta )
+ {
+ iPreviousDelta = 0;
+ syncLength = iReferenceTime / KSiKilo;
+ }
+ else
+ {
+ iPreviousDelta = timeDelta;
+ syncLength = aGroupLength;
+ }
+ }
+ else
+ {
+ // In record start and after pause uses only the reported group length
+ iPreviousDelta = 0;
+ syncLength = aGroupLength;
+ iReferenceTime+= aGroupLength * KSiKilo;
+ }
+
+ // Update group time
+ iGroupTime += syncLength;
+ iPreviousTime = iCurrentTime.Int64();
+
+ // Time shift ongoing?
+ if ( iMode == EModeTimeShift )
+ {
+ aGroupLength = syncLength;
+ }
+ else
+ {
+ // Update seek array
+ aGroupLength = 0;
+ if ( ( iGroupTime - iSeekArrayReference ) >= KSeekArrayInterval )
+ {
+ AppendSeekArrayL( iGroupTime, iThisGroup );
+ iSeekArrayReference = iGroupTime;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::WriteInitialMetaHeaderL
+// Writes initial meta data header of clip.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::WriteInitialMetaHeaderL(
+ const MRtpFileWriteObserver::SRtpRecParams& aParams )
+ {
+ LOG( "CRtpToFile::WriteInitialMetaHeaderL() in" );
+
+ CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
+ iFile, CRtpMetaHeader::EMetaWrite );
+ // Attributes
+ CRtpMetaHeader::SAttributes att;
+ att.iOngoing = ETrue;
+ att.iCompleted = EFalse;
+ att.iProtected = EFalse;
+ att.iFailed = EFalse;
+ att.iVersion = KCurrentClipVersion;
+ att.iQuality = KDummyFullQuality;
+ att.iPostRule = aParams.iPostRule;
+ att.iParental = aParams.iParental;
+ att.iPlayCount = 0;
+ att.iPlaySpot = KErrNone;
+ metaheader->WriteAttributesL( att );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), iPostRule: %d", att.iPostRule );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), iParental: %d", att.iParental );
+
+ // Start date/time
+ metaheader->WriteStartTimeL( aParams.iStartTime );
+ TName buf( KNullDesC );
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+ aParams.iStartTime.FormatL( buf, KTimeDateFormat );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), iStartTime: %S", &buf );
+#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
+
+ // End time
+ metaheader->WriteEndTimeL( aParams.iEndTime );
+
+ // Duration
+ metaheader->WriteDurationL( 0 );
+
+ // Seek array point
+ metaheader->WriteSeekArrayPointL( 0 );
+
+ // Mime info
+ CRtpUtil::GetMimeInfo( buf );
+ metaheader->WriteUserIdL( buf );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), Mime: %S", &buf );
+
+ // Device info
+ CRtpUtil::GetImeiL( buf );
+ metaheader->WriteDeviceInfoL( buf );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), IMEI: %S", &buf );
+
+ // ESG info
+ metaheader->WriteEsgDataL( aParams.iService, aParams.iProgram );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), Service: %S",
+ &aParams.iService );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), Program: %S",
+ &aParams.iProgram );
+ // SRTP data ( Reserved for future use )
+ TBuf8<3> srtp;
+ srtp.Num( KErrNotFound );
+ metaheader->WriteSrtpDataL( srtp );
+
+ // SDP file
+ metaheader->WriteSdpDataL( aParams.iSdpData );
+ LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), SDP length: %d",
+ aParams.iSdpData.Length() );
+ metaheader->CommitL();
+ iSeekHeaderPoint = metaheader->SeekHeaderPoint();
+ CleanupStack::PopAndDestroy( metaheader );
+
+ LOG( "CRtpToFile::WriteInitialMetaHeaderL() out" );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::WriteFinalMetaHeaderL
+// Writes final meta data header of clip.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::WriteFinalMetaHeaderL( const TInt aStatus )
+ {
+ LOG( "CRtpToFile::WriteFinalMetaHeaderL() in" );
+ CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
+ iFile, CRtpMetaHeader::EMetaUpdate );
+ // Update duration
+ UpdateDurationL( metaheader );
+
+ // Attributes
+ CRtpMetaHeader::SAttributes att;
+ metaheader->ReadAttributesL( att );
+ att.iOngoing = EFalse;
+ att.iCompleted = !aStatus;
+ att.iFailed = !iGroupsTotalCount;
+ metaheader->WriteAttributesL( att );
+ LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), Completed: %d", att.iCompleted );
+ LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), iFailed : %d", att.iFailed );
+
+ // End date/time
+ metaheader->ReadStartTimeL( iCurrentTime );
+ iRecordEndTime = iCurrentTime.Int64() + iGroupTime;
+ metaheader->WriteEndTimeL( iRecordEndTime );
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+ TName buf( KNullDesC ); TTime( iRecordEndTime ).FormatL( buf, KTimeDateFormat );
+ LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), endTime: %S", &buf );
+#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
+
+ // Seek array point
+ metaheader->WriteSeekArrayPointL( iNextGroupPoint );
+ LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), Seek array: %d", iNextGroupPoint );
+ CleanupStack::PopAndDestroy( metaheader );
+
+ // Final seek header
+ SaveSeekArrayL();
+ WriteSeekHeaderL();
+
+ // Set orginal start time as file date
+ iFile.SetModified( iCurrentTime );
+
+ LOG( "CRtpToFile::WriteFinalMetaHeaderL() out" );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::AddGroupHeaderL
+// Adds header of one RTP group.
+// Room for group header bytes and packets count comes from CCRRtpRecordSink.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::AddGroupHeaderL()
+ {
+ // Packets count (PTC) is added in CCRRtpRecordSink::SaveGroup()
+
+ // Group time
+ HBufC8* bytes = CRtpUtil::MakeBytesLC( iGroupTime );
+ iDataPtr.Insert( 0, bytes->Des() );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Previous group point
+ bytes = CRtpUtil::MakeBytesLC( iPrevGroupPoint );
+ iDataPtr.Insert( 0, bytes->Des() );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Next Group point
+ bytes = CRtpUtil::MakeBytesLC( iNextGroupPoint );
+ iDataPtr.Insert( 0, bytes->Des() );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Group total size
+ bytes = CRtpUtil::MakeBytesLC( iGroupTotalLen );
+ iDataPtr.Insert( 0, bytes->Des() );
+ CleanupStack::PopAndDestroy( bytes );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::UpdateDurationL
+// Updates clip's duration.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::UpdateDurationL( CRtpMetaHeader* aMetaHeader )
+ {
+ aMetaHeader->WriteDurationL( TInt( iGroupTime ) );
+ LOG1( "CRtpToFile::UpdateDurationL(), new duration: %u", iGroupTime );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpToFile::UpdateCurrentTimeL
+// Gets current time as network time.
+// -----------------------------------------------------------------------------
+//
+void CRtpToFile::UpdateCurrentTimeL()
+ {
+ iCurrentTime.UniversalTime();
+ }
+
+// End of File
+