Index: AudioPin.cpp
===================================================================
--- AudioPin.cpp	(revision 28131)
+++ AudioPin.cpp	(working copy)
@@ -208,7 +208,11 @@
         return NOERROR;
       }
 
-      buffer=demux.GetAudio();
+      if (!demux.m_bHoldFileRead)
+      {
+        CAutoLock flock (&demux.m_sectionFlushAudio);
+        buffer=demux.GetAudio();
+      }
 
       //did we reach the end of the file
       if (demux.EndOfFile()) // || ((GetTickCount()-m_LastTickCount > 3000) && !m_pTsReaderFilter->IsTimeShifting()))
@@ -343,6 +347,8 @@
 
         CRefTime RefTime,cRefTime ;
         bool HasTimestamp ;
+        float fTime = 0.0;
+        float clock = 0.0;
         //check if it has a timestamp
         if ((HasTimestamp=buffer->MediaTime(RefTime)))
         {
@@ -351,7 +357,13 @@
           //adjust the timestamp with the compensation
           cRefTime-= m_pTsReaderFilter->Compensation ;
 
-          if (cRefTime.m_time >= m_pTsReaderFilter->m_ClockOnStart) // m_rtStart.m_time+m_pTsReaderFilter->Compensation.m_time) // + PRESENT_DELAY)
+          REFERENCE_TIME RefClock = 0;
+          m_pTsReaderFilter->GetMediaPosition(&RefClock) ;
+          clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
+          fTime = (float)cRefTime.Millisecs()/1000.0f - clock ;
+
+          //if (cRefTime.m_time >= m_pTsReaderFilter->m_ClockOnStart) // m_rtStart.m_time+m_pTsReaderFilter->Compensation.m_time) // + PRESENT_DELAY)
+          if (fTime >= 0.0)
           {
             m_bPresentSample = true ;
             Sleep(5) ;
@@ -360,6 +372,7 @@
           {
             // Sample is too late.
             m_bPresentSample = false ;
+            m_bDiscontinuity = TRUE; //Next good sample will be discontinuous
           }
         }
 
@@ -385,11 +398,6 @@
             pSample->SetTime(&refTime,&refTime);
             if (m_dRateSeeking == 1.0)
             {
-              REFERENCE_TIME RefClock = 0;
-              m_pTsReaderFilter->GetMediaPosition(&RefClock) ;
-              float clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
-              float fTime=(float)cRefTime.Millisecs()/1000.0f - clock ;
-
               if (m_pTsReaderFilter->m_ShowBufferAudio || fTime < 0.030)
               {
                 LogDebug("Aud/Ref : %03.3f, Late              Compensated = %03.3f ( %0.3f A/V buffers=%02d/%02d), Clk : %f, State %d", (float)RefTime.Millisecs()/1000.0f, (float)cRefTime.Millisecs()/1000.0f, fTime,cntA,cntV, clock, m_pTsReaderFilter->State());
Index: DeMultiplexer.cpp
===================================================================
--- DeMultiplexer.cpp	(revision 28131)
+++ DeMultiplexer.cpp	(working copy)
@@ -52,9 +52,7 @@
 // *** UNCOMMENT THE NEXT LINE TO ENABLE DYNAMIC VIDEO PIN HANDLING!!!! ******
 #define USE_DYNAMIC_PINS
 
-extern int ShowBuffer;
 
-
 CDeMultiplexer::CDeMultiplexer(CTsDuration& duration,CTsReaderFilter& filter)
 :m_duration(duration)
 ,m_filter(filter)
@@ -87,7 +85,13 @@
   m_iAudioReadCount = 0;
   m_lastVideoPTS.IsValid = false;
   m_lastAudioPTS.IsValid = false;
+  m_bFlushDelegated = false;
+  m_bFlushDelgNow = false;
+  m_bHoldFileRead = false; 
+  m_bReadAheadFromFile = false;
   m_mpegParserTriggerFormatChange = false;
+  m_videoChanged=false;
+  m_audioChanged=false;
   SetMediaChanging(false);
   SetAudioChanging(false);
   m_DisableDiscontinuitiesFiltering = false;
@@ -178,8 +182,11 @@
         SetMediaChanging(true);
         m_filter.m_bForceSeekOnStop=true;     // Force stream to be resumed after
       }
-      else                                    // Mpeg parser info is required or audio graph is already rebuilding.
+      else   // Mpeg parser info is required or audio graph is already rebuilding.
+      {
         LogDebug("SetAudioStream : Media already changing");   // just wait 1st GOP
+        m_audioChanged = true;
+      }
     }
   }
   else
