/** 
Indicates the data source has filled the specified buffer.

Called by the CMMFDataPath2's MDataSource when it has filled the buffer.

@param aBuffer
       A pointer to the filled buffer.
*/
void CMMFDataPath2::BufferFilledL(CMMFBuffer* aBuffer)
	{	
#ifdef _DP_DEBUG
	RDebug::Print(_L("DP::BufferFilledL src has filled buffer %d (ptr=0x%x) with %d bytes EoF = %d  tick-%d    (this 0x%x)\n"),aBuffer->FrameNumber(),aBuffer, aBuffer->BufferSize(),aBuffer->LastBuffer(), User::TickCount(),this);
#endif
	
	TBool isInTruePause = (iState == EPrimed  && iPauseCalled && iIsUsingResumeSupport);
	//state only used if we are passing data
	__ASSERT_DEBUG((iState == EPlaying || iState == EConverting || iState == ERecording || isInTruePause), Panic(EMMFDataPathPanicBadState,__LINE__));

	__ASSERT_DEBUG((!iNoMoreSourceData), Panic(EMMFDataPathPanicBadState,__LINE__)); 
	
	//if we have been asked to repeat and this is the last buffer, reset last buffer flag and send to the device
	if(aBuffer!= NULL && aBuffer->LastBuffer())
		{
		iNumberOfTimesPlayed++;
		if ((iNumberOfTimesPlayed <= iNumberOfTimesToRepeat) || iNumberOfTimesToRepeat == KMdaRepeatForever)
			{
			aBuffer->SetLastBuffer(EFalse);
			
			//this will trigger the trailing silence timer next time a buffer is requested.
			iTrailingSilenceLeftToPlay = iTrailingSilence;
			iVerifyPlayComplete = ETrue;
			}
		}		
		
	iSourceBufferWithSource = EFalse;

	//Has the datapath stopped running, if so were not interested in any callbacks.
	if(iState == EStopped || (iState == EPrimed  && !isInTruePause))
		{
#ifdef _DP_DEBUG
		RDebug::Print(_L("DP::BufferFilledL called while not expecting callback iState=%d  iPauseCalled=%d  (this 0x%x)\n"),iState, iPauseCalled,this);
#endif
		return;
		}

#ifdef REPOSITION_SPEEDUP
	// if the source has been re-positioned, then go & get some more source data now
	if (!iObtainingAsyncSourceBuffer && iSourceBuffer->FrameNumber() != iCurrentSourceFrameNumber)
		{
#ifdef _DP_DEBUG
		RDebug::Print(_L("DP::BufferFilledL source was re-positioned re-requesting source data (this 0x%x)\n"),this);
#endif
		ChangeDataPathTransferState(ENeedSourceData);
		return;
		}
#endif //REPOSITION_SPEEDUP

	//bufer is NULL, indicating no more source data.
	if (!aBuffer)
		{
		//If we only hold a reference to the source buffer, set that to NULL
		if(iSnkBufRef)
			{
			iSourceBuffer = NULL;
			}
		
		iNoMoreSourceData = ETrue;

		if(!iCodec || //there's only one buffer and that has been returned as NULL, so must be end of data
		  iSinkBufferWithSink) //buffer is with sink, we don't have any more data to put in it, so must be end of data
			{
			ChangeDataPathTransferState(EEndOfData);
			}
		else //sink buffer is with datapath, see if there is anything to send to sink
			{
			ChangeDataPathTransferState(ENeedToMatchSourceToSink);
			}
		
#ifdef _DP_DEBUG
		RDebug::Print(_L("DP::BufferFilledL DONE aBuffer==NULL tick-%d (this 0x%x)\n"),User::TickCount(),this);
#endif
		return;
		} 

	
	//We were waiting for a response from the source to get an asynchronous buffer.
	//We now have it, and we proceed to transfer this data to the sink.
	if	(iObtainingAsyncSourceBuffer)
		{
		iObtainingAsyncSourceBuffer = EFalse;
		}
	

	aBuffer->SetStatus(EFull);

	if(iSourceBuffer != aBuffer)
		{//buffer has been changed by the source
		iSourceBuffer = aBuffer;
		if (!(iBuffersToUse & ENeedSinkBuffer))
			{//we only need one buffer and use source
			iSinkBuffer = iSourceBuffer;
			iSnkBufRef = ETrue;
			}
#ifdef _DP_DEBUG
	RDebug::Print(_L("DP::BufferFilledL - iSourceBuffer=0x%x ref=%d   iSinkBuffer=0x%x ref=%d (this 0x%x)\n"),iSourceBuffer,iSrcBufRef,iSinkBuffer,iSnkBufRef, this);
#endif	
		}
	//Is this the last buffer from the source (0 length or LastBuffer flag set)
	//or have reached the end of the play window; we only look at the play window here
	//if we are converting. For conversion we look at the data we have read. This is then passed onto 
	//the source
	if (!iSourceBuffer->BufferSize() || iSourceBuffer->LastBuffer() ||
		(((iState == EConverting) || (iState == EPlaying)) && (iPlayWindowEndPosition < iCachedSourceDuration) && ( InputPosition() >= iPlayWindowEndPosition ))) 
		{
		//When it resumes in silence , position of the buffer is in end so we need to skip the increament.
		if(!iPauseCalledInsilence) 
		{    
			iNumberOfTimesPlayed++;
		}else
		{
			iPauseCalledInsilence=EFalse;
		}
		if ((iNumberOfTimesPlayed <= iNumberOfTimesToRepeat) || iNumberOfTimesToRepeat == KMdaRepeatForever)
			{
			iSourceBuffer->SetLastBuffer(EFalse);
			//this will trigger the trailing silence timer next time a buffer is requested.
			iTrailingSilenceLeftToPlay = iTrailingSilence;
			iVerifyPlayComplete = ETrue;
			}
		else
			{		
	#ifdef _DP_DEBUG
			RDebug::Print(_L("DP::BufferFilledL end of input data  tick-%d   (this 0x%x)\n"),User::TickCount(),this);
			RDebug::Print(_L("iSourceBuffer->BufferSize()=%d\n"),iSourceBuffer->BufferSize());
			RDebug::Print(_L("iSourceBuffer->LastBuffer()=%d\n"),iSourceBuffer->LastBuffer());
			RDebug::Print(_L("InputPosition()=%d  >= iPlayWindowEndPosition=%d\n"),I64INT(InputPosition().Int64()),I64INT(iPlayWindowEndPosition.Int64()));
	#endif
			iNoMoreSourceData = ETrue;
			iSourceBuffer->SetLastBuffer(ETrue); //just in-case we are terminating on BufferSize == 0 or play window
			}
		}


	if (!iCodec)
		{
		ChangeDataPathTransferState(ESendDataToSink);
		}
	else if(!iSinkBufferWithSink) //sink buffer is with data path, can try to fill it
		{
		ChangeDataPathTransferState(ENeedToMatchSourceToSink);	
		}
	//else wait for sink to return buffer BufferEmptied will send us into ENeedToMatchSourceToSink state

#ifdef _DP_DEBUG
	RDebug::Print(_L("DP::BufferFilledL - DONE tick-%d   (this 0x%x)\n"),User::TickCount(),this);
#endif
	}
Example #2
0
	Evaluatable * Action::inputVal() const
	{
		return element_cast<Evaluatable>(inputAt(InputPosition()));
	}