]> git.sesse.net Git - vlc/blobdiff - src/input/input_ext-dec.c
* ./include/*, ./src/*: separated WIN32 #tests and UNDER_CE #tests, because
[vlc] / src / input / input_ext-dec.c
index 7563d84dbd773f4513eaf204eb1ad3369571aa98..79037f3dd89ef39ee4faebe7227e8b09cb9a5b1a 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.32 2002/06/01 12:32:01 sam Exp $
+ * $Id: input_ext-dec.c,v 1.41 2002/11/11 14:39:12 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -25,7 +25,6 @@
  * Preamble
  *****************************************************************************/
 #include <string.h>                                    /* memcpy(), memset() */
-#include <sys/types.h>                                              /* off_t */
 
 #include <vlc/vlc.h>
 
 #include "input_ext-plugins.h"
 
 /*****************************************************************************
- * InitBitstream: initialize a bit_stream_t structure
+ * InitBitstream: initialize a bit_stream_t structure and returns VLC_SUCCESS
+ *                on success.
  *****************************************************************************/
-void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
+int InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
                 void (* pf_bitstream_callback)( bit_stream_t *, vlc_bool_t ),
                 void * p_callback_arg )
 {
+    /* Get the first pes packet */
+    input_ExtractPES( p_fifo, &p_bit_stream->p_pes );
+    if( !p_bit_stream->p_pes )
+       return VLC_EGENERIC;
+
     p_bit_stream->p_decoder_fifo = p_fifo;
     p_bit_stream->pf_bitstream_callback = pf_bitstream_callback;
     p_bit_stream->p_callback_arg = p_callback_arg;
 
-    /* Get the first data packet. */
-    vlc_mutex_lock( &p_fifo->data_lock );
-    while ( p_fifo->p_first == NULL )
-    {
-        if ( p_fifo->b_die )
-        {
-            vlc_mutex_unlock( &p_fifo->data_lock );
-            return;
-        }
-        vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
-    }
-    p_bit_stream->p_data = p_fifo->p_first->p_first;
+    p_bit_stream->p_data = p_bit_stream->p_pes->p_first;
     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
     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->i_pts = p_bit_stream->p_pes->i_pts;
+    p_bit_stream->i_dts = p_bit_stream->p_pes->i_dts;
     p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
-    vlc_mutex_unlock( &p_fifo->data_lock );
 
     /* Call back the decoder. */
     if( p_bit_stream->pf_bitstream_callback != NULL )
@@ -80,6 +73,18 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
          * sizeof(WORD_TYPE) - 1 empty bytes in the bit buffer. */
         AlignWord( p_bit_stream );
     }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseBitstream: free the bitstream structure.