@@ -366,6 +373,7 @@
 void CDeMultiplexer::FlushVideo()
 {
   LogDebug("demux:flush video");
+  CAutoLock flock (&m_sectionFlushVideo);
   CAutoLock lock (&m_sectionVideo);
   delete m_pCurrentVideoBuffer;
   m_pCurrentVideoBuffer = NULL;
@@ -397,19 +405,21 @@
   m_FirstVideoSample = 0x7FFFFFFF00000000LL;
   m_LastVideoSample = 0;
   m_lastVideoPTS.IsValid = false;
-  m_VideoValidPES = true;
+  m_VideoValidPES = false;
   m_mVideoValidPES = false;
   m_WaitHeaderPES=-1 ;
   m_bVideoAtEof=false;
   m_MinVideoDelta = 10.0 ;
   m_filter.m_bRenderingClockTooFast=false ;
-
+  m_bSetVideoDiscontinuity=true;
+  
   Reset();  // PacketSync reset.
 }
 
 void CDeMultiplexer::FlushAudio()
 {
   LogDebug("demux:flush audio");
+  CAutoLock flock (&m_sectionFlushAudio);
   CAutoLock lock (&m_sectionAudio);
   delete m_pCurrentAudioBuffer;
   ivecBuffers it = m_vecAudioBuffers.begin();
@@ -437,13 +447,15 @@
   m_bAudioAtEof = false;
   m_MinAudioDelta = 10.0;
   m_filter.m_bRenderingClockTooFast=false;
-
+  m_bSetAudioDiscontinuity=true;
+  
   Reset();  // PacketSync reset.
 }
 
 void CDeMultiplexer::FlushSubtitle()
 {
   LogDebug("demux:flush subtitle");
+  CAutoLock flock (&m_sectionFlushSubtitle);
   CAutoLock lock (&m_sectionSubtitle);
   delete m_pCurrentSubtitleBuffer;
   ivecBuffers it = m_vecSubtitleBuffers.begin();
@@ -459,8 +471,12 @@
 /// Flushes all buffers
 void CDeMultiplexer::Flush()
 {
+  if (m_bHoldFileRead) return;
+    
   LogDebug("demux:flushing");
 
+  m_bHoldFileRead = true; //Stall GetVideo()/GetAudio()/GetSubtitle() calls from pins 
+
   m_iAudioReadCount = 0;
   m_LastDataFromRtsp = GetTickCount();
   bool holdAudio = HoldAudio();
@@ -475,6 +491,11 @@
   SetHoldAudio(holdAudio);
   SetHoldVideo(holdVideo);
   SetHoldSubtitle(holdSubtitle);
+  m_bFlushDelegated = false;
+  m_bFlushDelgNow = false;
+  m_bReadAheadFromFile = false;  
+  
+  m_bHoldFileRead = false;
 }
 
 ///
@@ -486,7 +507,7 @@
   if (m_currentSubtitlePid==0) return NULL;
   if (m_bEndOfFile) return NULL;
   if (m_bHoldSubtitle) return NULL;
-
+  
   //are there subtitle packets in the buffer?
   if (m_vecSubtitleBuffers.size()!=0 )
   {
@@ -506,10 +527,10 @@
 // or NULL if there is none available
 CBuffer* CDeMultiplexer::GetVideo()
 {
-  if (m_filter.GetVideoPin()->IsConnected() && ((m_iAudioStream == -1) || IsAudioChanging())) return NULL;
+  if (m_filter.GetVideoPin()->IsConnected() && (m_iAudioStream == -1)) return NULL;
 
   //if there is no video pid, then simply return NULL
-  if ((m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid==0) || IsMediaChanging())
+  if ((m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid==0) || IsMediaChanging() || IsAudioChanging())
   {
     ReadFromFile(false,true);
     return NULL;
@@ -532,6 +553,13 @@
     if (ReadFromFile(false,true)<READ_SIZE) break ;
   }
 
+  if (m_bAudioVideoReady && (m_vecVideoBuffers.size() < 3))
+  {
+    //Prefetch some data
+    m_bReadAheadFromFile = true;
+    m_filter.WakeThread();
+  }
+
   //are there video packets in the buffer?
   if (m_vecVideoBuffers.size()!=0 && !IsMediaChanging()) // && (m_FirstVideoSample.m_time < m_LastAudioSample.m_time))
   {
@@ -556,10 +584,10 @@
 CBuffer* CDeMultiplexer::GetAudio()
 {
   int SizeRead=READ_SIZE ;
-  if ((m_iAudioStream == -1) || IsAudioChanging()) return NULL;
+  if ((m_iAudioStream == -1)) return NULL;
 
   // if there is no audio pid, then simply return NULL
-  if ((m_audioPid==0) || IsMediaChanging())
+  if ((m_audioPid==0) || IsMediaChanging() || IsAudioChanging())
   {
     ReadFromFile(true,false);
     return NULL;
@@ -600,12 +628,20 @@
     m_bAudioVideoReady=true ;
   }
 
+  if (m_bAudioVideoReady && (m_vecAudioBuffers.size() < 3))
+  {
+    //Prefetch some data
+    m_bReadAheadFromFile = true;
+    m_filter.WakeThread();
+  }
+
   //yup, then return the next one
   CAutoLock lock (&m_sectionAudio);
 
   ivecBuffers it =m_vecAudioBuffers.begin();
   CBuffer* audiobuffer=*it;
   m_vecAudioBuffers.erase(it);
+  
 
   return audiobuffer;
 }
@@ -620,6 +656,8 @@
   m_bStarting=true ;
   m_receivedPackets=0;
   m_mpegParserTriggerFormatChange=false;
+  m_videoChanged=false;
+  m_audioChanged=false;
   m_bEndOfFile=false;
   m_bHoldAudio=false;
   m_bHoldVideo=false;
@@ -627,12 +665,14 @@
   m_ReqPatVersion=-1;
   m_bSetAudioDiscontinuity=false;
   m_bSetVideoDiscontinuity=false;
+  m_bReadAheadFromFile = false;
   DWORD dwBytesProcessed=0;
   DWORD m_Time = GetTickCount();
   while((GetTickCount() - m_Time) < 5000)
   {
     int BytesRead =ReadFromFile(false,false);
     if (BytesRead==0) Sleep(10);
+	  // LogDebug("demux:Start() BytesRead:%d, BytesProcessed:%d", BytesRead, dwBytesProcessed);
     if (dwBytesProcessed>INITIAL_READ_SIZE || GetAudioStreamCount()>0)
     {
       #ifdef USE_DYNAMIC_PINS
@@ -647,6 +687,7 @@
       Flush();
       m_streamPcr.Reset();
       m_bStarting=false;
+	    LogDebug("demux:Start() end1 BytesProcessed:%d", dwBytesProcessed);
       return;
     }
     dwBytesProcessed+=BytesRead;
@@ -654,6 +695,7 @@
   m_streamPcr.Reset();
   m_iAudioReadCount=0;
   m_bStarting=false;
+	LogDebug("demux:Start() end2 BytesProcessed:%d", dwBytesProcessed);
 }
 
 void CDeMultiplexer::SetEndOfFile(bool bEndOfFile)
@@ -666,6 +708,14 @@
   return m_bEndOfFile;
 }
 
+int CDeMultiplexer::ReadAheadFromFile()
+{
+  if (!m_bAudioVideoReady) return 0;
+	//LogDebug("demux:ReadAheadFromFile");
+  int SizeRead = ReadFromFile(false,false) ;
+  return SizeRead;
+}
+
 /// This method reads the next READ_SIZE bytes from the file
 /// and processes the raw data
 /// When a TS packet has been discovered, OnTsPacket(byte* tsPacket) gets called
@@ -674,7 +724,8 @@
 {
 //  if (m_bWeos) return 0 ;
 //  if (IsAudioChanging()) return 0 ;          // Do not read any data during stream selection from MP C#
-  if (m_filter.IsSeeking()) return 0;       // Ambass : to check
+  if (m_filter.IsSeeking() || m_bHoldFileRead) return 0;       // Ambass : to check
+    
   CAutoLock lock (&m_sectionRead);
   if (m_reader==NULL) return false;
   byte buffer[READ_SIZE];
@@ -702,7 +753,7 @@
       {
         //yes, then process the raw data
         result=true;
-        OnRawData(buffer,(int)dwReadBytes);
+        OnRawData2(buffer,(int)dwReadBytes);
         m_LastDataFromRtsp = GetTickCount();
       }
     }
@@ -737,7 +788,7 @@
       if (dwReadBytes > 0)
       {
         //succeeded, process data
-        OnRawData(buffer,(int)dwReadBytes);
+        OnRawData2(buffer,(int)dwReadBytes);
       }
       else
       {
@@ -773,6 +824,7 @@
 ///  - decode any audio/video packets and put the PES packets in the appropiate buffers
 void CDeMultiplexer::OnTsPacket(byte* tsPacket)
 {
+  //LogDebug("OnTsPacket() start");
   CTsHeader header(tsPacket);
 
   m_patParser.OnTsPacket(tsPacket);
@@ -846,11 +898,23 @@
   {
     return;
   }
+  
+  //Buffers about to be flushed
+  if (m_filter.IsThreadRunning() && m_bFlushDelgNow)
+  {
+  	return;
+  }
 
+//  //process the ts packet further
+//  FillSubtitle(header,tsPacket);
+//  FillAudio(header,tsPacket);
+//  FillVideo(header,tsPacket);
+//  FillTeletext(header,tsPacket);
+
   //process the ts packet further
+  FillVideo(header,tsPacket);
+  FillAudio(header,tsPacket);
   FillSubtitle(header,tsPacket);
-  FillAudio(header,tsPacket);
-  FillVideo(header,tsPacket);
   FillTeletext(header,tsPacket);
 }
 
@@ -879,7 +943,10 @@
   if(!CheckContinuity(m_AudioPrevCC, header))
   {
     LogDebug("Audio Continuity error... %x ( prev %x )", header.ContinuityCounter, m_AudioPrevCC);
-    if (!m_DisableDiscontinuitiesFiltering) m_AudioValidPES=false;  
+    if (!m_DisableDiscontinuitiesFiltering) 
+    {
+      m_AudioValidPES=false;  
+    }
   }
 
   m_AudioPrevCC = header.ContinuityCounter;
@@ -888,7 +955,26 @@
   //does tspacket contain the start of a pes packet?
   if (header.PayloadUnitStart)
   {
-    //yes packet contains start of a pes packet.
+    //Sanity check PES header
+    int posn=header.PayLoadStart;
+    if (
+           ((tsPacket[posn+0]!=0) || (tsPacket[posn+1]!=0) || (tsPacket[posn+2]!=1)) //Invalid start code
+        || ((tsPacket[posn+3] & 0x80)==0)     //Invalid stream ID
+        || ((tsPacket[posn+6] & 0xC0)!=0x80)  //Invalid marker bits
+        || ((tsPacket[posn+6] & 0x20)==0x20)  //Payload scrambled
+       )
+    {
+      //Discard this new/current PES packet
+      m_AudioValidPES=false;  
+      m_bSetAudioDiscontinuity=true;
+      LogDebug("PES audio 0-0-1 fail");
+      //Flushing is delegated to CTsReaderFilter::ThreadProc()
+      m_bFlushDelegated = true;
+      m_filter.WakeThread();  
+      return;
+    }
+    
+    //yes, packet contains start of a pes packet.
     //does current buffer hold any data ?
     if (m_pCurrentAudioBuffer->Length() > 0)
     {
@@ -896,18 +982,17 @@
       m_pCurrentAudioBuffer = new CBuffer();
     }
 
-    if (m_t_vecAudioBuffers.size())
+    if (m_t_vecAudioBuffers.size()) //Process the previous PES packet
     {
       CBuffer *Cbuf=*m_t_vecAudioBuffers.begin();
       byte *p = Cbuf->Data() ;
-      if ((p[0]==0) && (p[1]==0) && (p[2]==1) //Valid start code
-          && ((p[3] & 0x80)!=0)     //Valid stream ID
-          && ((p[6] & 0xC0)==0x80)  //Valid marker bits
-          && ((p[6] & 0x20)!=0x20)) //Payload not scrambled
+
+      if (m_AudioValidPES)
       {
         //get pts/dts from pes header
         CPcr pts;
         CPcr dts;
+        
         if (CPcr::DecodeFromPesHeader(p,0,pts,dts))
         {
           double diff;
@@ -917,10 +1002,16 @@
             diff=m_lastAudioPTS.ToClock()-pts.ToClock();
           else
             diff=pts.ToClock()-m_lastAudioPTS.ToClock();
-          if (diff>10.0)
+          if (diff>2.0)
           {
+            //Large PTS jump - flush the world...
             LogDebug("DeMultiplexer::FillAudio pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastAudioPTS.ToClock());
-            m_AudioValidPES=false;
+            m_lastAudioPTS.IsValid=false;
+            m_lastVideoPTS.IsValid=false;
+            m_bSetAudioDiscontinuity=true;
+            //Flushing is delegated to CTsReaderFilter::ThreadProc()
+            m_bFlushDelegated = true;
+            m_filter.WakeThread();            
           }
           else
           {
@@ -960,14 +1051,9 @@
         else
         {
           LogDebug(" No data");
-          m_AudioValidPES=false;
+          m_AudioValidPES=false; //stop further processing
         }
       }
-      else
-      {
-        LogDebug("Pes header 0-0-1 fail");
-        m_AudioValidPES=false;
-      }
 
       if (m_AudioValidPES)
       {
@@ -1012,7 +1098,7 @@
           delete *it;
           m_t_vecAudioBuffers.erase(it);
         }
-        m_bSetAudioDiscontinuity = true;
+        m_bSetAudioDiscontinuity = true; //Next good packet will be discontinuous
       }
     }
     m_AudioValidPES = true;     
@@ -1047,7 +1133,7 @@
 
 /// This method will check if the tspacket is an video packet
 void CDeMultiplexer::FillVideo(CTsHeader& header, byte* tsPacket)
-{
+{                  
   if (m_pids.videoPids.size() == 0 || m_pids.videoPids[0].Pid==0) return;
   if (header.Pid!=m_pids.videoPids[0].Pid) return;
 
@@ -1056,7 +1142,10 @@
   if (!CheckContinuity(m_VideoPrevCC, header))
   {
     LogDebug("Video Continuity error... %x ( prev %x )", header.ContinuityCounter, m_VideoPrevCC);
-    if (!m_DisableDiscontinuitiesFiltering) m_VideoValidPES = false;  
+    if (!m_DisableDiscontinuitiesFiltering)
+    {
+      m_VideoValidPES = false;  
+    }
   }
 
   m_VideoPrevCC = header.ContinuityCounter;
@@ -1072,7 +1161,6 @@
   }
   else
   {
-    //ParseVideoH264(header, tsPacket);
     FillVideoH264(header, tsPacket);
   }
 }
@@ -1120,13 +1208,24 @@
       return;
     }
 
-    if ((start[0]!=0) || (start[1]!=0) || (start[2]!=1) //Invalid start code
-        || ((start[3] & 0x80)==0)) //Invalid stream ID
+    if (
+           ((start[0]!=0) || (start[1]!=0) || (start[2]!=1)) //Invalid start code
+        || ((start[3] & 0x80)==0)    //Invalid stream ID
+      	|| ((start[6] & 0xC0)!=0x80) //Invalid marker bits
+        || ((start[6] & 0x20)==0x20) //Payload scrambled
+       )
     {
-      LogDebug("Pes 0-0-1 fail");
+      LogDebug("PES H264 0-0-1 fail");
+      //LogDebug("PES H264 0-0-1 fail, %x-%x-%x-%x-%x-%x-%x-%x", start[0], start[1], start[2], start[3], start[4], start[5], start[6], start[7]);
       m_VideoValidPES=false;
+      m_mVideoValidPES = false;
       m_p->rtStart = Packet::INVALID_TIME;
       m_WaitHeaderPES = -1;
+      m_bSetVideoDiscontinuity=true;
+      //Flushing is delegated to CTsReaderFilter::ThreadProc()
+      m_bFlushDelegated = true;
+      m_filter.WakeThread();
+      return;
     }
     else
     {
@@ -1137,11 +1236,6 @@
       }
       else
       { // full PES header is available.
-      	if ((start[6] & 0xC0)!=0x80   //Invalid marker bits
-          || (start[6] & 0x20)==0x20) //Payload scrambled
-        {
-          return;
-      	}
         CPcr pts;
         CPcr dts;
 
@@ -1155,14 +1249,19 @@
             diff=m_lastVideoPTS.ToClock()-pts.ToClock();
           else
             diff=pts.ToClock()-m_lastVideoPTS.ToClock();
-          if (diff>10.0)
+          if (diff>2.0)
           {
-            LogDebug("DeMultiplexer::FillVideo pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock());
-            m_VideoValidPES=false;
+            //Large PTS jump - flush the world...
+            LogDebug("DeMultiplexer::FillVideoH264 pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock());
+            m_lastAudioPTS.IsValid=false;
+            m_lastVideoPTS.IsValid=false;
+            //Flushing is delegated to CTsReaderFilter::ThreadProc()
+            m_bFlushDelegated = true;
+            m_filter.WakeThread();
           }
           else
           {
-            // LogDebug("DeMultiplexer::FillVideo pts : %f ", (float)pts.ToClock());
+            //LogDebug("DeMultiplexer::FillVideoH264 pts diff : %f ", (float)pts.ToClock());
             m_lastVideoPTS=pts;
           }
         }
@@ -1321,28 +1420,47 @@
           if (lastVidResX!=m_mpegPesParser->basicVideoInfo.width || lastVidResY!=m_mpegPesParser->basicVideoInfo.height)
           {
             LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced);
-            if (m_mpegParserTriggerFormatChange)
+            if (m_mpegParserTriggerFormatChange && !IsAudioChanging())
             {
-              LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser");
+              LogDebug("DeMultiplexer: OnMediaFormatChange triggered by H264Parser, aud %d, vid 1", m_audioChanged);
               SetMediaChanging(true);
-              m_filter.OnMediaTypeChanged(3);
+              if (m_audioChanged)
+                m_filter.OnMediaTypeChanged(3); //Video and audio
+              else
+                m_filter.OnMediaTypeChanged(2); //Video only
               m_mpegParserTriggerFormatChange=false;
             }
             LogDebug("DeMultiplexer: triggering OnVideoFormatChanged");
             m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced);
           }
-          else
+          else //video resolution is unchanged, but there may be other format changes
           {
-            if (m_mpegParserTriggerFormatChange && Gop)
+            if (m_mpegParserTriggerFormatChange && Gop && !IsAudioChanging())
             {
-              LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now.");
-              m_filter.OnMediaTypeChanged(3);
+              LogDebug("DeMultiplexer: Got GOP after channel change detected, format change, aud %d, vid %d", m_audioChanged, m_videoChanged);
+              if (m_audioChanged || m_videoChanged)
+              {
+                SetMediaChanging(true);
+                if (m_audioChanged && m_videoChanged)
+                  m_filter.OnMediaTypeChanged(3);
+                else if (m_audioChanged)
+                  m_filter.OnMediaTypeChanged(1);
+                else
+                  m_filter.OnMediaTypeChanged(2);
+              }
+              else
+              {
+                SetMediaChanging(false);
+              }
               m_mpegParserTriggerFormatChange=false;
             }
           }
         }
         else
+        {
           m_bSetVideoDiscontinuity = !m_mVideoValidPES;
+        }
+        
         m_pl.RemoveAll();
           
         p2->bDiscontinuity = m_p->bDiscontinuity; m_p->bDiscontinuity = FALSE;
@@ -1421,13 +1539,24 @@
       return;
     }
 
-    if ((start[0]!=0) || (start[1]!=0) || (start[2]!=1) //Invalid start code
-        || ((start[3] & 0x80)==0)) //Invalid stream ID
+    if (
+           ((start[0]!=0) || (start[1]!=0) || (start[2]!=1)) //Invalid start code
+        || ((start[3] & 0x80)==0)    //Invalid stream ID
+      	|| ((start[6] & 0xC0)!=0x80) //Invalid marker bits
+        || ((start[6] & 0x20)==0x20) //Payload scrambled
+       )
     {
-      LogDebug("Pes 0-0-1 fail");
-      m_VideoValidPES=false;
+      LogDebug("PES MPEG2 0-0-1 fail");
+      //LogDebug("Pes MPEG2 0-0-1 fail, %x-%x-%x-%x-%x-%x-%x-%x", start[0], start[1], start[2], start[3], start[4], start[5], start[6], start[7]);
+      m_VideoValidPES = false;
+      m_mVideoValidPES = false;
       m_p->rtStart = Packet::INVALID_TIME;
       m_WaitHeaderPES = -1;
+      m_bSetVideoDiscontinuity=true;
+      //Flushing is delegated to CTsReaderFilter::ThreadProc()
+      m_bFlushDelegated = true;
+      m_filter.WakeThread();    
+      return;        
     }
     else
     {
@@ -1438,15 +1567,10 @@
       }
       else
       { // full PES header is available.
-      	if ((start[6] & 0xC0)!=0x80   //Invalid marker bits
-          || (start[6] & 0x20)==0x20) //Payload scrambled
-        {
-          return;
-      	}
         CPcr pts;
         CPcr dts;
 
-//      m_VideoValidPES=true ;
+        m_VideoValidPES=true ;
         if (CPcr::DecodeFromPesHeader(start,0,pts,dts))
         {
           double diff;
@@ -1456,10 +1580,15 @@
             diff=m_lastVideoPTS.ToClock()-pts.ToClock();
           else
             diff=pts.ToClock()-m_lastVideoPTS.ToClock();
-          if (diff>10.0)
+          if (diff>2.0)
           {
-            LogDebug("DeMultiplexer::FillVideo pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock());
-            m_VideoValidPES=false;
+            //Large PTS jump - flush the world...
+            LogDebug("DeMultiplexer::FillVideoMPEG2 pts jump found : %f %f, %f", (float) diff, (float)pts.ToClock(), (float)m_lastVideoPTS.ToClock());
+            m_lastAudioPTS.IsValid=false;
+            m_lastVideoPTS.IsValid=false;
+            //Flushing is delegated to CTsReaderFilter::ThreadProc()
+            m_bFlushDelegated = true;
+            m_filter.WakeThread();
           }
           else
           {
@@ -1536,7 +1665,7 @@
           m_pl.AddTail(p2);
 //          LogDebug("DeMultiplexer::FillVideo Frame length : %d %x %x", size, *(DWORD*)start, *(DWORD*)next);
 
-          if (m_VideoValidPES)
+          if (m_mVideoValidPES)
           {
             CAutoPtr<Packet> p(new Packet());
             p = m_pl.RemoveHead();
@@ -1633,31 +1762,47 @@
             if (lastVidResX!=m_mpegPesParser->basicVideoInfo.width || lastVidResY!=m_mpegPesParser->basicVideoInfo.height)
             {
               LogDebug("DeMultiplexer: %x video format changed: res=%dx%d aspectRatio=%d:%d fps=%d isInterlaced=%d",header.Pid,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,m_mpegPesParser->basicVideoInfo.fps,m_mpegPesParser->basicVideoInfo.isInterlaced);
-              if (m_mpegParserTriggerFormatChange)
+              if (m_mpegParserTriggerFormatChange && !IsAudioChanging())
               {
-                LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser");
+                LogDebug("DeMultiplexer: OnMediaFormatChange triggered by mpeg2Parser, aud %d, vid 1", m_audioChanged);
                 SetMediaChanging(true);
-                m_filter.OnMediaTypeChanged(3);
+                if (m_audioChanged)
+                  m_filter.OnMediaTypeChanged(3); //Video and audio
+                else
+                  m_filter.OnMediaTypeChanged(2); //Video only
                 m_mpegParserTriggerFormatChange=false;
               }
               LogDebug("DeMultiplexer: triggering OnVideoFormatChanged");
               m_filter.OnVideoFormatChanged(m_mpegPesParser->basicVideoInfo.streamType,m_mpegPesParser->basicVideoInfo.width,m_mpegPesParser->basicVideoInfo.height,m_mpegPesParser->basicVideoInfo.arx,m_mpegPesParser->basicVideoInfo.ary,15000000,m_mpegPesParser->basicVideoInfo.isInterlaced);
             }
-            else
+            else //video resolution is unchanged, but there may be other format changes
             {
-              if (m_mpegParserTriggerFormatChange && Gop)
+              if (m_mpegParserTriggerFormatChange && Gop && !IsAudioChanging())
               {
-                LogDebug("DeMultiplexer: Got GOP after the channel change was detected without correct mpeg header parsing, so we trigger the format change now.");
-                m_filter.OnMediaTypeChanged(3);
+                LogDebug("DeMultiplexer: Got GOP after channel change detected, format change, aud %d, vid %d", m_audioChanged, m_videoChanged);
+                if (m_audioChanged || m_videoChanged)
+                {
+                  SetMediaChanging(true);
+                  if (m_audioChanged && m_videoChanged)
+                    m_filter.OnMediaTypeChanged(3);
+                  else if (m_audioChanged)
+                    m_filter.OnMediaTypeChanged(1);
+                  else
+                    m_filter.OnMediaTypeChanged(2);
+                }
+                else
+                {
+                  SetMediaChanging(false);
+                }
                 m_mpegParserTriggerFormatChange=false;
               }
             }
           }
           else
           {
-            m_bSetVideoDiscontinuity = true;
+            m_bSetVideoDiscontinuity = !m_mVideoValidPES;
           }
-          m_VideoValidPES=true ;                                    // We've just completed a frame, set flag until problem clears it 
+          //m_VideoValidPES=true ;                                    // We've just completed a frame, set flag until problem clears it 
           m_pl.RemoveAll() ;                                        
         }
         else                                                        // sequence_header_code
@@ -1772,6 +1917,8 @@
 {
   //CAutoLock lock (&m_section);
   CPidTable pids=info.PidTable;
+  
+  //LogDebug("OnNewChannel callback, pat version:%d->%d",m_iPatVersion, info.PatVersion);
 
   if (info.PatVersion != m_iPatVersion)
   {
@@ -1785,7 +1932,11 @@
     m_iPatVersion=info.PatVersion;
     m_bSetAudioDiscontinuity=true;
     m_bSetVideoDiscontinuity=true;
-    Flush();
+    //Flushing is delegated to CTsReaderFilter::ThreadProc()
+    m_bFlushDelgNow = true;
+    m_filter.WakeThread(); 
+   
+//    Flush();
 //    m_filter.m_bOnZap = true ;
   }
   else
@@ -1860,22 +2011,35 @@
   }
 
   bool changed=false;
-  bool videoChanged=false;
+  m_videoChanged=false;
+  m_audioChanged=false;
+
+  #ifdef USE_DYNAMIC_PINS
+  //Is the video pin connected?
+  if ((m_filter.GetVideoPin()->IsConnected()) && (m_pids.videoPids.size() > 0))
+  {
+    changed=true; //force a check in the mpeg parser
+    if (oldVideoServiceType != m_pids.videoPids[0].VideoServiceType)
+    {
+      m_videoChanged=true;
+    }
+  }
+  #else
   //did the video format change?
-  if (m_pids.videoPids.size() > 0 && oldVideoServiceType != m_pids.videoPids[0].VideoServiceType )
+  if (m_pids.videoPids.size() > 0 && oldVideoServiceType != m_pids.videoPids[0].VideoServiceType)
   {
     //yes, is the video pin connected?
     if (m_filter.GetVideoPin()->IsConnected())
     {
       changed=true;
-      videoChanged=true;
+      m_videoChanged=true;
     }
   }
-
+  #endif
+  
   m_iAudioStream = 0;
 
   LogDebug ("Setting initial audio index to : %i", m_iAudioStream);
-  bool audioChanged=false;
 
   //get the new audio format
   int newAudioStreamType=SERVICE_TYPE_AUDIO_MPEG2;
@@ -1891,7 +2055,7 @@
     if (m_filter.GetAudioPin()->IsConnected())
     {
       changed=true;
-      audioChanged=true;
+      m_audioChanged=true;
     }
   }
 
@@ -1899,13 +2063,22 @@
   if (changed)
   {
     #ifdef USE_DYNAMIC_PINS
-    // if we have a video stream and it's format changed, let the mpeg parser trigger the OnMediaTypeChanged
-    if (m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid>0x1 && videoChanged)  
+    // if we have a video stream, let the mpeg parser trigger the OnMediaTypeChanged
+    if (m_pids.videoPids.size() > 0 && m_pids.videoPids[0].Pid>0x1)  
     {
-      LogDebug("DeMultiplexer: We detected a new media type change which has a video stream, so we let the mpegParser trigger the event");
+      LogDebug("DeMultiplexer: We have a video stream, so we let the mpegParser check/trigger format changes");
       m_receivedPackets=0;
+      SetMediaChanging(true);
+      if (m_audioStreams.size() == 1)
+      {
+        if ((m_AudioStreamType == SERVICE_TYPE_AUDIO_UNKNOWN) || (m_AudioStreamType != newAudioStreamType))
+        {
+          m_AudioStreamType = newAudioStreamType ;
+          m_audioChanged=true;
+          LogDebug("DeMultiplexer: Audio media types changed");
+        }
+      }
       m_mpegParserTriggerFormatChange=true;
-      SetMediaChanging(true);
     }
     else
     {
@@ -1922,10 +2095,10 @@
       }
     }
     #else
-    if (audioChanged && videoChanged)
+    if (m_audioChanged && m_videoChanged)
       m_filter.OnMediaTypeChanged(3);
     else
-      if (audioChanged)
+      if (m_audioChanged)
         m_filter.OnMediaTypeChanged(1);
       else
         m_filter.OnMediaTypeChanged(2);
Index: DeMultiplexer.h
===================================================================
--- DeMultiplexer.h	(revision 28131)
+++ DeMultiplexer.h	(working copy)
@@ -130,10 +130,20 @@
   void SetAudioChanging(bool onOff);
   bool IsAudioChanging(void);
 
+  int ReadAheadFromFile();
+
   bool m_DisableDiscontinuitiesFiltering;
   DWORD m_LastDataFromRtsp;
   bool m_bAudioVideoReady;
+  bool m_bFlushDelegated;
+  bool m_bFlushDelgNow;
+  bool m_bHoldFileRead;
+  bool m_bReadAheadFromFile;
 
+  CCritSec m_sectionFlushAudio;
+  CCritSec m_sectionFlushVideo;
+  CCritSec m_sectionFlushSubtitle;
+
 private:
   struct stAudioStream
   {
@@ -219,6 +229,8 @@
   bool m_bStarting;
 
   bool m_mpegParserTriggerFormatChange;
+  bool m_videoChanged;
+  bool m_audioChanged;
   bool m_bSetAudioDiscontinuity;
   bool m_bSetVideoDiscontinuity;
   CPcr m_subtitlePcr;
Index: SubtitlePin.cpp
===================================================================
--- SubtitlePin.cpp	(revision 28131)
+++ SubtitlePin.cpp	(working copy)
@@ -217,13 +217,12 @@
         return NOERROR;
       }
 
-      if (m_pTsReaderFilter->m_bStreamCompensated)
+      if (m_pTsReaderFilter->m_bStreamCompensated && !demux.m_bHoldFileRead)
       {
         //get next buffer from demultiplexer
-        {
-          CAutoLock lock(&m_bufferLock);
-          buffer=demux.GetSubtitle();
-        }
+        CAutoLock flock (&demux.m_sectionFlushSubtitle);
+        CAutoLock lock(&m_bufferLock);
+        buffer=demux.GetSubtitle();
       }
 
       //did we reach the end of the file
Index: TsDuration.cpp
===================================================================
--- TsDuration.cpp	(revision 28131)
+++ TsDuration.cpp	(working copy)
@@ -69,27 +69,35 @@
 // Determines the total duration of the file (or timeshifting files)
 // 
 // 
-void CTsDuration::UpdateDuration()
+void CTsDuration::UpdateDuration(bool logging)
 {
 
-  byte buffer[32712];
+  byte buffer[188*330];
   DWORD dwBytesRead;
   int Loop=5 ;
+  int searchLoopCnt;
 
   do
   {
     m_bSearchStart=true;
     m_bSearchEnd=false;
-    m_bSearchMax=false;
     m_startPcr.Reset();
     m_maxPcr.Reset();
-    m_reader->SetFilePointer(0,FILE_BEGIN);
+    //m_reader->SetFilePointer(0,FILE_BEGIN);
+    searchLoopCnt = 2;
+    __int64 offset=0;
 
     Reset() ; // Reset internal "PacketSync" buffer
 
+    if (logging)
+    {
+      LogDebug("UpdateDuration - find pcr");
+    }
     //find the first pcr in the file
     while (!m_startPcr.IsValid)
     {
+      DWORD dwBytesRead;
+      m_reader->SetFilePointer(offset,FILE_BEGIN);
       if (!SUCCEEDED(m_reader->Read(buffer,sizeof(buffer),&dwBytesRead)))
       {
         //park filepointer at end of file
@@ -104,15 +112,26 @@
         m_reader->Read(buffer,1,&dwBytesRead);
         return;
       }
-      OnRawData(buffer,dwBytesRead);
+      OnRawData2(buffer,dwBytesRead);
+      if (searchLoopCnt<65)
+      {
+        searchLoopCnt++;
+      }
+      offset += (sizeof(buffer)*(searchLoopCnt/2)); //Move file pointer
+			Sleep(1) ;
     }
 
+    if (logging)
+    {
+      LogDebug("UpdateDuration - found startPcr, iterations:%d offset:%d", searchLoopCnt-2, offset);
+    }
     //find the last pcr in the file
     m_bSearchEnd=true;
     m_bSearchStart=false;
     m_endPcr.Reset();
-    __int64 offset=sizeof(buffer);
-    __int64 fileSize=m_reader->GetFileSize();
+    searchLoopCnt = 2;
+    offset=sizeof(buffer);
+    //__int64 fileSize=m_reader->GetFileSize();
   
     while (!m_endPcr.IsValid)
     {
@@ -127,9 +146,18 @@
         break;
       }
       Reset() ; // Reset internal "PacketSync" buffer
-      OnRawData(buffer,dwBytesRead);
-      offset+=sizeof(buffer);
+      OnRawData2(buffer,dwBytesRead);
+      if (searchLoopCnt<65)
+      {
+        searchLoopCnt++;
+      }
+      offset += ( (sizeof(buffer)*(searchLoopCnt/2)) - (188*16)); //step back a few packets less than a buffer so that buffers overlap
+			Sleep(1) ;
     }
+    if (logging)
+    {
+      LogDebug("UpdateDuration - found endPcr, iterations:%d offset:%d", searchLoopCnt-2, offset);
+    }
 
     Loop-- ;
     if(m_endPcr.PcrReferenceBase < m_startPcr.PcrReferenceBase)
@@ -160,26 +188,9 @@
   //and fill maxPcr
   if (m_endPcr.PcrReferenceBase < m_startPcr.PcrReferenceBase)
   {
-    //PCR rollover
-    m_bSearchMax=true;
-    m_bSearchEnd=false;
-    __int64 offset=sizeof(buffer);
-    while (!m_maxPcr.IsValid)
-    {
-      DWORD dwBytesRead;
-      m_reader->SetFilePointer(-offset,FILE_END);
-      if (!SUCCEEDED(m_reader->Read(buffer,sizeof(buffer),&dwBytesRead)))
-      {
-        break;
-      }
-      if (dwBytesRead==0) 
-      {
-        break;
-      }
-      Reset() ; // Reset internal "PacketSync" buffer
-      OnRawData(buffer,dwBytesRead);
-      offset+=sizeof(buffer);
-    }
+    m_maxPcr.PcrReferenceBase = 0x1ffffffffULL;
+    m_maxPcr.PcrReferenceExtension = 0x1ffULL;
+    m_maxPcr.IsValid = true;
   }
 
   //park filepointer at end of file
@@ -211,13 +222,6 @@
     {
       m_endPcr=field.Pcr;
     }
-    if (m_bSearchMax && m_pid==header.Pid)
-    {
-      if (field.Pcr.ToClock() >  m_startPcr.ToClock())
-      {
-        m_maxPcr=field.Pcr;
-      }
-    }
   }
 }
 
Index: TsDuration.h
===================================================================
--- TsDuration.h	(revision 28131)
+++ TsDuration.h	(working copy)
@@ -11,7 +11,7 @@
   virtual ~CTsDuration(void);
   void SetFileReader(FileReader* reader);
 	void OnTsPacket(byte* tsPacket);
-  void UpdateDuration();
+  void UpdateDuration(bool logging);
   void SetVideoPid(int pid);
   int  GetPid();
   CRefTime Duration();      
@@ -41,5 +41,4 @@
   CPcr         m_firstStartPcr;
   bool         m_bSearchStart;
   bool         m_bSearchEnd;
-  bool         m_bSearchMax;
 };
Index: TsFileSeek.cpp
===================================================================
--- TsFileSeek.cpp	(revision 28131)
+++ TsFileSeek.cpp	(working copy)
@@ -38,7 +38,6 @@
 CTsFileSeek::CTsFileSeek( CTsDuration& duration)
 :m_duration(duration)
 {
-  m_useBinarySearch = true;
 }
 
 CTsFileSeek::~CTsFileSeek(void)
@@ -73,49 +72,35 @@
   filePos/=188;
   filePos*=188;
 
-  if( m_duration.FirstStartPcr() > m_duration.EndPcr() )
-  {
-    // no PCR rollover is allowed when using binary search with seeking
-    m_useBinarySearch = false;
-  }
-  else
-  {
-    m_useBinarySearch = true;
-  }
-
   seekTimeStamp /= 1000.0f; // convert to seconds.
 
   m_seekPid=m_duration.GetPid();
   LogDebug("seek to %f filepos:%x pid:%x", seekTimeStamp,(DWORD)filePos, m_seekPid);
   
   byte buffer[188*10];
-  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;
-  }
-  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;
-  }
-  __int64 prevfilePos=filePos;
   __int64 binaryMax=m_reader->GetFileSize();
   __int64 binaryMin=0;
   __int64 lastFilePos=0;
   int seekingIteration=0;
 
-  SeekState state=FindPcr;
   Reset() ;   // Reset "PacketSync"
   while (true)
   {
     //sanity checks
-    if (filePos<0) return;
-    if (filePos+sizeof(buffer) > m_reader->GetFileSize()) return;
+    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;
+    }
+    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;
+    }
 
     //set filepointer to filePos
     m_reader->SetFilePointer(filePos,FILE_BEGIN);
@@ -132,138 +117,63 @@
     }
     //process data
     m_pcrFound.Reset();
