--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmfenh/advancedaudiocontroller/audiocontrollerpluginsvariant/3gpDataSourceAdapter/Src/3gpDataSourceAdapter.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,962 @@
+/*
+* 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: Class definition for the DataSourceAdapter functions.
+*
+*/
+
+
+// INCLUDES
+#include "3gpDataSourceAdapter.h"
+#include "DebugMacros.h"
+#include <mmfclip.h>
+//#include <mmfdatabuffer.h>
+#include <MultimediaDataSourceFactory.h>
+#include <mmffile.h>
+#include <caf/caf.h>
+#include <mmfcontroller.h>
+
+
+#include <oma2dcf.h> // EPeek
+const TInt KDataSourceReadBufferSize = 16*1024; // read from source
+const TInt KParserReadBufferSize = 2000; // read from parser - it only gives 1 frame
+const TInt KMaxFrameSize = 1536;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::C3gpDataSourceAdapter
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+C3gpDataSourceAdapter::C3gpDataSourceAdapter() :
+ MDataSink(KUidMmfFormatDecode)
+
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::ConstructL()
+ {
+ // should end up doing this for all sources
+ iMediaId = KUidMediaTypeAudio;
+ iParserBuf = CreateSourceBufferOfSizeL(KParserReadBufferSize);
+ iSrcBuf = CreateSourceBufferOfSizeL(KDataSourceReadBufferSize);
+ iZeroBuffer = CMMFDataBuffer::NewL(0); // this is just for test to allow source seek
+ iHdrBuffer = CMMFDataBuffer::NewL(20); // just enough to cover the header lengths create by recorder
+ iAsyncProxyFillBuffer = new(ELeave) CAsyncProxyFillBuffer(*this);
+
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C C3gpDataSourceAdapter* C3gpDataSourceAdapter::NewL()
+ {
+ DP0(_L("C3gpDataSourceAdapter::NewL"));
+ C3gpDataSourceAdapter* self = new(ELeave) C3gpDataSourceAdapter();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// Destructor
+EXPORT_C C3gpDataSourceAdapter::~C3gpDataSourceAdapter()
+ {
+ DP0(_L("C3gpDataSourceAdapter::~C3gpDataSourceAdapter"));
+ MP4ParseClose(iMP4Handle);
+ delete iParserBuf;
+ delete iSrcBuf;
+ delete iCafHandle;
+ iQueuedAsyncBuffers.Close(); // this is different from one in base class
+ delete iAsyncProxyFillBuffer; // this is different from one in base class
+ }
+
+// -----------------------------------------------------------------------------
+// From MDataSource
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void C3gpDataSourceAdapter::FillBufferL(CMMFBuffer* aBuffer, MDataSink* aDataSink,TMediaId /*aMediaId*/)
+ {
+ TInt status = KErrNone;
+ CMMFDataBuffer* buffer = static_cast<CMMFDataBuffer*>(aBuffer);
+
+ DP1(_L("C3gpDataSourceAdapter::FillBufferL buffer[%x]"), buffer->Data().Ptr());
+ if (aDataSink != this)
+ { // called from the controller
+ iControllerMDataSink = aDataSink;
+ iQueuedAsyncBuffers.Append(aBuffer);
+ if (iQueuedAsyncBuffers.Count() > 1)
+ {
+ DP1(_L("C3gpDataSourceAdapter::FillBufferL buffer queued count[%d]"), iQueuedAsyncBuffers.Count());
+ return;
+ }
+ }
+
+ if (iParserBuf->Data().Length())
+ {
+ // Audio Frames previously read is appended first
+ buffer->Data().Append(iParserBuf->Data().Ptr(), iParserBuf->Data().Length());
+ iParserBuf->Data().SetLength(0);
+ iParserBuf->SetPosition(0);
+ }
+
+ iFillingBuffer = aBuffer;
+ if (iReadMp4LibSync)
+ {
+ iAsyncProxyFillBuffer->ReadSync();
+ }
+ else
+ {
+ status = ReadAsync();
+ }
+
+ if (status == KErrNone)
+ {
+ // do nothing
+ }
+ else
+ { // define the use case for this...
+ DP1(_L("C3gpDataSourceAdapter::FillSharedBufferL, ReadAsync status[%d] calling frames available"), status);
+ M3GPMP4LibAudioFramesAvailable(status, 0, 0,0,0);
+ }
+ }
+
+EXPORT_C void C3gpDataSourceAdapter::SourcePrimeL()
+ {
+ DP0(_L("C3gpDataSourceAdapter::SourcePrimeL"));
+ iDataSource->SourcePrimeL();
+ if (!iMP4Handle)
+ {
+ PrepareMP4ParserL();
+ }
+ }
+
+EXPORT_C void C3gpDataSourceAdapter::SourceStopL()
+ {
+ DP0(_L("C3gpDataSourceAdapter::SourceStopL"));
+ ResetVariables();
+ MP4ParseClose(iMP4Handle);
+ iMP4Handle = NULL;
+ iDataSource->SourceStopL();
+ // Clear previously read Audio Frames
+ iParserBuf->Data().SetLength(0);
+ iParserBuf->SetPosition(0);
+ }
+
+// -----------------------------------------------------------------------------
+// From MMultimediaDataSourceObserver
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void C3gpDataSourceAdapter::BufferFilled(CMMFBuffer* aBuffer)
+ {
+ TRAPD(err,BufferFilledL(aBuffer));
+ if (err != KErrNone)
+ {//send event to client to notify error in source adapter
+ // SendEvent(TMMFEvent(KMMFEventCategoryPlaybackComplete, err));
+ }
+ }
+
+EXPORT_C void C3gpDataSourceAdapter::Event(TUid aEvent)
+ {
+ iControllerMMultimediaDataSourceObserver->Event(aEvent);
+ }
+
+EXPORT_C TInt C3gpDataSourceAdapter::GetBitRate(TUint& aBitRate)
+ {
+ return iControllerMMultimediaDataSourceObserver->GetBitRate(aBitRate);
+ }
+
+// -----------------------------------------------------------------------------
+// From CDataSourceAdapter
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt C3gpDataSourceAdapter::SeekToTime(TUint aTimeMs, TUint& aFoundTimeMs)
+ {
+ DP0(_L("C3gpDataSourceAdapter::SeekToTime"));
+ TInt status = KErrNone;
+ mp4_u32 audioTimeStamp, videoTimeStamp;
+ MP4Err err = MP4ParseSeek(iMP4Handle, aTimeMs, &audioTimeStamp, &videoTimeStamp, EFalse);
+
+ aFoundTimeMs = audioTimeStamp;
+
+ DP3(_L("C3gpDataSourceAdapter::SeekToTime stat[%d] timeMs[%d] foundtimeMs[%d]"), err, aTimeMs,aFoundTimeMs);
+
+ status = TranslateMP4Err(err);
+ return status;
+ }
+
+EXPORT_C void C3gpDataSourceAdapter::SetDataSourceL(MDataSource* aDataSource,
+ MMultimediaDataSourceObserver* aMMultimediaDataSourceObserver,
+ MAsyncEventHandler* aAsyncEventHandler)
+ {
+ DP0(_L("C3gpDataSourceAdapter::SetDataSource"));
+ iHeaderOnly = EFalse;
+ iControllerMMultimediaDataSourceObserver = aMMultimediaDataSourceObserver;
+ iAsyncEventHandler = aAsyncEventHandler;
+ ResetVariables();
+ if (iDataSource)
+ {
+ return;
+ }
+
+ if (iCafHandle)
+ {
+ delete iCafHandle;
+ iCafHandle = NULL;
+ }
+
+ iDataSource = aDataSource;
+ iSourceType = iDataSource->DataSourceType();
+ DP1(_L("C3gpDataSourceAdapter::SetDataSource DataSourceType[0x%x]"), iSourceType);
+
+ if ((iSourceType == KMmdsStreamingSourceUid) || (iSourceType == KMmdsProgDLSourceUid) ||
+ (iSourceType == KS60AudioStreamingSourceUid) || (iSourceType == KMmdsDescriptorSourceUid) ||
+ (iSourceType == KUidMmfDescriptorSource) || (iSourceType == KMmdsFileSourceUid))
+ { // data is streamed in buffers to parser and we read sync from parser - parser does not support seeking
+ iReadMp4LibSync = ETrue;
+ }
+ else
+ { // parser has file handle and we read async from parser - parser supports seeking
+ iReadMp4LibSync = EFalse;
+ iTimeSeekable = ETrue;
+ }
+
+ if ((iSourceType == KMmdsStreamingSourceUid) || (iSourceType == KMmdsProgDLSourceUid) ||
+ (iSourceType == KS60AudioStreamingSourceUid) || (iSourceType == KMmdsDescriptorSourceUid) ||
+ (iSourceType == KMmdsFileSourceUid))
+ { // data is written to parser
+ TInt err = CMultimediaDataSourceFactory::CreateDataSource(*iDataSource, iMMDataSource);
+
+ User::LeaveIfError(err);
+
+// iMMDataSource->SetObserver(*this);
+ User::LeaveIfError(iMMDataSource->SetObserver(*this));
+ User::LeaveIfError(iMMDataSource->Open());
+ }
+ if ((iSourceType == KUidMmfFileSource) || (iSourceType == KOldProgDLSourceUid))
+ { // parser has file handle
+ // read async from lib when it has a file handle
+ iClip = static_cast<CMMFClip*>(iDataSource);
+ iDataSource->SourcePrimeL();
+ iIsProtected = static_cast<CMMFFile*>(iDataSource)->IsProtectedL();
+ iClip->SourceThreadLogon(*aAsyncEventHandler);
+ iClip->ReadBufferL(iHdrBuffer,0);
+ iClip->ReadBufferL(iZeroBuffer, 0); // seek back to 0 position
+ const TUint8* ptr = iHdrBuffer->Data().Ptr();
+ if (iClip->Size() == 11)
+ { // check for just the header from recorder
+ TUint32* w1p = (TUint32*)ptr;
+ TUint32* w2p = (TUint32*)(ptr+4);
+ TUint32* w3p = (TUint32*)(ptr+8);
+ if (((*w1p & 0x1C000000)==0x1C000000) &&
+ ((*w2p & 0x70797466)==0x70797466) &&
+ ((*w3p & 0x0034706D)==0x0034706D))
+ {
+ iClip->SourceStopL();
+ iHeaderOnly = ETrue;
+ return;
+ }
+ }
+
+ if (iSourceType == KUidMmfFileSource)
+ {
+ CMMFFile* File = static_cast<CMMFFile*>(iDataSource);
+ RFile rFile = File->FileL();
+ iCafHandle = ContentAccess::CData::NewL(rFile, File->UniqueId(), EPeek);
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// From MDataSink
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void C3gpDataSourceAdapter::BufferFilledL(CMMFBuffer* aBuffer)
+ { // only talks to MMDataSource asynchronously using a single iSrcBuf
+ // aBuffer here is just the one iSrcBuf
+ CMMFDataBuffer* buffer = static_cast<CMMFDataBuffer*>(aBuffer);
+ DP2(_L("C3gpDataSourceAdapter::BufferFilledL[%x], LastBuffer[%d]"), buffer->Data().Ptr(), aBuffer->LastBuffer());
+
+ TUint bufferSize = buffer->Data().Length();
+
+ DP1(_L("C3gpDataSourceAdapter::BufferFilledL, Length[%d]"), bufferSize);
+
+ TUint8* bufPtr = const_cast<TUint8*>(buffer->Data().Ptr());
+ TInt err = KErrNone;
+/*
+ if ( bufferSize > 5 )
+ {
+ DP5(_L("C3gpDataSourceAdapter::BufferFilledL data[0x%x][0x%x][0x%x][0x%x][0x%x]"), \
+ *bufPtr,*(bufPtr+1),*(bufPtr+2),*(bufPtr+3),*(bufPtr+4));
+ }
+*/
+ if (bufferSize > 0)
+ {
+ err = TranslateMP4Err(MP4ParseWriteData(iMP4Handle, bufPtr, bufferSize));
+ //mp4_u32 audioLength, audioType, timeScale, averateBitRate;
+ mp4_u32 audioLength, timeScale, averateBitRate;
+ mp4_u8 framesPerSample;
+ if (!iMp4HeaderAvail)
+ {
+ if (MP4_OK == MP4ParseRequestAudioDescription(iMP4Handle, &audioLength, &iAudioType, &framesPerSample, &timeScale, &averateBitRate))
+ { // header is required to do anything.
+ iMp4HeaderAvail = ETrue;
+ }
+ }
+
+ DP3(_L("C3gpDataSourceAdapter::BufferFilledL, MP4ParseWriteData err[%d], bufferSize[%d] d0[%x]"), err, bufferSize, bufPtr[0]);
+ if (err == MP4_OUT_OF_MEMORY)
+ {
+ DP0(_L("C3gpDataSourceAdapter::BufferFilledL, out of memory abort"));
+ User::Leave(KErrAbort);
+ }
+ if (err == MP4_OK)
+ {
+ if (!aBuffer->LastBuffer())
+ {
+ // continue getting next buffer
+ DP1(_L("C3gpDataSourceAdapter::BufferFilledL, iMMDataSource->FillBuffer buffer[%x]"), iSrcBuf->Data().Ptr());
+ buffer->SetPosition(0);
+ buffer->Data().SetLength(0);
+ iMMDataSource->FillBuffer(iSrcBuf);
+ }
+ else
+ {
+ // do nothing, since the file has reach the end
+ DP0(_L("C3gpDataSourceAdapter::BufferFilledL, reach EOF"));
+ iLastBufferWrittenToMp4Lib = ETrue;
+ }
+ }
+ } // buffersize > 0
+ else
+ { // buffersize <= 0
+ // should never reach here, since no callback should occur if no data available for streaming
+ DP0(_L("C3gpDataSourceAdapter::BufferFilledL, unexpected 0 length buffer"));
+ User::Leave(KErrAbort);
+ }
+ if (iRestartSyncRead)
+ {
+ iRestartSyncRead = EFalse;
+ DP0(_L("C3gpDataSourceAdapter::BufferFilledL, restarting parser read ReadSync()"));
+ iAsyncProxyFillBuffer->ReadSync();
+ }
+ }
+
+EXPORT_C void C3gpDataSourceAdapter::EmptyBufferL(
+ CMMFBuffer* /*aBuffer*/,
+ MDataSource* /*aSupplier*/,
+ TMediaId /*aMediaId*/ )
+ {}
+
+EXPORT_C TFourCC C3gpDataSourceAdapter::SinkDataTypeCode(
+ TMediaId /*aMediaId*/ )
+ {
+ return KFourCCNULL;
+ }
+
+EXPORT_C TBool C3gpDataSourceAdapter::CanCreateSinkBuffer()
+ {
+ return EFalse;
+ }
+
+EXPORT_C CMMFBuffer* C3gpDataSourceAdapter::CreateSinkBufferL(
+ TMediaId /*aMediaId*/,
+ TBool& /*aReference*/ )
+ {
+ return NULL;
+ }
+
+EXPORT_C void C3gpDataSourceAdapter::ConstructSinkL(
+ const TDesC8& /*aInitData*/ )
+ {}
+
+EXPORT_C TBool C3gpDataSourceAdapter::IsPositonSeekable()
+ {
+ DP1(_L("C3gpDataSourceAdapter::IsPositonSeekable DataSourceType[0x%x]"), iSourceType);
+ if ((iSourceType == KMmdsStreamingSourceUid) || (iSourceType == KMmdsProgDLSourceUid) ||
+ (iSourceType == KS60AudioStreamingSourceUid) || (iSourceType == KMmdsDescriptorSourceUid) ||
+ (iSourceType == KUidMmfDescriptorSource) || (iSourceType == KMmdsFileSourceUid) ||
+ (iSourceType == KOldProgDLSourceUid))
+ {
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+// -----------------------------------------------------------------------------
+// From M3GPMP4LibAsyncObserver
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable(MP4Err aError,
+ mp4_u32 aAudioSize,
+ mp4_u32 /*aTimeStamp*/,
+ mp4_u32 /*aReturnedFrames*/,
+ mp4_u32 /*aTimestamp2*/)
+ {
+ DP2(_L("C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable, aError = %d, aAudioSize = %d"), aError, aAudioSize);
+ DP2(_L("C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable, iParserBuf[%x] d0[%x]"), static_cast<CMMFDataBuffer*>(iParserBuf)->Data().Ptr(), static_cast<CMMFDataBuffer*>(iParserBuf)->Data().Ptr()[0]);
+
+ TInt err = aError;
+ if (err == MP4_OK)
+ {
+ TUint8* bufPtr = const_cast<TUint8*>(iParserBuf->Data().Ptr());
+ TInt requestSize = static_cast<CMMFDataBuffer*>(iFillingBuffer)->RequestSize();
+ TInt bufferlength = static_cast<CMMFDataBuffer*>(iFillingBuffer)->Data().Length()+aAudioSize;
+
+ if (bufferlength <= requestSize)
+ {
+/* TUint32 timePositionInMilliSecs = I64INT(iPlayWindowEndPosition.Int64())/1000;
+
+ if ((iPlayWindowEndPosition != TTimeIntervalMicroSeconds(0)) && (aTimeStamp >= timePositionInMilliSecs))
+ {
+ iFillingBuffer->SetLastBuffer(ETrue);
+ iFillingBuffer->SetStatus(EFull);
+ }
+ else // Not reached end of playwindow or no playwindow at all
+*/ {
+ static_cast<CMMFDataBuffer*>(iFillingBuffer)->Data().Append(iParserBuf->Data().Ptr(), aAudioSize);
+ iParserBuf->Data().SetLength(0);
+ iParserBuf->SetPosition(0);
+
+ err = ReadAsync();
+ // this error return value is handled below
+
+ }
+ }
+ else
+ {
+ // Save this read for the next source buffer
+ DP2(_L("C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable, iFillingBuffer[%x] - FULL, Length[%d]"),
+ static_cast<CMMFDataBuffer*>(iFillingBuffer)->Data().Ptr(), static_cast<CMMFDataBuffer*>(iFillingBuffer)->Data().Length());
+ iParserBuf->Data().SetLength(aAudioSize);
+ iQueValid = ETrue;
+ TRAP(err,iControllerMDataSink->BufferFilledL(iFillingBuffer)); // setpos could come in here and clear the queue here and add another read
+ // this error return value is handled below
+ if (iQueValid)
+ { // this detects if the que has been cleared and refilled
+ // we don't want to do this with the new buffers in the queue
+ iQueuedAsyncBuffers.Remove(0);
+ if (iQueuedAsyncBuffers.Count() > 0)
+ {
+ DP0(_L("C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable calls FillBufferL"));
+ TRAP(err,FillBufferL(iQueuedAsyncBuffers[0],this,iMediaId));
+ // this error return value is handled below
+ }
+ }
+ }
+ }
+ if (err == MP4_NO_FRAME)
+ {
+ DP0(_L("C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable sending last buffer"));
+ iFillingBuffer->SetLastBuffer(ETrue);
+ TRAP(err,iControllerMDataSink->BufferFilledL(iFillingBuffer));
+ if (err != KErrNone)
+ {
+ DP1(_L("C3gpDataSourceAdapter::M3GPMP4LibAudioFramesAvailable, BufferFilledL err[%d]"), err);
+
+// SendEvent(TMMFEvent(KMMFEventCategoryPlaybackComplete, err));
+ }
+ }
+ else if (err != MP4_OK)
+ {
+ DP1(_L("error %d..."), TranslateMP4Err(err));
+
+ //send event to client to notify error in source adapter
+ if(iAsyncEventHandler)
+ {
+ iAsyncEventHandler->SendEventToClient(TMMFEvent(KMMFEventCategoryPlaybackComplete, KErrSourceAdapter));
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::M3GPMP4LibVideoFrameAvailable
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::M3GPMP4LibVideoFrameAvailable(MP4Err /*aError*/,
+ mp4_u32 /*aFrameSize*/,
+ mp4_u32 /*aTimeStamp*/,
+ mp4_bool /*aKeyFrame*/,
+ mp4_u32 /*aTimestamp2*/)
+ {
+ // do nothing, not used
+ }
+
+// -----------------------------------------------------------------------------
+// New
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt C3gpDataSourceAdapter::ReadHeader(TUint32& aAudioLength, TUint32& aAudioType,
+ TUint8& aFramesPerSample, TUint32& aTimeScale, TUint32& aAverateBitRate)
+ {
+ TInt err = MP4ParseRequestAudioDescription(iMP4Handle, &aAudioLength, &aAudioType, &aFramesPerSample, &aTimeScale, &aAverateBitRate);
+ DP6(_L("C3gpDataSourceAdapter::ReadHeader stat[%d] aAudioLength[%d], aAudioType[%d], aFramesPerSample[%d], aTimeScale[%d], aAverateBitRate[%d]"),
+ err, aAudioLength, aAudioType, aFramesPerSample, aTimeScale, aAverateBitRate);
+ iAudioType = aAudioType;
+ return(TranslateMP4Err(err));
+ }
+
+EXPORT_C TInt C3gpDataSourceAdapter::ReadAudioSpecificConfig(TUint8* aDecSpecInfo, TUint32 aDecSpecInfoSizeIn, TUint32* aDecSpecInfoSizeOut)
+ {
+ TInt err = KErrNone;
+ MP4Err stat = MP4ParseReadAudioDecoderSpecificInfo(iMP4Handle, aDecSpecInfo, aDecSpecInfoSizeIn, aDecSpecInfoSizeOut);
+ if ((stat == MP4_BUFFER_TOO_SMALL) && (aDecSpecInfo == NULL)) // This is valid Error as we are just getting the buffersize
+ {
+ err = KErrNone;
+ }
+ else
+ {
+ err = TranslateMP4Err(stat);
+ }
+ DP2(_L("C3gpDataSourceAdapter::ReadAudioSpecificConfig info[0x%x] err[%d]"), aDecSpecInfo, err);
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// Local
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::PrepareMP4ParserL()
+ {
+ DP0(_L("C3gpDataSourceAdapter::PrepareMP4ParserL"));
+
+ MP4Err err = MP4_ERROR;
+
+ if (iCafHandle)
+ {
+ // SourceStopL might terminate the access to the File, SourcePrimeL to regain access
+ err = MP4ParseOpenCAF(&iMP4Handle, iCafHandle);
+ DP1(_L("C3gpDataSourceAdapter::PrepareMP4ParserL, MP4ParseOpenCAF err = %d"), err);
+ User::LeaveIfError(TranslateMP4Err(err));
+ }
+ else if (iSourceType == KUidMmfDescriptorSource) // KUidMmfDescriptorSource
+ {
+ err = MP4ParseOpen(&iMP4Handle, NULL);
+ User::LeaveIfError(TranslateMP4Err(err));
+
+ CMMFClip* clip = static_cast<CMMFClip*>(iDataSource);
+
+ TBool endOfFile = EFalse;
+ iSourceReadPosition = 0;
+ TUint8* buffer = const_cast<TUint8*>(iSrcBuf->Data().Ptr());
+ while (!endOfFile)
+ {
+ clip->ReadBufferL(iSrcBuf, iSourceReadPosition);
+ TUint buffersize = iSrcBuf->Data().Length();
+
+ if (buffersize > 0)
+ {
+ err = MP4ParseWriteData(iMP4Handle, buffer, buffersize);
+ DP1(_L("C3gpDataSourceAdapter::PrepareMP4ParserL, write desc buffer to parser stat[%d]"), err);
+ User::LeaveIfError(TranslateMP4Err(err));
+ iSourceReadPosition += buffersize;
+ }
+ else
+ {
+ endOfFile = ETrue;
+ // This call with empty buffer indicates to the 3GP library that
+ // this is the last buffer.
+ iLastBufferWrittenToMp4Lib = ETrue;
+ err = MP4ParseWriteData(iMP4Handle, buffer, 0);
+ DP1(_L("C3gpDataSourceAdapter::PrepareMP4ParserL, write last desc buffer to parser stat[%d]"), err);
+ User::LeaveIfError(TranslateMP4Err(err));
+ }
+ }
+
+ clip->SourceStopL();
+ }
+ else if (iReadMp4LibSync && (iSourceType != KOldProgDLSourceUid))
+// (iSourceType == KMmdsStreamingSourceUid) || (iSourceType == KMmdsProgDLSourceUid) ||
+// (iSourceType == KS60AudioStreamingSourceUid) || (iSourceType == KMmdsFileSourceUid) ||
+// (iSourceType == KMmdsDescriptorSourceUid))
+ {
+ err = MP4ParseOpen(&iMP4Handle, NULL);
+ User::LeaveIfError(TranslateMP4Err(err));
+ DP1(_L("C3gpDataSourceAdapter::PrepareMP4ParserL, iMMDataSource->FillBuffer buffer[%x]"), iSrcBuf->Data().Ptr());
+ iSrcBuf->SetPosition(0);
+ iSrcBuf->Data().SetLength(0);
+ iMMDataSource->FillBuffer(iSrcBuf);
+ }
+ else if (iSourceType == KOldProgDLSourceUid)
+ {
+ err = MP4ParseOpen(&iMP4Handle, NULL);
+ User::LeaveIfError(TranslateMP4Err(err));
+
+ iSourceReadPosition = 0;
+ StartReadingSourceL();
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ // MP4ParseRequestAudioDescription() is used here to initialize the parser internally
+ // before other parser functions can be used.
+ // The data gathered here is not used and the function may return an error in some cases.
+ // mp4_u32 audioLength, audioType, timeScale, averateBitRate;
+ mp4_u32 audioLength, timeScale, averateBitRate;
+ mp4_u8 framesPerSample;
+ err = MP4ParseRequestAudioDescription(iMP4Handle, &audioLength, &iAudioType, &framesPerSample, &timeScale, &averateBitRate);
+ if (err == MP4_OK)
+ { // mmf descriptor source or a short file would put complete content to the parser
+ // so this needs to be set here.
+ iMp4HeaderAvail = ETrue;
+ }
+ if /*( ((iSourceType == KOldProgDLSourceUid) || (iSourceType == KMmdsFileSourceUid) ||
+ (iSourceType == KMmdsStreamingSourceUid) || (iSourceType == KMmdsProgDLSourceUid) ||
+ (iSourceType == KS60AudioStreamingSourceUid) || (iSourceType == KMmdsDescriptorSourceUid)) &&*/
+ ((err == MP4_NOT_AVAILABLE) || (err == MP4_FILE_ERROR)) //)
+ {
+ // do nothing
+ }
+ else
+ {
+ DP1(_L("C3gpDataSourceAdapter::PrepareMP4ParserL Leave, err = %d"), err);
+ User::LeaveIfError(TranslateMP4Err(err));
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::TranslateMP4Err
+// -----------------------------------------------------------------------------
+//
+TInt C3gpDataSourceAdapter::TranslateMP4Err(
+ MP4Err aError)
+ {
+ DP1(_L("C3gpDataSourceAdapter::TranslateMP4Err err = %d"), aError);
+ TInt err;
+ switch (aError)
+ {
+ case MP4_OK:
+ err = KErrNone;
+ break;
+ case MP4_OUT_OF_MEMORY:
+ err = KErrNoMemory;
+ break;
+ case MP4_NOT_AVAILABLE: // valid error for progressive download and streaming source
+ err = KErrNotReady;
+ break;
+ case MP4_FILE_ERROR:
+ err = KErrBadHandle;
+ break;
+ case MP4_INVALID_TYPE:
+ err = KErrNotSupported;
+ break;
+ case MP4_TIMESCALE_NOT_SET:
+ err = KErrNotReady;
+ break;
+ case MP4_NOT_STREAMABLE:
+ case MP4_NO_REQUESTED_FRAME:
+ case MP4_CANT_SEEK:
+ case MP4_INVALID_INPUT_STREAM:
+ case MP4_NO_FRAME:
+ err = KErrArgument;
+ break;
+ case MP4_ERROR:
+ case MP4_FILE_MODE:
+ case MP4_BUFFER_TOO_SMALL:
+ case MP4_END_OF_VIDEO:
+ case MP4_METADATA_ERROR:
+ case MP4_NO_VIDEO:
+ case MP4_NO_AUDIO:
+ err = KErrGeneral;
+ break;
+ default:
+ if (aError > 0) //For Any 3GPLib Errors
+ {
+ err = KErrGeneral;
+ }
+ else // For CAF Errors
+ {
+ err = aError;
+ }
+
+ break;
+ }
+
+ return err;
+ }
+
+
+CMMFDataBuffer* C3gpDataSourceAdapter::CreateSourceBufferOfSizeL(
+ TUint aSize )
+ {
+ CMMFDataBuffer* buffer = CMMFDataBuffer::NewL(aSize);
+ CleanupStack::PushL(buffer);
+ buffer->SetRequestSizeL(aSize);
+ buffer->SetPosition(0);
+ buffer->Data().SetLength(0);
+ CleanupStack::Pop(buffer);
+ return buffer;
+ }
+
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::StartReadingSourceL
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::StartReadingSourceL()
+ {
+ DP1(_L("C3gpDataSourceAdapter::StartReadingSourceL, iSourceReadPosition = %d"), iSourceReadPosition);
+
+ // kick off the asynchronous read from source
+// iClip->SourcePrimeL();
+// iClip->SourceThreadLogon(*this);
+ iSrcBuf->SetPosition(0);
+ iSrcBuf->Data().SetLength(0);
+ iClip->ReadBufferL(iSrcBuf, iSourceReadPosition, this);
+ iContinueReading = ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::ReadAsync
+// -----------------------------------------------------------------------------
+//
+TInt C3gpDataSourceAdapter::ReadAsync()
+ {
+ TUint8* bufPtr = const_cast<TUint8*>(iParserBuf->Data().Ptr());
+ mp4_u32 buffersize = iParserBuf->RequestSize();
+ DP2(_L("C3gpDataSourceAdapter::ReadAsync ptr[%x] size[%d]"), bufPtr, buffersize);
+ MP4Err err = MP4_ERROR;
+
+ if (iMP4Handle)
+ {
+ err = MP4ParseReadAudioFramesAsync(iMP4Handle, this, bufPtr, &buffersize);
+ }
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::ReadSyncL
+// -----------------------------------------------------------------------------
+//
+TInt C3gpDataSourceAdapter::ReadSyncL()
+ {
+ TInt err = MP4_ERROR;
+ CMMFDataBuffer* buffer = static_cast<CMMFDataBuffer*>(iFillingBuffer);
+ TUint8* bufPtr = const_cast<TUint8*>(buffer->Data().Ptr()) + iFillingBuffer->Position();
+ TInt buffersize = iFillingBuffer->RequestSize() - iFillingBuffer->Position();
+ DP4(_L("C3gpDataSourceAdapter::ReadSyncL, buffer[%x] length[%d] buffersize[%d] position[%d]"),
+ buffer->Data().Ptr(), buffer->Data().Length(), buffersize, iFillingBuffer->Position());
+
+ TInt bytesAdded = 0;
+ mp4_u32 framesize;
+
+ while (ETrue)
+ {
+ if (iMp4HeaderAvail)
+ { // know audio type after header read
+ err = MP4ParseNextFrameSize(iMP4Handle, iAudioType, &framesize);
+ if (err != MP4_OK)
+ { // default in case not enough data
+ framesize = KMaxFrameSize;
+ err = MP4_OK;
+ }
+ }
+ else
+ {
+ framesize = KMaxFrameSize;
+ }
+ if (buffersize >= framesize)
+ {
+ mp4_u32 audiosize, timestamp, returnedframes, timestamp2;
+ if (iMp4HeaderAvail)
+ {
+ err = MP4ParseReadAudioFrames(iMP4Handle, bufPtr, buffersize, &audiosize, ×tamp, &returnedframes, ×tamp2);
+ DP4(_L("C3gpDataSourceAdapter::ReadSyncL, MP4ParseReadAudioFrames err[%d] timestamp[%d] size[%d] d0[%x]"),
+ err, timestamp, audiosize, bufPtr[0]);
+ mp4_u32 bytes;
+ TInt s = MP4ParseGetBufferedBytes(iMP4Handle, &bytes);
+ DP2(_L("C3gpDataSourceAdapter::ReadSyncL bufferedbytes[%x] stat[%d]"),bytes,s);
+/*
+ TInt block,aNumber =2;
+ RHeap &heap = User::Heap();
+ RDebug::Print(_L("### SB-Cont%d"), aNumber);
+ RDebug::Print(_L("### SB-Cont%d: Heap Base Address: [0x%x]"),aNumber, heap.Base());
+ RDebug::Print(_L("### SB-Cont%d: Available Heap Memory [%6d]"),aNumber, heap.Available(block));
+ RDebug::Print(_L("### SB-Cont%d: Largest block: [%6d]"),aNumber, block);
+ RDebug::Print(_L("### SB-Cont%d: Size: [%8d]"),aNumber, heap.Size());
+ RDebug::Print(_L("### SB-Cont%d: Max length: [%8d]"),aNumber, heap.MaxLength());
+*/
+
+ }
+ else
+ {
+ err = MP4_NOT_AVAILABLE;
+ DP0(_L("C3gpDataSourceAdapter::ReadSyncL no read - header not available yet"));
+ }
+
+ if (err == MP4_OK)
+ {
+/* if (!((iSourceType == KMmfAudioStreamingSourceUid) || (iSourceType == KMmfAudioProgDLSourceUid)
+ || (iSourceType == KS60AudioStreamingSourceUid) || (iSourceType == KMmfFileSourceUid) || (iSourceType == KMmfDescriptorSourceUid))) // pay attention to the ! (not condition)
+ {
+ TUint32 timePositionInMilliSecs = I64LOW(iPlayWindowEndPosition.Int64()/1000);
+
+ if ((iPlayWindowEndPosition != TTimeIntervalMicroSeconds(0)) &&
+ (timestamp >= timePositionInMilliSecs))
+ {
+ aBuffer->SetLastBuffer(ETrue);
+ break;
+ }
+ }
+*/
+ bufPtr += audiosize;
+ buffersize -= audiosize;
+ bytesAdded += audiosize;
+ }
+ else if ((err == MP4_NO_FRAME) ||
+ ((err == MP4_NOT_AVAILABLE) && iLastBufferWrittenToMp4Lib))
+ { // if the file is cut short, it might return not_available - so check for last buffer
+ iFillingBuffer->SetLastBuffer(ETrue);
+ break;
+ }
+ else if (err == MP4_NOT_AVAILABLE)
+ { // in case parser is totally out of data
+ TInt pos = buffer->Data().Length()+bytesAdded;
+ buffer->Data().SetLength(pos); // must set length first to accomodate position
+ iFillingBuffer->SetPosition(pos);
+ iRestartSyncRead = ETrue;
+ DP3(_L("C3gpDataSourceAdapter::ReadSyncL, MP4_NOT_AVAILABLE bytesAdded[%d] pos[%d] length[%d]"),
+ bytesAdded, iFillingBuffer->Position(), buffer->Data().Length());
+ break;
+ }
+ } // if buffer large enough for read
+ else
+ { // if buffer too small for read
+ DP3(_L("C3gpDataSourceAdapter::ReadSyncL, buffersize[%d] too small for next frame[%d] err[%d] should be 0"),
+ buffersize, framesize, err);
+ break;
+ }
+ } // while ETrue keep filling buffer
+ if ((err == MP4_OK) || (iFillingBuffer->LastBuffer()))
+ {
+ iQueValid = ETrue;
+ buffer->Data().SetLength(buffer->Data().Length() + bytesAdded);
+ DP2(_L("C3gpDataSourceAdapter::ReadSyncL, sending buffer to controller iFillingBuffer[%x], Length[%d]"),
+ buffer->Data().Ptr(), buffer->Data().Length());
+ iControllerMDataSink->BufferFilledL(iFillingBuffer); // setpos could come in here and clear the queue here and add another read
+ if (iQueValid)
+ { // this detects if the que has been cleared and refilled
+ // we don't want to do this with the new buffers in the queue
+ iQueuedAsyncBuffers.Remove(0);
+ if (iQueuedAsyncBuffers.Count() > 0)
+ {
+ DP0(_L("C3gpDataSourceAdapter::ReadSyncL calls FillBufferL"));
+ FillBufferL(iQueuedAsyncBuffers[0],this,iMediaId);
+ }
+ }
+ }
+ TInt status = TranslateMP4Err(err);
+ return status;
+ }
+
+void C3gpDataSourceAdapter::ResetVariables()
+ {
+ iRestartSyncRead = EFalse;
+ iLastBufferWrittenToMp4Lib = EFalse;
+ iMp4HeaderAvail = EFalse;
+ iQueuedAsyncBuffers.Reset();
+ iQueValid = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer::CAsyncProxyFillBuffer
+// -----------------------------------------------------------------------------
+//
+C3gpDataSourceAdapter::CAsyncProxyFillBuffer::CAsyncProxyFillBuffer(C3gpDataSourceAdapter& a3gpDataSourceAdapter) :
+ CActive(EPriorityHigh),
+ i3gpDataSourceAdapter(a3gpDataSourceAdapter)
+ {
+ DP0(_L("C3gpDataSourceAdapter::CAsyncProxyFillBuffer::CAsyncProxyFillBuffer"));
+ CActiveScheduler::Add(this);
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer::~CAsyncProxyFillBuffer
+// -----------------------------------------------------------------------------
+//
+C3gpDataSourceAdapter::CAsyncProxyFillBuffer::~CAsyncProxyFillBuffer()
+ {
+ DP0(_L("C3gpDataSourceAdapter::CAsyncProxyFillBuffer::~CAsyncProxyFillBuffer"));
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer::GenerateCallback
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::CAsyncProxyFillBuffer::ReadSync()
+ {
+ DP0(_L("C3gpDataSourceAdapter::CAsyncProxyFillBuffer::ReadSync"));
+ iStatus = KRequestPending; // service request would be made here and pending set by service provider
+ SetActive();
+ iRequestStatus = &iStatus;
+ User::RequestComplete(iRequestStatus, KErrNone);
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer::DoCancel
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::CAsyncProxyFillBuffer::DoCancel()
+ {
+ DP0(_L("C3gpDataSourceAdapter::CAsyncProxyFillBuffer::DoCancel"));
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer::RunL
+// -----------------------------------------------------------------------------
+//
+void C3gpDataSourceAdapter::CAsyncProxyFillBuffer::RunL()
+ {
+ DP0(_L("C3gpDataSourceAdapter::CAsyncProxyFillBuffer::RunL"));
+ i3gpDataSourceAdapter.ReadSyncL();
+ }
+
+// -----------------------------------------------------------------------------
+// C3gpDataSourceAdapter::CAsyncProxyFillBuffer::RunError
+// -----------------------------------------------------------------------------
+//
+TInt C3gpDataSourceAdapter::CAsyncProxyFillBuffer::RunError(TInt aError)
+ {
+ if (aError)
+ {
+ DP1(_L("C3gpDataSourceAdapter::CAsyncProxyFillBuffer::RunError, aError = %d"), aError);
+ }
+ return KErrNone;
+ }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// End of File
+