/** 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 }
Evaluatable * Action::inputVal() const { return element_cast<Evaluatable>(inputAt(InputPosition())); }