]> git.sesse.net Git - vlc/blobdiff - src/input/input_pcr.c
Le retour du demoronifier qui n'est pas content.
[vlc] / src / input / input_pcr.c
index 7ed0551318b458d393f2a588d82500a52956e5d9..9132db7da641557eb69680589185f49587ce5bf6 100644 (file)
-/*******************************************************************************
- * pcr.c: PCR management 
+/*****************************************************************************
+ * pcr.c: PCR management
  * (c)1999 VideoLAN
- *******************************************************************************
+ *****************************************************************************
  * Manages structures containing PCR information.
- *******************************************************************************/
+ *****************************************************************************/
 
-/*******************************************************************************
+/*****************************************************************************
  * Preamble
- *******************************************************************************/
+ *****************************************************************************/
 #include <stdio.h>
-#include <pthread.h>
-#include <sys/uio.h>                                                 /* iovec */
-#include <stdlib.h>                               /* atoi(), malloc(), free() */
+#include <sys/types.h>
+#include <sys/uio.h>                                                /* iovec */
+#include <stdlib.h>                              /* atoi(), malloc(), free() */
+#include <sys/socket.h>
 #include <netinet/in.h>
 
 #include "config.h"
 #include "common.h"
 #include "mtime.h"
+#include "vlc_thread.h"
 #include "debug.h"
 #include "input.h"
 #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);
-
-    pthread_mutex_lock( &p_input->p_pcr->lock );
-
-    p_input->p_pcr->delta_clock = 0;
-    p_input->p_pcr->c_average = 0;
-    p_input->p_pcr->c_pts = 0;
-
-#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
+    ASSERT( p_input );
 
-    pthread_mutex_unlock( &p_input->p_pcr->lock );
+    p_input->p_pcr->delta_pcr       = 0;
+    p_input->p_pcr->last_pcr        = 0;
+    p_input->p_pcr->c_average_count = 0;
 }
 
-/******************************************************************************
+/*****************************************************************************
  * input_PcrInit : Initialize PCR decoder
- ******************************************************************************/
+ *****************************************************************************/
 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 );
     }
-    pthread_mutex_init( &p_input->p_pcr->lock, NULL );
     input_PcrReInit(p_input);
-    
+    p_input->p_pcr->i_synchro_state = SYNCHRO_NOT_STARTED;
+
     return( 0 );
 }
 
-/******************************************************************************
+/*****************************************************************************
  * input_PcrDecode : Decode a PCR frame
- ******************************************************************************/
+ *****************************************************************************/
 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;
-    if( p_es->b_discontinuity )
+
+    /* 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_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 ) ) )
     {
+        intf_DbgMsg("input debug: input_PcrReInit()\n");
         input_PcrReInit(p_input);
+        p_pcr->i_synchro_state = SYNCHRO_REINIT;
         p_es->b_discontinuity = 0;
     }
-    
-    /* Express 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;
-    
-    pthread_mutex_lock( &p_pcr->lock );
-    
-    if( p_pcr->c_average == PCR_MAX_AVERAGE_COUNTER )
+    p_pcr->last_pcr = pcr_time;
+
+    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++;
     }
 
-    pthread_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
 }
 
-/******************************************************************************
- * input_PcrClean : Clean PCR structures before dying
- ******************************************************************************/
-void input_PcrClean( input_thread_t *p_input )
+/*****************************************************************************
+ * input_PcrEnd : Clean PCR structures before dying
+ *****************************************************************************/
+void input_PcrEnd( input_thread_t *p_input )
 {
     ASSERT( p_input );