--- /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 <mmf/server/mmfdatabuffer.h>
+#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<CMccDataSource*>( 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<TUint>& payloads = item->RegisteredPayloadTypes();
+ static_cast<CMccRtpDataSource*>( 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<TUint>& aPayloadTypes )
+ {
+ __MULTIPLEXER( "CMccMultiplexer::RegClientForPayloadsL" )
+ __ASSERT_ALWAYS( iSource, User::Leave( KErrNotReady ) );
+ __ASSERT_ALWAYS( KMccRtpSourceUid == iSource->DataSourceType(),
+ User::Leave( KErrNotSupported ) );
+
+ FindSinkItemL( &aConsumer )->RegisterPayloadTypesL( aPayloadTypes );
+ static_cast<CMccRtpDataSource*>( 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<CMMFDataBuffer*>( 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<CMMFDescriptorBuffer*>( 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<const TMccInternalEvent&>( 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<CMccDataSource*>(
+ 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
+