+ *****************************************************************************/
+void CloseBitstream( bit_stream_t * p_bit_stream )
+{
+    if( p_bit_stream->p_pes )
+        input_DeletePES( p_bit_stream->p_decoder_fifo->p_packets_mgt,
+                         p_bit_stream->p_pes );
 }
 
 /*****************************************************************************
@@ -87,32 +92,25 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
  *****************************************************************************/
 void DecoderError( decoder_fifo_t * p_fifo )
 {
-    /* We take the lock, because we are going to read/write the start/end
-     * indexes of the decoder fifo */
-    vlc_mutex_lock (&p_fifo->data_lock);
+    /* No need to take the lock, because input_ExtractPES already takes it
+     * and also check for p_fifo->b_die */
 
     /* Wait until a `die' order is sent */
-    while (!p_fifo->b_die)
+    while( !p_fifo->b_die )
     {
         /* Trash all received PES packets */
-        input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
-        p_fifo->p_first = NULL;
-        p_fifo->pp_last = &p_fifo->p_first;
-
-        /* Waiting for the input thread to put new PES packets in the fifo */
-        vlc_cond_wait (&p_fifo->data_wait, &p_fifo->data_lock);
+        input_ExtractPES( p_fifo, NULL );
     }
-
-    /* We can release the lock before leaving */
-    vlc_mutex_unlock (&p_fifo->data_lock);
 }
 
 /*****************************************************************************
  * NextDataPacket: go to the data packet after *pp_data, return 1 if we
- * changed PES
+ * changed PES. This function can fail in case of end of stream, you can
+ * check p_bit_stream->p_data or p_bit_stream->p_pes to know wether we did get
+ * the next data packet.
  *****************************************************************************/
 static inline vlc_bool_t _NextDataPacket( decoder_fifo_t * p_fifo,
-                                          data_packet_t ** pp_data )
+                                          bit_stream_t * p_bit_stream )
 {
     vlc_bool_t b_new_pes;
 
@@ -122,68 +120,51 @@ static inline vlc_bool_t _NextDataPacket( decoder_fifo_t * p_fifo,
     {
         /* We were reading the last data packet of this PES packet... It's
          * time to jump to the next PES packet */
-        if( (*pp_data)->p_next == NULL )
+        if( p_bit_stream->p_data->p_next == NULL )
         {
-            pes_packet_t * p_next;
-
-            vlc_mutex_lock( &p_fifo->data_lock );
-
-            /* Free the previous PES packet. */
-            p_next = p_fifo->p_first->p_next;
-            p_fifo->p_first->p_next = NULL;
-            input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
-            p_fifo->p_first = p_next;
-            p_fifo->i_depth--;
-
-            if( p_fifo->p_first == NULL )
-            {
-                /* No PES in the FIFO. p_last is no longer valid. */
-                p_fifo->pp_last = &p_fifo->p_first;
-
-                /* Signal the input thread we're waiting. This is only
-                 * needed in case of slave clock (ES plug-in)  but it won't
-                 * harm. */
-                vlc_cond_signal( &p_fifo->data_wait );
-
-                /* Wait for the input to tell us when we receive a packet. */
-                vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
-            }
-
             /* The next packet could be found in the next PES packet */
-            *pp_data = p_fifo->p_first->p_first;
-
-            vlc_mutex_unlock( &p_fifo->data_lock );
-
+           input_DeletePES( p_fifo->p_packets_mgt, p_bit_stream->p_pes );
+            input_ExtractPES( p_fifo, &p_bit_stream->p_pes );
+           if( !p_bit_stream->p_pes )
+            {
+               /* Couldn't get the next PES, might be an eos */
+               p_bit_stream->p_data = NULL;
+               return 0;
+           }
+            p_bit_stream->p_data = p_bit_stream->p_pes->p_first;
             b_new_pes = 1;
         }
         else
         {
             /* Perhaps the next data packet of the current PES packet contains
              * real data (ie its payload's size is greater than 0). */
-            *pp_data = (*pp_data)->p_next;
+            p_bit_stream->p_data = p_bit_stream->p_data->p_next;
 
             b_new_pes = 0;
         }
-    } while ( (*pp_data)->p_payload_start == (*pp_data)->p_payload_end );
+    } while ( p_bit_stream->p_data->p_payload_start ==
+             p_bit_stream->p_data->p_payload_end );
 
     return( b_new_pes );
 }
 
-vlc_bool_t NextDataPacket( decoder_fifo_t * p_fifo, data_packet_t ** pp_data )
+vlc_bool_t NextDataPacket( decoder_fifo_t * p_fifo,
+                          bit_stream_t * p_bit_stream )
 {
-    return( _NextDataPacket( p_fifo, pp_data ) );
+    return( _NextDataPacket( p_fifo, p_bit_stream ) );
 }
 
 /*****************************************************************************
  * BitstreamNextDataPacket: go to the next data packet, and update bitstream
- * context
+ * context. This function can fail in case of eos!
  *****************************************************************************/
 static inline void _BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
 {
     decoder_fifo_t *    p_fifo = p_bit_stream->p_decoder_fifo;
     vlc_bool_t          b_new_pes;
 
-    b_new_pes = _NextDataPacket( p_fifo, &p_bit_stream->p_data );
+    b_new_pes = _NextDataPacket( p_fifo, p_bit_stream );
+    if( !p_bit_stream->p_pes ) return;
 
     /* We've found a data packet which contains interesting data... */
     p_bit_stream->p_byte = p_bit_stream->p_data->p_payload_start;
@@ -202,10 +183,10 @@ static inline void _BitstreamNextDataPacket( bit_stream_t * p_bit_stream )
     }
 
     /* Retrieve the PTS. */
-    if( b_new_pes && p_fifo->p_first->i_pts )
+    if( b_new_pes && p_bit_stream->p_pes->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->i_pts = p_bit_stream->p_pes->i_pts;
+        p_bit_stream->i_dts = p_bit_stream->p_pes->i_dts;
         p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
     }
 }
@@ -426,7 +407,7 @@ void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
 {
     /* 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;
+    ptrdiff_t p_diff = p_bit_stream->p_pts_validity - p_bit_stream->p_byte;
     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 */ )
@@ -443,3 +424,27 @@ void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
     }
 }
 
+/*****************************************************************************
+ * NextPTS: returns the PTS and DTS for the next starting byte
+ *****************************************************************************/
+void NextPTS( 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_pts_validity - p_bit_stream->p_byte - 1;
+    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;
+    }
+}