Index: AudioPin.cpp
===================================================================
--- AudioPin.cpp	(revision 27941)
+++ AudioPin.cpp	(working copy)
@@ -181,7 +181,6 @@
   return CSourceStream::BreakConnect();
 }
 
-extern int ShowBuffer;
 
 HRESULT CAudioPin::FillBuffer(IMediaSample *pSample)
 {
@@ -200,7 +199,7 @@
       //we dont try to read any packets, but simply return...
       if (m_pTsReaderFilter->IsSeeking() || m_pTsReaderFilter->IsStopping())// /*|| m_bSeeking*/ || m_pTsReaderFilter->IsSeekingToEof())
       {
-        //if (ShowBuffer) LogDebug("aud:isseeking");
+        //if (m_pTsReaderFilter->m_ShowBufferAudio) LogDebug("aud:isseeking");
         Sleep(20);
         pSample->SetTime(NULL,NULL);
         pSample->SetActualDataLength(0);
@@ -391,11 +390,11 @@
               float clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
               float fTime=(float)cRefTime.Millisecs()/1000.0f - clock ;
 
-              if (ShowBuffer || fTime < 0.030)
+              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());
               }
-              if (ShowBuffer) ShowBuffer--;
+              if (m_pTsReaderFilter->m_ShowBufferAudio) m_pTsReaderFilter->m_ShowBufferAudio--;
             }
           }
           else
Index: DeMultiplexer.cpp
===================================================================
--- DeMultiplexer.cpp	(revision 27941)
+++ DeMultiplexer.cpp	(working copy)
@@ -1640,6 +1640,10 @@
               }
             }
           }  
+          else
+          {
+            m_bSetVideoDiscontinuity = true;
+          }
           m_VideoValidPES=true ;                                    // We've just completed a frame, set flag until problem clears it 
           m_pl.RemoveAll() ;                                        
         }
Index: TsReader.cpp
===================================================================
--- TsReader.cpp	(revision 27941)
+++ TsReader.cpp	(working copy)
@@ -170,8 +170,8 @@
   TCHAR filename[1024];
   GetLogFile(filename);
   ::DeleteFile(filename);
-  LogDebug("--------- Fast forward debug ---------");
-  LogDebug("-------------- v0.4.7 ----------------");
+  LogDebug("------ FFDShow A/V sync fix ----------");
+  LogDebug("---------- v0.4.8 --------------------");
 
   m_fileReader=NULL;
   m_fileDuration=NULL;
@@ -223,6 +223,11 @@
   m_bForceSeekOnStop=false ;
   m_bForceSeekAfterRateChange=false ;
   m_bSeekAfterRcDone=false ;
+  m_videoDecoderCLSID=GUID_NULL;
+  m_bFastSyncAtStart=false;
+  m_ShowBufferAudio = INIT_SHOWBUFFERAUDIO;
+  m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO;
+  
   m_MPmainThreadID = GetCurrentThreadId() ;
 }
 
@@ -356,7 +361,7 @@
   return S_OK;
 }
 
-extern int ShowBuffer;
+
 STDMETHODIMP CTsReaderFilter::SetRelaxedMode(BOOL relaxedReading)
 {
   LogDebug("SetRelaxedMode");
@@ -415,7 +420,8 @@
     LogDebug("Elapsed time from pause to Audio/Video ( total zapping time ) : %d mS",GetTickCount()-m_lastPause);
   }
  
-  ShowBuffer=40;
+  m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO;
+  m_ShowBufferAudio = INIT_SHOWBUFFERAUDIO;
 
   CAutoLock cObjectLock(m_pLock);
 
@@ -502,10 +508,13 @@
 {
   return m_bTimeShifting;
 }
