--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipRepairer.cpp Thu Dec 17 09:14:38 2009 +0200
@@ -0,0 +1,432 @@
+/*
+* 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 file repairer class.*
+*/
+
+
+
+
+// INCLUDE FILES
+#include "CRtpClipRepairer.h"
+#include <ipvideo/CRtpMetaHeader.h>
+#include <ipvideo/CRtpUtil.h>
+#include <e32math.h>
+#include <bsp.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+const TInt KMaxGroupTime( 4000 ); // 4s
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::NewL
+// Static two-phased constructor. Leaves object to cleanup stack.
+// -----------------------------------------------------------------------------
+//
+CRtpClipRepairer* CRtpClipRepairer::NewL( MRtpClipRepairObserver* aObs )
+ {
+ CRtpClipRepairer* self = new( ELeave ) CRtpClipRepairer( aObs );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::CRtpClipRepairer
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CRtpClipRepairer::CRtpClipRepairer( MRtpClipRepairObserver* aObs )
+ : CRtpFileBase(),
+ iObs( aObs ),
+ iSeekArrayPoint( KErrNotFound )
+ {
+ // None
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::ConstructL()
+ {
+ LOG( "CRtpClipRepairer::ConstructL()" );
+
+ CRtpFileBase::ConstructL();
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+//
+CRtpClipRepairer::~CRtpClipRepairer()
+// -----------------------------------------------------------------------------
+ {
+ LOG( "CRtpClipRepairer::~CRtpClipRepairer()" );
+
+ Cancel();
+ delete iFileData;
+ delete iMetaHeader;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::CurrentClipName
+// Getter for the clip name under repairing.
+// -----------------------------------------------------------------------------
+//
+TPtrC CRtpClipRepairer::CurrentClipName()
+ {
+ if ( iCurrentPath )
+ {
+ return iCurrentPath->Des();
+ }
+
+ return KNullDesC();
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::CheckMetaHeaderL
+// Checks if corrupted meta header of clip is possible to fix.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::CheckMetaHeaderL( const TDesC& aClipName )
+ {
+ LOG1( "CRtpClipRepairer::CheckMetaHeaderL(), aClipName: %S", &aClipName );
+
+ // Only one repair at the time
+ if ( iMetaHeader || iCurrentPath )
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+
+ // Open clip and read the meta header
+ delete iCurrentPath; iCurrentPath = NULL;
+ iCurrentPath = aClipName.AllocL();
+ if ( !iFs.Handle() )
+ {
+ User::LeaveIfError( iFs.Connect() );
+ }
+ iFile.Close();
+ User::LeaveIfError( iFile.Open( iFs, aClipName,
+ EFileShareExclusive | EFileStream | EFileWrite ) );
+ delete iMetaHeader; iMetaHeader = NULL;
+ iMetaHeader = CRtpMetaHeader::NewL( iFile, CRtpMetaHeader::EMetaUpdate );
+
+ // Attributes
+ CRtpMetaHeader::SAttributes att;
+ TRAPD( err, iMetaHeader->ReadAttributesL( att ) );
+
+ // Verify that clip version not too old?
+ if ( att.iVersion < KMinValidClipVersion )
+ {
+ LOG( "CRtpClipRepairer::CheckMetaHeaderL(), Not Valid Clip Version" );
+ User::Leave( KErrGeneral );
+ }
+
+ // If error or rec ongoing -> recording interrupted ie. battery removed
+ if ( err || att.iOngoing )
+ {
+ att.iOngoing = EFalse;
+ att.iPlayCount = 0;
+ att.iPlaySpot = KErrNone;
+ iMetaHeader->WriteAttributesL( att );
+ }
+
+ // Duration
+ TInt duration( 0 );
+ iMetaHeader->ReadDurationL( duration );
+ LOG1( "CRtpClipRepairer::CheckMetaHeaderL(), duration: %d", duration );
+
+ // Update seek array
+ if ( ( !duration || duration > KSeekArrayInterval ) && !ValidSeekHeaderL() )
+ {
+ UpdateSeekArrayL();
+ }
+ else
+ {
+ // Set start time to file date
+ TTime startTime( 0 );
+ iMetaHeader->ReadStartTimeL( startTime );
+ iFile.SetModified( startTime );
+ iFile.Close();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::RunL
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::RunL()
+ {
+ User::LeaveIfError( iStatus.Int() );
+ const TUint prevTime( iGroupTime );
+ UpdateGroupHeaderVariablesL( iDataPtr );
+ delete iFileData; iFileData = NULL;
+
+ // Current header valid?
+ if ( iThisGroup > iNextGroupPoint || iThisGroup < iPrevGroupPoint ||
+ iGroupTime < prevTime || iGroupTime > ( prevTime + KMaxGroupTime ) )
+ {
+ iLastSeekAddr = iPrevGroupPoint;
+ iThisGroup = iSeekArrayPoint;
+ }
+ else
+ {
+ // Handle readed group
+ GroupToSeekArrayL();
+ }
+
+ // Continue with next group if repair asyncronous?
+ if ( iObs )
+ {
+ if ( iThisGroup < iSeekArrayPoint )
+ {
+ // Asyncronous ( normal clip repairing )
+ ReadNextGroupHeaderFromFileL();
+ }
+ else
+ {
+ // All done, finalize the clip
+ AddSpecialPacketL( MRtpFileWriteObserver::ERtpClipEnd );
+ FinalizeSeekArrayL( KErrNone );
+ iObs->RtpClipRepaired( KErrNone );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::RunError
+// Returns: System wide error code of indication send leave reason
+// -----------------------------------------------------------------------------
+//
+TInt CRtpClipRepairer::RunError( TInt aError )
+ {
+ LOG1( "CRtpClipRepairer::RunError(), RunL Leaved: %d", aError );
+
+ TRAP_IGNORE( FinalizeSeekArrayL( aError ) );
+ if ( iObs )
+ {
+ iObs->RtpClipRepaired( ( iGroupsTotalCount )? KErrNone: aError );
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::DoCancel()
+ {
+ LOG( "CRtpClipRepairer::DoCancel()" );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::ValidSeekHeaderL
+// Verifies if seek header and seek array are valid.
+// -----------------------------------------------------------------------------
+//
+TBool CRtpClipRepairer::ValidSeekHeaderL()
+ {
+ // Seek header
+ iSeekHeaderPoint = iMetaHeader->SeekHeaderPoint();
+ ReadSeekHeaderL();
+
+ // Seek array point
+ iMetaHeader->ReadSeekArrayPointL( iSeekArrayPoint );
+
+ // Verify seek array
+ if ( iLastSeekAddr > iFirstSeekAddr && iSeekArrayPoint > iLastSeekAddr )
+ {
+ TInt count( KErrNotFound );
+ TRAPD( err, count = ReadSeekArrayL( iSeekArrayPoint ) );
+ if ( !err && count > 0 )
+ {
+ // Seek array is ok
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::UpdateSeekArrayL
+// Scans all packet groups in clip and updates seek array.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::UpdateSeekArrayL()
+ {
+ LOG( "CRtpClipRepairer::UpdateSeekArrayL()" );
+
+ // Scan complete clip for seek array
+ ResetSeekArray();
+ User::LeaveIfError( iFile.Size( iSeekArrayPoint ) );
+ iThisGroup = iFirstSeekAddr;
+ iGroupTime = 0;
+ iNextGroupPoint = 0;
+ iGroupsTotalCount = 0;
+
+ // Start reading
+ if ( iObs )
+ {
+ // Asyncronous
+ ReadNextGroupHeaderFromFileL();
+ }
+ else
+ {
+ // Syncronous
+ TInt err( KErrNone );
+ do
+ {
+ ReadNextGroupHeaderFromFileL();
+ TRAP( err, RunL() );
+ }
+ while ( !err && iThisGroup < iSeekArrayPoint );
+
+ // All done, finalize the clip
+ AddSpecialPacketL( MRtpFileWriteObserver::ERtpClipPause );
+ FinalizeSeekArrayL( KErrNone );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::ReadNextGroupHeaderFromFileL
+// Reads RTP payload from a file.
+// Payload is allways after data header, so read position set is not needed.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::ReadNextGroupHeaderFromFileL()
+ {
+ iLastSeekAddr = iThisGroup;
+
+ iFileData = HBufC8::NewL( KGroupHeaderBytes );
+ iDataPtr.Set( iFileData->Des() );
+ if ( iObs )
+ {
+ iFile.Read( iThisGroup, iDataPtr, KGroupHeaderBytes, iStatus );
+ SetActive();
+ }
+ else
+ {
+ iStatus = iFile.Read( iThisGroup, iDataPtr, KGroupHeaderBytes );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::GroupToSeekArrayL
+// Appends next rec group's group time to seek array if interval time exeeded.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::GroupToSeekArrayL()
+ {
+ iGroupsTotalCount++;
+ const TInt delta( iGroupTime - iLastGroupTime );
+ if ( delta > KSeekArrayInterval )
+ {
+ LOG2( "CRtpClipRepairer::GroupToSeekArrayL(), iGroupsTotalCount: %d, iThisGroup: %d",
+ iGroupsTotalCount, iThisGroup );
+ iLastGroupTime = iGroupTime;
+ AppendSeekArrayL( iGroupTime, iThisGroup );
+ }
+
+ iPrevGroupPoint = iThisGroup;
+ iThisGroup = iNextGroupPoint;
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::AddSpecialPacketL
+// Adds special packet to a new group to the end of clip.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::AddSpecialPacketL(
+ const MRtpFileWriteObserver::TRtpType aType )
+ {
+ LOG1( "CRtpClipRepairer::AddSpecialPacketL(), aType: %d", aType );
+
+ // Read last group header
+ iThisGroup = iPrevGroupPoint;
+ ReadGroupHeaderL();
+
+ // End packet
+ HBufC8* bytes = CRtpUtil::SpecialPacketL( aType );
+ CleanupStack::PushL( bytes );
+ iFile.Write( iThisGroup + iGroupTotalLen, bytes->Des(), KSpecialPacketLength );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Update group total size (GTS)
+ iGroupTotalLen+= KSpecialPacketLength;
+ bytes = CRtpUtil::MakeBytesLC( iGroupTotalLen );
+ iFile.Write( iThisGroup, bytes->Des(), KIntegerBytes );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Update next group point (NGP)
+ iNextGroupPoint+= KSpecialPacketLength;
+ bytes = CRtpUtil::MakeBytesLC( iNextGroupPoint );
+ iFile.Write( iThisGroup + KIntegerBytes, bytes->Des(), KIntegerBytes );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Read packets total count (PTC)
+ bytes = HBufC8::NewLC( KPacketsCountBytes );
+ TPtr8 ptr( bytes->Des() );
+ iFile.Read( iThisGroup + KGroupHeaderBytes, ptr, KPacketsCountBytes );
+ const TInt packetsCount( CRtpUtil::GetValueL( ptr ) );
+ User::LeaveIfError( packetsCount );
+ CleanupStack::PopAndDestroy( bytes );
+
+ // Increment packets tolal count (PTC) by one
+ bytes = CRtpUtil::MakeBytesLC( packetsCount + 1 );
+ iFile.Write( iThisGroup + KGroupHeaderBytes, bytes->Des(), KPacketsCountBytes );
+ CleanupStack::PopAndDestroy( bytes );
+ }
+
+// -----------------------------------------------------------------------------
+// CRtpClipRepairer::FinalizeSeekArrayL
+// Appends next rec group to seek array.
+// -----------------------------------------------------------------------------
+//
+void CRtpClipRepairer::FinalizeSeekArrayL( const TInt aError )
+ {
+ LOG1( "CRtpClipRepairer::FinalizeSeekArrayL(), aError: %d", aError );
+
+ // New seek array point
+ iMetaHeader->WriteSeekArrayPointL( iNextGroupPoint );
+
+ // Update duration
+ iMetaHeader->WriteDurationL( iGroupTime );
+
+ // Last group time
+ CRtpMetaHeader::SAttributes att;
+ iMetaHeader->ReadAttributesL( att );
+ att.iFailed = !( !aError );
+ att.iOngoing = EFalse;
+ att.iPlayCount = 0;
+ att.iPlaySpot = KErrNone;
+ iMetaHeader->WriteAttributesL( att );
+
+ // Finalise
+ SaveSeekArrayL();
+ WriteSeekHeaderL();
+ iFile.Flush();
+
+ // Set start time to file date
+ TTime startTime( 0 );
+ iMetaHeader->ReadStartTimeL( startTime );
+ iFile.SetModified( startTime );
+ iFile.Close();
+ }
+
+// End of File