Ejemplo n.º 1
0
REFERENCE_TIME RtspSourcePin::SynchronizeTimestamp(const MediaPacketSample& mediaSample)
{
    auto SyncWithMediaSample = [this](const MediaPacketSample& mediaSample)
    {
        CRefTime streamTime;
        m_pFilter->StreamTime(streamTime);
        uint32_t latencyMSecs = static_cast<RtspSourceFilter*>(m_pFilter)->_latencyMSecs;
        _streamTimeBaseline = streamTime.GetUnits() + latencyMSecs * 10000i64;
        _rtpPresentationTimeBaseline = mediaSample.timestamp();
    };

    if (_firstSample)
    {
        SyncWithMediaSample(mediaSample);

        _firstSample = false;
        // If we're lucky the first sample is also synced using RTCP
        _rtcpSynced = mediaSample.isRtcpSynced();
    }
    // First sample wasn't RTCP sync'ed, try the next time
    else if (!_rtcpSynced)
    {
        _rtcpSynced = mediaSample.isRtcpSynced();
        if (_rtcpSynced)
            SyncWithMediaSample(mediaSample);
    }

    return mediaSample.timestamp() - _rtpPresentationTimeBaseline + _streamTimeBaseline;
}
Ejemplo n.º 2
0
//
// Run
//
// Overriden to open the dump file
//
STDMETHODIMP EMReadFrameFilter::Run(REFERENCE_TIME tStart)
{
	IReferenceClock *pClock = m_pClock;
    CAutoLock cObjectLock(m_pLock);
	CRefTime agnusStreamTimeObject;
	StreamTime(agnusStreamTimeObject);
	long millisekunder = agnusStreamTimeObject.Millisecs();
    return CBaseFilter::Run(tStart);
}
Ejemplo n.º 3
0
void TsStreamFileSource::seekToTimeAbsolute(CRefTime& seekTime, CTsDuration& duration) 
{
  	FileReader* reader = (FileReader*)fFid;
    double startTime = seekTime.Millisecs();
    startTime /= 1000.0f;
    LogDebug("StreamingServer::  Seek-> %f/%f", startTime, duration.Duration().Millisecs()/1000.0f);
    CTsFileSeek seek(duration);
    seek.SetFileReader(reader);
    
    for(int i(0) ; i < 4 ; i++)
    {
      bool eof = seek.Seek(seekTime);
      if (eof)
      {
        REFERENCE_TIME rollBackTime = reader->GetTimeshift() ? 5000000 : 30000000;  // 0.5s/3s 
        //reached end-of-file, try to seek to an earlier position
        if ((seekTime.m_time - rollBackTime) > 0)
        {
          seekTime.m_time -= rollBackTime;
        }
        else
        {
          break; //very short file....
        }
      }
      else
      {
        break; //we've succeeded
      }
    }
   
  	m_buffer.Clear();
}
Ejemplo n.º 4
0
//
// SeekDone
//
STDMETHODIMP CDVBSub::SeekDone( CRefTime& rtSeek )
{
  // Notify reset observer (clears all cached subtitles on client side)
  if( m_pResetObserver )
  {
    (*m_pResetObserver)();
  }

  // milliseconds to PCR (90Khz)
  m_CurrentSeekPosition = rtSeek.Millisecs() * 90;
  LogDebugPTS( "SeekDone", m_CurrentSeekPosition );
  return S_OK;
}
HRESULT CScreenCaptureSourcePin::FillBuffer(IMediaSample *pSample)
{
	FTL::FTLThreadWaitType waitType = _GetWaitType(INFINITE);
	switch (waitType)
	{
	case FTL::ftwtStop:
		return S_FALSE;	//quit
	case FTL::ftwtError:
		return E_UNEXPECTED;
	//case FTL::ftwtContinue:
	//case FTL::ftwtTimeOut:
	default:
		//just continue
		break;
	}

#if 0
	//FUNCTION_BLOCK_TRACE(1);
	CheckPointer(pSample, E_POINTER);
	ASSERT(m_mt.formattype == FORMAT_VideoInfo);

	m_nFrameNumber++;

	//make the samples scheduling
	HRESULT hr = S_OK;
	REFERENCE_TIME	rtLatency = 0;
	if (FAILED(GetLatency(&rtLatency)))
	{
		rtLatency = UNITS / DEFAULT_FPS ;
	}
	REFERENCE_TIME rtStart, rtStop;
	BOOL bShouldDeliver = FALSE;
	do 
	{
		if (m_dwAdviseToken == 0)
		{
			DX_VERIFY(m_pClock->GetTime(&m_rtClockStart));
			//fixed frame rate, so can use AdvisePeriodic
			DX_VERIFY(m_pClock->AdvisePeriodic(m_rtClockStart + rtLatency, 
				rtLatency, (HSEMAPHORE)m_hSemaphore, &m_dwAdviseToken));
		}
		else
		{
			DWORD dwResult = WaitForSingleObject(m_hSemaphore, INFINITE);
		}

		bShouldDeliver = TRUE;
		rtStart = m_rtStart;
		rtStop = m_rtStart + 1;
		DX_VERIFY(pSample->SetTime(&rtStart, &rtStop));
		FTLASSERT(m_pScreenCaptureImpl);
		if (m_pScreenCaptureImpl)
		{
			LPBYTE pBuffer = NULL;
			DX_VERIFY(pSample->GetPointer(&pBuffer));
			VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)m_mt.pbFormat;
			//int nSize = min(pVih->bmiHeader.biSizeImage, (DWORD)cbData);
			HBITMAP hDIB = m_pScreenCaptureImpl->CopyScreenToBitmap(&m_rcCapture, pBuffer, (BITMAPINFO *) &(pVih->bmiHeader));
			DeleteObject(hDIB);
		}

		DX_VERIFY(m_pClock->GetTime(&m_rtClockStop));
		DX_VERIFY(pSample->GetTime(&rtStart, &rtStop));

		if (rtLatency > 0 && rtLatency * 3 < m_rtClockStop - m_rtClockStart)
		{
			//Why?
			m_rtClockStop = m_rtClockStart + rtLatency;
		}
		rtStop = rtStart + (m_rtClockStop - m_rtClockStart);
		m_rtStart = rtStop;
		//lock (m_csPinLock)
		{
			rtStart -= m_rtStreamOffset;
			rtStop -= m_rtStreamOffset;
		}

		DX_VERIFY(pSample->SetMediaTime(&m_nFrameNumber, &m_nFrameNumber));
		DX_VERIFY(pSample->SetTime(&rtStart, &rtStop));
		m_rtClockStart = m_rtClockStop;

		bShouldDeliver = ((rtStart >= 0) && (rtStop >= 0));
		if (bShouldDeliver)
		{
			//lock (m_csPinLock)
			if (m_rtStartAt != -1)
			{
				if (m_rtStartAt > rtStart)
				{
					bShouldDeliver = FALSE;
				}
				else
				{
					if (m_dwStartCookie != 0 && !m_bStartNotified)
					{
						m_bStartNotified = TRUE;
						DX_VERIFY(m_pFilter->NotifyEvent(EC_STREAM_CONTROL_STARTED, (LONG_PTR)this, m_dwStartCookie));
						if (FAILED(hr)) 
						{
							return hr;
						}
					}
				}
			}
			if (!bShouldDeliver)
			{
				//Why?
				continue;
			}
			if (m_rtStopAt != -1)
			{
				if (m_rtStopAt < rtStart)
				{
					if (!m_bStopNotified)
					{
						m_bStopNotified = TRUE;
						if (m_dwStopCookie != 0)
						{
							DX_VERIFY(m_pFilter->NotifyEvent(EC_STREAM_CONTROL_STOPPED, (LONG_PTR)this, m_dwStopCookie));
							if (FAILED(hr))
							{
								return hr;
							}
						}
						bShouldDeliver = m_bShouldFlush;
					}
					else
					{
						bShouldDeliver = FALSE;
					}
					// EOS -- EndOfStream
					if (!bShouldDeliver)
					{
						return S_FALSE;
					}
				}
			}
		}

	} while (!bShouldDeliver);
	return hr;

	//DX_VERIFY(m_pFilter->StreamTime(rtStart));

	//LONGLONG llStartTime = m_ElapseCounter.GetElapseTime();
	//REFERENCE_TIME rtStreamTime = m_rtSampleTime;// llStartTime / 100; // rfStreamTime.GetUnits();
	
