diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccvideosourcesink/src/mccvideosinkimpl.cpp --- /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 +#include +#include +#include +#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 + +// 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( 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 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 comparison( VideoSinkUserMatch ); + return iUsers.Find( iSearchTermUser, comparison ); + } + +// --------------------------------------------------------------------------- +// CMccVideoSinkImpl::FindStreamIdForVideoSinkUser +// --------------------------------------------------------------------------- +// +TInt CMccVideoSinkImpl::FindStreamIdForVideoSinkUser( + CMccVideoSinkUser& aEntry, + TUint& aStreamId ) + { + TInt err( KErrNotFound ); + + TIdentityRelation 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 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 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( 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 +