mmfenh/advancedaudiocontroller/audiocontrollerpluginsvariant/3gpDataSourceAdapter/Src/3gpDataSourceAdapter.cpp
changeset 0 71ca22bcf22a
child 7 709f89d8c047
child 12 5a06f39ad45b
--- /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, &timestamp, &returnedframes, &timestamp2);
+	   		    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
+