]> git.sesse.net Git - vlc/commitdiff
* Fixed a bug in the DTS/PTS parsing ;
authorChristophe Massiot <massiot@videolan.org>
Fri, 29 Dec 2000 10:52:40 +0000 (10:52 +0000)
committerChristophe Massiot <massiot@videolan.org>
Fri, 29 Dec 2000 10:52:40 +0000 (10:52 +0000)
* Fixed a bug in vpar_headers.c synchro handling introduced before ;
* Enhanced synchro's handling of dates and frame structure changes.

src/input/mpeg_system.c
src/video_parser/vpar_headers.c
src/video_parser/vpar_synchro.c

index a0592f718388de51d98d2a1367b99f3ae020be35..e825fa13a5efe0170ca1acd4bfa5f396fa424300 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_system.c: TS, PS and PES management
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: mpeg_system.c,v 1.21 2000/12/28 17:57:39 massiot Exp $
+ * $Id: mpeg_system.c,v 1.22 2000/12/29 10:52:40 massiot Exp $
  *
  * Authors: 
  *
@@ -239,9 +239,9 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
                         }
                         p_pes->i_dts =
                         ( ((mtime_t)(p_full_header[7] & 0x0E) << 29) |
-                          (((mtime_t)U16_AT(p_full_header + 10) << 14)
+                          (((mtime_t)U16_AT(p_full_header + 8) << 14)
                                 - (1 << 14)) |
-                          ((mtime_t)U16_AT(p_full_header + 12) >> 1) ) * 300;
+                          ((mtime_t)U16_AT(p_full_header + 10) >> 1) ) * 300;
                         p_pes->i_dts /= 27;
                     }
                 }
@@ -362,9 +362,12 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
                     p_pes->i_pts += p_es->p_pgrm->delta_cr
                                          + p_es->p_pgrm->delta_absolute
                                          + DEFAULT_PTS_DELAY;
-                    p_pes->i_dts += p_es->p_pgrm->delta_cr
-                                         + p_es->p_pgrm->delta_absolute
-                                         + DEFAULT_PTS_DELAY;
+                    if( p_pes->i_dts )
+                    {
+                        p_pes->i_dts += p_es->p_pgrm->delta_cr
+                                             + p_es->p_pgrm->delta_absolute
+                                             + DEFAULT_PTS_DELAY;
+                    }
                     break;
                 }
             }
index bee81a12a374418085badc6632610a7a47d4654b..949f61eacf711d8e51af8fa65f13f88282c3d7f8 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_headers.c : headers parsing
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_headers.c,v 1.63 2000/12/27 18:09:02 massiot Exp $
+ * $Id: vpar_headers.c,v 1.64 2000/12/29 10:52:40 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
@@ -610,19 +610,22 @@ static void PictureHeader( vpar_thread_t * p_vpar )
                     (p_vpar->sequence.p_forward == NULL ||
                      p_vpar->sequence.p_backward == NULL)));
 