-    OnRawData(buffer,dwBytesRead);
+    OnRawData2(buffer,dwBytesRead);
 
     //did we find a pcr?
     if (m_pcrFound.IsValid)
     {
       //yes. pcr found
       double clockFound=m_pcrFound.ToClock();
-      if( m_useBinarySearch )
+      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)
       {
-        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(" stop seek: %f at %x - target: %f, diff: %f", 
-            clockFound, (DWORD)filePos, seekTimeStamp, diff);
-          m_reader->SetFilePointer(filePos,FILE_BEGIN);
-          return;
-        }
+        LogDebug(" stop seek: %f at %x - target: %f, diff: %f",
+          clockFound, (DWORD)filePos, seekTimeStamp, diff);
+        m_reader->SetFilePointer(filePos,FILE_BEGIN);
+        return;
+      }
 
-        seekingIteration++;
-        if( seekingIteration > MAX_SEEKING_ITERATIONS )
-        {
-          LogDebug(" stop seek max iterations reached (%d): %f at %x - target: %f, diff: %f", 
-            MAX_SEEKING_ITERATIONS, clockFound, (DWORD)filePos, seekTimeStamp, diff);
-          m_reader->SetFilePointer(filePos,FILE_BEGIN);
-          return;
-        }
+      seekingIteration++;
+      if( seekingIteration > MAX_SEEKING_ITERATIONS )
+      {
+        LogDebug(" stop seek max iterations reached (%d): %f at %x - target: %f, diff: %f",
+          MAX_SEEKING_ITERATIONS, clockFound, (DWORD)filePos, seekTimeStamp, diff);
+        m_reader->SetFilePointer(filePos,FILE_BEGIN);
+        return;
+      }
 