//loop:   
	//REFERENCE_TIME rtStart = rtStreamTime; //m_iFrameNumber * m_rtFrameLength;    
	//REFERENCE_TIME rtStop  = rtStart + m_rtFrameLength;
	
	//if (rtStreamTime > rtStop)
	//{
	//	OutputDebugString(L"lost capture \r\n");
	//	++m_iFrameNumber;
	//	goto loop;
	//}
	//while (rtStreamTime < rtStart)
	//{
	//	m_pFilter->StreamTime(rfStreamTime);
	//	rtStreamTime = rfStreamTime.GetUnits();
	//	// REFERENCE_TIME rtWaitTime = rtStart - rtStreamTime;
	//	// ::WaitForSingleObject(m_hWaitEvent, rtWaitTime/10000);
	//}

	BYTE *pData = NULL;
	long cbData = 0;

	{
		DX_VERIFY(pSample->GetPointer(&pData));
		cbData = pSample->GetSize();
		//if (m_bZeroMemory)
		//{
		//	ZeroMemory(pData, cbData);
		//}
		{
			CAutoLock cAutoLockShared(&m_cSharedState);

			ASSERT(m_mt.formattype == FORMAT_VideoInfo);
			VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)m_mt.pbFormat;

			int nSize = min(pVih->bmiHeader.biSizeImage, (DWORD)cbData);

			//*
			HBITMAP hDib = m_pScreenCaptureImpl->CopyScreenToBitmap(&m_rcCapture, pData, (BITMAPINFO *) &(pVih->bmiHeader));
			if (hDib)
			{
				DeleteObject(hDib);
			}
			//CRefTime rtStart = rfStreamTime; //m_rtSampleTime;
			//m_rtSampleTime +=   (LONG) m_iRepeatTime;
			CRefTime rtStop;// = m_ElapseCounter.GetElapseTime() / 100;
			
			DX_VERIFY(m_pFilter->StreamTime(rtStop));

			//m_rtSampleTime = rtStop;

			//ATLTRACE(TEXT("CScreenCaptureSourcePin::FillBuffer , start=%lld(%f ms), stop=%lld(%f ms)\n"),
			//	rtStart, float(rtStart) / 10000,  rtStop, float(rtStop) / 10000);

			DX_VERIFY(pSample->SetTime((REFERENCE_TIME *)&rtStart, (REFERENCE_TIME *)&rtStop));

			//每一帧都是一个同步点
			DX_VERIFY(pSample->SetSyncPoint(TRUE));


			BOOL bWait = FALSE;
			DWORD dwWillWaitTime = 0;
			//LONGLONG llElapseTime = rtStop.GetUnits() - rtStart.GetUnits();
			//	//m_ElapseCounter.GetElapseTime() -  llStartTime;
			//if ( llElapseTime < MILLISECONDS_TO_100NS_UNITS(m_iRepeatTime))
			//{
			//	bWait = TRUE;
			//	dwWillWaitTime = (MILLISECONDS_TO_100NS_UNITS(m_iRepeatTime) - llElapseTime) / 10000;
			//	if (dwWillWaitTime > 1)
			//	{
			//		//WaitForSingleObject(m_hStopEvent, dwWillWaitTime );
			//	}
			//}

		}
	}

	//FTLTRACE(TEXT("llElapseTime = %lld, bWait=%d, dwWillWaitTime=%d\n"), llElapseTime, bWait, dwWillWaitTime);
