dvrengine/CommonRecordingEngine/src/CCREngine.cpp
branchRCL_3
changeset 48 13a33d82ad98
parent 0 822a42b6c3f1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/src/CCREngine.cpp	Wed Sep 01 12:20:37 2010 +0100
@@ -0,0 +1,1592 @@
+/*
+* 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:    Engine part of the engine. In practice keeps count on*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <pathinfo.h>
+#include "VideoServiceUtilsConf.hrh" 
+#include "CCREngine.h"
+#include "CCRStreamingSession.h"
+#include "CCRSession.h"
+#include "CCRClientInformer.h"
+#include "CCRConnection.h"
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+#include <ipvideo/CRtpUtil.h>
+#include <ipvideo/CRtpClipHandler.h>
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+#include <e32msgqueue.h>
+#include <ipvideo/CRTypeDefs.h>
+#include <e32std.h>
+#include <es_sock.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+const TUint KCRELoopbackPortStart( 1106 );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCREngine::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCREngine* CCREngine::NewL( void )
+    {
+    CCREngine* self = new( ELeave ) CCREngine();
+
+    // Use CleanupClosePushL to make sure the Close function defined in CObject
+    // base class gets called. CObject will delete itself once its reference count
+    // reaches zero. Using CleanupStack::PushL here results in E32USER-CBase panic 33
+    // if there is a leave somewhere in construction
+    CleanupClosePushL( *self );
+
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::CCREngine
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CCREngine::CCREngine( void ) : iLoopbackPort( KCRELoopbackPortStart )
+    {
+    // None
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCREngine::ConstructL()
+    {
+    LOG( "CCREngine::ConstructL()" );
+    
+    // Note, quite high priority
+    iCleanUp = new ( ELeave ) CAsyncCallBack( CActive::EPriorityStandard ); 
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::~CCREngine
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CCREngine::~CCREngine()
+    {
+    LOG( "CCREngine::~CCREngine()" );
+
+    delete iCleanUp;
+    iSessions.ResetAndDestroy();
+    iSessionsToDelete.Reset(); 
+    delete iConnection;
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    delete iClipHandler;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    iSockServer.Close(); 
+    delete iInformer; 
+    delete iQueueName;
+    }
+
+// -----------------------------------------------------------------------------
+// Method for actual message handling.
+//
+// -----------------------------------------------------------------------------
+//
+void CCREngine::GeneralServiceL( const RMessage2& aMessage )
+    {
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+    if ( aMessage.Function() != ECRGetPosition )
+        {
+        LOG1( "CCREngine::GeneralService(), aMessage: %d", aMessage.Function() );
+        }
+#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
+
+    // Verify cababilities
+    VerifyCapabilitiesL( aMessage );
+
+    // Handle message
+    TInt err( KErrNone );
+    switch( aMessage.Function() )
+        {
+        case ECRSetIap:
+            {
+            TPckgBuf<SCRRtspIapParams> pckg;
+            Read( aMessage, 0, pckg );
+            err = SetConnectionId( pckg() );  
+            aMessage.Complete( err );
+            }
+            break;      
+            
+        case ECRCancelSetIap:
+            aMessage.Complete( CancelSetConnectionId() );
+            break;
+            
+        case ECRPlayRtspUrl:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRRtspParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, pckg0() = PlayRtspUrlL( pckg1() ) );
+            if ( !err )
+                {
+                Write( aMessage, 0, pckg0 );
+                }
+            aMessage.Complete( err );
+            }
+            break;      
+            
+        case ECRPlayDvbhLive:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRLiveParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, pckg0() = PlayDvbhLiveL( pckg1() ) );
+            if ( !err )    
+                {
+                Write( aMessage, 0, pckg0 );
+                }
+            aMessage.Complete( err );
+            }
+            break;      
+            
+        case ECRChangeService:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRLiveParams> pckg1;
+            Read( aMessage, 0, pckg0 );
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, pckg0() = ChangeDvbhServiceL( pckg0(), pckg1() ) );
+            if ( !err )    
+                {
+                Write( aMessage, 0, pckg0 );
+                }
+            aMessage.Complete( err );
+            }
+            break;
+            
+        case ECRPlayRtpFile:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRRtpPlayParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, pckg0() = PlayRtpFileL( pckg1() ) );
+            if ( !err )
+                {
+                Write( aMessage, 0, pckg0 );
+                }
+            aMessage.Complete( err );
+            }
+            break;      
+            
+        case ECRPlayRtpHandle:
+            {
+            RFile fileHandle;
+            err = fileHandle.AdoptFromClient( aMessage, 1, 2 );
+            if ( !err )
+                {
+                TPckgBuf<TUint> pckg( 0 );
+                TRAP( err, pckg() = PlayRtpFileL( fileHandle ) );
+                if ( !err )
+                    {
+                    Write( aMessage, 0, pckg );
+                    }
+                }
+            fileHandle.Close();
+            aMessage.Complete( err );
+            }
+            break;      
+            
+        case ECRRecordCurrentStream:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            TPckgBuf<SCRRecordParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, RecordCurrentStreamL( pckg0(), pckg1() ) );
+            aMessage.Complete( err );
+            }
+            break;
+            
+        case ECRRecordRtspStream:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRRtspParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TPckgBuf<SCRRecordParams> pckg2;
+            Read( aMessage, 2, pckg2 );
+            TRAP( err, pckg0() = RecordRtspStreamL( pckg1(), pckg2() ) );
+            aMessage.Complete( err );
+            }
+            break;
+            
+        case ECRRecordDvbhStream:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRLiveParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TPckgBuf<SCRRecordParams> pckg2;
+            Read( aMessage, 2, pckg2 );
+            TRAP( err, pckg0() = RecordDvbhStreamL( pckg1(), pckg2() ) );
+            aMessage.Complete( err );
+            }
+            break;
+            
+        case ECRPauseRecordStream:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            TPckgBuf<TBool> pckg1( 0 );
+            Read( aMessage, 1, pckg1 );
+            aMessage.Complete( PauseRecordStream( pckg0(), pckg1() ) );
+            }
+            break;
+            
+        case ECRStopRecordStream:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            aMessage.Complete( StopRecordStream( pckg0() ) );
+            }
+            break;
+            
+        case ECRStartTimeShift:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<TUint> pckg1( 0 );
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, pckg0() = StartTimeShiftL( pckg1() ) );
+            if ( !err )
+                {
+                Write( aMessage, 0, pckg0 );
+                }
+            aMessage.Complete( err );
+            }
+            break;
+            
+        case ECRStopTimeShift:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<TUint> pckg1( 0 );
+            Read( aMessage, 0, pckg0 );
+            Read( aMessage, 1, pckg1 );
+            aMessage.Complete( StopTimeShift( pckg0(), pckg1() ) );
+            }
+            break;
+            
+        case ECRPlayCommand:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            TPckgBuf<TInt64> pckg1( 0 );
+            Read( aMessage, 1, pckg1 );
+            TPckgBuf<TInt64> pckg2( 0 );
+            Read( aMessage, 2, pckg2 );
+            aMessage.Complete( PlayCommand( pckg0(), pckg1(), pckg2() ) );
+            }
+            break;
+        
+        case ECRPauseCommand:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            aMessage.Complete( PauseCommand( pckg0() ) );
+            }
+            break;
+        
+        case ECRStopCommand:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            aMessage.Complete( StopCommand( pckg0() ) );
+            }
+            break;
+        
+        case ECRSetPosition:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            TPckgBuf<TInt64> pckg1( 0 );
+            Read( aMessage, 1, pckg1 );
+            err = SetPosition( pckg0(), pckg1() );
+            aMessage.Complete( err );
+            }
+            break;
+        
+        case ECRGetPosition:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            TPckgBuf<TInt64> pckg1( 0 );
+            Read( aMessage, 1, pckg1 );
+            TPckgBuf<TInt64> pckg2( 0 );
+            err = GetPosition( pckg0(), pckg1(), pckg2() );
+            Write( aMessage, 1, pckg1 );
+            Write( aMessage, 2, pckg2 );
+            aMessage.Complete( err );
+            }
+            break;
+            
+        case ECRCloseSession:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            Read( aMessage, 0, pckg0 );
+            aMessage.Complete( CloseSession( pckg0() ) );
+            }
+            break;
+        
+        case ECRPlayNullSource:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TRAP( err, pckg0() = PlayNullSourceL() );
+            Write( aMessage, 0, pckg0 );
+            aMessage.Complete( err );
+            }
+            break;     
+        
+        case ECRPlayRtspUrlToNullSink:
+            {
+            TPckgBuf<TUint> pckg0( 0 );
+            TPckgBuf<SCRRtspParams> pckg1;
+            Read( aMessage, 1, pckg1 );
+            TRAP( err, pckg0() = PlayRtspUrlToNullSinkL( pckg1() ) );
+            Write( aMessage, 0, pckg0 );
+            aMessage.Complete( err );
+            }
+            break;     
+        
+        default:
+            aMessage.Complete( KErrNotSupported ); 
+            break; 
+        }
+    }
+    
+//-----------------------------------------------------------------------------
+// CCREngine::SessionStop()
+// So, a session wants to quit. we can't just delete it here as return.
+// Statement would then take us to deleted instance: put up a cleanup 
+// CAsyncCallBack and return.
+//-----------------------------------------------------------------------------
+//
+void CCREngine::SessionStop( CCRStreamingSession* aSession )
+    {
+    LOG1( "CCREngine::SessionStop(), Delete count: %d", iSessionsToDelete.Count() );    
+
+    // InsertInAddressOrder checks for duplicate, if there is already
+    // entry for that session, the array will remain unchanged
+    TRAPD( err, iSessionsToDelete.InsertInAddressOrderL( aSession ) ); 
+    if ( err )
+        {
+        LOG1( "CCREngine::SessionStop(), InsertInAddressOrder leaved: %d", err );      
+        }
+
+    // If not already active and sessions to delete?
+    if ( !iCleanUp->IsActive() && iSessionsToDelete.Count() ) 
+        {
+        TCallBack cb( SessionStopCallBack, this );
+        iCleanUp->Set( cb );
+        iCleanUp->CallBack();
+        }               
+    }
+    
+// -----------------------------------------------------------------------------
+// CCREngine::ConnectionStatusChange
+//
+// -----------------------------------------------------------------------------
+//
+void CCREngine::ConnectionStatusChange(
+    TInt aSessionId,
+    TCRConnectionStatus aStatus,
+    TInt aErr )
+    {
+    LOG3( "CCREngine::ConnectionStatusChange(), aSessionId: %d, aStatus: %d, Error: %d",
+                                                aSessionId, aStatus, aErr );
+    
+    SCRQueueEntry entry = { ECRMsgQueueConnectionError, KErrNone };
+    entry.iSessionId = aSessionId;
+
+    switch ( aStatus )
+        {           
+        case ECRConnectionError:
+            {               
+            entry.iMsg = ECRMsgQueueConnectionError;
+            entry.iErr = aErr;
+            }
+            break;
+        
+        case ECRAuthenticationNeeded:
+            {               
+            entry.iMsg = ECRMsgQueueAuthenticationNeeded;
+            entry.iErr = KErrNone;
+            }      
+            break;  
+        
+        case ECRNotEnoughBandwidth:
+            {               
+            entry.iMsg = ECRMsgQueueNotEnoughBandwidth;
+            entry.iErr = KErrNone;
+            }      
+            break;  
+        
+        case ECRNormalEndOfStream:
+            {               
+            entry.iMsg = ECRMsgQueueNormalEndOfStream;
+            entry.iErr = aErr;
+            }
+            break;
+        
+        case ECRAttachCompleted: // fall through
+        case ECRSwitchingToTcp:
+            {               
+            aStatus == ECRAttachCompleted ? 
+                           ( entry.iMsg = ECRMsgQueueAttachCompleted ) :
+                           ( entry.iMsg = ECRMsgQueueSwitchingToTcp );
+            
+            if ( aErr == KErrNone )
+                {
+                // Releasing RSocket takes almost 40 seconds so we need 
+                // to always use different port number, otherwise an  
+                // "Already in use" error will be occurred.
+                TTime now;
+                now.UniversalTime();                  
+                TInt port = KCRELoopbackPortStart + now.DateTime().Second();   
+                iLoopbackPort == port ? ( iLoopbackPort = port + 1 ) : 
+                                        ( iLoopbackPort = port );
+
+                // Loopback port for VIA
+                entry.iErr = iLoopbackPort;
+                }
+            else
+                {
+                entry.iErr = aErr;
+                }
+            }           
+            break;  
+            
+        case ECRStreamIsLiveStream:
+            {
+            entry.iMsg = ECRMsgQueueStreamIsLiveStream; 
+            entry.iErr = aErr; 
+            }
+            break; 
+
+        case ECRStreamIsRealMedia:
+            {
+            entry.iMsg = ECRMsgQueueStreamIsRealMedia; 
+            entry.iErr = aErr; 
+            }
+            break; 
+
+        case ECRBearerChanged:
+            {
+            // Nobody is interested about this on the other side...
+            return;         
+            }
+
+        case ECRTestSinkData:
+            {
+            entry.iMsg = ECRMsgQueueTestSinkData;
+            entry.iErr = aErr;
+            }
+            break;
+
+        case ECRSdpAvailable:
+            {
+            entry.iMsg = ECRMsgQueueSdpAvailable;
+            entry.iErr = aErr;
+            }
+            break;
+        
+        case ECRReadyToSeek:
+            {
+            entry.iMsg = ECRMsgQueueReadyToSeek; 
+            entry.iErr = aErr; 
+            }
+            break; 
+
+        case ECRRecordingStarted:
+            {
+            entry.iMsg = ECRMsgQueueRecordingStarted;
+            entry.iErr = aErr;
+            }
+            break;
+        
+        case ECRRecordingPaused:
+            {
+            entry.iMsg = ECRMsgQueueRecordingPaused;
+            entry.iErr = aErr;
+            }
+            break;
+        
+        case ECRRecordingEnded:
+            {
+            entry.iMsg = ECRMsgQueueRecordingEnded;
+            entry.iErr = aErr;
+            }
+            break;
+        
+        default:
+            // None
+            break;
+        }
+    
+    if ( iQueueName && iInformer )
+        {
+        iInformer->SendMessage( iQueueName->Des(), entry ); 
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifyCapabilitiesL
+// Checks capabilities of user of DVR API.
+// -----------------------------------------------------------------------------
+//
+void CCREngine::VerifyCapabilitiesL( const RMessage2& aMessage )
+    {
+    if ( !aMessage.HasCapability( ECapabilityNetworkServices, 
+         __PLATSEC_DIAGNOSTIC_STRING( "NetworkServices" ) ) )
+        {
+        LOG( "CCREngine::VerifyRbfCapabilitiesL(), Missing: NetworkServices !" );
+        User::Leave( KErrPermissionDenied );
+	    }
+    
+    if ( !aMessage.HasCapability( ECapabilityReadUserData,
+         __PLATSEC_DIAGNOSTIC_STRING( "ReadUserData" ) ) )
+	    {
+        LOG( "CCREngine::VerifyRbfCapabilitiesL(), Missing: ReadUserData !" );
+        User::Leave( KErrPermissionDenied );
+	    }
+                                 
+    if ( !aMessage.HasCapability( ECapabilityWriteUserData,
+         __PLATSEC_DIAGNOSTIC_STRING( "WriteUserData" ) ) )
+	    {
+        LOG( "CCREngine::VerifyRbfCapabilitiesL(), Missing: WriteUserData !" );
+        User::Leave( KErrPermissionDenied );
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::SetConnectionId
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::SetConnectionId( const SCRRtspIapParams& aIap ) 
+    {
+    LOG( "CCREngine::SetConnectionId() in" );
+
+    TRAPD ( err, CreateConnectionL() ) ;
+    if ( err == KErrNone )
+        {
+        delete iQueueName; iQueueName = NULL;
+        TRAP( err, iQueueName = aIap.iQueueName.AllocL() );
+        if ( err == KErrNone )
+            {
+            iConnection->Attach( aIap.iConnectionId );  
+            }
+        
+        }
+    LOG1( "CCREngine::SetConnectionId() out, err: %d", err );
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::CancelSetConnectionId
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::CancelSetConnectionId() 
+    {
+    LOG( "CCREngine::CancelSetConnectionId() in" );
+    
+    TInt err( KErrNone );
+    if ( iConnection ) 
+        {
+        iSessions.ResetAndDestroy();
+        delete iConnection; iConnection = NULL;
+        iSockServer.Close(); 
+        err = iSockServer.Connect( KESockDefaultMessageSlots * 3 );
+        if ( err == KErrNone ) 
+            {
+            TRAP( err, iConnection = CCRConnection::NewL( iSockServer ) );
+            if ( err == KErrNone && iConnection )
+                {
+                err = iConnection->RegisterObserver( this );                    
+                }
+            }
+        }
+    
+    LOG1( "CCREngine::CancelSetConnectionId() out, err: %d", err );
+    return err; 
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PlayRtspUrlL
+// Go through stream sessions and try to find if given url is already playing.
+// If not, create new RTSP session and add sink to it.
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::PlayRtspUrlL( const SCRRtspParams& aRtspParams ) 
+    {
+    LOG( "CCREngine::PlayRtspUrlL() in" );
+    
+    const TInt sessionIndex( VerifyRtspSessionL( aRtspParams ) );
+    iSessions[sessionIndex]->CreateRtspSinkL( iLoopbackPort );
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::PlayRtspUrlL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PlayDvbhLiveL
+// Go through stream sessions and try to find if current service is already
+// If not, create new DVB-H session and add sink to it.
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::PlayDvbhLiveL( const SCRLiveParams& aLiveParams ) 
+    {
+    LOG( "CCREngine::PlayDvbhLiveL() in" );
+
+    const TInt sessionIndex( VerifyDvbhSessionL( aLiveParams ) );
+    iSessions[sessionIndex]->CreateXpsSinkL();
+    iSessions[sessionIndex]->PostActionL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::PlayDvbhLiveL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::ChangeDvbhServiceL
+// Go through stream sessions and try to find if current service is already
+// If not, create new DVB-H session and add sink to it.
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::ChangeDvbhServiceL(
+    const TUint aSessionChk,
+    const SCRLiveParams& aLiveParams ) 
+    {
+    LOG( "CCREngine::ChangeDvbhServiceL() in" );
+
+    // Verify exist session
+    const TInt currentSession( VerifySession( aSessionChk ) );
+    User::LeaveIfError( currentSession );
+    
+    // Can't perform if recording or timeshift ongoing
+    if ( iSessions[currentSession]->ClipHandlerUsed() )
+        {
+        User::Leave( KErrInUse );
+        }
+
+    // New session for new service
+    const TInt sessionIndex( VerifyDvbhSessionL( aLiveParams ) );
+    if ( sessionIndex == currentSession )
+        {
+        // Same service, no actions
+        return aSessionChk;
+        }
+    
+    // Stop sockets of DVB-H source (filters released)
+    User::LeaveIfError( iSessions[currentSession]->StopCommand() );
+    
+    // Transfer ownership of existing XPS sink to a new session
+    User::LeaveIfError( iSessions[currentSession]->TransferSink( 
+        CCRStreamingSession::ECRXpsSinkId, *iSessions[sessionIndex] ) );
+    iSessions[sessionIndex]->PostActionL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    
+    // Delete existing unused session
+    SessionStop( iSessions[currentSession] );
+    LOG1( "CCREngine::ChangeDvbhServiceL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PlayRtpFileL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::PlayRtpFileL( const SCRRtpPlayParams& aRtpParams ) 
+    {
+    LOG( "CCREngine::PlayRtpFileL() in" );
+
+    const TInt sessionIndex( VerifyRtpFileSessionL( aRtpParams ) );
+    iSessions[sessionIndex]->CreateXpsSinkL();
+    iSessions[sessionIndex]->PostActionL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::PlayRtpFileL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PlayRtpFileL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::PlayRtpFileL( const RFile& aFileHandle ) 
+    {
+    LOG( "CCREngine::PlayRtpFileL() in, with hadle" );
+
+    TInt sessionIndex( VerifyRtpFileSessionL( aFileHandle ) );
+    iSessions[sessionIndex]->CreateXpsSinkL();
+    iSessions[sessionIndex]->PostActionL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::PlayRtpFileL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::RecordCurrentStreamL
+//
+// -----------------------------------------------------------------------------
+//
+void CCREngine::RecordCurrentStreamL(
+    const TUint aSessionChk,
+    const SCRRecordParams& aRecordParams ) 
+    {
+    LOG1( "CCREngine::StartRecordStreamL() in, aSessionChk: %d", aSessionChk );
+
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+        
+    // Session exist?
+    if ( sessionIndex > KErrNotFound )
+        {
+        CreateRecordingSinkL( sessionIndex, aRecordParams );
+        iSessions[sessionIndex]->PostActionL();
+        }
+
+    LOG1( "CCREngine::StartRecordStreamL() out, sessionIndex: %d", sessionIndex );
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::RecordRtspStreamL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::RecordRtspStreamL(
+    const SCRRtspParams& aRtspParams,
+    const SCRRecordParams& aRecordParams ) 
+    {
+    LOG( "CCREngine::RecordRtspStreamL() in" );
+
+    // Verify session
+    const TInt sessionIndex( VerifyRtspSessionL( aRtspParams ) );
+
+    // Recording sink
+    CreateRecordingSinkL( sessionIndex, aRecordParams );
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::RecordRtspStreamL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::RecordDvbhStreamL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::RecordDvbhStreamL(
+    const SCRLiveParams& aLiveParams,
+    const SCRRecordParams& aRecordParams ) 
+    {
+    LOG( "CCREngine::RecordDvbhStreamL() in" );
+
+    // Verify session
+    const TInt sessionIndex( VerifyDvbhSessionL( aLiveParams ) );
+
+    // Recording sink
+    CreateRecordingSinkL( sessionIndex, aRecordParams );
+    iSessions[sessionIndex]->PostActionL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::RecordDvbhStreamL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PauseRecordStream
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::PauseRecordStream( const TUint aSessionChk, const TBool& aStart ) 
+    {
+    LOG2( "CCREngine::PauseRecordStream() in, aSessionChk: %d, aStart: %d", 
+                                              aSessionChk, aStart );
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+        
+    // Session exist?
+    if ( sessionIndex > KErrNotFound )
+        {
+        TInt err( KErrNone );
+        if ( aStart )
+            {
+            // Clip format not known, so all types must try to pause
+            err = iSessions[sessionIndex]->PauseCommand(
+                  CCRStreamingSession::ECRRtpRecSinkId );
+            if ( err == KErrCompletion )
+                {
+                err = iSessions[sessionIndex]->PauseCommand(
+                      CCRStreamingSession::ECR3gpRecSinkId );
+                }
+            
+            ConnectionStatusChange( aSessionChk, ECRRecordingPaused, err );
+            }
+        else
+            {
+            // Clip format not known, so all types must try to pause
+            err = iSessions[sessionIndex]->RestoreCommand(
+                  CCRStreamingSession::ECRRtpRecSinkId );
+            if ( err == KErrCompletion )
+                {
+                err = iSessions[sessionIndex]->RestoreCommand(
+                      CCRStreamingSession::ECR3gpRecSinkId );
+                }
+
+            ConnectionStatusChange( aSessionChk, ECRRecordingStarted, err );
+            }
+        
+        LOG1( "CCREngine::PauseRecordStream() out, err: %d", err );
+        return err;
+        }
+        
+    LOG1( "CCREngine::PauseRecordStream() out, sessionIndex: %d", sessionIndex );
+    return sessionIndex;    
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::StopRecordStream
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::StopRecordStream( const TUint aSessionChk ) 
+    {
+    LOG1( "CCREngine::StopRecordStream() in, aSessionChk: %d", aSessionChk );
+    
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+        
+    // Session exist?
+    if ( sessionIndex > KErrNotFound )
+        {
+        // Clip format not known, so all types must try to stop
+        iSessions[sessionIndex]->StopCommand(
+            CCRStreamingSession::ECRRtpRecSinkId );
+        iSessions[sessionIndex]->StopCommand(
+            CCRStreamingSession::ECR3gpRecSinkId );
+        // Possible error(s) ignored
+        }
+        
+    LOG1( "CCREngine::StopRecordStream() out, sessionIndex: %d", sessionIndex );
+    return sessionIndex;    
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::StartTimeShift
+// Existing stream play will be splitted to two sessions. Existing source will
+// be directed to recording and existing sink will get new source from playback.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::StartTimeShiftL( const TUint aSessionChk ) 
+    {
+    LOG1( "CCREngine::StartTimeShiftL() in, aSessionChk: %d", aSessionChk );
+
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+    // Verify session
+    const TInt currentSession( VerifySession( aSessionChk ) );
+    User::LeaveIfError( currentSession );
+
+    // Initial time shift clip name
+    TPath initialName( KDvrTimeShiftFile );
+    initialName.AppendNum( 0 );
+    
+    // RTP clip handler
+    CreateClipHandlerL();
+
+    // Start recording of stream
+    SCRRecordParams recordParams;
+    recordParams.iFileName.Set( initialName );
+    recordParams.iFormat = ECRRecordTimeShift;
+    iSessions[currentSession]->CreateRtpRecordSinkL( recordParams, iClipHandler );
+    iSessions[currentSession]->PostActionL();
+
+    // Create new session for time shift clip playback
+    SCRRtpPlayParams params;
+    params.iFileName = initialName;
+    const TInt timeShiftSession( VerifyRtpFileSessionL( params ) );
+    iSessions[timeShiftSession]->PostActionL();
+
+    // Transfer ownership of existing XPS sink to a new session
+    User::LeaveIfError( iSessions[currentSession]->TransferSink( 
+        CCRStreamingSession::ECRXpsSinkId, *iSessions[timeShiftSession] ) );
+
+    // Session checksum
+    TUint sessionChk( iSessions[timeShiftSession]->SourceChecksum() );
+    LOG1( "CCREngine::StartTimeShiftL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+
+#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    ( void )aSessionChk;
+    return KErrNotSupported;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::StopTimeShift
+// Streaming is set back to one session. Streaming orginal source stays and sink
+// from temporary playback will be moved back to orginal session.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::StopTimeShift(
+    const TUint aTimeShiftChk,
+    const TUint aCurrentChk ) 
+    {
+    LOG2( "CCREngine::StopTimeShift() in, aTimeShiftChk: %d, aCurrentChk: %d", 
+                                          aTimeShiftChk, aCurrentChk );
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+    // Verify session
+    int ret( KErrNotFound );
+    const TInt currentSession( VerifySession( aCurrentChk ) );
+    const TInt timeShiftSession( VerifySession( aTimeShiftChk ) );
+        
+    // Session exist?
+    if ( currentSession > KErrNotFound && timeShiftSession > KErrNotFound )
+        {
+        // Stop time shift clip recording
+        iSessions[currentSession]->StopCommand( 
+            CCRStreamingSession::ECR3gpRecSinkId );
+        
+        // Stop time shift clip playback
+        iSessions[timeShiftSession]->StopCommand();
+
+        // Transfer ownership of existing XPS sink back to the old session
+        ret = iSessions[timeShiftSession]->TransferSink( 
+            CCRStreamingSession::ECRXpsSinkId, *iSessions[currentSession] );
+        
+        // Delete second session
+        SessionStop( iSessions[timeShiftSession] );
+        }
+    
+    // Clip handler not needed any longer
+    DeleteClipHandler( currentSession );
+
+    LOG1( "CCREngine::StopTimeShift() out, ret: %d", ret );
+    return ret;    
+
+#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    ( void )aTimeShiftChk;
+    ( void )aCurrentChk;
+    return KErrNotSupported;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PlayCommand
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::PlayCommand(
+    const TUint aSessionChk,
+    const TReal aStartPos,
+    const TReal aEndPos ) 
+    {
+    LOG1( "CCREngine::PlayCommand(), aSessionChk: %d", aSessionChk );
+
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+        
+    // New session needed?
+    if ( sessionIndex > KErrNotFound )
+        {
+        return iSessions[sessionIndex]->PlayCommand( aStartPos, aEndPos );
+        }
+        
+    return KErrNotReady;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PauseCommand
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::PauseCommand( const TUint aSessionChk )
+    {
+    LOG1( "CCREngine::PauseCommand(), aSessionChk: %d", aSessionChk );
+
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+        
+    // New session needed?
+    if ( sessionIndex > KErrNotFound )
+        {
+        return iSessions[sessionIndex]->PauseCommand();
+        }
+        
+    return KErrNotReady;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::StopCommand
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::StopCommand( const TUint aSessionChk )
+    {
+    LOG1( "CCREngine::StopCommand(), aSessionChk: %d", aSessionChk );
+
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+        
+    // New session needed?
+    if ( sessionIndex > KErrNotFound )
+        {
+        return iSessions[sessionIndex]->StopCommand();
+        }
+        
+    return KErrNotReady;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::SetPosition
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::SetPosition(
+    const TUint aSessionChk,
+    const TInt64 aPosition )
+    {
+    LOG1( "CCREngine::SetPosition(), aSessionChk: %d", aSessionChk );
+
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+    if ( sessionIndex > KErrNotFound )
+        {
+        return iSessions[sessionIndex]->SetPosition( aPosition );
+        }
+   
+    return KErrNotReady;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::GetPosition
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::GetPosition(
+    const TUint aSessionChk,
+    TInt64& aPosition,
+    TInt64& aDuration ) 
+    {
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+    if ( sessionIndex > KErrNotFound )
+        {
+        return iSessions[sessionIndex]->GetPosition( aPosition, aDuration );
+        }
+
+    return KErrNotReady;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::CloseSession
+//
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::CloseSession( const TUint aSessionChk )
+    {
+    LOG1( "CCREngine::CloseSession(), aSessionChk: %d", aSessionChk );
+    
+    // Verify session
+    const TInt sessionIndex( VerifySession( aSessionChk ) );
+    if ( sessionIndex > KErrNotFound )
+        {
+        SessionStop( iSessions[sessionIndex] );
+        }
+    
+    return KErrNone;
+    }
+    
+// -----------------------------------------------------------------------------
+// CCREngine::PlayNullSourceL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::PlayNullSourceL() 
+    {
+    LOG( "CCREngine::PlayNullSourceL() in" );
+
+    _LIT( KNullSourceClip, "NullSource.rtp" );
+    TFileName nullSourcePath;
+#if ( defined( __WINS__ ) || defined( __WINSCW__ ) )
+    nullSourcePath = PathInfo::PhoneMemoryRootPath();
+#else // __WINS__ || __WINSCW__
+    nullSourcePath = PathInfo::MemoryCardRootPath();
+#endif // __WINS__ || __WINSCW__
+    nullSourcePath.Append( KNullSourceClip );
+
+    TInt sessionIndex( VerifySession( nullSourcePath ) );
+    if ( sessionIndex == KErrNotFound )
+        {
+        CCRStreamingSession* session = CCRStreamingSession::NewL(
+                                       iSockServer, iConnection, *this );        
+        CleanupStack::PushL( session );
+        User::LeaveIfError( iSessions.Append( session ) );
+        CleanupStack::Pop( session );
+
+        // Only one source per session
+        sessionIndex = iSessions.Count() - 1;
+        iSessions[sessionIndex]->OpenSourceL( nullSourcePath );
+        }
+
+    iSessions[sessionIndex]->CreateXpsSinkL();
+    //iSessions[sessionIndex]->CreateNullSinkL();
+    iSessions[sessionIndex]->PostActionL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::PlayNullSourceL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PlayRtspUrlToNullSinkL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CCREngine::PlayRtspUrlToNullSinkL( const SCRRtspParams& aRtspParams ) 
+    {
+    LOG( "CCREngine::PlayRtspUrlToNullSinkL() in" );
+    
+    const TInt sessionIndex( VerifyRtspSessionL( aRtspParams ) );
+    iSessions[sessionIndex]->CreateNullSinkL();
+    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
+    LOG1( "CCREngine::PlayRtspUrlToNullSinkL() out, sessionChk: %d", sessionChk );
+    return sessionChk;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::CreateConnectionL
+// 
+// -----------------------------------------------------------------------------
+//
+void CCREngine::CreateConnectionL( void )
+    {
+    LOG( "CCREngine::CreateConnectionL() in" );
+
+    if ( iConnection == NULL )
+        {
+        User::LeaveIfError( iSockServer.Connect( KESockDefaultMessageSlots * 3 ) );
+        iConnection = CCRConnection::NewL( iSockServer );
+        User::LeaveIfError( iConnection->RegisterObserver( this ) );
+        
+        // Informer
+        if ( iInformer == NULL )
+            {
+            iInformer = CCRClientInformer::NewL();
+            }
+        }
+    
+    LOG( "CCREngine::CreateConnectionL() out" );
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::CreateClipHandlerL
+// 
+// -----------------------------------------------------------------------------
+//
+void CCREngine::CreateClipHandlerL( void )
+    {
+    LOG1( "CCREngine::CreateClipHandlerL(), iClipHandler: %d", iClipHandler );
+
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+    if ( !iClipHandler )
+        {
+        iClipHandler = CRtpClipHandler::NewL();
+        }
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifyRtspSessionL
+// Go through stream sessions and try to find if RTSP stream is already playing.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::VerifyRtspSessionL( const SCRRtspParams& aRtspParams ) 
+    {
+    TInt sessionIndex( VerifySession( aRtspParams.iUrl ) );
+    
+    // New session needed?
+    if ( sessionIndex == KErrNotFound )
+        {
+        CCRStreamingSession* session = CCRStreamingSession::NewL(
+                                       iSockServer, iConnection, *this ); 
+        CleanupStack::PushL( session );       
+        User::LeaveIfError( iSessions.Append( session ) );
+        CleanupStack::Pop( session );
+
+        // Only one source per session
+        sessionIndex = iSessions.Count() - 1;
+        iSessions[sessionIndex]->OpenSourceL( aRtspParams, aRtspParams.iUrl );
+        }
+    
+    User::LeaveIfError( sessionIndex );
+    return sessionIndex;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifyDvbhSessionL
+// Go through stream sessions and try to find if DVB-H live is already playing.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::VerifyDvbhSessionL( const SCRLiveParams& aLiveParams ) 
+    {
+    // Verify session
+    HBufC* definition = HBufC::NewLC( aLiveParams.iSdpData.Length() );
+    definition->Des().Copy( aLiveParams.iSdpData );
+    TInt sessionIndex( VerifySession( *definition ) );
+
+    // New session needed?
+    if ( sessionIndex == KErrNotFound )
+        {
+        CCRStreamingSession* session = CCRStreamingSession::NewL(
+                                       iSockServer, iConnection, *this );        
+        CleanupStack::PushL( session );
+        User::LeaveIfError( iSessions.Append( session ) );
+        CleanupStack::Pop( session );
+        
+        // Only one source per session
+        sessionIndex = iSessions.Count() - 1;
+        iSessions[sessionIndex]->OpenSourceL( aLiveParams, *definition );
+        }
+    
+    CleanupStack::PopAndDestroy( definition );
+    User::LeaveIfError( sessionIndex );
+    return sessionIndex;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifyRtpFileSessionL
+// Go through stream sessions and try to find if RTP clip is already playing.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::VerifyRtpFileSessionL( const SCRRtpPlayParams& aRtpParams ) 
+    {
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+    // Verify session
+    TInt sessionIndex( VerifySession( aRtpParams.iFileName ) );
+        
+    // New session needed?
+    if ( sessionIndex == KErrNotFound )
+        {
+        
+        CCRStreamingSession* session = CCRStreamingSession::NewL(
+                                       iSockServer, iConnection, *this );        
+        CleanupStack::PushL( session );
+        User::LeaveIfError( iSessions.Append( session ) );
+        CleanupStack::Pop( session );
+
+        // RTP clip handler
+        CreateClipHandlerL();
+        
+        // Only one source per session
+        sessionIndex = iSessions.Count() - 1;
+        iSessions[sessionIndex]->OpenSourceL( aRtpParams, iClipHandler, 
+                                              aRtpParams.iFileName );
+        }
+
+    User::LeaveIfError( sessionIndex );
+    return sessionIndex;
+
+#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    ( void )aRtpParams;
+    return KErrNotSupported;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifyRtpFileSessionL
+// Go through stream sessions and try to find if RTP clip is already playing.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::VerifyRtpFileSessionL( const RFile& aFileHandle ) 
+    {
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+    TFileName fileName( KNullDesC );
+    aFileHandle.FullName( fileName );
+    TInt sessionIndex( VerifySession( fileName ) );
+        
+    // New session needed?
+    if ( sessionIndex == KErrNotFound )
+        {
+        CCRStreamingSession* session = CCRStreamingSession::NewL(
+                                       iSockServer, iConnection, *this );        
+        CleanupStack::PushL( session );
+        User::LeaveIfError( iSessions.Append( session ) );
+        CleanupStack::Pop( session );
+
+        // RTP clip handler
+        CreateClipHandlerL();
+        
+        // Only one source per session
+        sessionIndex = iSessions.Count() - 1;
+        iSessions[sessionIndex]->OpenSourceL( aFileHandle, iClipHandler, fileName );
+        }
+
+    User::LeaveIfError( sessionIndex );
+    return sessionIndex;
+
+#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    ( void )aFileHandle;
+    return KErrNotSupported;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifySession
+// Go through stream sessions and try to find stream is already playing.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::VerifySession( const TDesC& aName ) 
+    {
+    if ( iSessions.Count() > 0 )
+        {
+        for ( TInt i( iSessions.Count() - 1 ); i >= 0; i-- )
+            {
+            const TUint chksm( iSessions[i]->SourceDefinition( aName ) );
+            if ( chksm == iSessions[i]->SourceChecksum() )
+                {
+                return i;
+                }
+            }
+        }
+
+    return KErrNotFound;
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::VerifySession
+// Go through stream sessions and try to find session index from active sessions.
+// -----------------------------------------------------------------------------
+//
+TInt CCREngine::VerifySession( const TUint aSessionChk ) 
+    {
+    if ( iSessions.Count() > 0 )
+        {
+        for ( TInt i( iSessions.Count() - 1 ); i >= 0; i-- )
+            {
+            if ( aSessionChk == iSessions[i]->SourceChecksum() )
+                {
+                return i;
+                }
+            }
+        }
+
+    return KErrNotFound;
+    }
+
+//-----------------------------------------------------------------------------
+// CCREngine::CreateRecordingSinkL
+//
+//-----------------------------------------------------------------------------
+//
+void CCREngine::CreateRecordingSinkL(
+    const TInt aSessionIndex,
+    const SCRRecordParams& aRecordParams )
+    {
+    LOG1( "CCREngine::CreateRecordingSinkL(), aSessionIndex: %d", aSessionIndex );
+    
+    User::LeaveIfError( aSessionIndex );
+    switch ( aRecordParams.iFormat )
+        {
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+        case ECRRecordFormatRtp:
+            // RTP clip handler
+            CreateClipHandlerL();
+            iSessions[aSessionIndex]->CreateRtpRecordSinkL(
+                aRecordParams, iClipHandler );
+            break;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+        case ECRRecordFormat3gp:
+            iSessions[aSessionIndex]->Create3gpRecordSinkL( aRecordParams );
+            break;
+
+        default:
+            LOG( "CCREngine::CreateRecordingSinkL(), Clip format invalid !");
+            User::Leave( KErrNotSupported );
+            break;
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCREngine::SessionStopCallBack
+//
+//-----------------------------------------------------------------------------
+//
+TInt CCREngine::SessionStopCallBack ( TAny* aThis ) 
+    {
+    LOG( "CCREngine::SessionStopCallBack()" );
+    
+    CCREngine* self = static_cast<CCREngine*>( aThis );
+    self->DoSessionStop();
+    return self->iSessionsToDelete.Count(); 
+    }
+    
+//-----------------------------------------------------------------------------
+// CCREngine::DoSessionStop
+//
+//-----------------------------------------------------------------------------
+//
+void CCREngine::DoSessionStop( void ) 
+    {
+    LOG1( "CCREngine::DoSessionStop() in, iSessionsToDelete.Count = %d", iSessionsToDelete.Count() );
+    
+    for ( TInt i( iSessionsToDelete.Count() - 1 ); i >= 0; i-- )
+        {
+        for ( TInt j( iSessions.Count() - 1 ); j >= 0; j-- )
+            {
+            if ( iSessions[j] == iSessionsToDelete[i] )
+                {
+                delete iSessions[j];
+                iSessions.Remove( j ); 
+                }
+            }
+        }
+    
+    // Supposed to be empty by now
+    DeleteClipHandler( KErrNotFound );
+    iSessionsToDelete.Reset();
+    LOG( "CCREngine::DoSessionStop() out" );
+    }
+    
+//-----------------------------------------------------------------------------
+// CCREngine::DeleteClipHandler
+//
+//-----------------------------------------------------------------------------
+//
+void CCREngine::DeleteClipHandler( const TInt aCurrentSessionIndex ) 
+    {
+    LOG1( "CCREngine::DeleteClipHandler(), aCurrentSessionIndex: %d",
+                                           aCurrentSessionIndex );
+#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
+
+    if ( iClipHandler )
+        {
+        // Find out clip handler usage
+        TBool notUsed( ETrue );
+        for ( TInt i( iSessions.Count() - 1 ); i >= 0; i-- )
+            {
+            if ( i != aCurrentSessionIndex && iSessions[i]->ClipHandlerUsed() )
+                {
+                notUsed = EFalse;
+                }
+            }
+
+        // Clip handler not needed any longer?
+        if ( notUsed )
+            {
+            delete iClipHandler; iClipHandler = NULL;    
+            LOG( "CCREngine::DeleteClipHandler(), RTP ClipHandler deleted !" );
+            }
+        }
+    
+#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    ( void )aCurrentSessionIndex;
+#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
+    }
+    
+// -----------------------------------------------------------------------------
+// CCREngine::Read
+// Read from the client thread, if unsuccessful, panic the client.
+// -----------------------------------------------------------------------------
+//
+void CCREngine::Read(
+    const RMessage2& aMessage, 
+    const TInt& aParam,
+    TDes8& aDes ) 
+    {
+    TRAPD( err, aMessage.ReadL( aParam, aDes ) );
+    if ( err )
+        {
+        PanicClient( ECRPanicBadDescriptor, aMessage );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::Read
+// Read from the client thread, if unsuccessful, panic the client.
+// -----------------------------------------------------------------------------
+//
+void CCREngine::Read(
+    const RMessage2& aMessage, 
+    const TInt& aParam,
+    TDes16& aDes ) 
+    {
+    TRAPD( err, aMessage.ReadL( aParam, aDes ) );
+    if ( err )
+        {
+        PanicClient( ECRPanicBadDescriptor, aMessage );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::Write
+// Write to the client thread, if unsuccessful, panic the client.
+// -----------------------------------------------------------------------------
+//
+void CCREngine::Write(
+    const RMessage2& aMessage, 
+    const TInt& aParam,
+    const TDesC8& aDes ) 
+    {
+    TRAPD( err, aMessage.WriteL( aParam, aDes ) );
+    if ( err )
+        {
+        PanicClient( ECRPanicBadDescriptor, aMessage );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::Write
+// Write to the client thread, if unsuccessful, panic the client.
+// -----------------------------------------------------------------------------
+//
+void CCREngine::Write(
+    const RMessage2& aMessage, 
+    const TInt& aParam,
+    const TDesC16& aDes ) 
+    {
+    TRAPD( err, aMessage.WriteL( aParam, aDes ) );
+    if ( err )
+        {
+        PanicClient( ECRPanicBadDescriptor, aMessage );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCREngine::PanicClient
+//
+// -----------------------------------------------------------------------------
+//
+void CCREngine::PanicClient( TInt aPanic, const RMessage2& aMessage )
+    {
+    // Panic the client on server side
+    _LIT( KRbfClientFault, "Common recording engine" );
+    aMessage.Panic( KRbfClientFault, aPanic );
+    }   
+    
+//  End of File