-        // lower bound becomes valid
-        if( clockFound > seekTimeStamp ) 
-        {
-          if (filePos < binaryMax) binaryMax = filePos-1;
-        }
-        else
-        {
-          if (filePos > binaryMin) binaryMin = filePos+1;
-        }
-
-        if (lastFilePos==filePos)
-        {
-          LogDebug(" stop seek closer target found : %f at %x - target: %f, diff: %f", 
-            clockFound, (DWORD)filePos, seekTimeStamp, diff);
-          m_reader->SetFilePointer(filePos,FILE_BEGIN);
-          return;
-        }
-
-        lastFilePos=filePos;
-        filePos = binaryMin + ( binaryMax - binaryMin ) / 2;
-        Reset() ;   // Random jump, Reset "PacketSync"
+      // lower bound becomes valid
+      if( clockFound > seekTimeStamp )
+      {
+        if (filePos < binaryMax) binaryMax = filePos-1;
       }
       else
       {
-        if (state==FindPcr)
-        {
-          prevfilePos=filePos;
-          //we found the pcr.
-          //compare it with the timestamp we want to seek to
-          if (clockFound < seekTimeStamp)
-          {
-            // pcr found is too low, move forward in file and seek next pcr
-            state=FindNextPcr;
-          
-            //LogDebug(" got %f at filepos %x ->find next", clockFound, (DWORD)filePos);
-            filePos += sizeof(buffer);
-          }
-          else if (clockFound > seekTimeStamp)
-          {
-            // pcr found is too high, move backward in file and seek previous pcr
-            //LogDebug(" got %f at filepos %x ->find prev", clockFound, (DWORD)filePos);
-            state=FindPreviousPcr;
-            filePos -= sizeof(buffer);
-            Reset() ;   // Backward jump, Reset "PacketSync"
-          }
-          else
-          {
-            //pcr is correct, just return
-            //LogDebug(" got %f", clockFound);
-            m_reader->SetFilePointer(filePos,FILE_BEGIN);
-            return;
-          }
-        }
-        else
-        {
-          //pcr found, check state
-          if (state==FindNextPcr)
-          {
-            //LogDebug(" got %f at filepos %x", clockFound, (DWORD)filePos);
-            //looking for a pcr > seektime
-            if (clockFound > seekTimeStamp)
-            {
-              //found it..
-              //LogDebug(" stop seek too big: %f at %x", clockFound, (DWORD)filePos);
-              m_reader->SetFilePointer(prevfilePos,FILE_BEGIN);
-              return;
-            }
-            prevfilePos=filePos;
-            filePos+=sizeof(buffer);
-          }
-          else if (state==FindPreviousPcr)
-          {
-            //LogDebug(" got %f at filepos %x", clockFound, (DWORD)filePos);
-            //looking for a pcr < seektime
-            if (clockFound < seekTimeStamp)
-            {
-              //found it...
-              //LogDebug(" stop seek too small: %f at %x", clockFound, (DWORD)filePos);
-              m_reader->SetFilePointer(filePos,FILE_BEGIN);
-              return;
-            }
-            prevfilePos=filePos;
-            filePos-=sizeof(buffer);
-            Reset() ;   // Backward jump, Reset "PacketSync"
-          }
-        }
+        if (filePos > binaryMin) binaryMin = filePos+1;
       }
