//****************************************************** /// Returns the file duration in REFERENCE_TIME /// For nomal .ts files it returns the current pcr - first pcr in the file /// for timeshifting files it returns the current pcr - the first pcr ever read /// So the duration keeps growing, even if timeshifting files are wrapped and being resued! // STDMETHODIMP CSubtitlePin::GetDuration(LONGLONG *pDuration) { if (m_pTsReaderFilter->IsTimeShifting()) { CTsDuration duration = m_pTsReaderFilter->GetDuration(); CRefTime totalDuration = duration.TotalDuration(); m_rtDuration = totalDuration; } else { REFERENCE_TIME refTime; m_pTsReaderFilter->GetDuration(&refTime); m_rtDuration=CRefTime(refTime); } return CSourceSeeking::GetDuration(pDuration); }
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(); }
//************************************************************************************************************** /// This method is running in its own thread /// Every second it will check the stream or local file and determine the total duration of the file/stream /// The duration can/will grow if we are playing a timeshifting buffer/stream // If the duration has changed it will update m_duration and send a EC_LENGTH_CHANGED event // to the graph void CTsReaderFilter::ThreadProc() { LogDebug("CTsReaderFilter::ThreadProc start()"); int durationUpdateLoop = 1; long Old_rtspDuration = -1 ; long PauseDuration =0; ::SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL); do { //if demuxer reached the end of the file, we can stop the thread //since we're no longer playing if (m_demultiplexer.EndOfFile()) break; //are we playing an RTSP stream? if (m_fileDuration!=NULL) { //no, then get the duration from the local file CTsDuration duration; duration.SetFileReader(m_fileDuration); duration.SetVideoPid(m_duration.GetPid()); duration.UpdateDuration(); //did we find a duration? if (duration.Duration().Millisecs()>0) { //yes, is it different then the one we determined last time? if (duration.StartPcr().PcrReferenceBase!=m_duration.StartPcr().PcrReferenceBase || duration.EndPcr().PcrReferenceBase!=m_duration.EndPcr().PcrReferenceBase) { //yes, then update it m_duration.Set(duration.StartPcr(), duration.EndPcr(), duration.MaxPcr()); // Local file // Is graph running? if (m_State == State_Running||m_State==State_Paused) { //yes, then send a EC_LENGTH_CHANGED event to the graph NotifyEvent(EC_LENGTH_CHANGED, NULL, NULL); SetDuration(); } } } if (m_bLiveTv && (m_State == State_Paused)) { // After 10 secs Pause, for sure, liveTv is cancelled. PauseDuration++ ; if (PauseDuration > 10) { m_bLiveTv=false; LogDebug("CTsReaderFilter, Live Tv is paused for more than 10 secs => m_bLiveTv=false."); } } else PauseDuration=0 ; } else { // we are not playing a local file // we are playing a (RTSP) stream? if(m_bTimeShifting || m_bRecording) { if(durationUpdateLoop == 0) { Old_rtspDuration = m_rtspClient.Duration(); m_rtspClient.UpdateDuration(); } CPcr pcrStart, pcrEnd, pcrMax ; double duration = m_rtspClient.Duration() / 1000.0f ; double start = m_duration.StartPcr().ToClock() ; double end = m_duration.EndPcr().ToClock() ; if (m_bTimeShifting) { // EndPcr is continuously increasing ( until ~26 hours for rollover that will fail ! ) // So, we refer duration to End, and just update start. end = (double)(GetTickCount()-m_tickCount)/1000.0 ; if(durationUpdateLoop == 0) { start = end - duration; if (start<0) start=0 ; } } else { end = start + duration ; if (Old_rtspDuration!=m_rtspClient.Duration()) // recording alive, continue to increase every second. { end += (double)(durationUpdateLoop % 5) ; } else { m_bRecording = false; } } //set the duration pcrStart.FromClock(start) ; pcrEnd.FromClock(end); m_duration.Set( pcrStart, pcrEnd, pcrMax); // Continuous update // LogDebug("Start : %f, End : %f",(float)m_duration.StartPcr().ToClock(),(float)m_duration.EndPcr().ToClock()) ; durationUpdateLoop = (durationUpdateLoop + 1) % 5; // Is graph running? if (m_State == State_Running) { //yes, then send a EC_LENGTH_CHANGED event to the graph NotifyEvent(EC_LENGTH_CHANGED, NULL, NULL); SetDuration(); } } } } while (!ThreadIsStopping(1000)) ; LogDebug("CTsReaderFilter::ThreadProc stopped()"); }