--- vlc-1.0.2.orig/modules/access/dvdread.c	2009-10-07 16:34:30.000000000 +0100
+++ vlc-1.0.2.new/modules/access/dvdread.c	2009-10-08 00:34:10.000000000 +0100
@@ -123,6 +123,9 @@
 /* how many blocks DVDRead will read in each loop */
 #define DVD_BLOCK_READ_ONCE 4
 
+/* maximum gap in scr before attempt to correct it */
+#define DVD_SCR_MAX_GAP (INT64_C(1000000)) /* 1s, no justification */
+
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -142,6 +145,7 @@
 
     tt_srpt_t    *p_tt_srpt;
     pgc_t        *p_cur_pgc;
+    pci_t        pci_pack;
     dsi_t        dsi_pack;
     int          i_ttn;
 
@@ -176,6 +180,16 @@
 
     /* SPU */
     uint32_t clut[16];
+
+    /* SCR discontinuity handling */
+    int64_t i_scr_offset;
+    int64_t i_pts_offset;
+    int64_t i_dts_offset;
+
+    int64_t i_scr_previous;
+    int64_t i_last_vobu_e_ptm;
+    int b_have_pci_pack;
+
 };
 
 static int Control   ( demux_t *, int, va_list );
@@ -187,9 +201,12 @@
 
 static int  DvdReadSetArea  ( demux_t *, int, int, int );
 static void DvdReadSeek     ( demux_t *, int );
+static void DvdReadHandlePCI( demux_t *, uint8_t * );
 static void DvdReadHandleDSI( demux_t *, uint8_t * );
 static void DvdReadFindCell ( demux_t * );
 
+static void SCRDiscontinuityReset ( demux_t * );
+
 /*****************************************************************************
  * Open:
  *****************************************************************************/
@@ -518,6 +535,9 @@
          * go to next title if so */
         //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
 
+        /* Parse the contained pci packet */
+        DvdReadHandlePCI( p_demux, p_buffer );
+
         /* Parse the contained dsi packet */
         DvdReadHandleDSI( p_demux, p_buffer );
 
@@ -539,11 +559,12 @@
             return 0; /* EOF */
         }
 
-        /* FIXME: Ugly kludge: we send the pack block to the input for it
-         * sometimes has a zero scr and restart the sync */
         p_sys->i_cur_block++;
         p_sys->i_title_offset++;
 
+        /* FIXME: Ugly kludge: We send the nav pack to DemuxInput as 
+           is contains the code for handing and fixing discontinuities
+           in the scr / pts / dts timestamps. */
         DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN );
     }
 
@@ -647,7 +668,27 @@
             int i_mux_rate;
             if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
             {
-                es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr );
+
+                /* Detect discontinuities */
+                if ( p_sys->i_scr_previous >= 0 && p_sys->i_last_vobu_e_ptm >= 0 && 
+                     ( (i_scr - p_sys->i_scr_previous) > DVD_SCR_MAX_GAP ||
+                       (i_scr - p_sys->i_scr_previous) < -DVD_SCR_MAX_GAP) )
+                {
+
+                    int64_t scr_correction = (p_sys->i_scr_previous - i_scr) + (int64_t) DVD_VIDEO_LB_LEN * 20000 / i_mux_rate;
+                    int64_t xts_correction = p_sys->i_last_vobu_e_ptm - (int64_t) (p_sys->pci_pack.pci_gi.vobu_s_ptm) * 100 / 9;
+
+                    msg_Warn( p_demux, "correcting scr discontinuty (scr += %"PRId64" pts,dts += %"PRId64")", scr_correction, xts_correction);
+
+                    p_sys->i_scr_offset += scr_correction;
+                    p_sys->i_pts_offset += xts_correction;
+                    p_sys->i_dts_offset += xts_correction;
+                  
+                }
+
+                p_sys->i_scr_previous = i_scr;
+
+                es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr + p_sys->i_scr_offset );
                 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
             }
             block_Release( p_pkt );
@@ -667,6 +708,17 @@
                 if( tk->b_seen && tk->es &&
                     !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
                 {
+
+                    if ( p_pkt->i_pts > VLC_TS_INVALID )
+                    {
+                        p_pkt->i_pts += p_sys->i_pts_offset;
+                    }
+
+                    if ( p_pkt->i_dts > VLC_TS_INVALID )
+                    {
+                        p_pkt->i_dts += p_sys->i_dts_offset;
+                    }
+
                     es_out_Send( p_demux->out, tk->es, p_pkt );
                 }
                 else
@@ -1053,6 +1105,8 @@
 #undef p_vts
 #undef p_vmg
 
+    SCRDiscontinuityReset( p_demux );
+
     return VLC_SUCCESS;
 }
 
@@ -1147,10 +1201,30 @@
 #undef p_vts
 #undef p_pgc
 
+    SCRDiscontinuityReset( p_demux );
+
     return;
 }
 
 /*****************************************************************************
+ * DvdReadHandlePCI
+ *****************************************************************************/
+static void DvdReadHandlePCI( demux_t *p_demux, uint8_t *p_data )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    if ( p_sys->b_have_pci_pack ) {
+        p_sys->i_last_vobu_e_ptm = (int64_t)(p_sys->pci_pack.pci_gi.vobu_e_ptm) * 100 / 9;
+    }
+
+#define PCI_START_BYTE (45) /* Almost cerainly shouldn't do this! */
+
+    navRead_PCI( &p_sys->pci_pack, &p_data[PCI_START_BYTE] );
+    p_sys->b_have_pci_pack = 1;
+
+}
+
+/*****************************************************************************
  * DvdReadHandleDSI
  *****************************************************************************/
 static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
@@ -1356,3 +1430,22 @@
 
 #undef tt_srpt
 }
+
+
+/*****************************************************************************
+ * SCRDiscontinuityReset 
+ *****************************************************************************/
+static void SCRDiscontinuityReset ( demux_t *p_demux )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+
+    p_sys->i_scr_offset = 1; /* Avoid scr == VLC_TS_INVALID when scr = 0 is read from dvd */
+    p_sys->i_pts_offset = 1;
+    p_sys->i_dts_offset = 1;
+
+    p_sys->i_scr_previous = -1;
+    p_sys->i_last_vobu_e_ptm = -1;
+
+    p_sys->b_have_pci_pack = 0;
+
+}