+
+      lastFilePos=filePos;
+      filePos = binaryMin + ( binaryMax - binaryMin ) / 2;
+      filePos/=188;
+      filePos*=188;
+
+      if (lastFilePos==filePos)
+      {
+        LogDebug(" stop seek closer target found : %f at %x - target: %f, diff: %f",
+          clockFound, (DWORD)filePos, seekTimeStamp, diff);
+        m_reader->SetFilePointer(filePos,FILE_BEGIN);
+        return;
+      }
+
+      Reset() ;   // Random jump, Reset "PacketSync"
     }
     else // no first PCR
     {
-      //no pcr found.
-      if (state == FindPreviousPcr)
-      {
-        //move filepointer back and continue searching for a PCR
-        filePos -=sizeof(buffer);
-        Reset() ;   // Backward jump, Reset "PacketSync"
-      }
-      else
-      {
-        //move filepointer forward and continue searching for a PCR
-        filePos += sizeof(buffer);
-      }
+      //move filepointer forward and continue searching for a PCR
+      filePos += sizeof(buffer);
     }
   }
 }
@@ -271,7 +181,7 @@
 
 //*********************************************************
 // Callback method. This method gets called via
-// CTsFileSeek::Seek()->OnRawData(buffer,dwBytesRead)
+// CTsFileSeek::Seek()->OnRawData2(buffer,dwBytesRead)
 // tsPacket : pointer to 188 byte Transport Stream packet
 //
 // This method checks if the ts packet contains a PCR timestamp
