--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/voipaudioservices/VoIPIntfc/src/VoIPDownlinkStreamImpl.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2007-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: VOIP Audio Services Downlink stream APIs.
+ *
+ */
+
+#include <e32base.h>
+#include <mmffourcc.h>
+#include <voipdatabuffer.h>
+#include "debugtracemacros.h"
+#include "VoIPAudioSession.h"
+#include "VoIPAudioClientServer.h"
+#include "VoIPFormatIntfcImpl.h"
+#include "VoIPBaseCodecIntfcImpl.h"
+#include "VoIPILBCDecoderIntfcImpl.h"
+#include "VoIPG711DecoderIntfcImpl.h"
+#include "VoIPG729DecoderIntfcImpl.h"
+#include "VoIPJitterBufferIntfcImpl.h"
+#include "VoIPSharedData.h"
+#include "VoIPDownlinkStreamImpl.h"
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::NewL
+// ---------------------------------------------------------------------------
+//
+CVoIPAudioDownlinkStreamImpl*
+CVoIPAudioDownlinkStreamImpl::NewL(const TMMFPrioritySettings aPriority)
+ {
+ CVoIPAudioDownlinkStreamImpl* self =
+ new (ELeave) CVoIPAudioDownlinkStreamImpl();
+ CleanupStack::PushL(self);
+ self->ConstructL(aPriority);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::~CVoIPAudioDownlinkStreamImpl
+// ---------------------------------------------------------------------------
+//
+CVoIPAudioDownlinkStreamImpl::~CVoIPAudioDownlinkStreamImpl()
+ {
+ Close();
+
+ if (iMsgQHandler)
+ {
+ iMsgQHandler->Cancel();
+ delete iMsgQHandler;
+ }
+
+ if (iMsgQComHandler)
+ {
+ iMsgQComHandler->Cancel();
+ delete iMsgQComHandler;
+ }
+
+ if (iMsgQueue.Handle() > 0)
+ {
+ iMsgQueue.Close();
+ }
+
+ if (iMsgComQueue.Handle() > 0)
+ {
+ iMsgComQueue.Close();
+ }
+
+ if (iVoIPAudioSession.Handle() > 0)
+ {
+ iVoIPAudioSession.Close();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::CVoIPAudioDownlinkStreamImpl
+// ---------------------------------------------------------------------------
+//
+CVoIPAudioDownlinkStreamImpl::CVoIPAudioDownlinkStreamImpl() :
+ iBufferPtr(0, 0, 0)
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::ConstructL(
+ const TMMFPrioritySettings aPriority)
+ {
+ // Pass ownership to the parent class
+ CVoIPAudioDownlinkStream::ConstructL(this);
+ iPriority = aPriority;
+ iG711FrameSize = KVoIPG711FrameLen20ms;
+ iFormat = EG711;
+ TInt err = iVoIPAudioSession.Connect();
+ User::LeaveIfError(err);
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::Open
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::Open(MVoIPDownlinkObserver& aObserver)
+ {
+ iObserver = &aObserver;
+
+ TInt err = CreateQueue(KDnLinkQueue, KVoIPMsgQSlots, EMsgBufQueue);
+
+ if (err == KErrNone)
+ {
+ err = CreateQueue(KDnLinkComQueue, KVoIPMsgComQSlots, EMsgComQueue);
+ }
+
+ if (err == KErrNone)
+ {
+ err = iVoIPAudioSession.OpenDownlink(iPriority);
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetVersion
+// Returns version of this component.
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::GetVersion(TVersion& aVersion)
+ {
+ aVersion = TVersion(1, 0, 0);
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetMaxVolume
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::GetMaxVolume(TInt& aVolume)
+ {
+ aVolume = iVoIPAudioSession.GetMaxVolume();
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::SetVolume
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::SetVolume(TInt aVolume)
+ {
+ TInt err = iVoIPAudioSession.SetVolume(aVolume);
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetVolume
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::GetVolume(TInt& aVolume)
+ {
+ aVolume = iVoIPAudioSession.GetVolume();
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetSupportedFormatsL
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::GetSupportedFormatsL(
+ const TMMFPrioritySettings aPriority,
+ RArray<TVoIPCodecFormat>& aFormats)
+ {
+ if (!iCodecFormats || aFormats.Count() <= 0)
+ {
+ RArray<TUint32> codecIDs;
+ CleanupClosePushL(codecIDs);
+ codecIDs.Reset();
+ iVoIPAudioSession.GetSupportedDecoders(aPriority, codecIDs,
+ iG711FrameSize);
+
+ TUint32 codec = 0;
+ TInt count = codecIDs.Count();
+ TVoIPCodecFormat format;
+ aFormats.Reset();
+
+ for (TInt i = 0; i < count; i++)
+ {
+ codec = codecIDs[i];
+
+#ifdef _DEBUG
+ TInt8 a = codec;
+ TInt8 b = codec >> 8;
+ TInt8 c = codec >> 16;
+ TInt8 d = codec >> 24;
+ RDebug::Print(_L("%c%c%c%c"), a, b, c, d);
+#endif
+ format = ConvertFourCC(codec);
+ if (format != ENULL)
+ {
+ aFormats.Append(format);
+ }
+ }
+
+ iCodecFormats = &aFormats;
+ CleanupStack::PopAndDestroy(&codecIDs);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::SetFormatL
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::SetFormatL(TVoIPCodecFormat aFormat,
+ CVoIPFormatIntfc*& aIntfc)
+ {
+ // Check if requested codec is on the list of supported codecs
+ if (!IsCodecSupportedL(aFormat))
+ {
+ iFormat = ENULL;
+ }
+
+ // TODO: reuse when switching codecs on the fly and same codec is selected
+ delete aIntfc;
+ aIntfc = NULL;
+
+ switch (iFormat)
+ {
+ case EG711:
+ case EG711_10MS:
+ {
+ aIntfc = CVoIPG711DecoderIntfcImpl::NewL(this);
+ iBufferLen = iG711FrameSize;
+ break;
+ }
+ case EG729:
+ {
+ aIntfc = CVoIPG729DecoderIntfcImpl::NewL(this);
+ iBufferLen = KVoIPG729FrameLen;
+ break;
+ }
+ case EILBC:
+ {
+ aIntfc = CVoIPILBCDecoderIntfcImpl::NewL(this);
+ iBufferLen = KVoIPILBCFrameLen;
+ break;
+ }
+ case EAMR_NB:
+ {
+ aIntfc = CVoIPBaseCodecIntfcImpl::NewL(this);
+ iBufferLen = KVoIPAMRNBFrameLen;
+ break;
+ }
+ case EPCM16:
+ {
+ aIntfc = CVoIPBaseCodecIntfcImpl::NewL(this);
+ iBufferLen = KVoIPPCM16FrameLen;
+ break;
+ }
+ default:
+ {
+ iFormat = ENULL;
+ iBufferLen = 0;
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+ TUint32 codecFourCC = CodecFourCC(iFormat);
+ iVoIPAudioSession.SetDecoder(codecFourCC);
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetFormat
+// ---------------------------------------------------------------------------
+//
+TVoIPCodecFormat CVoIPAudioDownlinkStreamImpl::GetFormat()
+ {
+ return iFormat;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::SetAudioDevice
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::SetAudioDevice(
+ const TVoIPOutputDevice aDevice)
+ {
+ TInt err = iVoIPAudioSession.SetAudioDevice(aDevice);
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetAudioDevice
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::GetAudioDevice(TVoIPOutputDevice& aDevice)
+ {
+ TInt err = iVoIPAudioSession.GetAudioDevice(aDevice);
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::Start
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::Start()
+ {
+ TInt err = iVoIPAudioSession.StartDownlink();
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::Stop
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::Stop()
+ {
+ TInt err = iVoIPAudioSession.StopDownlink();
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::Close
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::Close()
+ {
+ iVoIPAudioSession.CloseDownlink();
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::BufferFilled
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::BufferFilled(CVoIPDataBuffer* aBuffer)
+ {
+ TUint bufSeq = 0;
+ aBuffer->GetPayloadPtr(iBufferPtr);
+ CVoIPDataBuffer::TVoIPBufferType type;
+ aBuffer->GetBufferType(type);
+
+ if (type == CVoIPDataBuffer::EJitterBuffer)
+ {
+ static_cast<CVoIPJBDataBuffer*> (aBuffer)->GetBufferSequence(bufSeq);
+ }
+
+ TInt err = iVoIPAudioSession.BufferFilled(iBufferPtr, bufSeq);
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::CreateJitterBufferIntfcL
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::CreateJitterBufferIntfcL(
+ CVoIPJitterBufferIntfc*& aJBIntfc)
+ {
+ aJBIntfc = CVoIPJitterBufferIntfcImpl::NewL(&iVoIPAudioSession);
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::GetSession
+// ---------------------------------------------------------------------------
+//
+RVoIPAudioSession* CVoIPAudioDownlinkStreamImpl::GetSession()
+ {
+ return &iVoIPAudioSession;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioStream::CreateQueue
+// ---------------------------------------------------------------------------
+//
+TInt CVoIPAudioDownlinkStreamImpl::CreateQueue(const TDesC& aQueueName,
+ const TInt aNumSlots, const TQueueType aQueueType)
+ {
+ TInt err = KErrNone;
+
+ if (aQueueType == EMsgBufQueue)
+ {
+ if (iMsgQueue.Handle() <= 0)
+ {
+ err = iMsgQueue.CreateGlobal(aQueueName, aNumSlots);
+ if (err != KErrNone)
+ {
+ return err;
+ }
+ }
+
+ TRAP(err, ReceiveMsgQHandlerEventsL());
+ }
+ else if (aQueueType == EMsgComQueue)
+ {
+ if (iMsgComQueue.Handle() <= 0)
+ {
+ err = iMsgComQueue.CreateGlobal(aQueueName, aNumSlots);
+ if (err != KErrNone)
+ {
+ return err;
+ }
+ }
+
+ TRAP(err, ReceiveMsgQComHandlerEventsL());
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioStream::ReceiveMsgQHandlerEventsL
+// Starts message queue handler (A/O) to monitor server side events
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::ReceiveMsgQHandlerEventsL()
+ {
+ if (iMsgQHandler)
+ {
+ iMsgQHandler->Cancel();
+ }
+ else
+ {
+ iMsgQHandler = CQueueHandler::NewL(this, &iMsgQueue, iBufferLen);
+ }
+
+ iMsgQHandler->Start();
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioStream::ReceiveMsgQComHandlerEventsL
+// Starts message queue handler (A/O) to monitor server side events
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::ReceiveMsgQComHandlerEventsL()
+ {
+ if (iMsgQComHandler)
+ {
+ iMsgQComHandler->Cancel();
+ }
+ else
+ {
+ iMsgQComHandler = CQueueHandler::NewL(this, &iMsgComQueue);
+ }
+
+ iMsgQComHandler->Start();
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioStream::CodecFourCC
+// ---------------------------------------------------------------------------
+//
+TUint32 CVoIPAudioDownlinkStreamImpl::CodecFourCC(TVoIPCodecFormat aFormat)
+ {
+ TUint32 codecFourCC;
+
+ switch (aFormat)
+ {
+ case EG711_10MS:
+ case EG711:
+ {
+ codecFourCC = KMccFourCCIdG711;
+ break;
+ }
+ case EG729:
+ {
+ codecFourCC = KMccFourCCIdG729;
+ break;
+ }
+ case EILBC:
+ {
+ codecFourCC = KMccFourCCIdILBC;
+ break;
+ }
+ case EAMR_NB:
+ {
+ codecFourCC = KMccFourCCIdAMRNB;
+ break;
+ }
+ case EPCM16:
+ {
+ codecFourCC = KMMFFourCCCodePCM16;
+ break;
+ }
+ default:
+ {
+ codecFourCC = KFourCCNULL;
+ }
+ }
+
+ return codecFourCC;
+ }
+
+// -----------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::ConvertFourCC
+// -----------------------------------------------------------------------------
+//
+TVoIPCodecFormat CVoIPAudioDownlinkStreamImpl::ConvertFourCC(TUint32 aCodec)
+ {
+ TVoIPCodecFormat format;
+
+ switch (aCodec)
+ {
+ case KMccFourCCIdG711:
+ {
+ if (iG711FrameSize == KVoIPG711FrameLen10ms)
+ {
+ format = EG711_10MS;
+ TRACE_PRN_N(_L("VoIP->DNL: G711 10ms frame rate detected"));
+ }
+ else
+ {
+ format = EG711;
+ }
+ break;
+ }
+ case KMccFourCCIdG729:
+ format = EG729;
+ break;
+ case KMccFourCCIdILBC:
+ format = EILBC;
+ break;
+ case KMccFourCCIdAMRNB:
+ format = EAMR_NB;
+ break;
+ case KMMFFourCCCodePCM16:
+ format = EPCM16;
+ break;
+ default:
+ format = ENULL;
+ break;
+ }
+
+ return format;
+ }
+
+// -----------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::IsCodecSupportedL
+// -----------------------------------------------------------------------------
+//
+TBool CVoIPAudioDownlinkStreamImpl::IsCodecSupportedL(
+ TVoIPCodecFormat aFormat)
+ {
+ TBool status = EFalse;
+
+ if (!iCodecFormats)
+ {
+ // Client hasn't called GetSupportedFormatsL
+ RArray<TVoIPCodecFormat> codecs;
+ CleanupClosePushL(codecs);
+ codecs.Reset();
+ GetSupportedFormatsL(iPriority, codecs); //sets iCodecFormats
+ status = FindFormat(aFormat);
+ CleanupStack::PopAndDestroy(&codecs);
+ iCodecFormats = NULL;
+ }
+ else
+ {
+ status = FindFormat(aFormat);
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::FindFormat
+// -----------------------------------------------------------------------------
+//
+TBool CVoIPAudioDownlinkStreamImpl::FindFormat(TVoIPCodecFormat aFormat)
+ {
+ TBool found = EFalse;
+
+ if (iCodecFormats)
+ {
+ if (iCodecFormats->Count() > 0)
+ {
+ if (iCodecFormats->Find(aFormat) == KErrNotFound)
+ {
+ // For backward compatibility with VAS 1.0
+ if (aFormat == EG711)
+ {
+ if (iCodecFormats->Find(EG711_10MS) != KErrNotFound)
+ {
+ iFormat = EG711_10MS;
+ found = ETrue;
+ }
+ }
+ }
+ else
+ {
+ iFormat = aFormat;
+ found = ETrue;
+ }
+ }
+ }
+
+ return found;
+ }
+
+// ======== CALLBACK FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::FillBuffer
+// From MQueueHandlerObserver
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::FillBuffer(CVoIPDataBuffer* aBuffer)
+ {
+ iObserver->FillBuffer(*this, aBuffer);
+ }
+
+// ---------------------------------------------------------------------------
+// CVoIPAudioDownlinkStreamImpl::Event
+// From MQueueHandlerObserver
+// ---------------------------------------------------------------------------
+//
+void CVoIPAudioDownlinkStreamImpl::Event(TInt aEventType, TInt aError)
+ {
+ iObserver->Event(*this, aEventType, aError);
+ }
+
+// End of file