-    if( b_parsable )
+    if( p_vpar->picture.i_current_structure )
     {
-        if( p_vpar->picture.i_current_structure )
+        /* Second field of a frame. We will decode it if, and only if we
+         * have decoded the first field. */
+        if( b_parsable )
         {
-            /* Second field of a frame. We will decode it if, and only if we
-             * have decoded the first field. */
             b_parsable = (p_vpar->picture.p_picture != NULL);
         }
-        else
-        {
-            /* Warn synchro we have a new picture (updates pictures index). */
-            vpar_SynchroNewPicture( p_vpar, p_vpar->picture.i_coding_type );
+    }
+    else
+    {
+        /* Warn synchro we have a new picture (updates pictures index). */
+        vpar_SynchroNewPicture( p_vpar, p_vpar->picture.i_coding_type );
 
+        if( b_parsable )
+        {
             /* Does synchro say we have enough time to decode it ? */
             b_parsable = vpar_SynchroChoose( p_vpar,
                                p_vpar->picture.i_coding_type, i_structure );
@@ -647,14 +650,12 @@ static void PictureHeader( vpar_thread_t * p_vpar )
                 /* The frame is complete. */
                 p_vpar->picture.i_current_structure = i_structure;
 
-                vpar_SynchroNewPicture( p_vpar, p_vpar->picture.i_coding_type );
                 vpar_SynchroTrash( p_vpar, p_vpar->picture.i_coding_type, i_structure );
             }
         }
         else
         {
             /* Warn Synchro we have trashed a picture. */
-            vpar_SynchroNewPicture( p_vpar, p_vpar->picture.i_coding_type );
             vpar_SynchroTrash( p_vpar, p_vpar->picture.i_coding_type, i_structure );
         }
         p_vpar->picture.p_picture = NULL;
index d45c6da42ec7233417f4a7c8cea8b19638f4e082..c9435978d52a003fef3169f76806a7add1e3c153 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_synchro.c : frame dropping routines
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vpar_synchro.c,v 1.66 2000/12/27 18:35:45 massiot Exp $
+ * $Id: vpar_synchro.c,v 1.67 2000/12/29 10:52:40 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
@@ -41,6 +41,8 @@
  * Please bear in mind that B's and IP's will be inverted when displaying
  * (decoding order != presentation order). Thus, t1 < t0.
  *
+ * FIXME: write a few words about stream structure changes.
+ *
  * 2. Definitions
  *    ===========
  * t[0..12]     : Presentation timestamps of pictures 0..12.
  *
  * 3. General considerations
  *    ======================
- * We define to types of machines :
- *      2T > tauP  : machines capable of decoding all P pictures
+ * We define three types of machines :
  *      14T > tauI : machines capable of decoding all I pictures
+ *      2T > tauP  : machines capable of decoding all P pictures
+ *      T > tauB   : machines capable of decoding all B pictures
  *
  * 4. Decoding of an I picture
  *    ========================
@@ -67,7 +70,7 @@
  * before displaying :
  *      t0 - t > tau´I + DELTA
  *
- * 4. Decoding of a P picture
+ * 5. Decoding of a P picture
  *    =======================
  * On fast machines, we decode all P's.
  * Otherwise :
  * I picture, which is more important.
  *      t12 - t > tau´P + tau´I + DELTA
  *
- * 5. Decoding of a B picture
+ * 6. Decoding of a B picture
  *    =======================
- * First criterion : have time to decode it.
+ * On fast machines, we decode all B's. Otherwise :
  *      t1 - t > tau´B + DELTA
- *
- * Second criterion : it shouldn't prevent us from displaying the forthcoming
- * P picture, which is more important.
- *      t4 - t > tau´B + tau´P + DELTA
+ * Since the next displayed I or P is already decoded, we don't have to
+ * worry about it.
  *
  * I hope you will have a pleasant flight and do not forget your life
  * jacket.
- *                                                  --Meuuh (2000-11-09)
+ *                                                  --Meuuh (2000-12-29)
  */
 
 /*****************************************************************************
@@ -129,6 +130,7 @@ static int  SynchroType( void );
 
 /* Error margins */
 #define DELTA                   (int)(0.040*CLOCK_FREQ)
+#define PTS_THRESHOLD           (int)(0.030*CLOCK_FREQ)
 
 #define DEFAULT_NB_P            5
 #define DEFAULT_NB_B            1
@@ -301,22 +303,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
 
             if( (S.i_n_b + 1) * period > S.p_tau[P_CODING_TYPE] )
             {
-                if( period > S.p_tau[B_CODING_TYPE] )
-                {
-                    /* Security in case we're _really_ late */
-                    b_decode = (pts - now > 0);
-                }
-                else
-                {
-                    b_decode = (pts - now) > (TAU_PRIME(B_CODING_TYPE) + DELTA);
-
-                    /* next P or I */
-                    b_decode &= (pts - now
-                                 + period
-                                 * ( 2 * S.i_n_b - S.i_eta_b + 3))
-                                   > (TAU_PRIME(B_CODING_TYPE)
-                                       + TAU_PRIME(P_CODING_TYPE) + DELTA);
-                }
+                b_decode = (pts - now) > (TAU_PRIME(B_CODING_TYPE) + DELTA);
             }
             else
             {
@@ -429,13 +416,12 @@ mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar )
  *****************************************************************************/
 void vpar_SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
 {
-    /* FIXME: use decoder_fifo callback */
-    pes_packet_t * p_pes;
+    pes_packet_t *  p_pes;
+    mtime_t         period = 1000000 / (p_vpar->sequence.i_frame_rate) * 1001;
 
     switch( i_coding_type )
     {
     case I_CODING_TYPE:
-        p_vpar->synchro.i_eta_p = p_vpar->synchro.i_eta_b = 0;
         if( p_vpar->synchro.i_eta_p
                 && p_vpar->synchro.i_eta_p != p_vpar->synchro.i_n_p )
         {
@@ -443,6 +429,7 @@ void vpar_SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
                           p_vpar->synchro.i_n_p, p_vpar->synchro.i_eta_p );
             p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p;
         }
+        p_vpar->synchro.i_eta_p = p_vpar->synchro.i_eta_b = 0;
 #ifdef STATS
         if( p_vpar->synchro.i_type == VPAR_SYNCHRO_DEFAULT )
         {
@@ -478,49 +465,83 @@ void vpar_SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
         break;
     }
 
+    /* FIXME: use decoder_fifo callback */
     p_pes = DECODER_FIFO_START( *p_vpar->bit_stream.p_decoder_fifo );
 
+    p_vpar->synchro.current_pts += period;
+
     if( i_coding_type == B_CODING_TYPE )
     {
         if( p_pes->i_pts )
         {
-            if( p_pes->i_pts < p_vpar->synchro.current_pts )
+            if( p_pes->i_pts - p_vpar->synchro.current_pts > PTS_THRESHOLD
+                 || p_vpar->synchro.current_pts - p_pes->i_pts > PTS_THRESHOLD )
             {
                 intf_WarnMsg( 2,
-                        "vpar synchro warning: pts_date < current_date" );
+                        "vpar synchro warning: pts != current_date (%lld)",
+                        p_vpar->synchro.current_pts - p_pes->i_pts );
             }
             p_vpar->synchro.current_pts = p_pes->i_pts;
             p_pes->i_pts = 0;
         }
-        else
-        {
-            p_vpar->synchro.current_pts += 1000000
-                    / (p_vpar->sequence.i_frame_rate) * 1001;
-        }
     }
     else
     {
-        if( p_vpar->synchro.backward_pts == 0 )
-        {
-            p_vpar->synchro.current_pts += 1000000
-                    / (p_vpar->sequence.i_frame_rate) * 1001;
-        }
-        else
+        if( p_vpar->synchro.backward_pts )
         {
-            if( p_vpar->synchro.backward_pts < p_vpar->synchro.current_pts )
+            if( p_pes->i_dts && 
+                (p_pes->i_dts - p_vpar->synchro.backward_pts > PTS_THRESHOLD
+              || p_vpar->synchro.backward_pts - p_pes->i_dts > PTS_THRESHOLD) )
+            {
+                intf_WarnMsg( 2,
+                        "vpar synchro warning: backward_pts != dts (%lld)",
+                        p_vpar->synchro.backward_pts - p_pes->i_dts );
+            }
+
+            if( p_vpar->synchro.backward_pts - p_vpar->synchro.current_pts
+                    > PTS_THRESHOLD
+                 || p_vpar->synchro.current_pts - p_vpar->synchro.backward_pts
+                    > PTS_THRESHOLD )
             {
                 intf_WarnMsg( 2,
-                        "vpar warning: backward_date < current_date" );
+                   "vpar synchro warning: backward_pts != current_pts (%lld)",
+                   p_vpar->synchro.current_pts - p_vpar->synchro.backward_pts );
             }
             p_vpar->synchro.current_pts = p_vpar->synchro.backward_pts;
             p_vpar->synchro.backward_pts = 0;
         }
+        else if( p_pes->i_dts )
+        {
+            if( p_pes->i_dts - p_vpar->synchro.current_pts > PTS_THRESHOLD
+                 || p_vpar->synchro.current_pts - p_pes->i_dts > PTS_THRESHOLD )
+            {
+                intf_WarnMsg( 2,
+                        "vpar synchro warning: dts != current_pts (%lld)",
+                        p_vpar->synchro.current_pts - p_pes->i_dts );
+            }
+            /* By definition of a DTS. */
+            p_vpar->synchro.current_pts = p_pes->i_dts;
+            p_pes->i_dts = 0;
+        }
 
         if( p_pes->i_pts )
         {
+            int     i_n_b;
+
             /* Store the PTS for the next time we have to date an I picture. */
             p_vpar->synchro.backward_pts = p_pes->i_pts;
             p_pes->i_pts = 0;
+
+            i_n_b = (p_vpar->synchro.backward_pts
+                        - p_vpar->synchro.current_pts) / period - 1;
+            if( i_n_b != p_vpar->synchro.i_n_b )
+            {
+                intf_WarnMsg( 1,
+                        "Anticipating a stream periodicity change from"
+                        " B[%d] to B[%d]",
+                              p_vpar->synchro.i_n_b, i_n_b );
+                p_vpar->synchro.i_n_b = i_n_b;
+            }
         }
     }