@@ -290,7 +200,7 @@
     {
       // pid is valid
       // did we have a pcr rollover ??
-      if (m_duration.MaxPcr().IsValid)
+      if (m_duration.FirstStartPcr() > m_duration.EndPcr())
       {
         //pcr rollover occured.
         //next we need to convert the pcr into filestamp
@@ -298,23 +208,28 @@
         //but the file can start with any pcr timestamp
         if (field.Pcr.ToClock() <=m_duration.EndPcr().ToClock())
         {
-          // pcr < endpcr
-          //   pcrFound= (pcr-startpcr)
+          // pcr < endpcr (second half of the file)
+          //   pcrFound= pcr+(MAXIMUM_PCR - startpcr)
+          // StartPcr------>(0x1ffffffff;0x1ff), (0x0,0x0)--------->EndPcr
           m_pcrFound=field.Pcr;
           double d1=m_pcrFound.ToClock();
-          double start=m_duration.StartPcr().ToClock();//earliest pcr available in the file
-          d1-=start;
+          CPcr pcr2;
+          pcr2.PcrReferenceBase = 0x1ffffffffULL;
+          pcr2.PcrReferenceExtension = 0x1ffULL;
+          double start=pcr2.ToClock()- m_duration.StartPcr().ToClock();
+          d1+=start;
           m_pcrFound.FromClock(d1);
         }
         else
         {
-          //PCR > endpcr
-          //   pcrFound- pcr+(maxPcr-startpcr)
-          // StartPcr------>MaxPcr--->0--------->EndPcr
+          //PCR > endpcr (first half of the file)
+          //   pcrFound= (pcr-startpcr)
           m_pcrFound=field.Pcr;
           double d1=m_pcrFound.ToClock();
-          double start=m_duration.MaxPcr().ToClock()- m_duration.StartPcr().ToClock();
-          d1+=start;
+          double start=m_duration.StartPcr().ToClock();//earliest pcr available in the file
+          LogDebug(" found clock %f earliest is %f", d1, start);
+          d1-=start;
+          LogDebug(" after sub %f", d1);
           m_pcrFound.FromClock(d1);
         }
       }
Index: TsFileSeek.h
===================================================================
--- TsFileSeek.h	(revision 28131)
+++ TsFileSeek.h	(working copy)
@@ -8,12 +8,6 @@
 class CTsFileSeek: public CPacketSync
 {
 public:
-  enum SeekState
-  {
-    FindPreviousPcr=-1,
-    FindPcr=0,
-    FindNextPcr=1
-  };
   CTsFileSeek( CTsDuration& duration );
   virtual ~CTsFileSeek(void);
 	void OnTsPacket(byte* tsPacket);
@@ -25,5 +19,4 @@
   CTsDuration&  m_duration;
   CPcr          m_pcrFound;
   int           m_seekPid;
-  bool          m_useBinarySearch;
 };
Index: TsReader.cpp
===================================================================
--- TsReader.cpp	(revision 28131)
+++ TsReader.cpp	(working copy)
@@ -170,7 +170,8 @@
   TCHAR filename[1024];
   GetLogFile(filename);
   ::DeleteFile(filename);
-  LogDebug("---------- v0.4.12 -------------------");
+  LogDebug("----- Continue after corruption testing ---------");
+  LogDebug("---------- v0.4.28 XXX -------------------");
 
   m_fileReader=NULL;
   m_fileDuration=NULL;
@@ -228,11 +229,17 @@
   m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO;
   
   m_MPmainThreadID = GetCurrentThreadId() ;
+  
+  LogDebug("Start duration thread");
+  StartThread();
 }
 
 CTsReaderFilter::~CTsReaderFilter()
 {
   LogDebug("CTsReaderFilter::dtor");
+  //stop duration thread
+  StopThread();
+  
   HRESULT hr = m_pAudioPin->Disconnect();
   delete m_pAudioPin;
 
@@ -471,7 +478,7 @@
   }
 
   //stop duration thread
