diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccsubcontroller/src/mccsymulstream.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommscontroller/mmccsubcontroller/src/mccsymulstream.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,684 @@ +/* +* Copyright (c) 2004-2008 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: Mcc Symmetric subthread uplink stream +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include "mccsymulstream.h" +#include "mcculdatapath.h" +#include "mcccodecconfigurator.h" +#include "mccrtpmanager.h" +#include "mccrtpdatasink.h" +#include "mmccinterface.h" +#include "mccsubcontrollerlogs.h" +#include "mccmultiplexer.h" +#include "mccresources.h" +#include "amrpayloadformatwrite.h" +#include "mccinternaldef.h" + +#include "mccredpayloadwrite.h" +#include "mccuids.hrh" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::CMccSymUlStream +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMccSymUlStream::CMccSymUlStream( + TUint32 aMccStreamId, + MAsyncEventHandler* aEventhandler, + MMccResources* aMccResources, + CMccRtpManager* aManager, + TFourCC aFourCC, + TInt aStreamType, + CMccRtpMediaClock& aClock ) : + CMccSymStreamBase( aMccStreamId, + aEventhandler, + aMccResources, + aManager, + aStreamType ), + iFormatEncode( NULL ), + iFourCC( aFourCC ) + { + iRtpMediaClock = &aClock; + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMccSymUlStream* CMccSymUlStream::NewLC( + TUint32 aMccStreamId, + MAsyncEventHandler* aEventhandler, + MMccResources* aMccResources, + CMccRtpManager* aManager, + TFourCC aFourCC, + TInt aStreamType, + CMccRtpMediaClock& aClock ) + { + CMccSymUlStream* s = + new ( ELeave ) CMccSymUlStream( aMccStreamId, + aEventhandler, + aMccResources, + aManager, + aFourCC, + aStreamType, + aClock ); + CleanupStack::PushL( s ); + s->ConstructL(); + return s; + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::ConstructL() + { + __SUBCONTROLLER( "CMccSymUlStream::ConstructL" ) + __SUBCONTROLLER( "CMccSymUlStream::ConstructL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::~CMccSymUlStream +// Destructor +// ----------------------------------------------------------------------------- +// +CMccSymUlStream::~CMccSymUlStream() + { + __SUBCONTROLLER( "CMccSymUlStream::~CMccSymUlStream" ) + + if ( iSoundDevice ) + { + iSoundDevice = NULL; + } + + MultiplexerCleanup(); + + // Sink may need update since encoder logoff is routed to it + HandleSpecialSinksAndSources(); + + if ( iFormatEncode ) + { + iFormatEncode->SinkThreadLogoff(); + delete iFormatEncode; + } + + delete iRedFormatEncode; + + __SUBCONTROLLER( "CMccSymUlStream::~CMccSymUlStream, exit" ) + + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::SetPrioritySettingsL +// Sets the MMF priority settings for this stream +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::SetPrioritySettingsL( + const TMMFPrioritySettings& aPriority ) + { + __SUBCONTROLLER( "CMccSymUlStream::SetPrioritySettingsL start" ); + + __ASSERT_ALWAYS( iDatasource, User::Leave( KErrNotReady ) ); + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + if ( iDatasink->DataSinkType() == KUidMccVideoSink ) + { + iDatasink->SetSinkPrioritySettings( aPriority ); + } + + iDatasource->SetSourcePrioritySettings( aPriority ); + + __SUBCONTROLLER( "CMccSymUlStream::SetPrioritySettingsL end" ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::AddSinkAndSourceL +// From CMccSymStreamBase +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::AddSinkAndSourceL( MDataSink* aDatasink, + MDataSource* aDatasource ) + { + __SUBCONTROLLER( "CMccSymUlStream::AddSinkAndSourceL" ) + __ASSERT_ALWAYS( aDatasink, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( aDatasource, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( !iDatapath, User::Leave( KErrAlreadyExists ) ); + + __SUBCONTROLLER( "CMccSymUlStream::AddSinkAndSourceL, adding" ) + iDatasink = aDatasink; + iDatasource = aDatasource; + + iMultiplexer = iMccResources->MultiplexerL( iDatasource ); + + iDatapath = CMccUlDataPath::NewL( this, + iMccResources, + Type() ); + + iDatapath->AddDataSourceL( iMultiplexer ); + + // Add datapath as the sink of the multiplexer, logon is routed to the + // real datasource + User::LeaveIfError( + iMultiplexer->MultiplexerSourceThreadLogon( *this, *iDatapath, EFalse, Type() ) ); + + // Source logon must have been completed before fetching sounddevice + if ( iDatasource->DataSourceType() == KUidMmfAudioInput ) + { + __SUBCONTROLLER( "CMccSymUlStream::AddSinkAndSourceL, KUidMmfAudioInput" ) + + iSoundDevice = &( static_cast( iDatasource )->SoundDevice() ); + } + + // Inform datapath about ids of associated sink and source + iDatapath->SetAssociatedSink( iDatasink ); + iDatapath->SetAssociatedSource( iDatasource ); + + __SUBCONTROLLER( "CMccSymUlStream::AddSinkAndSourceL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::LoadCodecL +// From CMccSymStreamBase +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::LoadCodecL( const TMccCodecInfo& aCodecInfo, + const TDesC8& aFmtp ) + { + __SUBCONTROLLER_INT1( "CMccSymUlStream::LoadCodecL, codec state:", + CurrentCodecState() ) + + __ASSERT_ALWAYS( CurrentCodecState() == EStateCodecNone || + iCodecInfo.iFourCC == aCodecInfo.iFourCC, + User::Leave( KErrArgument ) ); + + iCodecInfo = aCodecInfo; + + if ( iDatasource && iDatasource->DataSourceType() == KUidMccFileSource ) + { + iCodecInfo.iSourceDefinedTimeStamps = ETrue; + } + + if ( CurrentCodecState() == EStateCodecNone ) + { + delete iFmtpAttr; + iFmtpAttr = NULL; + + iFmtpAttr = HBufC8::NewL( aFmtp.Length() ); + iFmtpAttr->Des().Copy( aFmtp ); + + iCodecInfo.iFmtpLength = iFmtpAttr->Length(); + + CreatePayloadFormatEncoderL(); + + if ( iDatasink->DataSinkType() == KMccRtpSinkUid ) + { + CMccRtpDataSink* dataSink = static_cast( iDatasink ); + dataSink->SetMediaClock( *iRtpMediaClock ); + } + + // Just negotiate the codec, load it later + static_cast( iDatapath )->NegotiateL( *iFormatEncode ); + + SetCodecState( EStateCodecNegotiated ); + } + else if ( CurrentCodecState() == EStateCodecNegotiated ) + { + // Codec is not fully usable yet, do just formatter initialization + MccCodecConfigurator::ConfigureCodecL( *iDatasource, + *iFormatEncode, + iCodecInfo, + *iRtpMediaClock, + CurrentCodecState(), + iDatasink ); + + SetCodecState( EStateCodecPrepared ); + } + else if ( CurrentCodecState() == EStateCodecPrepared ) + { + if ( CodecLoadingAllowed() ) + { + // Load the codec + static_cast( iDatapath )->LoadL( *iFormatEncode ); + + // Set state before updating as the state affects to update functionality + SetCodecState( EStateCodecLoaded ); + + UpdateCodecInformationL( iCodecInfo ); + } + } + else if ( CurrentCodecState() == EStateCodecLoaded || + CurrentCodecState() == EStateCodecLoadedAndUpdating ) + { + if ( iDatasink->DataSinkType() == KMccRtpSinkUid ) + { + CMccRtpDataSink* dataSink = + static_cast( iDatasink ); + + // For updating keep alive parameters + TMccCodecInfoBuffer infoBuffer( iCodecInfo ); + dataSink->ConfigureL( infoBuffer ); + } + // Update codec info + SetCodecState( EStateCodecLoadedAndUpdating ); + UpdateCodecInformationL( iCodecInfo ); + } + else + { + User::Leave( KErrNotReady ); + } + + __SUBCONTROLLER_INT1( "CMccSymUlStream::LoadCodecL, exit, new state:", + CurrentCodecState() ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::UpdateCodecInformationL +// From CMccSymStreamBase +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::UpdateCodecInformationL( TMccCodecInfo& /*aCodecInfo*/ ) + { + __SUBCONTROLLER( "CMccSymUlStream::UpdateCodecInformationL" ) + User::LeaveIfNull( iDatasource ); + User::LeaveIfNull( iFormatEncode ); + + HandleSpecialSinksAndSources(); + + iCodecInfo.iIsUpdate = ETrue; + + MccCodecConfigurator::ConfigureCodecL( *iDatasource, + *iFormatEncode, + iCodecInfo, + *iRtpMediaClock, + CurrentCodecState(), + iDatasink ); + + __SUBCONTROLLER( "CMccSymUlStream::UpdateCodecInformationL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::CreatePayloadFormatEncoderL +// Creates a payload format encoder for UL stream +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::CreatePayloadFormatEncoderL() + { + __SUBCONTROLLER( "CMccSymUlStream::CreatePayloadFormatEncoderL" ) + __ASSERT_ALWAYS( NULL == iFormatEncode, User::Leave( KErrAlreadyExists ) ); + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + TUid formatuid; + formatuid.iUid = iCodecInfo.iPayloadFormatEncoder; + + if ( EGenRedUsed == iCodecInfo.iAlgoUsed ) + { + __ASSERT_ALWAYS( KMccPayloadTypeMax != iCodecInfo.iRedundantPayload, + User::Leave( KErrArgument ) ); + + iRedFormatEncode = CMMFFormatEncode::NewL( + TUid::Uid( KImplUidRedPayloadFormatEncode ), iDatasink ); + + iFormatEncode = CMMFFormatEncode::NewL( formatuid, iRedFormatEncode ); + } + else + { + iFormatEncode = CMMFFormatEncode::NewL( formatuid, iDatasink ); + } + + User::LeaveIfError( iFormatEncode->SetSinkDataTypeCode( + iCodecInfo.iFourCC, iCodecInfo.iType ) ); + User::LeaveIfError( iFormatEncode->SinkThreadLogon( *this ) ); + __SUBCONTROLLER( "CMccSymUlStream::CreatePayloadFormatEncoderL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::PrimeL +// Primes the audio stream ready +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::PrimeL( const TUint32 aEndpointId ) + { + __SUBCONTROLLER( "CMccSymUlStream::PrimeL" ) + + TBool controlNetworkResources = SetStateL( EStatePrepared, aEndpointId ); + + if ( controlNetworkResources && !LocalStream() ) + { + iRtpmanager->CreateTransmitStreamL( *iDatasink, iCodecInfo ); + } + + LoadCodecL( iCodecInfo, KNullDesC8 ); + + DoPrimeL(); + + InformStreamStateChange( KMccStreamPrepared, aEndpointId ); + + __SUBCONTROLLER( "CMccSymUlStream::PrimeL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::PlayL +// Starts audio streaming +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::PlayL( TUint32 aEndpointId, + TBool /*aStreamPaused*/, + TBool aEnableRtcp ) + { + __SUBCONTROLLER( "CMccSymUlStream::PlayL" ) + + TBool controlNetworkResources = SetStateL( EStateStreaming, aEndpointId ); + + if ( !LocalStream() ) + { + if ( controlNetworkResources ) + { + iRtpmanager->StartSessionL(); + } + + User::LeaveIfError( iRtpmanager->SetRTCPSendReceive( aEnableRtcp ) ); + } + + UpdateCodecLoadingPermission( IsCodecOperationAllowed() ); + + LoadCodecL( iCodecInfo, KNullDesC8 ); + + DoPlayL(); + + InformStreamStateChange( KMccStreamStarted, aEndpointId ); + + __SUBCONTROLLER( "CMccSymUlStream::PlayL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::PauseL +// Pauses audio streaming +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::PauseL( const TUint32 aEndpointId, + TBool aEnableRtcp ) + { + __SUBCONTROLLER( "CMccSymUlStream::PauseL" ) + + SetStateL( EStatePaused, aEndpointId ); + + if ( !LocalStream() ) + { + User::LeaveIfError( iRtpmanager->SetRTCPSendReceive( aEnableRtcp ) ); + } + + DoPauseL(); + + InformStreamStateChange( KMccStreamPaused, aEndpointId ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::ResumeL +// Resumes paused audio streaming +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::ResumeL( const TUint32 aEndpointId, + TBool aEnableRtcp ) + { + __SUBCONTROLLER( "CMccSymUlStream::ResumeL" ) + + SetStateL( EStateStreaming, aEndpointId ); + + if ( !LocalStream() ) + { + User::LeaveIfError( iRtpmanager->SetRTCPSendReceive( aEnableRtcp ) ); + } + + DoResumeL(); + + InformStreamStateChange( KMccStreamResumed, aEndpointId ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::StopL +// Stops the audio streaming +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::StopL( const TUint32 aEndpointId ) + { + __SUBCONTROLLER( "CMccSymUlStream::StopL" ) + + SetStateL( EStateStopped, aEndpointId ); + + DoStopL(); + + InformStreamStateChange( KMccStreamStopped, aEndpointId ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::SetBalanceL +// Sets the current record balance +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::SetBalanceL( TInt aLeftBal, TInt aRightBal ) + { + if( !iSoundDevice ) + { + User::Leave( KErrNotReady ); + } + else + { + iSoundDevice->SetRecordBalanceL( aLeftBal, aRightBal ); + } + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::GetBalanceL +// Returns the current record balance +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::GetBalanceL( TInt& aLeftbal, TInt& aRightbal ) + { + if( !iSoundDevice ) + { + User::Leave( KErrNotReady ); + } + else + { + iSoundDevice->GetRecordBalanceL( aLeftbal, aRightbal ); + } + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::GetSSRCL +// Returns SSRC value +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::GetSSRCL( TUint32& aSSRCValue ) + { + __ASSERT_ALWAYS( !LocalStream(), User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + CMccRtpDataSink* sink = static_cast( iDatasink ); + aSSRCValue = sink->GetSSRC(); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::ResetCountersL +// +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::ResetCountersL( ) + { + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::SendMediaSignalL +// Uplink can send RTCP media signals +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::SendMediaSignalL( const TMccEvent& aEvent ) + { + __ASSERT_ALWAYS( !LocalStream(), User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + CMccRtpDataSink* p = static_cast( iDatasink ); + p->SendMediaSignallingL( aEvent ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::DoChangeBitrateL +// Uplink can change bitrate during AMR streaming +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::DoChangeBitrateL( TInt aBitrate ) + { + // This function is trapped inside ChangeBitrate() function + __SUBCONTROLLER_INT1( "CMccSymUlStream::DoChangeBitrateL CURRENT:", iCodecInfo.iBitrate ); + __SUBCONTROLLER_INT1( "CMccSymUlStream::DoChangeBitrateL NEW:", aBitrate ); + + // If using AMR codec and bitrate has changed for what it was set + // then change it. + const TUint32 fourCC = iCodecInfo.iFourCC.FourCC(); + + if ( ( KMccFourCCIdAMRNB == fourCC || KMccFourCCIdAMRWB == fourCC ) && + iSoundDevice && iFormatEncode ) + { + // Change the bitrate only if it needs to be changed + if( iCodecInfo.iBitrate != aBitrate ) + { + CAmrPayloadFormatWrite* write = + static_cast( iFormatEncode ); + + if ( write->IsBitrateChangeValid( aBitrate ) ) + { + MccCodecConfigurator::ChangeBitrateL( + iCodecInfo, aBitrate, *iSoundDevice ); + iCodecInfo.iBitrate = aBitrate; + } + } + } + else + { + // Other codec than AMR is in use and we cannot change the bitrate + __SUBCONTROLLER( "CMccSymUlStream::DoChangeBitrateL KErrNotSupported" ); + User::Leave( KErrNotSupported ); + } + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::SendRTCPSenderReportL +// Sends a RTCP sender report +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::SendRTCPSenderReportL() + { + __ASSERT_ALWAYS( !LocalStream(), User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + CMccRtpDataSink* dSink = static_cast( iDatasink ); + User::LeaveIfError( dSink->SendRTCPSenderReport() ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::SendRTCPDataL +// Sends Non-RTCP data +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::SendRTCPDataL( const TDesC8& aData ) + { + __ASSERT_ALWAYS( !LocalStream(), User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + CMccRtpDataSink* dSink = static_cast( iDatasink ); + dSink->SendRTCPDataL( aData ); + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::IsUplink +// ----------------------------------------------------------------------------- +// +TBool CMccSymUlStream::IsUplink() + { + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::StandByL +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::StandByL() + { + } + +// ----------------------------------------------------------------------------- +// CMccSymUlStream::MultiplexerSink +// ----------------------------------------------------------------------------- +// +MDataSink* CMccSymUlStream::MultiplexerSink() + { + return iDatapath; + } + +// ----------------------------------------------------------------------------- +// CMccSymDlStream::BindContextIntoStreamL +// ----------------------------------------------------------------------------- +// +void CMccSymUlStream::BindContextIntoStreamL( TUint32 aEndpointId, + const TMccCryptoContext& aContextParams ) + { + __ASSERT_ALWAYS( iDatasink, User::Leave( KErrNotReady ) ); + + if ( iDatasink->DataSinkType() == KMccRtpSinkUid && + aEndpointId == MCC_ENDPOINT_ID( iDatasink ) ) + { + CMccRtpDataSink* dataSink = static_cast( iDatasink ); + dataSink->ApplyCryptoContextL( aContextParams ); + } + else + { + User::Leave( KErrNotFound ); + } + } + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// End of File