]> git.sesse.net Git - vlc/commitdiff
Refonte de la synchro qui devrait eliminer les problemes rencontres
authorJean-Marc Dressler <polux@videolan.org>
Fri, 7 Jan 2000 16:18:46 +0000 (16:18 +0000)
committerJean-Marc Dressler <polux@videolan.org>
Fri, 7 Jan 2000 16:18:46 +0000 (16:18 +0000)
lors des changements de flux.

include/input.h
include/input_pcr.h
src/input/input.c
src/input/input_pcr.c

index 2946549299a85c263b2f9b9cf5f851624db10c3a..a00025a9eacccab18e0f434b2e313e9d50eea5e6 100644 (file)
@@ -207,23 +207,15 @@ typedef struct
 
 typedef struct pcr_descriptor_struct
 {
-    vlc_mutex_t             lock;                    /* pcr modification lock */
+    /* system_date = PTS_date + delta_pcr + delta_absolute */
+    mtime_t                 delta_pcr;
+    mtime_t                 delta_absolute;
 
-    mtime_t                 delta_clock;
-    mtime_t                 delta_decode;
-                           /* represents decoder_time - pcr_time in usecondes */
     mtime_t                 last_pcr;
 
-    count_t                 c_average;
+    u32                     i_synchro_state;
+    count_t                 c_average_count;
                             /* counter used to compute dynamic average values */
-    count_t                 c_pts;
-#ifdef STATS
-    /* Stats */
-    count_t     c_average_jitter;
-    mtime_t     max_jitter;                   /* the evalueted maximum jitter */
-    mtime_t     average_jitter;               /* the evalueted average jitter */
-    count_t     c_pcr;           /* the number of PCR which have been decoded */
-#endif
 } pcr_descriptor_t;
 
 /******************************************************************************
index ebe0a32b192eae58cf447b2ed436c1d38f695d8a..370da30e53670e904a8720d469a983033e2fc1fd 100644 (file)
@@ -9,9 +9,14 @@
  * new_average = (old_average * c_average + new_sample_value) / (c_average +1) */
 #define PCR_MAX_AVERAGE_COUNTER 40
 
-/* Maximum allowed gap between two PCRs. */
+/* Maximum gap allowed between two PCRs. */
 #define PCR_MAX_GAP 1000000
 
+/* synchro states */
+#define SYNCHRO_NOT_STARTED 1
+#define SYNCHRO_START       2
+#define SYNCHRO_REINIT      3
+
 /******************************************************************************
  * Prototypes
  ******************************************************************************/
index 2d45f9e8130256274026ab424091b10bf7ed72ac..715b0263a8a416400b02254ac2423290048950f1 100644 (file)
@@ -915,27 +915,38 @@ static __inline__ void input_DemuxPES( input_thread_t *p_input,
                     pcr_descriptor_t * p_pcr;
 
                     p_pcr = p_input->p_pcr;
-                    vlc_mutex_lock( &p_pcr->lock );
-                    if( p_pcr->delta_clock == 0 )
+                    
+                    p_pes->i_pts = 
+                        ( ((mtime_t)(p_pes->p_pes_header[9] & 0x0E) << 29) |
+                          (((mtime_t)U16_AT(p_pes->p_pes_header + 10) << 14) - (1 << 14)) |
+                          ((mtime_t)U16_AT(p_pes->p_pes_header + 12) >> 1) ) * 300;
+                    p_pes->i_pts /= 27;
+                    
+                    if( p_pcr->i_synchro_state )
                     {
-                        p_pes->b_has_pts = 0;
+                        switch( p_pcr->i_synchro_state )
+                        {
+                            case SYNCHRO_NOT_STARTED:
+                                p_pes->b_has_pts = 0;
+                                break;
+
+                            case SYNCHRO_START:
+                                p_pes->i_pts += p_pcr->delta_pcr;
+                                p_pcr->delta_absolute = mdate() - p_pes->i_pts + 500000;
+                                p_pes->i_pts += p_pcr->delta_absolute;
+                                p_pcr->i_synchro_state = 0;
+                                break;
+
+                            case SYNCHRO_REINIT: /* We skip a PES */
+                                p_pes->b_has_pts = 0;
+                                p_pcr->i_synchro_state = SYNCHRO_START;
+                                break;
+                        }
                     }
                     else
                     {
-                        p_pes->i_pts = ( ((mtime_t)(p_pes->p_pes_header[9] & 0x0E) << 29) |
-                                         (((mtime_t)U16_AT(p_pes->p_pes_header + 10) << 14) - (1 << 14)) |
-                                         ((mtime_t)U16_AT(p_pes->p_pes_header + 12) >> 1) );
-                        p_pes->i_pts *= 300;
-                        p_pes->i_pts /= 27;
-                        p_pes->i_pts += p_pcr->delta_clock;
-                        if( p_pcr->c_pts == 0 )
-                        {
-                            p_pcr->delta_decode = mdate() - p_pes->i_pts + 500000;
-                        }
-                        p_pes->i_pts += p_pcr->delta_decode;
-                        p_pcr->c_pts += 1;
+                        p_pes->i_pts += p_pcr->delta_pcr + p_pcr->delta_absolute;
                     }
-                    vlc_mutex_unlock( &p_pcr->lock );
                 }
                 break;
             }
