Index: DeMultiplexer.cpp
===================================================================
--- DeMultiplexer.cpp	(revision 28016)
+++ 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)
@@ -88,6 +86,8 @@
   m_lastVideoPTS.IsValid = false;
   m_lastAudioPTS.IsValid = false;
   m_mpegParserTriggerFormatChange = false;
+  m_videoChanged=false;
+  m_audioChanged=false;
   SetMediaChanging(false);
   SetAudioChanging(false);
   m_DisableDiscontinuitiesFiltering = false;
@@ -620,6 +620,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;
@@ -1324,26 +1326,45 @@
             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)
             {
-              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 the unchanged, but there may be other format changes
           {
             if (m_mpegParserTriggerFormatChange && Gop)
             {
-              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);
+              if (m_audioChanged || m_videoChanged)
+              {
+                SetMediaChanging(true);
+                LogDebug("DeMultiplexer: Got GOP after channel change detected, trigger format change, aud %d, vid %d", m_audioChanged, m_videoChanged);
+                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;
@@ -1638,20 +1659,36 @@
               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)
               {
-                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 the unchanged, but there may be other format changes
             {
               if (m_mpegParserTriggerFormatChange && Gop)
               {
-                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);
+                if (m_audioChanged || m_videoChanged)
+                {
+                  SetMediaChanging(true);
+                  LogDebug("DeMultiplexer: Got GOP after channel change detected, trigger format change, aud %d, vid %d", m_audioChanged, m_videoChanged);
+                  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;
               }
             }
@@ -1863,22 +1900,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?
+    //yes, is the audio 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;
@@ -1894,7 +1944,7 @@
     if (m_filter.GetAudioPin()->IsConnected())
     {
       changed=true;
-      audioChanged=true;
+      m_audioChanged=true;
     }
   }
 
@@ -1902,10 +1952,10 @@
   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;
       m_mpegParserTriggerFormatChange=true;
       SetMediaChanging(true);
@@ -1925,10 +1975,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 28016)
+++ DeMultiplexer.h	(working copy)
@@ -219,6 +219,8 @@
   bool m_bStarting;
 
   bool m_mpegParserTriggerFormatChange;
+  bool m_videoChanged;
+  bool m_audioChanged;
   bool m_bSetAudioDiscontinuity;
   bool m_bSetVideoDiscontinuity;
   CPcr m_subtitlePcr;
Index: TsDuration.cpp
===================================================================
--- TsDuration.cpp	(revision 28016)
+++ TsDuration.cpp	(working copy)
@@ -80,7 +80,6 @@
   {
     m_bSearchStart=true;
     m_bSearchEnd=false;
-    m_bSearchMax=false;
     m_startPcr.Reset();
     m_maxPcr.Reset();
     m_reader->SetFilePointer(0,FILE_BEGIN);
@@ -160,26 +159,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 +193,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 28016)
+++ TsDuration.h	(working copy)
@@ -41,5 +41,4 @@
   CPcr         m_firstStartPcr;
   bool         m_bSearchStart;
   bool         m_bSearchEnd;
-  bool         m_bSearchMax;
 };
Index: TsFileSeek.cpp
===================================================================
--- TsFileSeek.cpp	(revision 28016)
+++ 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);
@@ -139,131 +124,56 @@
     {
       //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);
     }
   }
 }
@@ -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 28016)
+++ 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 28016)
+++ TsReader.cpp	(working copy)
@@ -170,7 +170,8 @@
   TCHAR filename[1024];
   GetLogFile(filename);
   ::DeleteFile(filename);
-  LogDebug("---------- v0.4.12 -------------------");
+  LogDebug("----- Graph rebuild testing ---------");
+  LogDebug("---------- v0.4.14 XXX -------------------");
 
   m_fileReader=NULL;
   m_fileDuration=NULL;
