Example #1
0
void CRTSPClient::FillBuffer(DWORD byteCount)
{	
  LogDebug("CRTSPClient::Fillbuffer...%d\n",byteCount);
  DWORD tickCount=GET_TIME_NOW();
  while ( IsRunning() && m_buffer.Size() < byteCount)
  {
    Sleep(5);
    if (GET_TIME_NOW()-tickCount > 3000) break;
  }
  LogDebug("CRTSPClient::Fillbuffer...%d/%d\n",byteCount,m_buffer.Size() );
}
Example #2
0
//******************************************************
/// Called when thread is about to start delivering data to the codec
///
HRESULT CVideoPin::OnThreadStartPlay()
{  
  DWORD thrdID = GetCurrentThreadId();
  LogDebug("vidPin:OnThreadStartPlay(%f), rate:%02.2f, threadID:0x%x, GET_TIME_NOW:0x%x", (float)m_rtStart.Millisecs()/1000.0f, m_dRateSeeking, thrdID, GET_TIME_NOW());

  //set discontinuity flag indicating to codec that the new data
  //is not belonging to any previous data
  m_bDiscontinuity=TRUE;
  m_bPresentSample=false;
  m_delayedDiscont = 0;
  m_FillBuffSleepTime = 1;
  m_LastFillBuffTime = GET_TIME_NOW();
  m_sampleCount = 0;
  m_bInFillBuffer=false;

  m_pTsReaderFilter->m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO;

  m_llLastComp = 0;
  m_llLastMTDts = 0;
  m_nNextMTD = 0;
	m_fMTDMean = 0;
	m_llMTDSumAvg = 0;
  ZeroMemory((void*)&m_pllMTD, sizeof(REFERENCE_TIME) * NB_MTDSIZE);

  //get file-duration and set m_rtDuration
  GetDuration(NULL);

  if( !m_bPinNoNewSegFlush ) //MS DTV video decoder can hang if we flush here...
  {
    //Downstream flush
    DeliverBeginFlush();
    DeliverEndFlush();
  }

  //start playing
  DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
  return CSourceStream::OnThreadStartPlay( );
}
Example #3
0
//******************************************************
/// Called when thread is about to start delivering data to the codec
///
HRESULT CAudioPin::OnThreadStartPlay()
{
  DWORD thrdID = GetCurrentThreadId();
  LogDebug("audPin:OnThreadStartPlay(%f), rate:%02.2f, threadID:0x%x, GET_TIME_NOW:0x%x", (float)m_rtStart.Millisecs()/1000.0f, m_dRateSeeking, thrdID, GET_TIME_NOW());
  
  //set flag to compensate any differences in the stream time & file time
  m_pTsReaderFilter->m_bStreamCompensated = false;

  m_pTsReaderFilter->m_bForcePosnUpdate = true;
  m_pTsReaderFilter->WakeThread();

  m_pTsReaderFilter->m_ShowBufferAudio = INIT_SHOWBUFFERAUDIO;

  //set discontinuity flag indicating to codec that the new data
  //is not belonging to any previous data
  m_bDiscontinuity = TRUE;
  m_bPresentSample = false;
  m_sampleCount = 0;
  m_bInFillBuffer=false;
  m_pTsReaderFilter->m_audioReady = false;

  m_FillBuffSleepTime = 1;
  m_LastFillBuffTime = GET_TIME_NOW();

  ClearAverageFtime();
  
  //get file-duration and set m_rtDuration
  GetDuration(NULL);

  //Downstream flush
  DeliverBeginFlush();
  DeliverEndFlush();
  
  //start playing
  DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
  return CSourceStream::OnThreadStartPlay( );
}
Example #4
0
HRESULT CAudioPin::FillBuffer(IMediaSample *pSample)
{
  try
  {
    CDeMultiplexer& demux=m_pTsReaderFilter->GetDemultiplexer();
    CBuffer* buffer=NULL;
    bool earlyStall = false;
    
    //get file-duration and set m_rtDuration
    GetDuration(NULL);
    
    do
    {
      //Check if we need to wait for a while
      DWORD timeNow = GET_TIME_NOW();
      while (timeNow < (m_LastFillBuffTime + m_FillBuffSleepTime))
      {      
        Sleep(1);
        timeNow = GET_TIME_NOW();
      }
      m_LastFillBuffTime = timeNow;

      //did we reach the end of the file
      if (demux.EndOfFile())
      {
        int ACnt, VCnt;
        demux.GetBufferCounts(&ACnt, &VCnt);
        if (ACnt <= 0 && VCnt <= 0) //have we used all the data ?
        {
          LogDebug("audPin:set eof");
          m_FillBuffSleepTime = 5;
          CreateEmptySample(pSample);
          m_bInFillBuffer = false;
          return S_FALSE; //S_FALSE will notify the graph that end of file has been reached
        }
      }

      //if the filter is currently seeking to a new position
      //or this pin is currently seeking to a new position then
      //we dont try to read any packets, but simply return...
      if (m_pTsReaderFilter->IsSeeking() || m_pTsReaderFilter->IsStopping() || demux.m_bFlushRunning || !m_pTsReaderFilter->m_bStreamCompensated)
      {
        m_FillBuffSleepTime = 5;
        CreateEmptySample(pSample);
        m_bInFillBuffer = false;
        if (demux.m_bFlushRunning || !m_pTsReaderFilter->m_bStreamCompensated)
        {
          //Force discon on next good sample
          m_sampleCount = 0;
          m_bDiscontinuity=true;
        }
        if (!m_pTsReaderFilter->m_bStreamCompensated && (m_nNextAFT != 0))
        {
          ClearAverageFtime();
        }
        return NOERROR;
      }
      else
      {
        m_FillBuffSleepTime = 1;
        m_bInFillBuffer = true;
      }     
                  
      // Get next audio buffer from demultiplexer
      buffer=demux.GetAudio(earlyStall, m_rtStart);

      if (buffer==NULL)
      {
        m_FillBuffSleepTime = 5;
      }
      else
      {
        m_bPresentSample = true ;
        
        if (buffer->GetForcePMT())
        {
          m_bAddPMT = true;
        }
        if (buffer->GetDiscontinuity())
        {
          m_bDiscontinuity = true;
        }
        
        CRefTime RefTime,cRefTime ;
        bool HasTimestamp ;
        double fTime = 0.0;
        double clock = 0.0;
        double stallPoint = AUDIO_STALL_POINT;
        //check if it has a timestamp
        if ((HasTimestamp=buffer->MediaTime(RefTime)))
        {
          cRefTime = RefTime ;
					cRefTime -= m_rtStart ;
          //adjust the timestamp with the compensation
          cRefTime-= m_pTsReaderFilter->GetCompensation() ;
          
          //Check if total compensation offset is more than +/-10ms
          if (abs(m_pTsReaderFilter->GetTotalDeltaComp()) > 100000)
          {
            if (!m_bDisableSlowPlayDiscontinuity)
            {
              //Force downstream filters to resync by setting discontinuity flag
              pSample->SetDiscontinuity(TRUE);
            }
            m_pTsReaderFilter->ClearTotalDeltaComp();
          }

          REFERENCE_TIME RefClock = 0;
          m_pTsReaderFilter->GetMediaPosition(&RefClock) ;
          clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
          fTime = ((double)cRefTime.m_time/10000000.0) - clock ;
          
          //Calculate a mean 'fTime' value using 'raw' fTime data
          CalcAverageFtime(fTime);
          if (timeNow < (m_pTsReaderFilter->m_lastPauseRun + (30*1000)))
          {
            //do this for 30s after start of play, a flush or pause
            m_fAFTMeanRef = m_fAFTMean;
          }
          
          //Add compensation time for external downstream audio delay
          //to stop samples becoming 'late' (note: this does NOT change the actual sample timestamps)
          fTime -= m_fAFTMeanRef;  //remove the 'mean' offset
          fTime += ((AUDIO_STALL_POINT/2.0) + 0.2); //re-centre the timing                 

          //Discard late samples at start of play,
          //and samples outside a sensible timing window during play 
          //(helps with signal corruption recovery)
          cRefTime -= m_pTsReaderFilter->m_ClockOnStart.m_time;

          if (fTime < -2.0)
          {                          
            if ((m_dRateSeeking == 1.0) && (m_pTsReaderFilter->State() == State_Running) && (clock > 8.0) && !demux.m_bFlushDelegated)
            { 
              //Very late - request internal flush and re-sync to stream
              demux.DelegatedFlush(false, false);
              LogDebug("audPin : Audio to render very late, flushing") ;
            }
          }
          
          if ((cRefTime.m_time >= PRESENT_DELAY) && 
              (fTime > ((cRefTime.m_time >= FS_TIM_LIM) ? -0.3 : -0.5)) && (fTime < 2.5))
          {
            if ((fTime > stallPoint) && (m_sampleCount > 2))
            {
              //Too early - stall to avoid over-filling of audio decode/renderer buffers,
              //but don't enable at start of play to make sure graph starts properly
              m_FillBuffSleepTime = 10;
              buffer = NULL;
              earlyStall = true;
              continue;
            }           
          }
          else //Don't drop samples normally - it upsets the rate matching in the audio renderer
          {
            // Sample is too late.
            m_bPresentSample = false ;
          }
          cRefTime += m_pTsReaderFilter->m_ClockOnStart.m_time;         
        }

        if (m_bPresentSample && (m_dRateSeeking == 1.0) && (buffer->Length() > 0))
        {
          //do we need to set the discontinuity flag?
          if (m_bDiscontinuity)
          {
            //ifso, set it
            pSample->SetDiscontinuity(TRUE);
            
            LogDebug("audPin: Set discontinuity L:%d B:%d fTime:%03.3f SampCnt:%d", m_bDiscontinuity, buffer->GetDiscontinuity(), (float)fTime, m_sampleCount);
            m_bDiscontinuity=FALSE;
          }

          if (m_bAddPMT && !m_pTsReaderFilter->m_bDisableAddPMT && !m_bPinNoAddPMT)
          {
            //Add MediaType info to sample
            CMediaType mt; 
            int audioIndex = 0;
            demux.GetAudioStream(audioIndex);
            demux.GetAudioStreamType(audioIndex, mt, m_iPosition);
            pSample->SetMediaType(&mt); 
            SetMediaType(&mt);               
            WAVEFORMATEX* wfe = (WAVEFORMATEX*)mt.Format();         
            LogDebug("audPin: Add pmt, fTime:%03.3f SampCnt:%d, Ch:%d, Sr:%d", (float)fTime, m_sampleCount, wfe->nChannels, wfe->nSamplesPerSec);
            m_bAddPMT = false; //Only add once
          }   

          if (HasTimestamp)
          {
            //now we have the final timestamp, set timestamp in sample
            REFERENCE_TIME refTime=(REFERENCE_TIME)cRefTime;
            refTime = (REFERENCE_TIME)((double)refTime/m_dRateSeeking);
            refTime += m_pTsReaderFilter->m_regAudioDelay; //add offset (to produce delay relative to video)

            pSample->SetSyncPoint(TRUE);
            pSample->SetTime(&refTime,&refTime);
            
            if (m_pTsReaderFilter->m_ShowBufferAudio || fTime < 0.02 || (m_sampleCount < 3))
            {
              int cntA, cntV;
              CRefTime firstAudio, lastAudio;
              CRefTime firstVideo, lastVideo, zeroVideo;
              cntA = demux.GetAudioBufferPts(firstAudio, lastAudio); 
              cntV = demux.GetVideoBufferPts(firstVideo, lastVideo, zeroVideo);
              
              LogDebug("Aud/Ref : %03.3f, Compensated = %03.3f ( %0.3f A/V buffers=%02d/%02d), Clk : %f, SampCnt %d, Sleep %d ms, stallPt %03.3f", (float)RefTime.Millisecs()/1000.0f, (float)cRefTime.Millisecs()/1000.0f, fTime,cntA,cntV, clock, m_sampleCount, m_FillBuffSleepTime, (float)stallPoint);
            }
            if (m_pTsReaderFilter->m_ShowBufferAudio) m_pTsReaderFilter->m_ShowBufferAudio--;
            // CalcAverageFtime(fTime);
              
            if (((float)cRefTime.Millisecs()/1000.0f) > AUDIO_READY_POINT)
            {
              m_pTsReaderFilter->m_audioReady = true;
            }
          }
          else
          {
            //buffer has no timestamp
            pSample->SetTime(NULL,NULL);
            pSample->SetSyncPoint(FALSE);
          }

          //copy buffer in sample
          BYTE* pSampleBuffer;
          pSample->SetActualDataLength(buffer->Length());
          pSample->GetPointer(&pSampleBuffer);
          memcpy(pSampleBuffer,buffer->Data(),buffer->Length());
          //delete the buffer and return
          delete buffer;
          demux.EraseAudioBuff();
        }
        else
        { // Buffer was not displayed because it was out of date, search for next.
          delete buffer;
          demux.EraseAudioBuff();
          buffer=NULL ;
          m_FillBuffSleepTime = (m_dRateSeeking == 1.0) ? 1 : 2;
          m_bDiscontinuity = TRUE; //Next good sample will be discontinuous
        }
      }      
      earlyStall = false;
    } while (buffer==NULL);

    m_bInFillBuffer = false;
    return NOERROR;
  }

  // Should we return something else than NOERROR when hitting an exception?
  catch(int e)
  {
    LogDebug("audPin:fillbuffer exception %d", e);
  }
  catch(...)
  {
    LogDebug("audPin:fillbuffer exception ...");
  }
  m_FillBuffSleepTime = 5;
  CreateEmptySample(pSample);
  m_bDiscontinuity = TRUE; //Next good sample will be discontinuous  
  m_bInFillBuffer = false; 
  return NOERROR;
}
Example #5
0
HRESULT CVideoPin::FillBuffer(IMediaSample *pSample)
{
  try
  {
    CDeMultiplexer& demux = m_pTsReaderFilter->GetDemultiplexer();
    CBuffer* buffer = NULL;    
    bool earlyStall = false;

    //get file-duration and set m_rtDuration
    GetDuration(NULL);

    do
    {
      //Check if we need to wait for a while
      DWORD timeNow = GET_TIME_NOW();
      while (timeNow < (m_LastFillBuffTime + m_FillBuffSleepTime))
      {      
        Sleep(1);
        timeNow = GET_TIME_NOW();
      }
      m_LastFillBuffTime = timeNow;

      //did we reach the end of the file
      if (demux.EndOfFile())
      {
        int ACnt, VCnt;
        demux.GetBufferCounts(&ACnt, &VCnt);
        if (ACnt <= 0 && VCnt <= 0) //have we used all the data ?
        {
          LogDebug("vidPin:set eof");
          m_FillBuffSleepTime = 5;
          CreateEmptySample(pSample);
          m_bInFillBuffer = false;
          return S_FALSE; //S_FALSE will notify the graph that end of file has been reached
        }
      }

      //if the filter is currently seeking to a new position
      //or this pin is currently seeking to a new position then
      //we dont try to read any packets, but simply return...
      if (m_pTsReaderFilter->IsSeeking() || m_pTsReaderFilter->IsStopping() || demux.m_bFlushRunning || !m_pTsReaderFilter->m_bStreamCompensated)
      {
        m_FillBuffSleepTime = 5;
        CreateEmptySample(pSample);
        m_bInFillBuffer = false;
        if (demux.m_bFlushRunning || !m_pTsReaderFilter->m_bStreamCompensated)
        {
          //Force discon on next good sample
          m_sampleCount = 0;
          m_bDiscontinuity=true;
        }
        return NOERROR;
      }
      else
      {
        m_FillBuffSleepTime = 1;
        m_bInFillBuffer = true;
      }     
                  
      // Get next video buffer from demultiplexer
      buffer=demux.GetVideo(earlyStall);

      if (buffer == NULL)
      {
        m_FillBuffSleepTime = 5;
      }
      else if (buffer->Length() > m_bufferSize)
      {
        //discard buffer
        delete buffer;
        demux.EraseVideoBuff();
        m_bDiscontinuity = TRUE; //Next good sample will be discontinuous
        buffer = NULL;
        m_FillBuffSleepTime = 1;
        LogDebug("vidPin : Error - buffer too large for sample") ;        
      }
      else
      {
        m_bPresentSample = true ;
        
        CRefTime RefTime, cRefTime;
        double fTime = 0.0;
        double clock = 0.0;
        double stallPoint = VIDEO_STALL_POINT;
        //check if it has a timestamp
        bool HasTimestamp=buffer->MediaTime(RefTime);
        if (HasTimestamp)
        {
          bool ForcePresent = false;
          CRefTime compTemp = m_pTsReaderFilter->GetCompensation();
          if (m_pTsReaderFilter->m_bFastSyncFFDShow && (compTemp != m_llLastComp))
          {
            m_bDiscontinuity = true;
          }
          m_llLastComp = compTemp;
          cRefTime = RefTime;
          cRefTime -= m_rtStart;
          //adjust the timestamp with the compensation
          cRefTime -= compTemp;
          cRefTime -= m_pTsReaderFilter->m_ClockOnStart.m_time;
          
          // 'fast start' timestamp modification, during first (AddVideoComp + 1 sec) of play
          double fsAdjLimit = (1.0 * (double)m_pTsReaderFilter->AddVideoComp.m_time) + (double)FS_ADDON_LIM; //(1 * vid comp) + 1 second
          if (m_pTsReaderFilter->m_EnableSlowMotionOnZapping && ((double)cRefTime.m_time < fsAdjLimit) )
          {
            //float startCref = (float)cRefTime.m_time/(1000*10000); //used in LogDebug below only
            //Assume desired timestamp span is zero to fsAdjLimit, actual span is AddVideoComp to fsAdjLimit
            double offsetRatio = fsAdjLimit/(double)FS_ADDON_LIM; // == fsAdjLimit/(fsAdjLimit - (double)m_pTsReaderFilter->AddVideoComp.m_time);
            double currOffset = fsAdjLimit - (double)cRefTime.m_time;
            double newOffset = currOffset * offsetRatio;
            cRefTime = (fsAdjLimit > newOffset) ? (REFERENCE_TIME)(fsAdjLimit - newOffset) : 0;  //Don't allow negative cRefTime
            ForcePresent = true;
            //LogDebug("VFS cOfs %03.3f, nOfs %03.3f, cRefTimeS %03.3f, cRefTimeN %03.3f", (float)currOffset/(1000*10000), (float)newOffset/(1000*10000), startCref, (float)cRefTime.m_time/(1000*10000));         
            if (m_pTsReaderFilter->m_bFastSyncFFDShow)
            {
              m_delayedDiscont = 2; //Force I-frame timestamp updates for FFDShow
            }
          }          

          REFERENCE_TIME RefClock = 0;
          m_pTsReaderFilter->GetMediaPosition(&RefClock) ;
          clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
          fTime = ((double)(cRefTime.m_time + m_pTsReaderFilter->m_ClockOnStart.m_time)/10000000.0) - clock ;
                                                                      
          if (m_dRateSeeking == 1.0)
          {
            if ((fTime < -2.0) && (m_pTsReaderFilter->State() == State_Running) && (clock > 8.0) && !ForcePresent && !demux.m_bFlushDelegated)
            {                            
              //Very late - request internal flush and re-sync to stream
              demux.DelegatedFlush(false, false);
              LogDebug("vidPin : Video to render very late, flushing") ;
            }

            //Discard late samples at start of play,
            //and samples outside a sensible timing window during play 
            //(helps with signal corruption recovery)
            if ((fTime > (ForcePresent ? -1.0 : -0.3)) && (fTime < (demux.m_dVidPTSJumpLimit + 1.0))   )
            {
              if ((fTime > stallPoint) && (m_sampleCount > 10))
              {
                //Too early - stall for a while to avoid over-filling of video pipeline buffers,
                //but don't enable at start of play to make sure graph starts properly
                m_FillBuffSleepTime = 10;
                buffer = NULL;
                earlyStall = true;
                continue;
              }
            }
            else
            {              
              // Sample is too late.
              m_bPresentSample = false ;
            }
          }
          else if ((fTime < -1.0) || (fTime > 3.0)) //Fast-forward limits
          {
            // Sample is too late.
            m_bPresentSample = false ;
          }
          cRefTime += m_pTsReaderFilter->m_ClockOnStart.m_time;
        }

        if (m_bPresentSample && (buffer->Length() > 0))
        {
          
          //do we need to set the discontinuity flag?
          if (m_bDiscontinuity || buffer->GetDiscontinuity())
          {
            if ((m_sampleCount == 0) && m_bAddPMT && !m_pTsReaderFilter->m_bDisableAddPMT && !m_bPinNoAddPMT)
            {
              //Add MediaType info to first sample after OnThreadStartPlay()
              CMediaType mt; 
              if (demux.GetVideoStreamType(mt))
              {
                pSample->SetMediaType(&mt); 
                SetMediaType(&mt);               
                LogDebug("vidPin: Add pmt and set discontinuity L:%d B:%d fTime:%03.3f SampCnt:%d", m_bDiscontinuity, buffer->GetDiscontinuity(), (float)fTime, m_sampleCount);
              }
              else
              {
                LogDebug("vidPin: Add pmt failed - set discontinuity L:%d B:%d fTime:%03.3f SampCnt:%d", m_bDiscontinuity, buffer->GetDiscontinuity(), (float)fTime, m_sampleCount);
              }
              m_bAddPMT = false; //Only add once each time
            }   
            else
            {        
              LogDebug("vidPin: Set discontinuity L:%d B:%d fTime:%03.3f SampCnt:%d", m_bDiscontinuity, buffer->GetDiscontinuity(), (float)fTime, m_sampleCount);
            }

            pSample->SetDiscontinuity(TRUE);           
            m_bDiscontinuity=FALSE;
          }

          //LogDebug("vidPin: video buffer type = %d", buffer->GetVideoServiceType());

          if (HasTimestamp)
          {
            //now we have the final timestamp, set timestamp in sample
            REFERENCE_TIME refTime=(REFERENCE_TIME)cRefTime;
            pSample->SetSyncPoint(TRUE);
            
            bool stsDiscon = TimestampDisconChecker(refTime); //Update with current timestamp

            refTime = (REFERENCE_TIME)((double)refTime/m_dRateSeeking);
            pSample->SetTime(&refTime,&refTime);
            if (m_pTsReaderFilter->m_bFastSyncFFDShow && (m_dRateSeeking == 1.0))
            {
              if (stsDiscon || (pSample->IsDiscontinuity()==S_OK))
              {
                pSample->SetDiscontinuity(TRUE);
                m_delayedDiscont = 2;
              }

              if ((m_delayedDiscont > 0) && (buffer->GetFrameType() == 'I'))
              {
                if ((buffer->GetVideoServiceType() == SERVICE_TYPE_VIDEO_MPEG1 ||
                     buffer->GetVideoServiceType() == SERVICE_TYPE_VIDEO_MPEG2))
                {
                   //Use delayed discontinuity
                   pSample->SetDiscontinuity(TRUE);
                   m_delayedDiscont--;
                   LogDebug("vidPin:set I-frame discontinuity, count %d", m_delayedDiscont);
                }
                else
                {
                   m_delayedDiscont = 0;
                }      
              }                             
            }

            if (m_pTsReaderFilter->m_ShowBufferVideo || ((fTime < 0.02) && (m_dRateSeeking == 1.0)) || (m_sampleCount < 3))
            {
              int cntA, cntV;
              CRefTime firstAudio, lastAudio;
              CRefTime firstVideo, lastVideo, zeroVideo;
              cntA = demux.GetAudioBufferPts(firstAudio, lastAudio); 
              cntV = demux.GetVideoBufferPts(firstVideo, lastVideo, zeroVideo);

              LogDebug("Vid/Ref : %03.3f, %c-frame(%02d), Compensated = %03.3f ( %0.3f A/V buffers=%02d/%02d), Clk : %f, SampCnt %d, stallPt %03.3f", (float)RefTime.Millisecs()/1000.0f,buffer->GetFrameType(),buffer->GetFrameCount(), (float)cRefTime.Millisecs()/1000.0f, fTime, cntA,cntV,clock, m_sampleCount, (float)stallPoint);              
            }
            
            if (m_pTsReaderFilter->m_ShowBufferVideo) m_pTsReaderFilter->m_ShowBufferVideo--;
          }
          else
          {
            //buffer has no timestamp
            pSample->SetTime(NULL,NULL);
            pSample->SetSyncPoint(FALSE);
          }
          
          // copy buffer into the sample
          BYTE* pSampleBuffer;
          pSample->SetActualDataLength(buffer->Length());
          pSample->GetPointer(&pSampleBuffer);
          memcpy(pSampleBuffer,buffer->Data(),buffer->Length());
                    
          // delete the buffer
          delete buffer;
          demux.EraseVideoBuff();
          //m_sampleCount++ ;         
        }
        else
        { // Buffer was not displayed because it was out of date, search for next.
          delete buffer;
          demux.EraseVideoBuff();
          m_bDiscontinuity = TRUE; //Next good sample will be discontinuous
          buffer = NULL;
          m_FillBuffSleepTime = 1;
        }
      }      
      earlyStall = false;
    } while (buffer == NULL);

    m_bInFillBuffer = false;
    return NOERROR;
  }

  catch(...)
  {
    LogDebug("vidPin:fillbuffer exception");
  }
  m_FillBuffSleepTime = 5;
  CreateEmptySample(pSample);
  m_bDiscontinuity = TRUE; //Next good sample will be discontinuous
  m_bInFillBuffer = false;  
  return NOERROR;
}