diff -r 798ee5f1972c -r 826cea16efd9 dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpToFile.cpp --- a/dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpToFile.cpp Thu Aug 19 10:54:18 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,712 +0,0 @@ -/* -* 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 -#include -#include -#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 -