* More precise way to retrieve a PTS from the bit stream.
authorChristophe Massiot <massiot@videolan.org>
Mon, 14 Jan 2002 23:46:35 +0000 (23:46 +0000)
committerChristophe Massiot <massiot@videolan.org>
Mon, 14 Jan 2002 23:46:35 +0000 (23:46 +0000)
* Fixed issues in the PTS handling of the mad plug-in (incomplete).

12 files changed:
include/common.h
include/input_ext-dec.h
plugins/ac3_adec/ac3_adec.c
plugins/lpcm_adec/lpcm_adec.c
plugins/mad/mad_adec.c
plugins/mad/mad_adec.h
plugins/mad/mad_libmad.c
plugins/mpeg_adec/mpeg_adec.c
plugins/mpeg_vdec/video_parser.c
plugins/mpeg_vdec/vpar_headers.c
src/input/input_ext-dec.c
src/misc/modules_plugin.h

index d00f3d0..7752515 100644 (file)
@@ -3,7 +3,7 @@
  * Collection of useful common types and macros definitions
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: common.h,v 1.68 2002/01/13 18:13:07 gbazin Exp $
+ * $Id: common.h,v 1.69 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Samuel Hocevar <sam@via.ecp.fr>
  *          Vincent Seguin <seguin@via.ecp.fr>
@@ -571,6 +571,8 @@ typedef struct module_symbols_s
     u32  ( * UnalignedShowBits )    ( struct bit_stream_s *, unsigned int );
     void ( * UnalignedRemoveBits )  ( struct bit_stream_s * );
     u32  ( * UnalignedGetBits )     ( struct bit_stream_s *, unsigned int );
+    void ( * CurrentPTS )           ( struct bit_stream_s *, mtime_t *,
+                                      mtime_t * );
 
     char * ( * DecodeLanguage ) ( u16 );
 
index 41efe6b..9fc6369 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-dec.h: structures exported to the VideoLAN decoders
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: input_ext-dec.h,v 1.50 2001/12/30 07:09:54 sam Exp $
+ * $Id: input_ext-dec.h,v 1.51 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Michel Kaempf <maxx@via.ecp.fr>
@@ -168,6 +168,12 @@ typedef struct bit_stream_s
     /* Optional argument to the callback */
     void *                  p_callback_arg;
 
+    /*
+     * PTS retrieval
+     */
+    mtime_t                 i_pts, i_dts;
+    byte_t *                p_pts_validity;
+
     /*
      * Byte structures
      */
@@ -215,10 +221,12 @@ typedef struct bit_stream_s
 u32  UnalignedShowBits( struct bit_stream_s *, unsigned int );
 void UnalignedRemoveBits( struct bit_stream_s * );
 u32  UnalignedGetBits( struct bit_stream_s *, unsigned int );
+void CurrentPTS( struct bit_stream_s *, mtime_t *, mtime_t * );
 #else
 #   define UnalignedShowBits p_symbols->UnalignedShowBits
 #   define UnalignedRemoveBits p_symbols->UnalignedRemoveBits
 #   define UnalignedGetBits p_symbols->UnalignedGetBits