index 575defb100daf1dc7392ecea84c5a6f88c461026..a4f9cb26b73d502363979ada49e8ca0c799cc946 100644 (file)
 #include "intf_msg.h"
 #include "input_pcr.h"
 
+/* Note:
+ *   
+ *   SYNCHRONIZATION METHOD
+ *   
+ *   We compute an average for the pcr because we want to eliminate the
+ *   network jitter and keep the low frequency variations. The average is
+ *   in fact a low pass filter and the jitter is a high frequency signal
+ *   that is why it is eliminated by the filter/average.
+ *   
+ *   The low frequency variations enable us to synchronize the client clock
+ *   with the server clock because they represent the time variation between
+ *   the 2 clocks. Those variations (ie the filtered pcr) are used to compute
+ *   the presentation dates for the audio and video frames. With those dates
+ *   we can decoding (or trashing) the MPEG2 stream at "exactly" the same rate
+ *   as it is sent by the server and so we keep the synchronization between
+ *   the server and the client.
+ *   
+ *   It is a very important matter if you want to avoid underflow or overflow
+ *   in all the FIFOs, but it may be not enough.
+ *
+ */
+
 /******************************************************************************
  * input_PcrReInit : Reinitialize the pcr_descriptor
  ******************************************************************************/
 void input_PcrReInit( input_thread_t *p_input )
 {
-    ASSERT(p_input);
-
-    p_input->p_pcr->delta_clock = 0;
-    p_input->p_pcr->c_average = 0;
-    p_input->p_pcr->c_pts = 0;
-    p_input->p_pcr->last_pcr = 0;
+    ASSERT( p_input );
 
-#ifdef STATS
-    p_input->p_pcr->c_average_jitter = 0;
-    p_input->p_pcr->c_pcr = 0;
-    p_input->p_pcr->max_jitter = 0;
-    /* For the printf in input_PcrDecode() (for debug purpose only) */
-    printf("\n");
-#endif
+    p_input->p_pcr->delta_pcr       = 0;
+    p_input->p_pcr->last_pcr        = 0;
+    p_input->p_pcr->c_average_count = 0;
 }
 
 /******************************************************************************
@@ -48,14 +61,14 @@ void input_PcrReInit( input_thread_t *p_input )
  ******************************************************************************/
 int input_PcrInit( input_thread_t *p_input )
 {
-    ASSERT(p_input);
+    ASSERT( p_input );
 
     if( (p_input->p_pcr = malloc(sizeof(pcr_descriptor_t))) == NULL )
     {
         return( -1 );
     }
-    vlc_mutex_init( &p_input->p_pcr->lock );
     input_PcrReInit(p_input);
+    p_input->p_pcr->i_synchro_state = SYNCHRO_NOT_STARTED;
     
     return( 0 );
 }