-extern int ShowBuffer;
+
+
 STDMETHODIMP CTsReaderFilter::Pause()
 {
-  ShowBuffer=100 ;
+  //m_ShowBufferVideo = INIT_SHOWBUFFERVIDEO;
+  //m_ShowBufferAudio = INIT_SHOWBUFFERAUDIO;
+
   LogDebug("CTsReaderFilter::Pause() - IsTimeShifting = %d - state = %d", IsTimeShifting(), m_State);
   CAutoLock cObjectLock(m_pLock);
 
@@ -1550,6 +1559,29 @@
   *pMediaPos = (m_MediaPos + m_LastTime - m_BaseTime) ;
   return ; 
 }
+
+//----------------------------------------------------
+// Derived from FFDShow code
+CLSID CTsReaderFilter::GetCLSIDFromPin(IPin* pPin)
+{
+  if (!pPin) 
+  {
+    return GUID_NULL;
+  }
+  CLSID clsid=GUID_NULL;
+  PIN_INFO pi;
+  if (SUCCEEDED(pPin->QueryPinInfo(&pi))) 
+  {
+    if (pi.pFilter) // IBaseFilter pointer
+    {
+      pi.pFilter->GetClassID(&clsid);
+      pi.pFilter->Release();
+    }
+  }
+  return clsid;
+}
+
+
 ////////////////////////////////////////////////////////////////////////
 //
 // Exported entry points for registration and unregistration
Index: TsReader.h
===================================================================
--- TsReader.h	(revision 27941)
+++ TsReader.h	(working copy)
@@ -32,6 +32,10 @@
 #include "IAudioStream.h"
 #include "ITeletextSource.h"
 #include <map>
+
+#define INIT_SHOWBUFFERVIDEO 20
+#define INIT_SHOWBUFFERAUDIO 5
+
 using namespace std;
 
 class CSubtitlePin;
@@ -44,6 +48,15 @@
 DEFINE_GUID(IID_ITSReader, 0xb9559486, 0xe1bb, 0x45d3, 0xa2, 0xa2, 0x9a, 0x7a, 0xfe, 0x49, 0xb2, 0x4f);
 //DEFINE_GUID(IID_ITSReaderAudioChange, 0xb9559486, 0xe1bb, 0x45d3, 0xa2, 0xa2, 0x9a, 0x7a, 0xfe, 0x49, 0xb2, 0x5f);
 
+// CLSIDs used to identify connected filters
+// {04FE9017-F873-410e-871E-AB91661A4EF7}
+DEFINE_GUID(CLSID_FFDSHOWVIDEO, 0x04fe9017, 0xf873, 0x410e, 0x87, 0x1e, 0xab, 0x91, 0x66, 0x1a, 0x4e, 0xf7);
+// {0B390488-D80F-4a68-8408-48DC199F0E97}
+DEFINE_GUID(CLSID_FFDSHOWDXVA, 0xb0eff97, 0xc750, 0x462c, 0x94, 0x88, 0xb1, 0xe, 0x7d, 0x87, 0xf1, 0xa6);
+// {DBF9000E-F08C-4858-B769-C914A0FBB1D7}
+DEFINE_GUID(CLSID_FFDSHOWSUBTITLES, 0xdbf9000e, 0xf08c, 0x4858, 0xb7, 0x69, 0xc9, 0x14, 0xa0, 0xfb, 0xb1, 0xd7);
+
+
 DECLARE_INTERFACE_(ITSReaderCallback, IUnknown)
 {
 	STDMETHOD(OnMediaTypeChanged) (int mediaTypes)PURE;	
@@ -186,6 +199,14 @@
   bool            m_bForceSeekAfterRateChange;
   bool            m_bSeekAfterRcDone;
 
+  int             m_ShowBufferAudio;
+  int             m_ShowBufferVideo;
+
+  CLSID           m_videoDecoderCLSID;
+  bool            m_bFastSyncAtStart;
+
+  CLSID           GetCLSIDFromPin(IPin* pPin);
+
 protected:
   void ThreadProc();
 
Index: VideoPin.cpp
===================================================================
--- VideoPin.cpp	(revision 27941)
+++ VideoPin.cpp	(working copy)
@@ -125,14 +125,32 @@
   //LogDebug("vid:CheckConnect()");
   return CBaseOutputPin::CheckConnect(pReceivePin);
 }