+#   define CurrentPTS p_symbols->CurrentPTS
 #endif
 
 /*****************************************************************************
index bee6a55..bd10efc 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_adec.c: ac3 decoder module main file
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ac3_adec.c,v 1.13 2002/01/09 00:33:37 asmax Exp $
+ * $Id: ac3_adec.c,v 1.14 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Michel Lespinasse <walken@zoy.org>
  *
@@ -316,14 +316,12 @@ static int decoder_Run ( decoder_config_t * p_config )
                 return( -1 );
             }
         }
-        
-        if (p_ac3thread->p_fifo->p_first->i_pts)
+
+        CurrentPTS( &p_ac3thread->ac3_decoder->bit_stream,
+            &p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->l_end_frame],
+            NULL );
+        if( !p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->l_end_frame] )
         {
-            p_ac3thread->p_aout_fifo->date[
-                p_ac3thread->p_aout_fifo->l_end_frame] =
-                p_ac3thread->p_fifo->p_first->i_pts;
-            p_ac3thread->p_fifo->p_first->i_pts = 0;
-        } else {
             p_ac3thread->p_aout_fifo->date[
                 p_ac3thread->p_aout_fifo->l_end_frame] =
                 LAST_MDATE;
index 0b04331..5b2f43a 100644 (file)
@@ -2,7 +2,7 @@
  * lpcm_decoder_thread.c: lpcm decoder thread
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: lpcm_adec.c,v 1.8 2001/12/30 07:09:55 sam Exp $
+ * $Id: lpcm_adec.c,v 1.9 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Henri Fallon <henri@videolan.org>
@@ -170,14 +170,11 @@ void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
     int i_loop;
     byte_t byte1, byte2;
 
-    if( p_lpcmdec->p_fifo->p_first->i_pts )
+    CurrentPTS( &p_lpcmdec->bit_stream,
+        &p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame],
+        NULL );
+    if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] )
     {
-        p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
-            p_lpcmdec->p_fifo->p_first->i_pts;
-        p_lpcmdec->p_fifo->p_first->i_pts = 0;
-    }
-    else
-    { 
         p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
             LAST_MDATE;
     }
index 6127350..12efe1d 100644 (file)
@@ -170,6 +170,8 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
                       "for decoder_InitThread() to allocate p_mad_adec->libmad_decder" );
        return -1;
     }
+    p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
+
     /*
      * Initialize bit stream
      */
@@ -178,8 +180,6 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
                                              NULL,    /* pf_bitstream_callback */
                                              NULL );  /* void **/
 