@@ -66,91 +79,51 @@ int input_PcrInit( input_thread_t *p_input )
 void input_PcrDecode( input_thread_t *p_input, es_descriptor_t *p_es,
                       u8* p_pcr_data )
 {
-    mtime_t pcr_time, sys_time, delta_clock;
+    mtime_t pcr_time, sys_time, delta_pcr;
     pcr_descriptor_t *p_pcr;
         
-    ASSERT(p_pcr_data);
-    ASSERT(p_input);
-    ASSERT(p_es);
+    ASSERT( p_pcr_data );
+    ASSERT( p_input );
+    ASSERT( p_es );
 
     p_pcr = p_input->p_pcr;
     
-    /* Express the PCR in microseconde
+    /* Convert the PCR in microseconde
      * WARNING: do not remove the casts in the following calculation ! */
-    pcr_time = ( (( (mtime_t)U32_AT((u32*)p_pcr_data) << 1 ) | ( p_pcr_data[4] >> 7 )) * 300 ) / 27;
-    sys_time = mdate();
-    delta_clock = sys_time - pcr_time;
-    
-    vlc_mutex_lock( &p_pcr->lock );
+    pcr_time  = ( (( (mtime_t)U32_AT((u32*)p_pcr_data) << 1 ) | ( p_pcr_data[4] >> 7 )) * 300 ) / 27;
+    sys_time  = mdate();
+    delta_pcr = sys_time - pcr_time;
     
     if( p_es->b_discontinuity ||
         ( p_pcr->last_pcr != 0 && 
-         ( (p_pcr->last_pcr - pcr_time) > PCR_MAX_GAP
-           || (p_pcr->last_pcr - pcr_time) < - PCR_MAX_GAP ) ) )
+             (    (p_pcr->last_pcr - pcr_time) > PCR_MAX_GAP
+               || (p_pcr->last_pcr - pcr_time) < - PCR_MAX_GAP ) ) )
     {
         intf_DbgMsg("input debug: input_PcrReInit()\n");
         input_PcrReInit(p_input);
+        p_pcr->i_synchro_state = SYNCHRO_REINIT;
         p_es->b_discontinuity = 0;
     }
     p_pcr->last_pcr = pcr_time;
 
-    if( p_pcr->c_average == PCR_MAX_AVERAGE_COUNTER )
+    if( p_pcr->c_average_count == PCR_MAX_AVERAGE_COUNTER )
     {
-        p_pcr->delta_clock = (delta_clock + (p_pcr->delta_clock * (PCR_MAX_AVERAGE_COUNTER-1)))
-                             / PCR_MAX_AVERAGE_COUNTER;
+        p_pcr->delta_pcr = 
+            ( delta_pcr + (p_pcr->delta_pcr * (PCR_MAX_AVERAGE_COUNTER-1)) )
+            / PCR_MAX_AVERAGE_COUNTER;
     }
     else
     {
-        p_pcr->delta_clock = (delta_clock + (p_pcr->delta_clock *  p_pcr->c_average))
-                             / (p_pcr->c_average + 1);
-        p_pcr->c_average++;
+        p_pcr->delta_pcr =
+            ( delta_pcr + (p_pcr->delta_pcr * p_pcr->c_average_count) )
+            / ( p_pcr->c_average_count + 1 );
+        p_pcr->c_average_count++;
     }
 
-    vlc_mutex_unlock( &p_pcr->lock );
-    
-#ifdef STATS
+    if( p_pcr->i_synchro_state == SYNCHRO_NOT_STARTED )
     {
-        mtime_t jitter;
-        
-        jitter = delta_clock - p_pcr->delta_clock;
-        /* Compute the maximum jitter */
-        if( jitter < 0 )
-        {
-            if( (p_pcr->max_jitter <= 0 && p_pcr->max_jitter >= jitter) ||
-                (p_pcr->max_jitter >= 0 && p_pcr->max_jitter <= -jitter))
-                {
-                    p_pcr->max_jitter = jitter;
-                }
-        }
-        else
-        {
-            if( (p_pcr->max_jitter <= 0 && -p_pcr->max_jitter <= jitter) ||
-                (p_pcr->max_jitter >= 0 && p_pcr->max_jitter <= jitter))
-                {
-                    p_pcr->max_jitter = jitter;
-                }
-        }        
-                    
-        /* Compute the average jitter */
-        if( p_pcr->c_average_jitter == PCR_MAX_AVERAGE_COUNTER )
-        {
-            p_pcr->average_jitter = (jitter + (p_pcr->average_jitter * (PCR_MAX_AVERAGE_COUNTER-1)))
-                                    / PCR_MAX_AVERAGE_COUNTER;
-        }
-        else
-        {
-            p_pcr->average_jitter = (jitter + (p_pcr->average_jitter *  p_pcr->c_average_jitter))
-                                    / (p_pcr->c_average + 1);
-            p_pcr->c_average_jitter++;
-        }
-        
-        printf("delta: % 13Ld, max_jitter: % 9Ld, av. jitter: % 6Ld, PCR %6ld \r",
-               p_pcr->delta_clock , p_pcr->max_jitter, p_pcr->average_jitter, p_pcr->c_pcr);    
-        fflush(stdout);
-        
-        p_pcr->c_pcr++;
+        p_pcr->i_synchro_state = SYNCHRO_START;
     }
-#endif
 }
 
 /******************************************************************************