-  StopThread();
+  //StopThread();
 
   LogDebug("CTsReaderFilter::Stop()  -stop source");
   //stop filter
@@ -614,13 +621,13 @@
     m_demultiplexer.m_LastDataFromRtsp = GetTickCount() ;
   }
 
-  //is the duration update thread running?
-  if (!IsThreadRunning())
-  {
-    //nop? then start it
-    //LogDebug("  CTsReaderFilter::Pause()->start duration thread");
-    StartThread();
-  }
+//  //is the duration update thread running?
+//  if (!IsThreadRunning())
+//  {
+//    //nop? then start it
+//    //LogDebug("  CTsReaderFilter::Pause()->start duration thread");
+//    StartThread();
+//  }
 
   LogDebug("CTsReaderFilter::Pause() - END - state = %d", m_State);
   return hr;
@@ -772,7 +779,7 @@
 
     //get file duration
     m_duration.SetFileReader(m_fileDuration);
-    m_duration.UpdateDuration();
+    m_duration.UpdateDuration(true);
 
     float milli = m_duration.Duration().Millisecs();
     milli /= 1000.0;
@@ -1041,8 +1048,9 @@
 
 	  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_demultiplexer.FlushAudio() ;
+	    //m_demultiplexer.FlushVideo() ;
+	    m_demultiplexer.Flush();
     }
     m_bOnZap=false ;
 //    m_demultiplexer.SetHoldAudio(false) ;
@@ -1136,14 +1144,19 @@
 /// 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
+//  to the graph.
+//  Flushing after large video/audio PTS jump and PES '0-0-1 fail' errors 
+//  are also delegated to this thread.
 void CTsReaderFilter::ThreadProc()
 {
   LogDebug("CTsReaderFilter::ThreadProc start()");
 
-  int durationUpdateLoop = 1;
+  int  durationUpdateLoop = 1;
   long Old_rtspDuration = -1 ;
   long PauseDuration =0;
+  int timeNow = GetTickCount();
+  int  lastFlushTime = timeNow;
+  int  lastDurTime = timeNow - 2000;
 
   ::SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_BELOW_NORMAL);
   do
@@ -1152,107 +1165,161 @@
     //since we're no longer playing
     if (m_demultiplexer.EndOfFile())
       break;
-    //are we playing an RTSP stream?
-    if (m_fileDuration!=NULL)
+
+    timeNow = GetTickCount();
+
+    //Flush delegated to this thread
+    if (m_demultiplexer.m_bFlushDelegated || m_demultiplexer.m_bFlushDelgNow)
     {
-      //no, then get the duration from the local file
-      CTsDuration duration;
-      duration.SetFileReader(m_fileDuration);
-      duration.SetVideoPid(m_duration.GetPid());
-      duration.UpdateDuration();
+      if (!m_demultiplexer.m_bFlushDelgNow && ((timeNow - 500) < lastFlushTime) && (timeNow > lastFlushTime)) 
+      { 
+        // Too early for next flush
+        m_demultiplexer.m_bFlushDelegated = false;
+      }
+      else
+      {
+        lastFlushTime = timeNow;
+  
+        LogDebug("CTsReaderFilter::ThreadProc - Flush");     
+        //Flush the internal data
+        m_demultiplexer.Flush();
+        m_bStreamCompensated=false ;
+        m_demultiplexer.m_bAudioVideoReady=false ;
+      }
+    }
 
-      //did we find a duration?
-      if (duration.Duration().Millisecs()>0)
+    //File read prefetch
+    if (m_demultiplexer.m_bReadAheadFromFile)
+    {
+      m_demultiplexer.m_bReadAheadFromFile = false;
+      m_demultiplexer.ReadAheadFromFile();
+    }
+     
+    if ((((timeNow - 1000) > lastDurTime) || (timeNow < lastDurTime)) && IsFilterRunning())
+    {
+      lastDurTime = timeNow;
+      //are we playing an RTSP stream?
+      if (m_fileDuration!=NULL)
       {
-        //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)
+        //no, then get the duration from the local file
+        if (m_demultiplexer.m_bAudioVideoReady) //Normal play started
+        {          
+          if((durationUpdateLoop == 2) || m_bRecording)
           {
-            //yes, then send a EC_LENGTH_CHANGED event to the graph
-            NotifyEvent(EC_LENGTH_CHANGED, NULL, NULL);
-            SetDuration();
+            CTsDuration duration;
+            duration.SetFileReader(m_fileDuration);
+            duration.SetVideoPid(m_duration.GetPid());
+            duration.UpdateDuration(false);
+    
+            //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 - we must be timeshifting or playing an in-progress recording
+                m_duration.Set(duration.StartPcr(), duration.EndPcr(), duration.MaxPcr());  // Local file
+                m_bRecording = true;
+      
+                // 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();
+                }
+              }
+              else
+              {
+                m_bRecording = false;
+              }
+            }
           }
+          
+          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 ;
+          }
         }
-      }
-      if (m_bLiveTv && (m_State == State_Paused))
-      {
-        // After 10 secs Pause, for sure, liveTv is cancelled.
-        PauseDuration++ ;
-        if (PauseDuration > 10)
+        else
         {
-          m_bLiveTv=false;
-          LogDebug("CTsReaderFilter, Live Tv is paused for more than 10 secs => m_bLiveTv=false.");
+          m_bRecording = true; //Force duration update next time m_bAudioVideoReady is true
         }
       }
       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)