-    RealignBits( &p_mad_adec->bit_stream );
-
     mad_decoder_init( p_mad_adec->libmad_decoder,
                      p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
                      libmad_input,     /* input_func */
index 01bbe26..6bf3d3f 100644 (file)
@@ -50,7 +50,7 @@ typedef struct mad_adec_thread_s
     decoder_config_t *  p_config;
 
     /* Store i_pts for syncing audio frames */
-    mtime_t            i_pts_save;
+    mtime_t            i_current_pts, i_next_pts;
 
     /*
      * Output properties
index cfbcb9c..5f2a36b 100644 (file)
@@ -50,13 +50,14 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
     size_t ReadSize, Remaining;
     unsigned char      *ReadStart;
 
-    /* Store time stamp of current frame */
-    if ( p_mad_adec->p_fifo->p_first->i_pts ) {
-         p_mad_adec->i_pts_save = p_mad_adec->p_fifo->p_first->i_pts;
-         p_mad_adec->p_fifo->p_first->i_pts = 0;
+    if ( p_mad_adec->p_fifo->b_die == 1 ) {
+        intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
+        return MAD_FLOW_STOP;
     }
-    else {
-         p_mad_adec->i_pts_save = LAST_MDATE;
+
+    if ( p_mad_adec->p_fifo->b_error == 1 ) {
+        intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );    
+        return MAD_FLOW_IGNORE;
     }
 
     /* libmad_stream_buffer does not consume the total buffer, it consumes only data
@@ -64,56 +65,80 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
      */
     if ((p_libmad_stream->buffer==NULL) || (p_libmad_stream->error==MAD_ERROR_BUFLEN))
     {
+        /* libmad does not consume all the buffer it's given. Some
+         * datas, part of a truncated frame, is left unused at the
+         * end of the buffer. Those datas must be put back at the
+         * beginning of the buffer and taken in account for
+         * refilling the buffer. This means that the input buffer
+         * must be large enough to hold a complete frame at the
+         * highest observable bit-rate (currently 448 kb/s). XXX=XXX
+         * Is 2016 bytes the size of the largest frame?
+         * (448000*(1152/32000))/8
+         */
+        if(p_libmad_stream->next_frame!=NULL)
+        {
+            Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
+            memmove(p_mad_adec->buffer,p_libmad_stream->next_frame,Remaining);
+            ReadStart=p_mad_adec->buffer+Remaining;
+            ReadSize=(MAD_BUFFER_SIZE)-Remaining;
+
+            /* Store time stamp of next frame */
+            p_mad_adec->i_current_pts = p_mad_adec->i_next_pts;
+            CurrentPTS( &p_mad_adec->bit_stream, &p_mad_adec->i_next_pts, NULL );
+        }
+        else
+        {
+            ReadSize=(MAD_BUFFER_SIZE);
+            ReadStart=p_mad_adec->buffer;
+            Remaining=0;
+            p_mad_adec->i_next_pts = 0;
+            CurrentPTS( &p_mad_adec->bit_stream, &p_mad_adec->i_current_pts, NULL );
+        }
 
-       /* libmad does not consume all the buffer it's given. Some
-        * datas, part of a truncated frame, is left unused at the
-        * end of the buffer. Those datas must be put back at the
-        * beginning of the buffer and taken in account for
-        * refilling the buffer. This means that the input buffer
-        * must be large enough to hold a complete frame at the
-        * highest observable bit-rate (currently 448 kb/s). XXX=XXX
-        * Is 2016 bytes the size of the largest frame?
-        * (448000*(1152/32000))/8
-        */
-       if(p_libmad_stream->next_frame!=NULL)
-       {
-               Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
-               memmove(p_mad_adec->buffer,p_libmad_stream->next_frame,Remaining);
-               ReadStart=p_mad_adec->buffer+Remaining;
-               ReadSize=(MAD_BUFFER_SIZE)-Remaining;
-       }
-       else
-       {
-               ReadSize=(MAD_BUFFER_SIZE);
-               ReadStart=p_mad_adec->buffer;
-               Remaining=0;
-       }
-       //intf_ErrMsg( "mad_adec debug: buffer size remaining [%d] and readsize [%d] total [%d]", 
-       //              Remaining, ReadSize, ReadSize+Remaining);
-
-       /* Fill-in the buffer. If an error occurs print a message
-        * and leave the decoding loop. If the end of stream is
-        * reached we also leave the loop but the return status is
-        * left untouched.
-        */
-       GetChunk( &p_mad_adec->bit_stream, ReadStart, ReadSize );
+        /* Fill-in the buffer. If an error occurs print a message
+         * and leave the decoding loop. If the end of stream is
+         * reached we also leave the loop but the return status is
+         * left untouched.
+         */
+#if 0
+        /* This is currently buggy --Meuuh */
+        if( ReadSize > p_mad_adec->bit_stream.p_end
+                        - p_mad_adec->bit_stream.p_byte )
+        {
+            FAST_MEMCPY( ReadStart, p_mad_adec->bit_stream.p_byte,
+               p_mad_adec->bit_stream.p_end - p_mad_adec->bit_stream.p_byte );
+            p_mad_adec->bit_stream.pf_next_data_packet( &p_mad_adec->bit_stream );
+        }
+        else
+        {
+            FAST_MEMCPY( ReadStart, p_mad_adec->bit_stream.p_byte,
+                         ReadSize );
+            p_mad_adec->bit_stream.p_byte += ReadSize;
+        }
+#else
+        /* This is PTS-inaccurate --Meuuh */
+        GetChunk( &p_mad_adec->bit_stream, ReadStart, ReadSize );
+#endif
 
-        if ( p_mad_adec->p_fifo->b_die == 1 ) {
+        if ( p_mad_adec->p_fifo->b_die == 1 )
+        {
             intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
             return MAD_FLOW_STOP;
         }
 
-        if ( p_mad_adec->p_fifo->b_error == 1 ) {
-            intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );        
+        if ( p_mad_adec->p_fifo->b_error == 1 )
+        {
+            intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );    
             return MAD_FLOW_IGNORE;
         }
 
-       /* Pipe the new buffer content to libmad's stream decoder facility.
-         * Libmad never copies the buffer, but just references it. So keep it in 
-        * mad_adec_thread_t structure.
-        */
-       mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,ReadSize+Remaining);
-       p_libmad_stream->error=0;
+        /* Pipe the new buffer content to libmad's stream decoder facility.
+         * Libmad never copies the buffer, but just references it. So keep it in
+         * mad_adec_thread_t structure.
+         */
+        mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,
+                          MAD_BUFFER_SIZE);
+        p_libmad_stream->error=0;
     }
 
     return MAD_FLOW_CONTINUE;
