--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccvideosourcesink/src/mccvideosinkimpl.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1951 @@
+/*
+* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+*/
+
+
+
+
+// INCLUDES FILES
+#include <w32std.h>
+#include <AudioPreference.h>
+#include <mmcccodecinformationfactory.h>
+#include <mmcccodecinformation.h>
+#include "mccvideosinkimpl.h"
+#include "mmcccodech263.h"
+#include "mccvideosourcesinklogs.h"
+#include "mccinternalevents.h"
+#include "CXPSPacketSink.h"
+#include "mmcccodecamr.h"
+#include "mccvideosinkuser.h"
+#include "mccdef.h"
+#include "mccredrawhandler.h"
+#include "mccinternaldef.h"
+#include <videoplayer2.h>
+
+// CONSTANTS
+
+
+_LIT8( KMccSdpInboundStart,
+"v=0\r\n\
+o=- 63327476467155000 63327476467155000 IN IP4 0.0.0.0\r\n\
+s=-\r\n\
+c=IN IP4 0.0.0.0\r\n\
+t=0 0\r\n" );
+
+_LIT8( KMccSdpInboundAudio,
+"m=audio 25001 RTP/AVP %d\r\n\
+a=rtpmap:%d %S/8000\r\n\
+a=ptime:%d\r\n\
+a=maxptime:%d\r\n\
+a=fmtp:%d octet-align=%d; mode-set=%S\r\n" );
+
+_LIT8( KMccSdpInboundVideo,
+"m=video 25002 RTP/AVP %d\r\n\
+a=rtpmap:%d %S/90000\r\n\
+a=fmtp:%d %S\r\n\
+a=XpsPyldBufSize:integer;%d\r\n\
+a=FrameWidth:integer;%d\r\n\
+a=FrameHeight:integer;%d\r\n" );
+
+_LIT8( KMccSdpInboundPreroll, "a=DisableMinPrerollCheck:integer;1\r\n\
+a=Preroll:integer;%d\r\n" );
+
+_LIT8( KMccSdpInboundDisableVideoClock, "a=DisableVideoClock:integer;1\r\n" );
+
+
+_LIT( KMccWindowGroupName,"32MccVideoWindow" );
+_LIT( KMccHelixSource,"MccDataSource%d");
+// NOTE: filepath separator changed to unix style because of problem at Helix side
+_LIT( KMccPacketSource, "file://c:/notinuse.xps?XPSServer=%S" );
+
+// MACROS
+
+#define MCC_BITRATE_IN_MASK( bitratemask, bitrate ) bitrate == ( bitratemask & bitrate )
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+
+// ---------------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkImpl::CMccVideoSinkImpl( TUint32 aEndpointId ) :
+ iEndpointId( aEndpointId ),
+ iVolumeAdaptation( 0 ),
+ iPreroll( 0 ),
+ iPrerollSet( EFalse )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::CMccVideoSinkImpl" )
+
+ iSettings.iVideoFrameRate = KMccDefaultVideoFrameRate;
+ }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::ConstructL( const TMccVideoSinkSetting& aSettings )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL" )
+
+ iSettings = aSettings;
+
+ SetVideoFrameRate( aSettings.iVideoFrameRate );
+
+ const TInt KMccVideoSinkMaxSdpLen = 800;
+ iSdp = HBufC8::NewL( KMccVideoSinkMaxSdpLen );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL, init Helix" )
+ iPacketSink = CXPSPacketSink::New();
+ __ASSERT_ALWAYS(iPacketSink, User::Leave( KErrNotReady ) );
+
+ const TInt KMaxTUintAsDesLen = 12;
+ iServerName =
+ HBufC::NewL( KMccHelixSource().Length() + KMaxTUintAsDesLen );
+ iServerName->Des().AppendFormat( KMccHelixSource, (TUint32)this );
+
+ iPacketSink->Init( *iServerName, this );
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL, init Helix complete" )
+
+ iSearchTermUser = CMccVideoSinkUser::NewL(
+ NULL, KNullUid, 0, iSettings.iVideoFrameRate, *iPacketSink );
+
+ User::LeaveIfError( iRwSession.Connect() );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructL connected to ws" )
+ __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window pos:",
+ iSettings.iLocation.iX, " ", iSettings.iLocation.iY )
+ __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window size (w,h):",
+ iSettings.iSize.iWidth, " ", iSettings.iSize.iHeight )
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal pos:",
+ iSettings.iWindowOrdinalPosition )
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal priority:",
+ iSettings.iWindowOrdinalPriority )
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl rotation:",
+ iSettings.iRotation )
+
+ // Create window group
+ TInt groupId = iRwSession.GetFocusWindowGroup();
+ iRwGroup = new (ELeave) RWindowGroup( iRwSession );
+
+ User::LeaveIfError( iRwGroup->Construct( groupId, EFalse ) );
+ iRwGroup->SetName( KMccWindowGroupName );
+
+ // TBD: use also iWindowOrdinalPriority
+ iRwGroup->SetOrdinalPosition( iSettings.iWindowOrdinalPosition );
+
+ // Create screen device
+ iDev = new (ELeave) CWsScreenDevice( iRwSession );
+ User::LeaveIfError( iDev->Construct( iSettings.iDeviceIndex ) );
+
+ // Create window
+ iRw = new (ELeave) RWindow( iRwSession );
+
+ User::LeaveIfError( iRw->Construct( *iRwGroup, (TUint32)iRw ) );
+
+ iRw->SetPosition( iSettings.iLocation );
+ iRw->SetSize( iSettings.iSize );
+
+ iRw->SetOrdinalPosition( iSettings.iWindowOrdinalPosition );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: creating graphics context ..." )
+ User::LeaveIfError( iDev->CreateContext( iGc ) );
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: graphics context created!" )
+
+
+ iRw->Activate();
+
+ iRwSession.Flush();
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: creating redraw handler" )
+
+ iRedrawHandler = CMccRedrawHandler::NewL( iRwSession, *iRw, *iGc );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: created redraw handler" )
+
+ // Videoplayer needs to be created last, otherwise destruction
+ // order causes problems
+ iVideoPlayer = CVideoPlayerUtility2::NewL(
+ *this,
+ iSettings.iPriority.iPriority,
+ iSettings.iPriority.iPref );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl: created CVideoPlayerUtility2" )
+
+ // Wait for MvpuoOpenComplete before adding display window
+
+ RegisterForVideoLoadingNotification( *this );
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkImpl* CMccVideoSinkImpl::NewL(
+ const TMccVideoSinkSetting& aSettings,
+ TUint32 aEndpointId )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::NewL" )
+ CMccVideoSinkImpl* self = new ( ELeave ) CMccVideoSinkImpl( aEndpointId );
+
+ CleanupStack::PushL( self );
+
+ self->ConstructL( aSettings );
+
+ CleanupStack::Pop( self ); // self
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkImpl::~CMccVideoSinkImpl()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::~CMccVideoSinkImpl" )
+
+ SetCurrentUser( NULL );
+
+ delete iSdp;
+
+ if ( iPacketSink )
+ {
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ iPacketSink->StreamEnd( iUsers[ i ]->iStreamId );
+ }
+ iPacketSink->Reset();
+ }
+
+
+ iUsers.ResetAndDestroy();
+
+ delete iPacketSink;
+
+ if( iVideoPlayer )
+ {
+ Stop();
+ iVideoPlayer->Close();
+ }
+
+ delete iVideoPlayer;
+
+ delete iRedrawHandler;
+
+ delete iGc;
+ delete iDev;
+
+ delete iRw;
+ delete iRwGroup;
+ iRwSession.Close();
+
+ delete iServerName;
+
+ delete iSearchTermUser;
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::~CMccVideoSinkImpl, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SinkThreadLogon()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::SinkThreadLogon( MAsyncEventHandler& aEventHandler )
+ {
+ // Give zero stream id at beginning, correct id is set later
+ TRAPD( err, AddUserL( aEventHandler ) );
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SinkThreadLogoff()
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::SinkThreadLogoff()
+ {
+ if ( iCurrentUser )
+ {
+ TUint streamId( 0 );
+ if ( ResolveStreamId( iCurrentUser, streamId ) == KErrNone )
+ {
+ RemoveVideoSinkUser( iCurrentUser, streamId );
+ }
+ iCurrentUser = NULL;
+ }
+ return ( iUsers.Count() == 0 );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetCurrentUser()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetCurrentUser( MAsyncEventHandler* aEventHandler )
+ {
+ iCurrentUser = aEventHandler;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::OpenL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::OpenL()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL" )
+ if ( SetVideoSinkState( EOpening ) )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL, doing setup" )
+
+ RemoteSetupL();
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL, opening" )
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+ __ASSERT_ALWAYS( iPacketSink, User::Leave( KErrArgument ) );
+
+ const TUid KUidController = { 0x101F8514 }; //RNAVCONTROLLER.DLL
+
+ HBufC* url =
+ HBufC::NewLC( KMccPacketSource().Length() + iServerName->Length() );
+ url->Des().AppendFormat( KMccPacketSource, &*iServerName );
+ iVideoPlayer->OpenUrlL( *url, 0, KNullDesC8, KUidController );
+ CleanupStack::PopAndDestroy( url );
+ }
+ else if ( iState == EOpened )
+ {
+ // If already opened, prepare can be called immediately
+ Prepare();
+ }
+ else
+ {
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::OpenL, waiting for opening" )
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::OpenL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Prepare()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Prepare()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Prepare" )
+
+ if ( SetVideoSinkState( EPrepared ) && iVideoPlayer )
+ {
+ iVideoPlayer->Prepare();
+
+ // Wait for async completion
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RemoteSetupL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RemoteSetupL()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RemoteSetup" )
+
+ __ASSERT_ALWAYS( iVideoPlayer && iPacketSink, User::Leave( KErrNotReady ) );
+
+ ConstructSdpL();
+
+ __V_SOURCESINK_CONTROLL_INT1( "Sending SDP to helix, len= ", iSdp->Length() )
+
+ TUint numStreams( iUsers.Count() );
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::RemoteSetup, num streams:", numStreams );
+
+ User::LeaveIfError( iPacketSink->SetSessionDescription( *iSdp, numStreams ) );
+
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ CMccVideoSinkUser& entry = *iUsers[ i ];
+
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::RemoteSetup, stream:", entry.iStreamId );
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::RemoteSetup, queuesize defined:",
+ entry.IsQueueSizeDefined() );
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::RemoteSetup, queuesize:", entry.QueueSize() );
+ User::LeaveIfError(
+ iPacketSink->ConfigStream( entry.iStreamId, entry.QueueSize() ) );
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RemoteSetup, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::StartL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::StartL()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::StartL" )
+
+ if ( SetVideoSinkState( EPlaying ) )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::StartL, playing" )
+
+ CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+
+ UpdateSettingsL( iSettings, ETrue );
+
+ DoPlay();
+
+ // No need to wait any async completion
+ if ( IsStartedOnce( userEntry ) )
+ {
+ SendStreamEventToClient( KMccStreamResumed, iCurrentUser );
+ }
+ else
+ {
+ iRedrawHandler->BlackDrawingL( ETrue );
+ SendStreamEventToClient( KMccStreamStarted, iCurrentUser );
+ SetStartedOnce( userEntry, ETrue );
+ }
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::StartL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Stop()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Stop()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Stop" )
+
+ TBool playerOpened( IsPlayerOpened() );
+
+ if ( SetVideoSinkState( EStopped ) && iVideoPlayer )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Stop, hiding window disabled" )
+
+ // Stopping the player before opening has completed can cause crash
+ if ( playerOpened )
+ {
+ iVideoPlayer->Stop();
+ }
+
+ // No need to wait any async completion
+ SendStreamEventToClient( KMccStreamStopped, iCurrentUser );
+
+ CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+ SetStartedOnce( userEntry, EFalse );
+
+ DoPauseForUser( userEntry );
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Stop, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Pause()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::PauseL()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::PauseL" )
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+
+ if ( SetVideoSinkState( EPaused ) )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::PauseL, pausing" )
+
+ DoPauseL();
+
+ DoResetL();
+
+ // No need to wait any async completion
+ SendStreamEventToClient( KMccStreamPaused, iCurrentUser );
+ }
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::PauseL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Close()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Close()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Close" )
+ if ( iVideoPlayer )
+ {
+ iVideoPlayer->Close();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetDisplayWindowL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetDisplayWindowL(
+ RWsSession& aWs,
+ CWsScreenDevice& aScreenDevice,
+ RWindow& aWindow )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetDisplayWindowL" )
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+ iVideoPlayer->RemoveDisplayWindow( aWindow );
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetDisplayWindowL, removed old" )
+ iVideoPlayer->AddDisplayWindowL( aWs, aScreenDevice, aWindow );
+
+ iVideoPlayer->SetAutoScaleL( aWindow, EAutoScaleBestFit );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetDisplayWindowL, added new" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Priority()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::Priority( TInt& aPriority,
+ TInt& aPreference )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Priority" )
+
+ aPriority = iSettings.iPriority.iPriority;
+ aPreference = iSettings.iPriority.iPref;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetPriority()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetPriority( TInt aPriority,
+ TInt aPreference )
+ {
+ if ( iSettings.iPriority.iPriority != aPriority ||
+ iSettings.iPriority.iPref != aPreference )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetPriority, mmf priority:", aPriority )
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetPriority, mmf preference:", aPreference )
+
+ iSettings.iPriority.iPriority = aPriority;
+ iSettings.iPriority.iPref = aPreference;
+
+ if ( IsPlayerOpened() && iVideoPlayer )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetPriority, setting" )
+
+
+ TRAPD( err, iVideoPlayer->SetPriorityL( iSettings.iPriority.iPriority,
+ iSettings.iPriority.iPref ) );
+ if ( err )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetPriority, failed with err:", err )
+ err++;
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Volume()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::Volume() const
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Volume" )
+
+ if ( iVideoPlayer )
+ {
+ return iVideoPlayer->Volume();
+ }
+ else
+ {
+ return KErrArgument;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MaxVolume()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::MaxVolume() const
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MaxVolume" )
+
+ if ( iVideoPlayer )
+ {
+ return iVideoPlayer->MaxVolume();
+ }
+ else
+ {
+ return KErrArgument;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetVolumeL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetVolumeL( TInt aVolume )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetVolumeL, vol:", aVolume )
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+
+ iVolume = aVolume;
+
+ if ( iVolumeAdaptation == 0 && iMccMaxVolume != 0 && IsPlayerOpened() )
+ {
+ TInt playerMaxVolume = iVideoPlayer->MaxVolume();
+
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetVolumeL, player max volume:",
+ playerMaxVolume )
+
+ iVolumeAdaptation = TReal( playerMaxVolume ) / iMccMaxVolume;
+
+ __V_SOURCESINK_CONTROLL_REAL(
+ "CMccVideoSinkImpl::SetVolumeL, vol adapt:", iVolumeAdaptation )
+ }
+
+ if ( iVolumeAdaptation != 0 )
+ {
+ aVolume = (TInt) ( iVolume * iVolumeAdaptation );
+
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetVolumeL, after adaptation:", aVolume )
+
+ iVideoPlayer->SetVolumeL( aVolume );
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetVolumeL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetMaxVolume()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetMaxVolume( TInt aMaxVolume )
+ {
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::SetMaxVolume, max vol:", aMaxVolume )
+
+ iMccMaxVolume = aMaxVolume;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Balance()
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::Balance() const
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Balance" )
+
+ if ( iVideoPlayer )
+ {
+ return iVideoPlayer->Balance();
+ }
+ else
+ {
+ return KErrArgument;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetBalanceL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetBalanceL( TInt aBalance )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetBalanceL" )
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+ iVideoPlayer->SetBalanceL(aBalance);
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RegisterForVideoLoadingNotification()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RegisterForVideoLoadingNotification(
+ MVideoLoadingObserver& aCallback )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RegisterForVideoLoadingNotification" )
+
+ if ( iVideoPlayer )
+ {
+ iVideoPlayer->RegisterForVideoLoadingNotification( aCallback );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::Version()
+// ---------------------------------------------------------------------------
+//
+TVersion CMccVideoSinkImpl::Version() const
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::Version" )
+ return TVersion(0, 1, 0);
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FormatVideoSDPInfoL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::FormatVideoSDPInfoL( const TMccCodecInfo& aVideoCodec )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::FormatVideoSDPInfoL" )
+
+ // Update payload type since it might not have been provided at
+ // initialization phase
+ iSettings.iVideoPayloadType = aVideoCodec.iPayloadType;
+
+ CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+ __ASSERT_ALWAYS( userEntry, User::Leave( KErrNotFound ) );
+ userEntry->iMediaType = KUidMediaTypeVideo;
+ userEntry->SetCodecInfoL( aVideoCodec );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FormatAudioSDPInfoL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::FormatAudioSDPInfoL( const TMccCodecInfo& aAudioCodec )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::FormatAudioSDPInfoL" )
+
+ // Update payload type since it might not have been provided at
+ // initialization phase
+ iSettings.iAudioPayloadType = aAudioCodec.iPayloadType;
+
+ CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+ __ASSERT_ALWAYS( userEntry, User::Leave( KErrNotFound ) );
+ userEntry->iMediaType = KUidMediaTypeAudio;
+ userEntry->SetCodecInfoL( aAudioCodec );
+ }
+
+// ---------------------------------------------------------------------------
+// void CMccVideoSinkImpl::EmptyBufferL
+//
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::EmptyBufferL( CMMFBuffer* aBuffer,
+ MDataSource* /*aSupplier*/,
+ TMediaId aMediaId,
+ TRtpRecvHeader& aHeaderInfo )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::EmptyBufferL" )
+
+ if ( iState != EPlaying )
+ {
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::EmptyBufferL, not playing, ignore buffer!" )
+ return;
+ }
+
+ TInt index = FindVideoSinkUserEntryByMediaType( aMediaId.iMediaType );
+ __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) );
+
+ CMccVideoSinkUser& user = *iUsers[ index ];
+
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::EmptyBufferL, streamId:", user.iStreamId )
+
+ CMMFDataBuffer* buf = static_cast<CMMFDataBuffer*>( aBuffer );
+
+ TInt dataSize = buf->Data().Length();
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::EmptyBufferL, data size:",
+ dataSize )
+
+ if ( AnalyzeTimeStampL( user, aHeaderInfo ) &&
+ user.PacketOverflowState() != CMccVideoSinkUser::EOccured &&
+ dataSize >= KMccMinPacketSize )
+ {
+ iRedrawHandler->BlackDrawingL( EFalse );
+
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::EmptyBufferL, sending packet to helix" )
+
+ CMccVideoJitterBuffer::TMccPacketBufferingStatus bufferingStatus =
+ user.EnqueueL( aHeaderInfo, buf->Data() );
+
+ if ( bufferingStatus == CMccVideoJitterBuffer::EPlaying )
+ {
+ DoMvloLoadingComplete( ETrue );
+ }
+ else
+ {
+ DoMvloLoadingStarted( ETrue );
+ }
+
+ iNumPacketsEnqueued++;
+ }
+ else
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::EmptyBufferL, packet dropped" )
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::EmptyBufferL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::UpdateSettingsL()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::UpdateSettingsL(
+ const TMccVideoSinkSetting& aSettings,
+ TBool aForceUpdate )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::UpdateSettingsL" )
+
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrNotReady ) );
+
+ if ( aForceUpdate ||
+ iSettings.iWindowOrdinalPosition != aSettings.iWindowOrdinalPosition ||
+ iSettings.iWindowOrdinalPriority != aSettings.iWindowOrdinalPriority ||
+ iSettings.iLocation != aSettings.iLocation ||
+ iSettings.iSize != aSettings.iSize ||
+ iSettings.iDeviceIndex != aSettings.iDeviceIndex ||
+ iSettings.iRotation != aSettings.iRotation )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::UpdateSettingsL, settings changed" )
+
+ __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window pos:",
+ aSettings.iLocation.iX, " ", aSettings.iLocation.iY )
+ __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl window size (w,h):",
+ aSettings.iSize.iWidth, " ", aSettings.iSize.iHeight )
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal pos:",
+ aSettings.iWindowOrdinalPosition )
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl window ordinal priority:",
+ aSettings.iWindowOrdinalPriority )
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl rotation:",
+ aSettings.iRotation )
+
+ __ASSERT_ALWAYS( iRw && iRwGroup && iDev, User::Leave( KErrNotReady ) );
+
+ // TBD: use also aSettings.iWindowOrdinalPriority
+ iRwGroup->SetOrdinalPosition( aSettings.iWindowOrdinalPosition );
+
+ iRw->SetPosition( aSettings.iLocation );
+ iRw->SetSize( aSettings.iSize );
+ iRw->SetOrdinalPosition( aSettings.iWindowOrdinalPosition );
+
+ iRwSession.Flush();
+
+ SetDisplayWindowL( iRwSession, *iDev, *iRw );
+
+ SetRotationL( aSettings.iRotation, aForceUpdate );
+
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::UpdateSettingsL, videoplyer updated" )
+ }
+
+ // Store new settings
+ iSettings = aSettings;
+
+ SetVideoFrameRate( aSettings.iVideoFrameRate );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::UpdateSettingsL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetCurrentSettings()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::GetCurrentSettings( TMccVideoSinkSetting& aSettings ) const
+ {
+ aSettings = iSettings;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RestorePacketSupply()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RestorePacketSupply( TUint aStreamId )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::RestorePacketSupply, streamId:", aStreamId )
+ iSearchTermUser->Set( 0, KNullUid, aStreamId );
+ TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+ TInt index = iUsers.Find( iSearchTermUser, comparison );
+ if ( index != KErrNotFound )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RestorePacketSupply, found entry")
+
+ iUsers[ index ]->SetPacketOverflow( CMccVideoSinkUser::ERecovered );
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::RestorePacketSupply, exit" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvloLoadingStarted()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvloLoadingStarted()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MvloLoadingStarted" )
+
+ DoMvloLoadingStarted();
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvloLoadingComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvloLoadingComplete()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MvloLoadingComplete" )
+
+ DoMvloLoadingComplete();
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoOpenComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoOpenComplete( TInt aError )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::MvpuoOpenComplete" )
+
+ if ( !aError && ( iState != EStopped ) )
+ {
+ iState = EOpened;
+ SetPriority( iSettings.iPriority.iPriority, iSettings.iPriority.iPref );
+ TRAP( aError,
+ {
+ SetDisplayWindowL( iRwSession, *iDev, *iRw );
+ SetVolumeL( iVolume );
+ SetRotationL( iSettings.iRotation, ETrue );
+ } );
+
+ if ( !aError )
+ {
+ Prepare();
+ }
+ }
+
+ if ( aError )
+ {
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoOpenComplete, error:",
+ aError )
+
+ SendStreamEventToAllClients( KMccStreamPrepared, aError );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoPrepareComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoPrepareComplete( TInt aError )
+ {
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoPrepareComplete(), \
+aError=", aError)
+
+ SendStreamEventToAllClients( KMccStreamPrepared, aError );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoFrameReady()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoFrameReady( CFbsBitmap& /*aFrame*/,
+#ifdef _DEBUG
+TInt aError
+#else
+TInt /*aError*/
+#endif
+ )
+ {
+#ifdef _DEBUG
+
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoFrameReady, \
+aError=", aError )
+#endif
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoPlayComplete()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoPlayComplete( TInt aError )
+ {
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::MvpuoPlayComplete(), \
+aError=", aError)
+
+ if ( aError )
+ {
+ SendStreamEventToAllClients( KMccStreamStopped, aError );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MvpuoEvent()
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::MvpuoEvent( const TMMFEvent& aEvent )
+ {
+ __V_SOURCESINK_CONTROLL_INT2( "CMccVideoSinkImpl::MvpuoEvent(), \
+aEvent.iEventType=", (TInt)aEvent.iEventType.iUid, "aEvent.iErrorCode",
+ aEvent.iErrorCode)
+
+ if ( aEvent.iEventType == KMMFEventCategoryVideoPlayerGeneralError /*&&
+ aEvent.iErrorCode == KConnectionDone*/ )
+ {
+ // NOP
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetVideoSinkState
+// -----------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::SetVideoSinkState( TMccVideoSinkState aState )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetVideoSinkState, state:", aState )
+
+ TBool controlSink( iState != aState );
+
+ TMccEventType eventType = KMccEventNone;
+
+ switch ( aState )
+ {
+ case EOpening:
+ {
+ // No event to client
+ if ( AllUsersReady() )
+ {
+ iState = aState;
+ }
+ else
+ {
+ // All users not ready, don't start opening yet
+ controlSink = EFalse;
+ }
+ break;
+ }
+ case EOpened:
+ {
+ // No event to client
+ iState = aState;
+ break;
+ }
+ case EPrepared:
+ {
+ eventType = KMccStreamPrepared;
+ iState = aState;
+ break;
+ }
+ case EPlaying:
+ {
+ CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+ if ( IsStartedOnce( userEntry ) )
+ {
+ eventType = KMccStreamResumed;
+ }
+ else
+ {
+ eventType = KMccStreamStarted;
+
+ if ( !controlSink )
+ {
+ SetStartedOnce( userEntry, ETrue );
+ }
+ }
+ iState = aState;
+ break;
+ }
+ case EPaused:
+ {
+ eventType = KMccStreamPaused;
+ iState = aState;
+ break;
+ }
+ case EStopped:
+ {
+ eventType = KMccStreamStopped;
+ CMccVideoSinkUser* userEntry = FindVideoSinkUserEntryForCurrent();
+ SetStartedOnce( userEntry, EFalse );
+ iState = aState;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ if ( eventType != KMccEventNone && !controlSink )
+ {
+ SendStreamEventToClient( eventType, iCurrentUser );
+ }
+
+ return controlSink;
+ }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::CreateModesetDesL()
+// -----------------------------------------------------------------------------
+//
+HBufC8* CMccVideoSinkImpl::CreateModesetDesL( TUint aBitrateMask )
+ {
+ _LIT8( KModesetDelim, "," );
+ const TInt KModeValMaxLength = 2;
+ const TInt KModesMaxAmount = 8;
+ const TInt KModesetDelimLength = KModesetDelim().Length();
+
+ HBufC8* modeset =
+ HBufC8::NewL( KModesMaxAmount *
+ ( KModeValMaxLength + KModesetDelimLength ) );
+
+ TPtr8 modesetPtr( modeset->Des() );
+
+ TBool allModes(
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrateAll ) );
+
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate475 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode0 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate515 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode1 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate590 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode2 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate670 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode3 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate740 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode4 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate795 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode5 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate102 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode6 );
+ modesetPtr.Append( KModesetDelim );
+ }
+ if ( allModes ||
+ MCC_BITRATE_IN_MASK( aBitrateMask, KMccAllowedAmrNbBitrate122 ) )
+ {
+ modesetPtr.AppendNum( KAMRMode7 );
+ modesetPtr.Append( KModesetDelim );
+ }
+
+ if ( modesetPtr.Length() - KModesetDelimLength >= 0 )
+ {
+ // Remove last delimiter
+ modesetPtr.Delete( modesetPtr.Length() - KModesetDelimLength,
+ KModesetDelimLength );
+ }
+
+ return modeset;
+ }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::SendStreamEventToAllClients()
+// -----------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SendStreamEventToAllClients(
+ TMccEventType aEventType,
+ TInt aError,
+ TBool aAllEndpoints )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SendStreamEventToAllClients" )
+
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ SendStreamEventToClient( aEventType,
+ iUsers[ i ]->iAsyncEventHandler,
+ aError,
+ aAllEndpoints );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::SendStreamEventToClient()
+// -----------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SendStreamEventToClient(
+ TMccEventType aEventType,
+ MAsyncEventHandler* aEventHandler,
+ TInt aError,
+ TBool aAllEndpoints )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SendStreamEventToClient" )
+
+ if ( aEventHandler )
+ {
+ aEventType = aError ? KMccStreamError : aEventType;
+
+ TUint32 endpointId =
+ aAllEndpoints ? 0 : iEndpointId;
+
+ TMccEvent event( 0,
+ 0,
+ 0,
+ endpointId,
+ KMccEventCategoryStream,
+ aEventType,
+ aError,
+ KNullDesC8 );
+
+ TMccInternalEvent internalEvent( KMccVideoSinkUid,
+ EMccInternalEventNone,
+ event );
+
+ aEventHandler->SendEventToClient( internalEvent );
+ }
+ else
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SendStreamEventToClient, \
+ aEventHandler=NULL" )
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResolveStreamId()
+// -----------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::ResolveStreamId( TMediaId aMediaId, TUint& aStreamId )
+ {
+ iSearchTermUser->Set( 0, aMediaId.iMediaType, 0 );
+ return FindStreamIdForVideoSinkUser( *iSearchTermUser, aStreamId );
+ }
+
+// -----------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResolveStreamId()
+// -----------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::ResolveStreamId(
+ MAsyncEventHandler* aUser,
+ TUint& aStreamId )
+ {
+ iSearchTermUser->Set( aUser, KNullUid, 0 );
+ return FindStreamIdForVideoSinkUser( *iSearchTermUser, aStreamId );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GenerateStreamId
+// ---------------------------------------------------------------------------
+//
+TUint CMccVideoSinkImpl::GenerateStreamId()
+ {
+ return iHelixStreamId++;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FindVideoSinkUserEntryByMediaType
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::FindVideoSinkUserEntryByMediaType( TUid aMediaType )
+ {
+ iSearchTermUser->Set( NULL, aMediaType, 0 );
+ TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+ return iUsers.Find( iSearchTermUser, comparison );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FindStreamIdForVideoSinkUser
+// ---------------------------------------------------------------------------
+//
+TInt CMccVideoSinkImpl::FindStreamIdForVideoSinkUser(
+ CMccVideoSinkUser& aEntry,
+ TUint& aStreamId )
+ {
+ TInt err( KErrNotFound );
+
+ TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+ TInt index = iUsers.Find( &aEntry, comparison );
+ if ( index != KErrNotFound )
+ {
+ aStreamId = iUsers[ index ]->iStreamId;
+ err = KErrNone;
+ }
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::FindVideoSinkUserEntryForCurrent
+// ---------------------------------------------------------------------------
+//
+CMccVideoSinkUser* CMccVideoSinkImpl::FindVideoSinkUserEntryForCurrent()
+ {
+ iSearchTermUser->Set( iCurrentUser, KNullUid, 0 );
+ TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+ TInt index = iUsers.Find( iSearchTermUser, comparison );
+ if ( index != KErrNotFound )
+ {
+ return iUsers[ index ];
+ }
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RemoveVideoSinkUser
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::RemoveVideoSinkUser(
+ MAsyncEventHandler* aUser, TUint aStreamId )
+ {
+ iSearchTermUser->Set( aUser, KNullUid, aStreamId );
+ TIdentityRelation<CMccVideoSinkUser> comparison( VideoSinkUserMatch );
+ TInt index = iUsers.Find( iSearchTermUser, comparison );
+ if ( index != KErrNotFound )
+ {
+ delete iUsers[ index ];
+ iUsers.Remove( index );
+ }
+
+ // If there's no more users for this stream id, packet sink is notified
+ // about stream ending
+ iSearchTermUser->Set( NULL, KNullUid, aStreamId );
+ index = iUsers.Find( iSearchTermUser, comparison );
+ if ( iPacketSink && index == KErrNotFound )
+ {
+ iPacketSink->StreamEnd( aStreamId );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::VideoSinkUserMatch
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::VideoSinkUserMatch(
+ const CMccVideoSinkUser& aUser1,
+ const CMccVideoSinkUser& aUser2 )
+ {
+ // First argument is always the search term
+
+ TBool match( EFalse );
+ if ( aUser1.iAsyncEventHandler )
+ {
+ match = ( aUser1.iAsyncEventHandler == aUser2.iAsyncEventHandler );
+ }
+ else if ( aUser1.iMediaType != KNullUid )
+ {
+ match = ( aUser1.iMediaType == aUser2.iMediaType );
+ }
+ else
+ {
+ match = ( aUser1.iStreamId == aUser2.iStreamId );
+ }
+ return match;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::ConstructSdpL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::ConstructSdpL()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructSdpL" )
+
+ __ASSERT_ALWAYS( iSdp, User::Leave( KErrNotReady ) );
+
+ iSdp->Des().Copy( KMccSdpInboundStart );
+
+
+ // Check amount of mediatypes before constructing sdp as
+ // sdp contents are affected on that information
+ TBool multipleMediaTypes( MultipleMediaTypes() );
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ iUsers[ i ]->SetMultipleMediaTypesL( multipleMediaTypes );
+ }
+
+ HandleAudioSdpL();
+
+ HandleVideoSdpL();
+
+ __V_SOURCESINK_CONTROLL_STR8( "SDP:", *iSdp )
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::ConstructSdpL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::HandleAudioSdpL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::HandleAudioSdpL()
+ {
+ TInt audioEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeAudio );
+ if ( audioEntry == KErrNotFound )
+ {
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::HandleAudioSdpL, no audio codec defined" )
+ return;
+ }
+
+ // Set correct stream id
+ iUsers[ audioEntry ]->iStreamId = GenerateStreamId();
+
+ // Form sdp from codec information
+ TMccCodecInfo& audioCodec = iUsers[ audioEntry ]->CodecInfo();
+
+ HBufC8* modeset = CreateModesetDesL( audioCodec.iBitrateMask );
+
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::HandleAudioSdpL, AudioPayloadType:",
+ iSettings.iAudioPayloadType )
+
+ iSdp->Des().AppendFormat( KMccSdpInboundAudio,
+ iSettings.iAudioPayloadType,
+ iSettings.iAudioPayloadType,
+ &audioCodec.iSdpName,
+ audioCodec.iPtime,
+ audioCodec.iMaxPtime,
+ iSettings.iAudioPayloadType,
+ ( audioCodec.iCodecMode == KAmrCodecModeOctetAlign ),
+ &*modeset );
+
+
+ delete modeset;
+
+ iSdp->Des().AppendFormat(
+ KMccSdpInboundPreroll, iUsers[ audioEntry ]->GetPreroll() );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::HandleVideoSdpL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::HandleVideoSdpL()
+ {
+ TUint streamId( 0 );
+ TBool firstUserHandled( EFalse );
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ CMccVideoSinkUser& user = *iUsers[ i ];
+ if ( user.iMediaType == KUidMediaTypeVideo )
+ {
+ if ( !firstUserHandled )
+ {
+ streamId = GenerateStreamId();
+
+ // Form sdp from codec information
+ TMccCodecInfo& videoCodec = user.CodecInfo();
+
+ // Helix uses width and height info for loading appropriate
+ // video decoder
+ TInt frameWidth = KH263FrameWidth;
+ TInt frameHeight = KH263FrameHeight;
+
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::HandleVideoSdpL, VideoPayloadType:",
+ iSettings.iVideoPayloadType )
+
+ HBufC8* fmtp = GetFmtpLC( videoCodec );
+ iSdp->Des().AppendFormat( KMccSdpInboundVideo,
+ iSettings.iVideoPayloadType,
+ iSettings.iVideoPayloadType,
+ &videoCodec.iSdpName,
+ iSettings.iVideoPayloadType,
+ &*fmtp,
+ user.GetPayloadSize(),
+ frameWidth,
+ frameHeight );
+ CleanupStack::PopAndDestroy( fmtp );
+
+
+ iPreroll = user.GetPreroll();
+
+ if ( RealTimeMode() )
+ {
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::HandleVideoSdpL, disable clock" )
+ iSdp->Des().Append( KMccSdpInboundDisableVideoClock );
+
+ // Currently, preroll needs to be set to some value
+ // until disable video clock feature is working fully
+ // at Helix side, once supported fully, preroll value
+ // will not have any effect.
+ const TInt KMccVideoSinkRealTimeTransitionPreroll = 500;
+ iPreroll = KMccVideoSinkRealTimeTransitionPreroll;
+ }
+
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::HandleVideoSdpL, iPreroll ", iPreroll )
+ iPrerollSet = ETrue;
+ iSdp->Des().AppendFormat( KMccSdpInboundPreroll, iPreroll );
+
+ firstUserHandled = ETrue;
+ }
+
+ // Set correct stream id (all video users will have the same id)
+ user.iStreamId = streamId;
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::AnalyzeTimeStampL
+// Checks whether rtp packet belongs to currently played stream. Check is done
+// based on timestamp monitoring. If this is new stream, helix needs to be
+// resetted as it cannot cope with stream change. Helix is resetted
+// immediately if one of media types is detected to be from new stream.
+// Packets of other media types need to be dropped until also new stream
+// in those begins.
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::AnalyzeTimeStampL(
+ CMccVideoSinkUser& aUser,
+ TRtpRecvHeader& aHeaderInfo )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::AnalyzeTimeStampL" )
+
+ aUser.CalculateAverageTimeStampDifference();
+
+ if ( aUser.IsResetNeeded( aHeaderInfo ) )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::AnalyzeTimeStampL, reset needed" )
+
+ if ( ResetOngoing() )
+ {
+ // XPS was resetted already earlier, allow queueing for this user
+ aUser.Reset( ETrue );
+ }
+ else
+ {
+ DoResetL( ETrue, &aUser );
+
+ // Other media types cannot pass their data until new stream
+ // in them begin
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ if ( iUsers[ i ] != &aUser )
+ {
+ iUsers[ i ]->SetAllowFrame( EFalse );
+ }
+ }
+ }
+
+ }
+
+ aUser.AddTimeStamp( (TInt64)aHeaderInfo.iTimestamp, aHeaderInfo.iSeqNum );
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::AnalyzeTimeStampL, exit" )
+
+ return aUser.AllowFrame();
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoResetL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoResetL( TBool aFullReset, CMccVideoSinkUser* aUser )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL" )
+
+ // Start from scratch.
+ //
+
+ if ( iVideoPlayer )
+ {
+ // If playing, have to pause, otherwise set position will not work
+ if ( iState == EPlaying )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL, mode 1" )
+ DoPauseL( aUser );
+ ResetPacketSink();
+ iVideoPlayer->SetPositionL( TTimeIntervalMicroSeconds( 0 ) );
+ DoPlay( aUser );
+ }
+ else
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL, mode 2" )
+ ResetPacketSink();
+ iVideoPlayer->SetPositionL( TTimeIntervalMicroSeconds( 0 ) );
+ }
+ }
+
+ if ( aUser )
+ {
+ aUser->Reset( aFullReset );
+ }
+ else
+ {
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ iUsers[ i ]->Reset( aFullReset );
+ }
+ }
+
+ iNumPacketsEnqueued = 0;
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoResetL, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::IsPlayerOpened
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::IsPlayerOpened() const
+ {
+ return ( iState > EOpening );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResetPacketSink
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::ResetPacketSink()
+ {
+ if ( iPacketSink )
+ {
+ iPacketSink->Reset();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::IsStartedOnce
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::IsStartedOnce( const CMccVideoSinkUser* aUser )
+ {
+ return ( aUser && aUser->iStartedOnce );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetStartedOnce
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetStartedOnce(
+ CMccVideoSinkUser* aUser,
+ TBool aIsStartedOnce )
+ {
+ if ( aUser )
+ {
+ aUser->iStartedOnce = aIsStartedOnce;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetRotationL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetRotationL(
+ TMccVideoRotation aRotation,
+ TBool aForceUpdate )
+ {
+ __V_SOURCESINK_CONTROLL_INT1( "CMccVideoSinkImpl::SetRotationL, rotation:",
+ aRotation )
+ __ASSERT_ALWAYS( iVideoPlayer, User::Leave( KErrArgument ) );
+
+ if ( aForceUpdate || ( aRotation != iSettings.iRotation ) )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetRotationL, setting" )
+
+ // Enums for videoplayer rotation and mcc rotation are identical
+ iVideoPlayer->SetRotationL( *iRw, static_cast<TVideoRotation>( aRotation ) );
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetRotationL, exit" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetActualPrerollL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::GetActualPrerollL( TInt& aPreroll )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::GetActualPrerollL, iPrerollSet:", iPrerollSet )
+ TInt videoEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeVideo );
+ if ( videoEntry == KErrNotFound )
+ {
+ __V_SOURCESINK_CONTROLL(
+ "CMccVideoSinkImpl::GetActualPrerollL, no video codec defined" )
+ return;
+ }
+
+ aPreroll = iUsers[ videoEntry ]->GetActualPreroll();
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetVideoFrameRate
+// ---------------------------------------------------------------------------
+//
+TReal CMccVideoSinkImpl::GetVideoFrameRate()
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::GetVideoFrameRate" )
+ return iSettings.iVideoFrameRate;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::SetVideoFrameRate
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::SetVideoFrameRate( TReal aFrameRate )
+ {
+ __V_SOURCESINK_CONTROLL_INT1(
+ "CMccVideoSinkImpl::SetVideoFrameRate, framerate:", (TUint32) aFrameRate )
+
+ if ( aFrameRate > 0 )
+ {
+ iSettings.iVideoFrameRate = aFrameRate;
+
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ TRAP_IGNORE( iUsers[ i ]->SetFrameRateL( iSettings.iVideoFrameRate ) )
+ }
+ }
+ else
+ {
+ iSettings.iVideoFrameRate = KMccDefaultVideoFrameRate;
+ }
+
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::SetVideoFrameRate, exit" )
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::ResetOngoing
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::ResetOngoing() const
+ {
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ if ( !iUsers[ i ]->AllowFrame() )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::GetFmtpLC
+// ---------------------------------------------------------------------------
+//
+HBufC8* CMccVideoSinkImpl::GetFmtpLC( const TMccCodecInfo& aCodecInfo )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::GetFmtpLC" )
+
+ CMccCodecInformationFactory* factory = CMccCodecInformationFactory::NewL();
+ CleanupStack::PushL( factory );
+ CMccCodecInformation* codec =
+ factory->CreateCodecInformationL( aCodecInfo.iSdpName );
+ CleanupStack::PushL( codec );
+ codec->SetValues( aCodecInfo );
+ HBufC8* fmtp = codec->GetFmtpL().AllocL();
+ CleanupStack::PopAndDestroy( codec );
+ CleanupStack::PopAndDestroy( factory );
+ CleanupStack::PushL( fmtp );
+ return fmtp;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoPauseL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoPauseL( const CMccVideoSinkUser* aUser )
+ {
+ if ( !RealTimeMode() )
+ {
+ iVideoPlayer->PauseL();
+ }
+
+ DoPauseForUser( aUser );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoPauseForUser
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoPauseForUser( const CMccVideoSinkUser* aUser )
+ {
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ if ( !aUser || aUser == iUsers[ i ] )
+ {
+ iUsers[ i ]->Pause();
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoPlay
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoPlay( const CMccVideoSinkUser* aUser )
+ {
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ if ( !aUser || aUser == iUsers[ i ] )
+ {
+ iUsers[ i ]->Play();
+ }
+ }
+
+ iVideoPlayer->Play();
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::MultipleMediaTypes
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::MultipleMediaTypes()
+ {
+ TInt audioEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeAudio );
+ TInt videoEntry = FindVideoSinkUserEntryByMediaType( KUidMediaTypeVideo );
+ return ( audioEntry != KErrNotFound && videoEntry != KErrNotFound );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::RealTimeMode
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::RealTimeMode()
+ {
+ TBool realTimeMode( EFalse );
+ if ( !MultipleMediaTypes() )
+ {
+ for ( TInt i = 0; i < iUsers.Count() && !realTimeMode; i++ )
+ {
+ // If preroll is zero, real time mode is used
+ if ( iUsers[ i ]->GetPreroll() == 0 )
+ {
+ realTimeMode = ETrue;
+ }
+ }
+ }
+
+ return realTimeMode;
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::AddUserL
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::AddUserL( MAsyncEventHandler& aEventHandler )
+ {
+ __ASSERT_ALWAYS( iPacketSink, User::Leave( KErrNotReady ) );
+ CMccVideoSinkUser* user = CMccVideoSinkUser::NewLC(
+ &aEventHandler, KNullUid, 0, iSettings.iVideoFrameRate, *iPacketSink );
+ iUsers.AppendL( user );
+ CleanupStack::Pop( user );
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoMvloLoadingComplete
+// If in realtime mode, helix gives loading completion istantly after starting
+// whichis not desired as buffering is done at MCC side. In that case
+// loading completion is not notified until MCC jitter buffer completes
+// loading (i.e. play threshold is reached).
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoMvloLoadingComplete( TBool aSimulated )
+ {
+ if ( RealTimeMode() )
+ {
+ if ( aSimulated && !iSimulatedStreamingEventSent )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoMvloLoadingComplete, simulate" )
+
+ SendStreamEventToAllClients( KMccStreamPlaying, KErrNone, ETrue );
+
+ iSimulatedBufferingEventSent = EFalse;
+ iSimulatedStreamingEventSent = ETrue;
+ }
+ }
+ else if ( !aSimulated )
+ {
+ SendStreamEventToAllClients( KMccStreamPlaying, KErrNone, ETrue );
+ }
+ else
+ {
+ // NOP
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::DoMvloLoadingComplete
+// If in realtime mode, helix gives loading started instantly after starting
+// it (even before passing in any packets). Loading starting is not notified
+// until first packet has been passed to MCC video jitterbuffer.
+// ---------------------------------------------------------------------------
+//
+void CMccVideoSinkImpl::DoMvloLoadingStarted( TBool aSimulated )
+ {
+ if ( RealTimeMode() )
+ {
+ if ( aSimulated && !iSimulatedBufferingEventSent )
+ {
+ __V_SOURCESINK_CONTROLL( "CMccVideoSinkImpl::DoMvloLoadingStarted, simulate" )
+
+ SendStreamEventToAllClients( KMccStreamBuffering, KErrNone, ETrue );
+
+ iSimulatedBufferingEventSent = ETrue;
+ iSimulatedStreamingEventSent = EFalse;
+ }
+ }
+ else if ( !aSimulated )
+ {
+ SendStreamEventToAllClients( KMccStreamBuffering, KErrNone, ETrue );
+ }
+ else
+ {
+ // NOP
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CMccVideoSinkImpl::AllUsersReady
+// Check if some user hasn't yet configured its settings
+// ---------------------------------------------------------------------------
+//
+TBool CMccVideoSinkImpl::AllUsersReady()
+ {
+ TBool allUsersReady( ETrue );
+ for ( TInt i = 0; i < iUsers.Count(); i++ )
+ {
+ if ( iUsers[ i ]->iMediaType == KNullUid )
+ {
+ allUsersReady = EFalse;
+ }
+ }
+ return allUsersReady;
+ }
+
+// End of file
+