diff -r 826cea16efd9 -r 13a33d82ad98 dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipHandler.cpp Wed Sep 01 12:20:37 2010 +0100 @@ -0,0 +1,584 @@ +/* +* 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 RTP clip handler class.* +*/ + + + + +// INCLUDE FILES +#include +#include "CRtpToFile.h" +#include "CRtpFromFile.h" +#include "videoserviceutilsLogger.h" + +// CONSTANTS +const TInt KDvrMaxTimeshiftDelta( 1 * 60 * 60 ); // 1 hour + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CRtpClipHandler* CRtpClipHandler::NewL() + { + CRtpClipHandler* self = new( ELeave ) CRtpClipHandler(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::CRtpClipHandler +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CRtpClipHandler::CRtpClipHandler() + : iClipVersion( 0 ), + iSaveNameIndex( KErrNotFound ), + iReadNameIndex( KErrNotFound ), + iTsPauseState( EFalse ) + { + // None + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CRtpClipHandler::ConstructL() + { + LOG( "CRtpClipHandler::ConstructL()" ); + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::~CRtpClipHandler +// Destructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CRtpClipHandler::~CRtpClipHandler() + { + LOG( "CRtpClipHandler::~CRtpClipHandler() in" ); + + StopRecording( KErrCancel ); + StopPlayBack( KErrCancel, 0 ); + + LOG( "CRtpClipHandler::~CRtpClipHandler() out" ); + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::RegisterWriteObserver +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::RegisterWriteObserver( + MRtpFileWriteObserver* aObs ) + { + LOG1( "CRtpClipHandler::RegisterWriteObserver(), aObs: %d", aObs ); + iWriteObs = aObs; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::RegisterReadObserver +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::RegisterReadObserver( MRtpFileReadObserver* aObs ) + { + LOG1( "CRtpClipHandler::RegisterReadObserver(), aObs: %d", aObs ); + + iReadObs = aObs; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::StartRecordingL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::StartRecordingL( + const MRtpFileWriteObserver::SRtpRecParams& aRecParams, + const MRtpFileWriteObserver::TRtpSaveAction& aAction ) + { + LOG1( "CRtpClipHandler::StartRecordingL() in, aAction: %d", aAction ); + + // Stop possible existing recording + StopRecording( KErrNone ); + iSaveNameIndex = 0; + + // If InitRtpSaveL leaves, iRtpSave is not NULL, but is in undefined state. + // This causes problems - may crash when StopRecording is called. + // Better to trap and cleanup here. + TRAPD( err, + // Init recording ( iRtpSave deleted in StopRecording() ) + iRtpSave = CRtpToFile::NewL( *this, *iWriteObs ); + iRtpSave->InitRtpSaveL( aRecParams, aAction ); + ); + if ( err ) + { + delete iRtpSave; iRtpSave = NULL; + User::Leave( err ); + } + + LOG( "CRtpClipHandler::StartRecordingL() out" ); + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::SaveNextGroupL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::SaveNextGroupL( + TPtr8& aGroup, + TUint aGroupLength, + const MRtpFileWriteObserver::TRtpSaveAction& aAction ) + { + User::LeaveIfNull( iWriteObs ); + User::LeaveIfNull( iRtpSave ); + + // Passes save action to ring buffer + const TUint seekPoint( iRtpSave->SaveNextGroupL( + aGroup, aGroupLength, aAction ) ); + + // aGroupLength is set to non zero if time shift ongoing? + if ( aGroupLength > 0 ) + { + CRtpFileBase::STimeShiftSeek shiftSeek; + shiftSeek.iGroupTime = aGroupLength; + shiftSeek.iSeekpoint = seekPoint; + shiftSeek.iNameIndex = iSaveNameIndex; + iShiftSeek.Append( shiftSeek ); + + // Time shift max length + if ( ( ( iShiftSeek.Count() - 1 ) * KNormalRecGroupLength ) > + KDvrMaxTimeshiftDelta ) + { + LOG( "CRtpClipHandler::SaveNextGroupL(), Timeshift max time !" ); + } + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::WritingActive +// +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CRtpClipHandler::WritingActive( void ) const + { + if ( iRtpSave ) + { + return iRtpSave->IsActive(); + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::GetCurrentLength +// +// ----------------------------------------------------------------------------- +// +EXPORT_C TUint CRtpClipHandler::GetCurrentLength( void ) const + { + TUint length( 0 ); + if ( iRtpRead ) + { + length = iRtpRead->Duration(); + } + else + { + if ( iRtpSave ) + { + const TInt count( iShiftSeek.Count() ); + if ( count > 0 ) + { + // Time shift + for ( TInt i( 0 ); i < count; i++ ) + { + length += iShiftSeek[i].iGroupTime; + } + } + else + { + // Rec ongoing + length = iRtpSave->GetCurrentLength(); + } + } + } + + return length; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::TimeShiftPauseL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::TimeShiftPauseL() + { + LOG2( "CRtpClipHandler::TimeShiftPauseL(), iRtpSave: %d, iTsPauseState: %d", + iRtpSave, iTsPauseState ); + User::LeaveIfNull( iRtpSave ); + if ( !iTsPauseState ) + { + // Use clip as a ring buffer + iRtpSave->ActivateGroupsReuseL(); + iTsPauseState = ETrue; + } + else + { + // Switch to next file + iSaveNameIndex++; + MRtpFileWriteObserver::SRtpRecParams recParams; + DefaultRecParams( recParams, iSaveNameIndex ); + iRtpSave->SwapClipL( recParams ); + iTsPauseState = EFalse; + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::DefaultRecParams +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::DefaultRecParams( + MRtpFileWriteObserver::SRtpRecParams& aParams, + const TInt aIndex ) + { + aParams.iClipPath = KDvrTimeShiftFile; + aParams.iClipPath.AppendNum( aIndex ); + aParams.iSdpData.Set( NULL, 0 ); + aParams.iService.Set( KNullDesC ); + aParams.iProgram.Set( KNullDesC ); + aParams.iPostRule = 0; + aParams.iParental = 0; + aParams.iStartTime = 0; + aParams.iEndTime = TInt64( KDvrMaximumTimeShift ) * 1e6; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::UpdateRecordEndTime +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::UpdateRecordEndTime( const TTime& aEndTime ) + { + if ( iRtpSave ) + { + iRtpSave->UpdateRecordEndTime( aEndTime ); + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::ResumeRecordingL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::ResumeRecordingL( void ) + { + LOG1( "CRtpClipHandler::ResumeRecordingL(), iRtpSave: %d", iRtpSave ); + + if ( iRtpSave ) + { + iRtpSave->UpdatePreviousTimeL(); + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::StopRecording +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::StopRecording( const TInt aError ) + { + LOG2( "CRtpClipHandler::StopRecording(), aError: %d, iRtpSave: %d", + aError, iRtpSave ); + + if ( iRtpSave ) + { + // Update clip end point if watching sametime + if ( iRtpRead ) + { + iRtpRead->UpdateLastSeekAddr(); + } + + // Stop recording + iRtpSave->StopRtpSave( aError ); + + // Delete possible time shift files + if ( !iRtpRead ) + { + iRtpSave->DeleteTimeShiftFiles( iShiftSeek ); + } + } + + delete iRtpSave; iRtpSave = NULL; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::StartPlayBackL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::StartPlayBackL( + const SCRRtpPlayParams& aParams, + const TBool aTimeShift ) + { + LOG1( "CRtpClipHandler::StartPlayBackL(), path: %S", &aParams.iFileName ); + LOG1( "CRtpClipHandler::StartPlayBackL(), aTimeShift: %d", aTimeShift ); + + // Stop possible existing + StopPlayBack( KErrNone, 0 ); + + // Time shift mode? + if ( aTimeShift ) + { + // Open file for time shift mode + User::LeaveIfNull( iRtpSave ); + iRtpRead = CRtpFromFile::NewL( *iReadObs, iRtpSave ); + iReadNameIndex = ( iShiftSeek.Count() )? iShiftSeek[0].iNameIndex: 0; + TPath clipPath( KDvrTimeShiftFile ); + clipPath.AppendNum( iReadNameIndex ); + iRtpRead->InitRtpReadL( clipPath, iClipVersion, aTimeShift ); + } + else + { + // Open file, during recording? + if ( iRtpSave && iRtpSave->ClipPath() ) + { + if ( !aParams.iFileName.Compare( iRtpSave->ClipPath()->Des() ) ) + { + iRtpRead = CRtpFromFile::NewL( *iReadObs, iRtpSave ); + } + } + + // Open file, normal playback? + if ( !iRtpRead ) + { + iRtpRead = CRtpFromFile::NewL( *iReadObs, NULL ); + } + + iRtpRead->InitRtpReadL( aParams.iFileName, iClipVersion, EFalse ); + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::StartPlayBackL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::StartPlayBackL( const RFile& aFileHandle ) + { + LOG( "CRtpClipHandler::StartPlayBackL(), with handle" ); + + // Stop possible existing + StopPlayBack( KErrNone, 0 ); + + // Open file, during recording? + if ( iRtpSave && iRtpSave->ClipPath() ) + { + TPath name( KNullDesC ); + aFileHandle.FullName( name ); + if ( !name.Compare( iRtpSave->ClipPath()->Des() ) ) + { + iRtpRead = CRtpFromFile::NewL( *iReadObs, iRtpSave ); + } + } + + // Open file, normal playback? + if ( !iRtpRead ) + { + iRtpRead = CRtpFromFile::NewL( *iReadObs, NULL ); + } + + iRtpRead->InitRtpReadL( aFileHandle, iClipVersion ); + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::GetClipSdpL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C HBufC8* CRtpClipHandler::GetClipSdpL( void ) const + { + HBufC8* sdp = NULL; + if ( iRtpRead ) + { + sdp = iRtpRead->GetClipSdpL(); + } + + return sdp; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::NextClipGroupL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::NextClipGroupL( void ) + { + User::LeaveIfNull( iRtpRead ); + if ( !iRtpRead->IsTimeShift() ) + { + iRtpRead->ReadNextGroupL( KErrNotFound ); + } + else + { + // Handle time shift + TInt err( KErrNotFound ); + if ( iShiftSeek.Count() ) + { + // Need swap file? + SwapClipIfNeededL(); + + // Read next group + TRAP( err, iRtpRead->ReadNextGroupL( iShiftSeek[0].iSeekpoint ) ); + if ( err != KErrInUse ) + { + iShiftSeek.Remove( 0 ); + } + } + + // End time shift? + if ( err == KErrEof ) + { + LOG( "CRtpClipHandler::NextClipGroupL(), Time shift play reached live !" ); + User::LeaveIfNull( iReadObs ); + iReadObs->ReadStatus( MRtpFileReadObserver::ERtpTimeShifTEnd ); + } + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::SetSeekPointL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::SetSeekPointL( const TUint aTime ) + { + LOG1( "CRtpClipHandler::SetSeekPointL(), aTime: %u", aTime ); + + User::LeaveIfNull( iRtpRead ); + if ( !iShiftSeek.Count() ) + { + iRtpRead->SetSeekPointL( aTime ); + } + else + { + const TInt count( iShiftSeek.Count() ); + if ( count > 0 ) + { + TUint total( 0 ); + for ( TInt index( 0 ); index < count && aTime > total; index++ ) + { + total += iShiftSeek[0].iGroupTime; + SwapClipIfNeededL(); + iShiftSeek.Remove( 0 ); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::StopPlayBack +// ----------------------------------------------------------------------------- +// +EXPORT_C void CRtpClipHandler::StopPlayBack( + const TInt aError, + const TUint aPlayerBuf ) + { + LOG2( "CRtpClipHandler::StopPlayBack(), aError: %d, iRtpRead: %d", + aError, iRtpRead ); + if ( iRtpRead ) + { + iRtpRead->StopRtpRead( aError, aPlayerBuf ); + + // Delete possible time shift files + if ( !iRtpSave ) + { + iRtpRead->DeleteTimeShiftFiles( iShiftSeek ); + } + } + + delete iRtpRead; iRtpRead = NULL; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::RtpGroupSaved +// Indicates that RPT packet save is ready. +// ----------------------------------------------------------------------------- +// +void CRtpClipHandler::RtpGroupSaved( const TInt aAction ) + { + // Inform file reader that new group saved + if ( iRtpRead && aAction >= KErrNone ) + { + iRtpRead->ReadSkippedGroup(); + } + + // Group saved + if ( iWriteObs ) + { + if ( aAction != MRtpFileWriteObserver::ESaveEnd ) + { + // Ready for next group + iWriteObs->GroupSaved(); + } + else + { + // Recording full time + iWriteObs->WriteStatus( KErrNone ); + } + } + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::CurrentFileReadPoint +// Getter for file reader current point. +// ----------------------------------------------------------------------------- +// +TInt CRtpClipHandler::CurrentFileReadPoint( const TInt aIndex ) + { + if ( iShiftSeek.Count() > aIndex ) + { + if ( iShiftSeek[aIndex].iNameIndex == iSaveNameIndex ) + { + return iShiftSeek[aIndex].iSeekpoint; + } + + return KErrNone; + } + + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CRtpClipHandler::SwapClipIfNeededL +// Swap to next available clip in time shift array if needed. +// ----------------------------------------------------------------------------- +// +void CRtpClipHandler::SwapClipIfNeededL( void ) + { + if ( iShiftSeek[0].iNameIndex != iReadNameIndex ) + { + iReadNameIndex = iShiftSeek[0].iNameIndex; + TPath clipPath( KDvrTimeShiftFile ); + clipPath.AppendNum( iReadNameIndex ); + iRtpRead->SwapClipL( clipPath ); + } + } + +// End of File