+
+
 HRESULT CVideoPin::CompleteConnect(IPin *pReceivePin)
 {
-  //LogDebug("vid:CompleteConnect()");
   HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin);
   if (SUCCEEDED(hr))
   {
+    CLSID &ref=m_pTsReaderFilter->GetCLSIDFromPin(pReceivePin);
+    m_pTsReaderFilter->m_videoDecoderCLSID = ref;
+    if (m_pTsReaderFilter->m_videoDecoderCLSID == CLSID_FFDSHOWVIDEO)
+    {
+      m_pTsReaderFilter->m_bFastSyncAtStart=true;
+      LogDebug("vid:CompleteConnect() FFDShow Video Decoder connected, fast sync enabled");
+    }
+    else if (m_pTsReaderFilter->m_videoDecoderCLSID == CLSID_FFDSHOWDXVA)
+    {
+      m_pTsReaderFilter->m_bFastSyncAtStart=true;
+      LogDebug("vid:CompleteConnect() FFDShow DXVA Video Decoder connected, fast sync enabled");
+    }
+    else
+    {
+      m_pTsReaderFilter->m_bFastSyncAtStart=false;
+    }
+    
+    m_bConnected=true;    
     LogDebug("vid:CompleteConnect() done");
-    m_bConnected=true;
   }
   else
   {
@@ -245,7 +263,6 @@
   return S_FALSE;
 }
 