@@ -270,7 +295,8 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
 #endif
 
     /* Creating the audio output fifo */
-    if (p_mad_adec->p_aout_fifo==NULL) {
+    if (p_mad_adec->p_aout_fifo==NULL)
+    {
        p_mad_adec->p_aout_fifo = aout_CreateFifo(  
                AOUT_ADEC_STEREO_FIFO,          /* fifo type */
                p_libmad_pcm->channels,         /* nr. of channels */
@@ -284,10 +310,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
                return( -1 );
        }
 
-       intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
+        intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
     }
-    else {
-       p_mad_adec->p_aout_fifo->l_rate = p_libmad_pcm->samplerate;
+    else
+    {
+        p_mad_adec->p_aout_fifo->l_rate = p_libmad_pcm->samplerate;
     }
 
 /* Some frames are nog quite right. Why ??? I do not know. Probably syncing and CRC errors ??
@@ -306,7 +333,17 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
     }
 
     /* Set timestamp to synchronize audio and video decoder fifo's */
-    p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame] = p_mad_adec->i_pts_save;
+    p_mad_adec->p_aout_fifo->l_rate = p_libmad_header->samplerate;
+    if( p_mad_adec->i_current_pts )
+    {
+        p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame]
+                = p_mad_adec->i_current_pts;
+    }
+    else
+    {
+        p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame]
+                = LAST_MDATE;
+    }
     mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
 
     buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->l_end_frame * MAD_OUTPUT_SIZE);
