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; }
// // 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); }
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(); }
// // 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; }
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 ; }
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; }
//********************************************************* // 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; }