dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipRepairer.cpp
changeset 0 822a42b6c3f1
--- /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