index a0989b1..c0e3244 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_adec.c: MPEG audio decoder thread
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: mpeg_adec.c,v 1.13 2002/01/10 23:41:08 asmax Exp $
+ * $Id: mpeg_adec.c,v 1.14 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Michel Lespinasse <walken@via.ecp.fr>
@@ -153,7 +153,7 @@ static int decoder_Run ( decoder_config_t * p_config )
 }
 
 /*
- * Following finctions are local to this module
+ * Following functions are local to this module
  */
 
 /*****************************************************************************
@@ -203,13 +203,10 @@ static void DecodeThread( adec_thread_t * p_adec )
         buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
                     + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
 
-        if( p_adec->p_fifo->p_first->i_pts )
-        {
-            p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
-                p_adec->p_fifo->p_first->i_pts;
-            p_adec->p_fifo->p_first->i_pts = 0;
-        }
-        else
+        CurrentPTS( &p_adec->bit_stream,
+            &p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame],
+            NULL );
+        if( !p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] )
         {
             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
                 LAST_MDATE;
index 49d1361..a35e614 100644 (file)
@@ -2,7 +2,7 @@
  * video_parser.c : video parser thread
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: video_parser.c,v 1.10 2001/12/30 07:09:56 sam Exp $
+ * $Id: video_parser.c,v 1.11 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Samuel Hocevar <sam@via.ecp.fr>
@@ -384,10 +384,6 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream,
 
     if( b_new_pes )
     {
-        p_vpar->sequence.next_pts =
-            p_bit_stream->p_decoder_fifo->p_first->i_pts;
-        p_vpar->sequence.next_dts =
-            p_bit_stream->p_decoder_fifo->p_first->i_dts;
         p_vpar->sequence.i_current_rate =
             p_bit_stream->p_decoder_fifo->p_first->i_rate;
 
index bcdcec1..7b6a55a 100644 (file)
@@ -2,7 +2,7 @@
  * vpar_headers.c : headers parsing
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: vpar_headers.c,v 1.11 2002/01/14 22:26:05 massiot Exp $
+ * $Id: vpar_headers.c,v 1.12 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          St├ęphane Borel <stef@via.ecp.fr>
@@ -263,7 +263,6 @@ int vpar_ParseHeader( vpar_thread_t * p_vpar )
     {
     case SEQUENCE_HEADER_CODE:
         p_vpar->c_sequences++;
-
         SequenceHeader( p_vpar );
         return 0;
         break;
@@ -540,6 +539,10 @@ static void PictureHeader( vpar_thread_t * p_vpar )
     int                 i_structure, i_previous_coding_type;
     boolean_t           b_parsable = 0;
 
+    /* Retrieve the PTS. */
+    CurrentPTS( &p_vpar->bit_stream, &p_vpar->sequence.next_pts,
+                &p_vpar->sequence.next_dts );
+
     /* Recover in case of stream discontinuity. */
     if( p_vpar->sequence.b_expect_discontinuity )
     {
index fe39a1d..9239ac3 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-dec.c: services to the decoders
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input_ext-dec.c,v 1.27 2001/12/31 03:26:27 massiot Exp $
+ * $Id: input_ext-dec.c,v 1.28 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -63,6 +63,9 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
     p_bit_stream->p_end  = p_bit_stream->p_data->p_payload_end;
     p_bit_stream->fifo.buffer = 0;
     p_bit_stream->fifo.i_available = 0;
+    p_bit_stream->i_pts = p_fifo->p_first->i_pts;
+    p_bit_stream->i_dts = p_fifo->p_first->i_dts;
+    p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
     vlc_mutex_unlock( &p_fifo->data_lock );
 
     /* Call back the decoder. */
@@ -170,6 +173,20 @@ void NextDataPacket( bit_stream_t * p_bit_stream )
     {
         p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
     }
+
+    /* Discontinuity management. */
+    if( p_bit_stream->p_data->b_discard_payload )
+    {
+        p_bit_stream->i_pts = p_bit_stream->i_dts = 0;
+    }
+
+    /* Retrieve the PTS. */
+    if( b_new_pes && p_fifo->p_first->i_pts )
+    {
+        p_bit_stream->i_pts = p_fifo->p_first->i_pts;
+        p_bit_stream->i_dts = p_fifo->p_first->i_dts;
+        p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
+    }
 }
 
 /*****************************************************************************
@@ -375,3 +392,28 @@ void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
     }
 }
 
+/*****************************************************************************
+ * CurrentPTS: returns the current PTS and DTS
+ *****************************************************************************/
+void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
+                 mtime_t * pi_dts )
+{
+    /* Check if the current PTS is already valid (ie. if the first byte
+     * of the packet has already been used in the decoder). */
+    ptrdiff_t p_diff = p_bit_stream->p_byte - p_bit_stream->p_pts_validity;
+    if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
+         || (p_diff * 8) >= p_bit_stream->fifo.i_available
+            /* We have buffered less bytes than actually read */ )
+    {
+        *pi_pts = p_bit_stream->i_pts;
+        if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
+        p_bit_stream->i_pts = 0;
+        p_bit_stream->i_dts = 0;
+    }
+    else
+    {
+        *pi_pts = 0;
+        if( pi_dts != NULL) *pi_dts = 0;
+    }
+}
+
index 0535ca0..1872a79 100644 (file)
@@ -2,7 +2,7 @@
  * modules_plugin.h : Plugin management functions used by the core application.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: modules_plugin.h,v 1.4 2002/01/09 02:01:14 sam Exp $
+ * $Id: modules_plugin.h,v 1.5 2002/01/14 23:46:35 massiot Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -226,6 +226,7 @@ module_error( void )
     (p_symbols)->UnalignedGetBits = UnalignedGetBits; \
     (p_symbols)->UnalignedRemoveBits = UnalignedRemoveBits; \
     (p_symbols)->UnalignedShowBits = UnalignedShowBits; \
+    (p_symbols)->CurrentPTS = CurrentPTS; \
     (p_symbols)->DecodeLanguage = DecodeLanguage; \
     (p_symbols)->module_Need = module_Need; \
     (p_symbols)->module_Unneed = module_Unneed;