--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/src/CCREngine.cpp Thu Dec 17 09:14:38 2009 +0200
@@ -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