#endif

	CheckPointer(pSample, E_POINTER);

	HRESULT hr = E_FAIL;

	CRefTime rfStreamTime;
	{
		//CAutoLock cObjectLock(m_pLock);
		DX_VERIFY(m_pFilter->StreamTime(rfStreamTime));
	}
	REFERENCE_TIME rtStreamTime = rfStreamTime.GetUnits();
	if (m_rfMaxRecordTime != 0 && rtStreamTime > m_rfMaxRecordTime)
	{
		//max time over

		//if there is preview window, just return S_FALSE is OK
		//if there is NOT preview window, can not stop graph automatic
		m_pFilter->NotifyEvent(TIME_OVER, static_cast<LONG_PTR>(m_rfMaxRecordTime / (UNITS / MILLISECONDS)), 0);
		return S_FALSE;
	}
	REFERENCE_TIME rtStart = 0; 
	REFERENCE_TIME rtStop = 0;

	do 
	{
		rtStart = m_nFrameNumber * m_nAvgTimePerFrame;
		rtStop = rtStart + m_nAvgTimePerFrame;
		if( rtStreamTime > rtStop)
		{
			OutputDebugString(L"lost capture \r\n");
			++m_nFrameNumber;
		}
	} while (rtStreamTime > rtStop);

	while (rtStreamTime < rtStart)
	{
		m_pFilter->StreamTime(rfStreamTime);
		rtStreamTime = rfStreamTime.GetUnits();
		// REFERENCE_TIME rtWaitTime = rtStart - rtStreamTime;
		// ::WaitForSingleObject(m_hWaitEvent, rtWaitTime/10000);
	}

	BYTE *pData = NULL;
	long cbData = 0;
	CAutoLock cAutoLockShared(&m_cSharedState);
	DX_VERIFY(pSample->GetPointer(&pData));
	cbData = pSample->GetSize();

	ASSERT(m_mt.formattype == FORMAT_VideoInfo);
	VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)m_mt.pbFormat;


	int nSize = min(pVih->bmiHeader.biSizeImage, (DWORD)cbData);
	HBITMAP hDib = m_pScreenCaptureImpl->CopyScreenToBitmap(&m_rcCapture, pData, (BITMAPINFO *) &(pVih->bmiHeader));    

	if (hDib)
	{
		if (m_bFirstFrame)
		{
			m_bFirstFrame = FALSE;
			DX_VERIFY(m_pFilter->NotifyEvent(FIRST_FRAME, (LONG_PTR)(hDib), NULL));
		}
		else
		{
			DeleteObject(hDib);
		}
	}  

	//REFERENCE_TIME rtTemp;
	//IReferenceClock *pClock;
	//m_pFilter->GetSyncSource(&pClock);
	//pClock->GetTime(&rtTemp);
	//pClock->Release();    

	//ST_FRAME_TIME *pTmp = new ST_FRAME_TIME();
	//pTmp->llStartTime = rtStart;
	//pTmp->llStopTime = rtStop;
	//pTmp->nFrameIndex = m_iFrameNumber;    
	//m_pFilter->NotifyEvent(FRAME_TIME, (LONG_PTR)pTmp, NULL);

	DX_VERIFY(pSample->SetTime(&rtStart, &rtStop));
	m_nFrameNumber++;

	DX_VERIFY(pSample->SetSyncPoint(TRUE));

	return S_OK;

	return hr;
}
Ejemplo n.º 6
0
void CTsReaderFilter::SeekPreStart(CRefTime& rtAbsSeek)
{
  bool doSeek = true;
  CTsDuration tsduration=GetDuration();

  SetMediaPosition(rtAbsSeek.m_time) ;

  //Note that the seek timestamp (m_rtStart) is done in the range
  //from earliest - latest from GetAvailable()
  //We however would like the seek timestamp to be in the range 0-fileduration
  CRefTime rtSeek = rtAbsSeek;
  float seekTime = (float)rtSeek.Millisecs();
  seekTime /= 1000.0f;

  //get the earliest timestamp available in the file
  float earliesTimeStamp = 0;
  earliesTimeStamp = tsduration.StartPcr().ToClock() - tsduration.FirstStartPcr().ToClock();

  if (earliesTimeStamp < 0) earliesTimeStamp = 0;

  //correct the seek time
  seekTime -= earliesTimeStamp;
  if (seekTime < 0) seekTime = 0;

  seekTime *= 1000.0f;
  rtSeek = CRefTime((LONG)seekTime);
  // Now rtSeek contains the "relative" position from "0 to buffer/file duration"

  // Should we really seek ?
  
  // Because all skips generated after "Stop()" cause a lot of problem
  // This remove all these stupid skips. 
  if(m_State == State_Stopped)
  {   
    if ((m_bStoppedForUnexpectedSeek || (m_absSeekTime==rtAbsSeek)) && !m_bForceSeekOnStop && !m_bForceSeekAfterRateChange)
    {
//      LogDebug("CTsReaderFilter::--SeekStart() Stopped state -- No new seek %f", 
//      (float)rtSeek.Millisecs()/1000.0f);
      m_bStoppedForUnexpectedSeek=false ;
      m_seekTime = rtSeek ;
      m_absSeekTime = rtAbsSeek ;
      return ;
    }
  }

  if (((m_absSeekTime==rtAbsSeek) && !m_bStreamCompensated && !m_bForceSeekAfterRateChange) || (m_demultiplexer.IsMediaChanging() && !m_bOnZap && !m_bForceSeekOnStop && !m_bForceSeekAfterRateChange))  
  {
    doSeek = false;
    LogDebug("CTsReaderFilter::--SeekStart()-- No new seek %f ( Abs %f / %f ) - Stream compensated: %d, OnZap: %d, Force %d, Media changing: %d", 
		(float)rtSeek.Millisecs()/1000.0f, (float)rtAbsSeek.Millisecs()/1000.0f, (float)m_duration.EndPcr().ToClock(),m_bStreamCompensated,m_bOnZap,m_bForceSeekOnStop, m_demultiplexer.IsMediaChanging());
//	  m_bStreamCompensated=false ;
    m_bForceSeekOnStop = false ;
  }
  else
  {
    LogDebug("CTsReaderFilter::--SeekStart()-- LiveTv : %d, TimeShifting: %d %3.3f ( Abs %f / %f ), OnZap: %d, Force %d, ForceRC %d, Media changing %d",
		m_bLiveTv,m_bTimeShifting,(float)rtSeek.Millisecs()/1000.0,(float)rtAbsSeek.Millisecs()/1000.0f, (float)m_duration.EndPcr().ToClock(),m_bOnZap,m_bForceSeekOnStop,m_bForceSeekAfterRateChange,m_demultiplexer.IsMediaChanging());

    m_bForceSeekOnStop = false ;
    
    if (m_bForceSeekAfterRateChange)
    {
      m_bSeekAfterRcDone = true;
      m_bForceSeekAfterRateChange = false ; 
    }

    if (m_bTimeShifting)
    {
      LONG duration = m_duration.Duration().Millisecs() ;
      LONG seekTime = rtSeek.Millisecs() ;
      if (seekTime + 200 > duration) // End of timeshift buffer requested.
      {
        if (m_bLiveTv && !m_bAnalog  && (m_fileDuration != NULL)) doSeek=false ;       // Live & not analog & not RTSP do not seek
        m_bLiveTv=true ;
      }
      else
        m_bLiveTv=false ;

      LogDebug("Zap to File Seek : %d mS ( %f / %f ) LiveTv : %d, Seek : %d",GetTickCount()-m_lastPause, (float)seekTime/1000.0f, (float)duration/1000.0f, m_bLiveTv, doSeek);
    }

    m_seekTime=rtSeek ;
    m_absSeekTime = rtAbsSeek ;

    if (!doSeek && !m_bOnZap) return ;

//    m_demultiplexer.SetHoldAudio(true) ;
//    m_demultiplexer.SetHoldVideo(true) ;
 
    m_WaitForSeekToEof=1 ; // 

    m_demultiplexer.CallTeletextEventCallback(TELETEXT_EVENT_SEEK_START,TELETEXT_EVENTVALUE_NONE);
 
    // Stop threads ////

    if (GetAudioPin()->IsConnected())
    {
      //deliver a begin-flush to the codec filter so it stops asking for data
      GetAudioPin()->DeliverBeginFlush();

      //stop the thread
      GetAudioPin()->Stop();
    }

    if (GetVideoPin()->IsConnected())
    {
      //deliver a begin-flush to the codec filter so it stops asking for data
      GetVideoPin()->DeliverBeginFlush();

      //stop the thread
      GetVideoPin()->Stop();
    }

    m_bStreamCompensated=false ;
    m_demultiplexer.m_bAudioVideoReady=false ;

	  if (!m_bOnZap || !m_demultiplexer.IsNewPatReady() || m_bAnalog) // On zapping, new PAT has occured, we should not flush to avoid loosing data.
	  {                                                               //             new PAT has not occured, we should flush to avoid restart with old data.							
	    m_demultiplexer.FlushAudio() ;
	    m_demultiplexer.FlushVideo() ;
    }
    m_bOnZap=false ;
//    m_demultiplexer.SetHoldAudio(false) ;
//    m_demultiplexer.SetHoldVideo(false) ;

    //do the seek...
    if (doSeek && !m_demultiplexer.IsMediaChanging()&& !m_demultiplexer.IsAudioChanging()) Seek(rtSeek, true);

    //tell filter we're done with seeking
//    m_pTsReaderFilter->SeekDone(rtSeek);

    m_WaitForSeekToEof=0 ; // 

    if (m_fileDuration != NULL)
    {
      if (rtSeek >= m_duration.Duration())
      {
        rtSeek=m_duration.Duration();
      }
    }

    if (GetAudioPin()->IsConnected())
    {
      // deliver a end-flush to the codec filter so it will start asking for data again
      GetAudioPin()->DeliverEndFlush();

      // Update m_rtStart in case of has not seeked yet
      GetAudioPin()->SetStart(rtAbsSeek) ;

      // and restart the thread
      GetAudioPin()->Run();
    }

    if (GetVideoPin()->IsConnected())
    {
      //deliver a end-flush to the codec filter so it will start asking for data again
      GetVideoPin()->DeliverEndFlush();

      // Update m_rtStart in case of has not seeked yet
      GetVideoPin()->SetStart(rtAbsSeek) ;

      // and restart the thread
      GetVideoPin()->Run();
    }

    m_demultiplexer.CallTeletextEventCallback(TELETEXT_EVENT_SEEK_END,TELETEXT_EVENTVALUE_NONE);

    if (m_pDVBSubtitle)
    {
      m_pDVBSubtitle->SetFirstPcr(m_duration.FirstStartPcr().PcrReferenceBase);
      m_pDVBSubtitle->SeekDone(rtSeek);
    }
  }

  return ;
}
Ejemplo n.º 7
0
HRESULT RtspSourcePin::FillBuffer(IMediaSample* pSample)
{
    MediaPacketSample mediaSample;
    _mediaPacketQueue.pop(mediaSample);
    if (mediaSample.invalid())
    {
        DebugLog("%S pin: End of streaming!\n", m_pName);
        return S_FALSE;
    }

    BYTE* pData;
    HRESULT hr = pSample->GetPointer(&pData);
    if (FAILED(hr))
        return hr;
    long length = pSample->GetSize();

    if (_codecFourCC == DWORD('h264'))
    {
        // Append SPS and PPS to the first packet (they come out-band)
        if (_firstSample)
        {
            // Retrieve them from media type format buffer
            BYTE* decoderSpecific = (BYTE*)(((VIDEOINFOHEADER2*)_mediaType.Format()) + 1);
            ULONG decoderSpecificLength = _mediaType.FormatLength() - sizeof(VIDEOINFOHEADER2);
            memcpy_s(pData, length, decoderSpecific, decoderSpecificLength);
            pData += decoderSpecificLength;
            length -= decoderSpecificLength;
        }

        // Append 4-byte start code 00 00 00 01 in network byte order that precedes each NALU
        ((uint32_t*)pData)[0] = 0x01000000;
        pData += startCodesSize;
        length -= startCodesSize;
        // Finally copy media packet contens to IMediaSample
        memcpy_s(pData, length, mediaSample.data(), mediaSample.size());
        pSample->SetActualDataLength(mediaSample.size() + startCodesSize);
        pSample->SetSyncPoint(IsIdrFrame(mediaSample));
    }
    else if (_codecFourCC == DWORD('avc1'))
    {
        // Append 4-byte length field (network byte order) that precedes each NALU
        uint32_t lengthField = static_cast<uint32_t>(mediaSample.size());
        pData[0] = ((uint8_t*)&lengthField)[3];
        pData[1] = ((uint8_t*)&lengthField)[2];
        pData[2] = ((uint8_t*)&lengthField)[1];
        pData[3] = ((uint8_t*)&lengthField)[0];
        pData += lengthFieldSize;
        length -= lengthFieldSize;
        // Finally copy media packet contens to IMediaSample
        memcpy_s(pData, length, mediaSample.data(), mediaSample.size());
        pSample->SetActualDataLength(mediaSample.size() + lengthFieldSize);
        pSample->SetSyncPoint(IsIdrFrame(mediaSample));
    }
    else
    {
        // No appending - just copy raw data
        memcpy_s(pData, length, mediaSample.data(), mediaSample.size());
        pSample->SetActualDataLength(mediaSample.size());
        pSample->SetSyncPoint(FALSE);
    }

    REFERENCE_TIME ts = SynchronizeTimestamp(mediaSample);
    pSample->SetTime(&ts, NULL);

    // Calculate current play time (does not include offset from initial time seek)
    CRefTime streamTime;
    m_pFilter->StreamTime(streamTime);
    uint32_t latencyMSecs = static_cast<RtspSourceFilter*>(m_pFilter)->_latencyMSecs;
    _currentPlayTime = streamTime.GetUnits() - (_streamTimeBaseline - latencyMSecs * 10000i64);

    return S_OK;
}
Ejemplo n.º 8
0
//*********************************************************
// Seeks in the file to the specific timestamp
// refTime : timestamp. Should be 0 < timestamp < duration
//
// The method will make a guess where the timestamp is located in the file
// and do a PCR seek from there until it finds the correct timestamp
//
bool CTsFileSeek::Seek(CRefTime refTime)
{
  double fileDuration=(double)m_duration.Duration().Millisecs();
  double seekTimeStamp=(double)refTime.Millisecs();
  
  //sanity checks...
  if (seekTimeStamp < 0) seekTimeStamp=0;
  //if (seekTimeStamp > fileDuration) seekTimeStamp=fileDuration;

  //make a guess where should start looking in the file
  double percent=seekTimeStamp/fileDuration;
  __int64 filePos=(__int64)(m_reader->GetFileSize()*percent);

  filePos/=188;
  filePos*=188;

  seekTimeStamp /= 1000.0f; // convert to seconds.

  m_seekPid=m_duration.GetPid();
  LogDebug("FileSeek: seek to %f filepos:%x pid:%x", seekTimeStamp,(DWORD)filePos, m_seekPid);
  
  byte buffer[188*10];
  __int64 binaryMax=m_reader->GetFileSize();
  __int64 binaryMin=0;
  __int64 lastFilePos=0;
  int seekingIteration=0;
  __int64 firstFilePos=filePos;
  int noPCRIteration=0;
  bool noPCRloop = false;

  Reset() ;   // Reset "PacketSync"
  while (true)
  {
    //sanity checks
    if (filePos<=0)
    {
      //no need to seek for timestamp 0,
      //simply set the pointer at the beginning of the file
      m_reader->SetFilePointer(0,FILE_BEGIN);
      return false;
    }
    if (filePos+sizeof(buffer) > m_reader->GetFileSize())
    {
      //no need to seek when we want to seek to end of file
      //simply set the pointer at the end of the file
      m_reader->SetFilePointer(0,FILE_END);
      return false;
    }

    //set filepointer to filePos
    m_reader->SetFilePointer(filePos,FILE_BEGIN);

    //read buffer from file at position filePos
    DWORD dwBytesRead;
    if (!SUCCEEDED(m_reader->Read(buffer, sizeof(buffer),&dwBytesRead)))
    {
      LogDebug("FileSeek: read failed at filePos: %x - target time: %f, iterations: %d", (DWORD)filePos, seekTimeStamp, seekingIteration);
      return true;
    }
    if (dwBytesRead <= 0) //end-of-file
    {
      LogDebug("FileSeek: end-of-file at filePos: %x - target time: %f, iterations: %d", (DWORD)filePos, seekTimeStamp, seekingIteration);
      return true;
    }
    //process data
    m_pcrFound.Reset();
    OnRawData2(buffer,dwBytesRead);

    //did we find a pcr?
    if (m_pcrFound.IsValid)
    {
      //yes. pcr found
      double clockFound=m_pcrFound.ToClock();
      double diff = clockFound - seekTimeStamp;
      //LogDebug(" got %f at filepos %x diff %f ( %I64x, %I64x )", clockFound, (DWORD)filePos, diff, binaryMin, binaryMax);

      // Make sure that seeking position is at least the target one
      if (0 <= diff && diff <= SEEKING_ACCURACY)
      {
        LogDebug("FileSeek: stop seek: %f at %x - target: %f, diff: %f, iterations: %d",
          clockFound, (DWORD)filePos, seekTimeStamp, diff, seekingIteration);
        m_reader->SetFilePointer(filePos,FILE_BEGIN);
        return false;
      }

      noPCRIteration = 0;
      seekingIteration++;
      if( seekingIteration > MAX_SEEKING_ITERATIONS )
      {
        LogDebug("FileSeek: stop seek max iterations reached (%d): %f at %x - target: %f, diff: %f",
          MAX_SEEKING_ITERATIONS, clockFound, (DWORD)filePos, seekTimeStamp, diff);
          
        if (fabs(diff) < 2.0)
        {
          m_reader->SetFilePointer(filePos,FILE_BEGIN);
        }
        else
        {
          //Set the file pointer to the initial estimate - the best we can do...
          m_reader->SetFilePointer(firstFilePos,FILE_BEGIN);
        }
        return false;
      }

      // lower bound becomes valid
      if( clockFound > seekTimeStamp )
      {
        if (filePos < binaryMax) binaryMax = filePos-1;
      }
      else
      {
        if (filePos > binaryMin) binaryMin = filePos+1;
      }

      lastFilePos=filePos;
      filePos = binaryMin + ( binaryMax - binaryMin ) / 2;
      filePos/=188;
      filePos*=188;

      if (lastFilePos==filePos)
      {
        LogDebug("FileSeek: stop seek closer target found : %f at %x - target: %f, diff: %f",
          clockFound, (DWORD)filePos, seekTimeStamp, diff);
        m_reader->SetFilePointer(filePos,FILE_BEGIN);
        return false;
      }

      Reset() ;   // Random jump, Reset "PacketSync"
    }
    else // no first PCR
    {
      //move filepointer forward and continue searching for a PCR
      filePos += sizeof(buffer);
      noPCRIteration++;
      if (noPCRIteration > MAX_BUFFER_ITERATIONS)
      {
        if (noPCRloop) //second time this has happened
        {
          LogDebug("FileSeek: stop seek, no PCR found, max iterations reached (%d)", MAX_BUFFER_ITERATIONS);
          //Set the file pointer to the initial estimate - the best we can do...
          m_reader->SetFilePointer(firstFilePos,FILE_BEGIN);
          return false;
        }
        //Let's try looking for any PCR pid 
        //starting again from the initial position
        LogDebug("FileSeek: No PCR found (pid = %d), trying for any PCR pid", m_seekPid);
        m_seekPid = -1;
        filePos = firstFilePos;
        noPCRIteration = 0;
        noPCRloop = true;
      }
    }
  }
  return false;
}