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