diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmccmultiplexer/src/mccmultiplexer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommscontroller/mmccmultiplexer/src/mccmultiplexer.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,958 @@ +/* +* Copyright (c) 2006 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: +* +*/ + + + + +// INCLUDE FILES +#include +#include "mccmultiplexer.h" +#include "mccsinkitem.h" +#include "mccinternaldef.h" +#include "mccinternalevents.h" +#include "mccmultiplexerlogs.h" +#include "mccinternalevents.h" +#include "mccrtpdatasource.h" + +// MACROS + +// LOCAL FUNCTION PROTOTYPES + +// LOCAL CONSTANTS +const TUint KMultiplexerDefBufSize( 160 ); + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::NewL +// ----------------------------------------------------------------------------- +// +EXPORT_C CMccMultiplexer* CMccMultiplexer::NewL( MDataSource* aSource ) + { + CMccMultiplexer* self = new ( ELeave ) CMccMultiplexer; + CleanupStack::PushL( self ); + self->ConstructL( aSource ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::~CMccMultiplexer +// ----------------------------------------------------------------------------- +// +EXPORT_C CMccMultiplexer::~CMccMultiplexer() + { + __MULTIPLEXER( "CMccMultiplexer::~CMccMultiplexer" ) + + iSinkItems.ResetAndDestroy(); + delete iDataBuf; + + __MULTIPLEXER( "CMccMultiplexer::~CMccMultiplexer, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourceThreadLogon +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CMccMultiplexer::MultiplexerSourceThreadLogon( + MAsyncEventHandler& aEventHandler, + MDataSink& aSink, + TBool aSinkIsDecoder, + TUid aMediaType, + TBool aPassAllBuffersSink ) + { + __MULTIPLEXER_INT1( "CMccMultiplexer::MultiplexerSourceThreadLogon, endpoint:", + MCC_ENDPOINT_ID( &aSink ) ) + + TInt err( KErrNone ); + + TRAP( err, + AddSinkL( &aSink, aSinkIsDecoder, aMediaType, aPassAllBuffersSink ) ); + + // Gather events from source and propagate them to all sink owners + + if ( !err && !iSourceLogonDone ) + { + __MULTIPLEXER( "CMccMultiplexer::MultiplexerSourceThreadLogon, source logon" ) + + err = iSource->SourceThreadLogon( *this ); + iSourceLogonDone = ETrue; + } + + if ( !err ) + { + err = FindSinkItemIndex( &aSink ); + if ( err != KErrNotFound ) + { + err = iSinkItems[ err ]->SourceThreadLogon( aEventHandler ); + } + if ( MCC_INTERNAL_ENDPOINT( iSource->DataSourceType().iUid ) ) + { + static_cast( iSource )->AddUser( &aEventHandler ); + } + } + + __MULTIPLEXER( "CMccMultiplexer::SourceThreadLogon, exit" ) + + return err; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourceThreadLogoff +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CMccMultiplexer::MultiplexerSourceThreadLogoff( MDataSink* aSink ) + { + __MULTIPLEXER_INT1( "CMccMultiplexer::MultiplexerSourceThreadLogoff, endpoint:", + MCC_ENDPOINT_ID( aSink ) ) + + if ( aSink ) + { + TInt index = FindSinkItemIndex( aSink ); + if ( index != KErrNotFound ) + { + CMccSinkItem* item = iSinkItems[ index ]; + if ( KMccRtpSourceUid == iSource->DataSourceType() ) + { + const RArray& payloads = item->RegisteredPayloadTypes(); + static_cast( iSource ) + ->UnRegisterPayloadTypes( payloads ); + } + + // Clear current user + if ( item == iCurrentUser ) + { + iCurrentUser = NULL; + } + + TBool passedAllRequests = PassAllRequestsToSource( *item ); + + iSinkItems.Remove( index ); + + UpdateSinkModes(); + + // Update primary buffer or logoff source + HandleCleanup( item, passedAllRequests ); + + return KErrNone; + } + return KErrNotFound; + } + return KErrArgument; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SetCurrentUserL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMccMultiplexer::SetCurrentUserL( MDataSink& aSink ) + { + __MULTIPLEXER_INT1( "CMccMultiplexer::SetCurrentUserL, endpoint:", + MCC_ENDPOINT_ID( &aSink ) ) + + iCurrentUser = FindSinkItemL( &aSink ); + + __MULTIPLEXER( "CMccMultiplexer::SetCurrentUserL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::RegClientForPayloadsL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMccMultiplexer::RegClientForPayloadsL( MDataSink& aConsumer, + const RArray& aPayloadTypes ) + { + __MULTIPLEXER( "CMccMultiplexer::RegClientForPayloadsL" ) + __ASSERT_ALWAYS( iSource, User::Leave( KErrNotReady ) ); + __ASSERT_ALWAYS( KMccRtpSourceUid == iSource->DataSourceType(), + User::Leave( KErrNotSupported ) ); + + FindSinkItemL( &aConsumer )->RegisterPayloadTypesL( aPayloadTypes ); + static_cast( iSource ) + ->RegisterPayloadTypesL( aPayloadTypes ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::Streams +// ----------------------------------------------------------------------------- +// +TUint CMccMultiplexer::Streams( TUid /*aMediaType*/ ) const + { + return 1; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::FrameTimeInterval +// ----------------------------------------------------------------------------- +// +TTimeIntervalMicroSeconds CMccMultiplexer::FrameTimeInterval( + TMediaId /*aMediaId*/ ) const + { + return TTimeIntervalMicroSeconds( TInt64( 0 ) ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::DataSourceType +// ----------------------------------------------------------------------------- +// +TUid CMccMultiplexer::DataSourceType() const + { + return KMccMultiplexerUid; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::FillBufferL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::FillBufferL( + CMMFBuffer* aBuffer, + MDataSink* aConsumer, + TMediaId aMediaId ) + { + __MULTIPLEXER_INT1( "CMccMultiplexer::FillBufferL, endpoint:", + MCC_ENDPOINT_ID( aConsumer ) ) + __MULTIPLEXER_INT1( "CMccMultiplexer::FillBufferL, mediaId uid:", + aMediaId.iMediaType.iUid ) + + __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( aBuffer->Type() == KUidMmfDataBuffer, + User::Leave( KErrArgument ) ); + __ASSERT_ALWAYS( aConsumer, User::Leave( KErrArgument ) ); + + // Store request + CMccSinkItem* item = FindSinkItemL( aConsumer ); + item->FillBufferRequestL( aBuffer ); + + // If not in pass all mode, only one sink at the time can control + // the source + if ( iState == EPlaying && + ( item->PassAllRequestsToSource() || CanCommandSource( aConsumer ) ) ) + { + __MULTIPLEXER( "CMccMultiplexer::FillBufferL, command source" ) + + if ( KMccRtpSourceUid == iSource->DataSourceType() ) + { + // Multiplexer buffer needed for payload type multiplexing + __ASSERT_ALWAYS( + static_cast( aBuffer ) + ->Data().MaxSize() <= iDataBuf->Data().MaxSize(), + User::Leave( KErrTooBig ) ); + + __MULTIPLEXER( "CMccMultiplexer::FillBufferL, using own buffer" ) + iDataBuf->SetStatus( EBeingFilled ); + iDataBuf->SetLastBuffer( EFalse ); + iSource->FillBufferL( iDataBuf, this, aMediaId ); + } + else + { + iSource->FillBufferL( aBuffer, this, aMediaId ); + } + } + + __MULTIPLEXER( "CMccMultiplexer::FillBufferL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourceDataTypeCode +// ----------------------------------------------------------------------------- +// +TFourCC CMccMultiplexer::SourceDataTypeCode( + TMediaId aMediaId ) + { + return iSource->SourceDataTypeCode( aMediaId ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SetSourceDataTypeCode +// ----------------------------------------------------------------------------- +// +TInt CMccMultiplexer::SetSourceDataTypeCode( + TFourCC aSourceFourCC, + TMediaId aMediaId ) + { + return iSource->SetSourceDataTypeCode( aSourceFourCC, aMediaId ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourceThreadLogon +// ----------------------------------------------------------------------------- +// +TInt CMccMultiplexer::SourceThreadLogon( + MAsyncEventHandler& /*aEventHandler*/ ) + { + return KErrNotSupported; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::NegotiateSourceL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::NegotiateSourceL( MDataSink& aDataSink ) + { + __MULTIPLEXER( "CMccMultiplexer::NegotiateSourceL" ) + + if ( !iSourceNegotiationDone ) + { + if ( KUidMmfAudioInput == iSource->DataSourceType() ) + { + // Audio input need settings from real sink. + // This is just quick workaround, better way would be to route + // those requests through multiplexer to the sink + + __MULTIPLEXER( "CMccMultiplexer::NegotiateSourceL, negotiate (use sink)" ) + + iSource->NegotiateSourceL( aDataSink ); + } + else + { + __MULTIPLEXER( "CMccMultiplexer::NegotiateSourceL, negotiate (normal)" ) + + iSource->NegotiateSourceL( *this ); + } + + iSourceNegotiationDone = ETrue; + } + __MULTIPLEXER( "CMccMultiplexer::NegotiateSourceL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourceThreadLogoff +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SourceThreadLogoff() + { + // NOP + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourcePrimeL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SourcePrimeL() + { + __MULTIPLEXER( "CMccMultiplexer::SourcePrimeL" ) + + if ( SetMultiplexerState( EPrepared ) ) + { + iSource->SourcePrimeL(); + } + + __MULTIPLEXER( "CMccMultiplexer::SourcePrimeL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourcePlayL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SourcePlayL() + { + __MULTIPLEXER( "CMccMultiplexer::SourcePlayL" ) + + if ( SetMultiplexerState( EPlaying ) ) + { + iSource->SourcePlayL(); + } + + __MULTIPLEXER( "CMccMultiplexer::SourcePlayL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourcePauseL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SourcePauseL() + { + __MULTIPLEXER( "CMccMultiplexer::SourcePauseL" ) + + if ( SetMultiplexerState( EResourcePaused ) ) + { + iSource->SourcePauseL(); + } + + __MULTIPLEXER( "CMccMultiplexer::SourcePauseL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SourceStopL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SourceStopL() + { + __MULTIPLEXER( "CMccMultiplexer::SourceStopL" ) + + if ( SetMultiplexerState( EResourceStopped ) ) + { + iSource->SourceStopL(); + } + + __MULTIPLEXER( "CMccMultiplexer::SourceStopL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::DataBufferFilledL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::DataBufferFilledL( + CMMFBuffer* aBuffer, + const TRtpRecvHeader& aRtpHeader ) + { + __MULTIPLEXER( "CMccMultiplexer::DataBufferFilledL" ) + __ASSERT_ALWAYS( NULL != aBuffer, User::Leave( KErrArgument ) ); + + DoBufferFilledL( aBuffer, &aRtpHeader ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::ConfigurePayloadFormatL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::ConfigurePayloadFormatL( const TDesC8& /*aConfigParams*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::BufferFilledL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::BufferFilledL( CMMFBuffer* aBuffer ) + { + __MULTIPLEXER( "CMccMultiplexer::BufferFilledL" ) + __ASSERT_ALWAYS( NULL != aBuffer, User::Leave( KErrArgument ) ); + + DoBufferFilledL( aBuffer, 0 ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::Duration +// ----------------------------------------------------------------------------- +// +TTimeIntervalMicroSeconds CMccMultiplexer::Duration( + TMediaId /*aMediaType*/ ) const + { + return TTimeIntervalMicroSeconds( TInt64( 0 ) ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::CanCreateSourceBuffer +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::CanCreateSourceBuffer() + { + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::CreateSourceBufferL +// Created buffer is not intended for sink use. +// ----------------------------------------------------------------------------- +// +CMMFBuffer* CMccMultiplexer::CreateSourceBufferL( + TMediaId /*aMediaId*/, + TBool& aReference ) + { + __MULTIPLEXER( "CMccMultiplexer::CreateSourceBufferL" ) + __ASSERT_ALWAYS( iSuggestedBufSize, User::Leave( KErrNotReady ) ); + + aReference = EFalse; + + if ( iDataBuf->Data().MaxSize() < iSuggestedBufSize ) + { + static_cast( iDataBuf ) + ->ReAllocBufferL( iSuggestedBufSize ); + } + + CMMFDataBuffer* buf = CMMFDataBuffer::NewL( iSuggestedBufSize ); + iSuggestedBufSize = 0; + return buf; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SuggestSourceBufferSize +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SuggestSourceBufferSize( TUint aSuggestedBufferSize ) + { + __MULTIPLEXER_INT1( "CMccMultiplexer::SuggestSourceBufferSize, SIZE: ", + aSuggestedBufferSize ) + + iSuggestedBufSize = aSuggestedBufferSize; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SendEventToClient +// ----------------------------------------------------------------------------- +// +TInt CMccMultiplexer::SendEventToClient( const TMMFEvent& aEvent ) + { + __MULTIPLEXER( "CMccMultiplexer::SendEventToClient" ) + + // Stream control event has to be stored at this level since control + // request can go back to source synchronously causing stream state change + // event, which then overwrites the control event. + // + if ( IS_MCC_EVENT( aEvent ) ) + { + TMccEvent* mccEventPtr = + reinterpret_cast( aEvent ).iMccEvent; + + if ( mccEventPtr && + MCC_STREAM_STATE_CHANGE_EVENT( mccEventPtr ) && + mccEventPtr->iEventNumData != KMccAutomaticEvent ) + { + if ( iCurrentUser ) + { + return iCurrentUser->SendEventToClient( aEvent ); + } + else + { + __MULTIPLEXER( "CMccMultiplexer::SendEventToClient, KErrNotReady" ) + return KErrNotReady; + } + } + + if ( mccEventPtr && + mccEventPtr->iEventCategory == KMccEventCategoryStreamControl ) + { + iStreamControlEvent = *mccEventPtr; + TMccInternalEvent internalEvent( KMccMultiplexerUid, EMccInternalEventNone, + iStreamControlEvent ); + + SendEventToAllClients( internalEvent ); + + return KErrNone; + } + } + + SendEventToAllClients( aEvent ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::CMccMultiplexer +// ----------------------------------------------------------------------------- +// +CMccMultiplexer::CMccMultiplexer() + { + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::ConstructL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::ConstructL( MDataSource* aSource ) + { + __ASSERT_ALWAYS( aSource, User::Leave( KErrArgument ) ); + + iSource = aSource; + iDataBuf = CMMFDataBuffer::NewL( KMultiplexerDefBufSize ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::FindSinkItemL +// ----------------------------------------------------------------------------- +// +CMccSinkItem* CMccMultiplexer::FindSinkItemL( MDataSink* aSink ) + { + TInt index = FindSinkItemIndex( aSink ); + __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) ); + + return iSinkItems[ index ]; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::FindSinkItemIndex +// ----------------------------------------------------------------------------- +// +TInt CMccMultiplexer::FindSinkItemIndex( MDataSink* aSink ) + { + for ( TInt i = 0; i < iSinkItems.Count(); i++ ) + { + if ( iSinkItems[ i ]->Match( aSink ) ) + { + return i; + } + } + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::CanCommandSource +// Primary sink has always preferred access to source, other sinks can use +// source only if primary is not using it +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::CanCommandSource( MDataSink* aSink ) + { + TBool canCommandSource( EFalse ); + if ( IsPrimarySink( aSink ) ) + { + canCommandSource = ETrue; + } + else if ( iSinkItems.Count() > 0 && + !IsActiveState( iSinkItems[ 0 ]->MultiplexerState() ) ) + { + canCommandSource = ETrue; + } + else + { + // NOP + } + return canCommandSource; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::IsPrimarySink +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::IsPrimarySink( MDataSink* aSink ) + { + // Primary sink is always the first one + return ( iSinkItems.Count() > 0 && iSinkItems[ 0 ]->Match( aSink ) ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::DoBufferFilledL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::DoBufferFilledL( + CMMFBuffer* aBuffer, + const TRtpRecvHeader* aRtpHeader ) + { + TUid mediaType = KNullUid; + iDataBuf->SetStatus( EFull ); + + if ( iResolveFilledBufferMediaType ) + { + for ( TInt i = 0; i < iSinkItems.Count() && mediaType == KNullUid; i++ ) + { + mediaType = iSinkItems[ i ]->ResolveMediaType( aBuffer ); + } + } + + for ( TInt i = 0; i < iSinkItems.Count(); i++ ) + { + // First item is always the primary sink, but multiplexer can be + // also set into mode where all fillbuffer requests are passed to the + // source (i.e. all sinks are kind of primary ones). In such case, + // incoming buffer must match the one which was given when fillbuffer + // request was issued (i.e. source cannot return different buffer). + TBool isPrimary( !i ); + + iSinkItems[ i ]->BufferFilledL( aBuffer, + aRtpHeader, + isPrimary, + mediaType ); + } + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::AddSinkL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::AddSinkL( + MDataSink* aSink, + TBool aSinkIsDecoder, + TUid aMediaType, + TBool aPassAllBuffersSink ) + { + __ASSERT_ALWAYS( FindSinkItemIndex( aSink ) == KErrNotFound, + User::Leave( KErrAlreadyExists ) ); + + CMccSinkItem* item = CMccSinkItem::NewLC( aSink, + aSinkIsDecoder, + aMediaType, + aPassAllBuffersSink ); + iSinkItems.AppendL( item ); + CleanupStack::Pop( item ); + + // Update sinks + UpdateSinkModes(); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SetMultiplexerState +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::SetMultiplexerState( TMccMultiplexerState aState ) + { + __MULTIPLEXER_INT1( "CMccMultiplexer::SetMultiplexerState, state:", aState ) + + // If state of the multiplexed source is already what is tried to be set, + // multiplexer generates the corresponding completion event + TBool controlSource( iState != aState ); + + TMccEventType eventType = KMccEventNone; + + switch ( aState ) + { + case EPrepared: + { + eventType = KMccStreamPrepared; + + if ( iState == EPlaying || iState == EResourcePaused ) + { + controlSource = EFalse; + } + else + { + iState = aState; + } + break; + } + case EPlaying: + { + eventType = KMccStreamStarted; + iState = aState; + break; + } + case EResourcePaused: + { + eventType = KMccStreamPaused; + iState = aState; + break; + } + case EResourceStopped: + { + eventType = KMccStreamStopped; + iState = aState; + break; + } + default: + { + break; + } + } + + if ( iCurrentUser ) + { + iCurrentUser->SetMultiplexerState( iState ); + } + + if ( eventType != KMccEventNone && !controlSource ) + { + SendStreamEventToClient( eventType ); + } + + return controlSource; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SendStreamEventToClient +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SendStreamEventToClient( TMccEventType& aEventType ) + { + __MULTIPLEXER( "CMccMultiplexer::SendStreamEventToClient" ) + + TMccEvent event( 0, + 0, + 0, + MCC_ENDPOINT_ID( iSource ), + KMccEventCategoryStream, + aEventType, + KErrNone, + KNullDesC8 ); + + TMccInternalEvent internalEvent( KMccMultiplexerUid, + EMccInternalEventNone, + event ); + + if ( iCurrentUser ) + { + __MULTIPLEXER( "CMccMultiplexer::SendStreamEventToClient, sending to current user" ) + + iCurrentUser->SendEventToClient( internalEvent ); + } + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::UpdateSinkModes +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::UpdateSinkModes() + { + __MULTIPLEXER( "CMccMultiplexer::UpdateSinkModes" ) + + // Check if mediatype has to be resolved for each filled buffer + iResolveFilledBufferMediaType = EFalse; + + for ( TInt i = 0; i < iSinkItems.Count(); i++ ) + { + TBool passAllRequestsToSource = PassAllRequestsToSource( *iSinkItems[ i ] ); + iSinkItems[ i ]->SetSourceMode( passAllRequestsToSource ); + + iResolveFilledBufferMediaType |= passAllRequestsToSource; + } + + __MULTIPLEXER_INT1( "CMccMultiplexer::UpdateSinkModes, resolve buffers mode:", + iResolveFilledBufferMediaType ) + __MULTIPLEXER( "CMccMultiplexer::UpdateSinkModes, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::PassAllRequestsToSource +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::PassAllRequestsToSource( CMccSinkItem& aItem ) const + { + // If source is filesource, it can support two primary sinks; one for audio + // and one for video. + // + + if ( iSource->DataSourceType() == KMccFileSourceUid ) + { + TUid mediaType = aItem.MediaType(); + for ( TInt i = 0; i < iSinkItems.Count(); i++ ) + { + // If sinkitem has highest preference from group of sinkitems of same + // media type, all its requests can be passed to the source + if ( mediaType == iSinkItems[ i ]->MediaType() ) + { + return ( iSinkItems[ i ] == &aItem ); + } + } + } + else if ( iSource->DataSourceType() == KMccRtpSourceUid ) + { + // Payload type multiplexing is used with network resource. Multiple + // clients are allowed to request fillbuffer from RTP-source. + return ETrue; + } + else + { + // Make PC-LINT happy + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::IsSupportedMediaType +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::IsSupportedMediaType( TUid aMediaType ) const + { + return ( aMediaType == KUidMediaTypeVideo || + aMediaType == KUidMediaTypeAudio ); + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::SendEventToAllClients +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::SendEventToAllClients( const TMMFEvent& aEvent ) + { + for ( TInt i = 0; i < iSinkItems.Count(); i++ ) + { + iSinkItems[ i ]->SendEventToClient( aEvent ); + } + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::HandleCleanup +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::HandleCleanup( + CMccSinkItem* aSinkItem, + TBool aPassedAllRequests ) + { + TRAP_IGNORE( HandleCleanupL( aSinkItem, aPassedAllRequests ) ) + delete aSinkItem; + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::HandleCleanupL +// ----------------------------------------------------------------------------- +// +void CMccMultiplexer::HandleCleanupL( + CMccSinkItem* aSinkItem, + TBool aPassedAllRequests ) + { + __MULTIPLEXER( "CMccMultiplexer::HandleCleanupL" ) + + if ( iSinkItems.Count() == 0 ) + { + // If no more sinks, source can be logged off + iSource->SourceThreadLogoff(); + iSourceLogonDone = EFalse; + } + else + { + // Update source's sinkbuffer (may be also NULL) and user info + + if ( aSinkItem ) + { + if ( aPassedAllRequests ) + { + __MULTIPLEXER( "CMccMultiplexer::HandleCleanupL, clear old" ) + iSource->FillBufferL( NULL, this, TMediaId( aSinkItem->MediaType() ) ); + } + + if ( MCC_INTERNAL_ENDPOINT( iSource->DataSourceType().iUid ) ) + { + static_cast( + iSource )->RemoveUser( aSinkItem->EventHandler() ); + } + } + + CMMFBuffer* newPrimaryBuf = iSinkItems[ 0 ]->RequestedBuffer(); + + if ( newPrimaryBuf && KMccRtpSourceUid == iSource->DataSourceType() ) + { + // When payload type multiplexing, multiplexer's own buffer is used + newPrimaryBuf = iDataBuf; + } + + __MULTIPLEXER( "CMccMultiplexer::HandleCleanupL, set new" ) + iSource->FillBufferL( newPrimaryBuf, + this, + TMediaId( iSinkItems[ 0 ]->MediaType() ) ); + } + + __MULTIPLEXER( "CMccMultiplexer::HandleCleanupL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccMultiplexer::IsActiveState +// ----------------------------------------------------------------------------- +// +TBool CMccMultiplexer::IsActiveState( TMccMultiplexerState aState ) const + { + return ( aState == EPlaying ); + } + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// ----------------------------------------------------------------------------- +// E32Dll. +// DLL Entry point +// Returns: KErrNone +// ----------------------------------------------------------------------------- +// +#ifndef EKA2 +EXPORT_C TInt E32Dll( TDllReason ) + { + return KErrNone; + } +#endif + + +// End of File +