+        // we are not playing a local file
+        // we are playing a (RTSP) stream?
+        if(m_bTimeShifting || m_bRecording)
         {
-        	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 ;
+          	Old_rtspDuration = m_rtspClient.Duration();
+            m_rtspClient.UpdateDuration();
           }
-				}
-				else
-				{
-          end = start + duration ;
-					if (Old_rtspDuration!=m_rtspClient.Duration())  // recording alive, continue to increase every second.
-					{
-            end += (double)(durationUpdateLoop % 5) ;
-					}
-          else
+    	
+          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)
           {
-            m_bRecording = false;
+            // 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()) ;
+  
+          // 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();
           }
-				}           
-        //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();
         }
       }
+      
+      durationUpdateLoop = (durationUpdateLoop + 1) % 5;
     }
+    
+    Sleep(1);
   }
-  while (!ThreadIsStopping(1000)) ;
+  while (!ThreadIsStopping(210)) ;
   LogDebug("CTsReaderFilter::ThreadProc stopped()");
 }
 
Index: TSThread.cpp
===================================================================
--- TSThread.cpp	(revision 28131)
+++ TSThread.cpp	(working copy)
@@ -51,6 +51,7 @@
 {
 	m_hStopEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
 	m_hDoneEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
+	m_hWakeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //Auto-reset
 	m_threadHandle = INVALID_HANDLE_VALUE;
   m_bThreadRunning=FALSE;
 }
@@ -60,6 +61,7 @@
 	StopThread();
 	CloseHandle(m_hStopEvent);
 	CloseHandle(m_hDoneEvent);
+	CloseHandle(m_hWakeEvent);
 }
 
 
@@ -102,10 +104,34 @@
 	return hr;
 }
 
+void TSThread::WakeThread()
+{
+  if (m_bThreadRunning)
+  {
+	  SetEvent(m_hWakeEvent);
+	}  
+}
+
 BOOL TSThread::ThreadIsStopping(DWORD dwTimeoutMilliseconds)
 {
-	DWORD result = WaitForSingleObject(m_hStopEvent, dwTimeoutMilliseconds);
-	return (result != WAIT_TIMEOUT);
+  HANDLE hEvts[] = {m_hStopEvent, m_hWakeEvent};
+
+	DWORD result = WaitForMultipleObjects(2, hEvts, FALSE, dwTimeoutMilliseconds);
+  switch (result)
+  {
+    case WAIT_OBJECT_0 : //m_hStopEvent
+	    return true;
+      break;
+    case WAIT_OBJECT_0 + 1 : //m_hWakeEvent
+	    ResetEvent(m_hWakeEvent);
+	    return false;
+      break;
+    case WAIT_TIMEOUT : //Timeout
+	    return false;
+      break;
+    default : //Error conditions
+	    return true;      
+  }
 }
 
 void TSThread::InternalThreadProc()
Index: TSThread.h
===================================================================
--- TSThread.h	(revision 28131)
+++ TSThread.h	(working copy)
@@ -36,6 +36,7 @@
 	virtual void ThreadProc() = 0;
 	HRESULT StartThread();
 	HRESULT StopThread(DWORD dwTimeoutMilliseconds = 1000);
+  void WakeThread();
 
 	BOOL ThreadIsStopping(DWORD dwTimeoutMilliseconds = 10);
   BOOL IsThreadRunning();
@@ -43,6 +44,7 @@
 	virtual void InternalThreadProc();
 	HANDLE m_hDoneEvent;
 	HANDLE m_hStopEvent;
+	HANDLE m_hWakeEvent;
 
 private:
   BOOL   m_bThreadRunning;
Index: VideoPin.cpp
===================================================================
--- VideoPin.cpp	(revision 28131)
+++ VideoPin.cpp	(working copy)
@@ -139,11 +139,11 @@
       m_pTsReaderFilter->m_bFastSyncFFDShow=true;
       LogDebug("vid:CompleteConnect() FFDShow Video Decoder connected, fast sync enabled");
     }
-    else if (m_pTsReaderFilter->m_videoDecoderCLSID == CLSID_FFDSHOWDXVA)
-    {
-      m_pTsReaderFilter->m_bFastSyncFFDShow=true;
-      LogDebug("vid:CompleteConnect() FFDShow DXVA Video Decoder connected, fast sync enabled");
-    }
+//    else if (m_pTsReaderFilter->m_videoDecoderCLSID == CLSID_FFDSHOWDXVA)
+//    {
+//      m_pTsReaderFilter->m_bFastSyncFFDShow=true;
+//      LogDebug("vid:CompleteConnect() FFDShow DXVA Video Decoder connected, fast sync enabled");
+//    }
     else
     {
       m_pTsReaderFilter->m_bFastSyncFFDShow=false;
@@ -287,8 +287,9 @@
         return NOERROR;
       }
 
-      if (m_pTsReaderFilter->m_bStreamCompensated)
-      {
+      if (m_pTsReaderFilter->m_bStreamCompensated && !demux.m_bHoldFileRead)
+      {       
+        CAutoLock flock (&demux.m_sectionFlushVideo);
         // Get next video buffer from demultiplexer
         buffer=demux.GetVideo();
       }
@@ -312,6 +313,8 @@
       {
         CRefTime RefTime, cRefTime;
         bool HasTimestamp;
+        float fTime = 0.0;
+        float clock = 0.0;
         //check if it has a timestamp
         if ((HasTimestamp=buffer->MediaTime(RefTime)))
         {
@@ -322,9 +325,6 @@
           //adjust the timestamp with the compensation
           cRefTime -= m_pTsReaderFilter->Compensation;
 
-          //CRefTime Dur;
-          //Dur = (m_pTsReaderFilter->AddVideoComp.m_time * DRIFT_RATE);
-
           if (!m_pTsReaderFilter->m_bFastSyncFFDShow && (cRefTime.m_time < (m_pTsReaderFilter->AddVideoComp.m_time * DRIFT_RATE)) )
           {
             // Ambass : try to stretch video after zapping
@@ -336,13 +336,25 @@
             cRefTime += AddOffset;
             cRefTime += m_pTsReaderFilter->m_ClockOnStart.m_time;
           }
+
+          REFERENCE_TIME RefClock = 0;
+          m_pTsReaderFilter->GetMediaPosition(&RefClock) ;
+          clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
+          fTime = (float)cRefTime.Millisecs()/1000.0f - clock ;
                                                                       
-          if (cRefTime.m_time >= 0)
+          if (fTime >= 0.0)
           {
-            Sleep(1); // Ambass : avoid blocking audio FillBuffer method ( on audio/video starting ) by excessive video Fill buffer preemption
+            m_bPresentSample = true;
+            Sleep(2); // Ambass : avoid blocking audio FillBuffer method ( on audio/video starting ) by excessive video Fill buffer preemption
           }
+          else
+          {
+            // Sample is too late.
+            m_bPresentSample = false ;
+            m_bDiscontinuity = TRUE; //Next good sample will be discontinuous
+          }
 
-          m_bPresentSample = true;
+          //m_bPresentSample = true;
         }
 
         if (m_bPresentSample)
@@ -394,11 +406,6 @@
                 }                
               }
               
-              REFERENCE_TIME RefClock = 0;
-              m_pTsReaderFilter->GetMediaPosition(&RefClock) ;
-              float clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
-              float fTime=(float)cRefTime.Millisecs()/1000.0f - clock ;
-
               if (m_pTsReaderFilter->m_ShowBufferVideo || fTime < 0.030)
               {
                 int cntA, cntV;
@@ -468,10 +475,10 @@
   }
 
     // Check for discontinuity
-  if (stsDiff > (m_fMTDMean + (500 * 10000))) // diff - mean > 500ms
+  if (stsDiff > (m_fMTDMean + (800 * 10000))) // diff - mean > 800ms
   {
     mtdDiscontinuity = true;
-    LogDebug("vid:Timestamp discontinuity, TsDiff %0.3f ms, TsMeanDiff %0.3f ms, samples %d", (float)stsDiff/10000.0f, (float)m_fMTDMean/10000.0f, m_nNextMTD);
+    //LogDebug("vid:Timestamp discontinuity, TsDiff %0.3f ms, TsMeanDiff %0.3f ms, samples %d", (float)stsDiff/10000.0f, (float)m_fMTDMean/10000.0f, m_nNextMTD);
   }
 
     // Update the rolling timestamp difference sum
