diff -r 826cea16efd9 -r 13a33d82ad98 dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipRepairer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipRepairer.cpp Wed Sep 01 12:20:37 2010 +0100 @@ -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 +#include +#include +#include +#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