-int ShowBuffer=100;
 
 HRESULT CVideoPin::FillBuffer(IMediaSample *pSample)
 {
@@ -264,7 +281,7 @@
       //we dont try to read any packets, but simply return...
       if (m_pTsReaderFilter->IsSeeking() || m_pTsReaderFilter->IsStopping()) //|| m_bSeeking*/ || m_pTsReaderFilter->IsSeekingToEof())
       {
-        //if (ShowBuffer) LogDebug("vid:isseeking:%d %d",m_pTsReaderFilter->IsSeeking() ,m_bSeeking);
+        //if (m_pTsReaderFilter->m_ShowBufferVideo) LogDebug("vid:isseeking:%d %d",m_pTsReaderFilter->IsSeeking() ,m_bSeeking);
         Sleep(5);
         pSample->SetActualDataLength(0);
         return NOERROR;
@@ -304,30 +321,29 @@
           cRefTime -= m_rtStart;
           //adjust the timestamp with the compensation
           cRefTime -= m_pTsReaderFilter->Compensation;
-          cRefTime -= AddOffset;
-          cRefTime -= m_pTsReaderFilter->m_ClockOnStart.m_time;
 
-          CRefTime Dur;
-          Dur = (m_pTsReaderFilter->AddVideoComp.m_time * DRIFT_RATE);
+          //CRefTime Dur;
+          //Dur = (m_pTsReaderFilter->AddVideoComp.m_time * DRIFT_RATE);
 
-          if (cRefTime.m_time < (m_pTsReaderFilter->AddVideoComp.m_time * DRIFT_RATE))
+          if (!m_pTsReaderFilter->m_bFastSyncAtStart && (cRefTime.m_time < (m_pTsReaderFilter->AddVideoComp.m_time * DRIFT_RATE)) )
           {
             // Ambass : try to stretch video after zapping
+            cRefTime -= AddOffset;
+            cRefTime -= m_pTsReaderFilter->m_ClockOnStart.m_time;
             AddOffset = cRefTime.m_time / DRIFT_RATE;
             // LogDebug("%03.3f, %03.3f, %03.3f", (float)AddOffset.Millisecs()/1000.0f,(float)cRefTime.Millisecs()/1000.0f, (float)m_pTsReaderFilter->AddVideoComp.Millisecs()/1000.0f);
             // m_pTsReaderFilter->AddVideoComp.m_time =0;
+            cRefTime += AddOffset;
+            cRefTime += m_pTsReaderFilter->m_ClockOnStart.m_time;
           }
-
-          cRefTime += AddOffset;
-          cRefTime += m_pTsReaderFilter->m_ClockOnStart.m_time;
                                                                       
           if (cRefTime.m_time >= 0)
+          {
             Sleep(1); // Ambass : avoid blocking audio FillBuffer method ( on audio/video starting ) by excessive video Fill buffer preemption
+          }
+
           m_bPresentSample = true;
-          //else
-          // Sample is too late.
-          //m_ShowSample = false ;
-       }
+        }
 
         if (m_bPresentSample)
         {
@@ -356,7 +372,7 @@
               float clock = (double)(RefClock-m_rtStart.m_time)/10000000.0 ;
               float fTime=(float)cRefTime.Millisecs()/1000.0f - clock ;
 
-              if (ShowBuffer || fTime < 0.030)
+              if (m_pTsReaderFilter->m_ShowBufferVideo || fTime < 0.030)
               {
                 int cntA, cntV;
                 CRefTime firstAudio, lastAudio;
@@ -365,8 +381,14 @@
                 cntV = demux.GetVideoBufferPts(firstVideo, lastVideo) + 1;
 
                 LogDebug("Vid/Ref : %03.3f, Late %c-frame(%02d), Compensated = %03.3f ( %0.3f A/V buffers=%02d/%02d), Clk : %f, State %d", (float)RefTime.Millisecs()/1000.0f,buffer->GetFrameType(),buffer->GetFrameCount(), (float)cRefTime.Millisecs()/1000.0f, fTime, cntA,cntV,clock, m_pTsReaderFilter->State());
-								}
-              if (ShowBuffer) ShowBuffer--;
+              }
+              
+              if (m_pTsReaderFilter->m_bFastSyncAtStart && m_pTsReaderFilter->m_ShowBufferVideo == INIT_SHOWBUFFERVIDEO)
+              {
+                pSample->SetDiscontinuity(TRUE);
+                LogDebug("vid: ShowBuffer = %d, force discontinuity", m_pTsReaderFilter->m_ShowBufferVideo);
+              }
+              if (m_pTsReaderFilter->m_ShowBufferVideo) m_pTsReaderFilter->m_ShowBufferVideo--;
             }
           }
           else
@@ -437,6 +459,12 @@
     m_dRateSeeking = 1.0;  // Reset to a reasonable value.
     return E_FAIL;
   }
+  if( m_dRateSeeking > 2.0 && m_pTsReaderFilter->m_videoDecoderCLSID == CLSID_FFDSHOWVIDEO)
+  {
+    //FFDShow video decoder doesn't handle rate > 2.0 properly
+    m_dRateSeeking = 1.0;  // Reset to a reasonable value.
+    return E_FAIL;
+  }
   LogDebug("vid: ChangeRate, m_dRateSeeking %f, Force seek done %d",(float)m_dRateSeeking, m_pTsReaderFilter->m_bSeekAfterRcDone);
   if (!m_pTsReaderFilter->m_bSeekAfterRcDone) //Don't force seek if another pin has already triggered it
   {
Index: VideoPin.h
===================================================================
--- VideoPin.h	(revision 27941)
+++ VideoPin.h	(working copy)
@@ -23,6 +23,7 @@
 #define __VideoPin_H
 #include "tsreader.h"
 
+
 class CVideoPin : public CSourceStream, public CSourceSeeking
 {
 public:
@@ -39,6 +40,7 @@
   HRESULT FillBuffer(IMediaSample *pSample);
   HRESULT BreakConnect();
 
+
   HRESULT DoBufferProcessingLoop(void);
 
   // CSourceSeeking
