dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpClipHandler.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:37 +0100
branchRCL_3
changeset 23 13a33d82ad98
parent 0 822a42b6c3f1
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201029 Kit: 201035

/*
* 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 <ipvideo/CRtpClipHandler.h>
#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