]> git.sesse.net Git - vlc/blobdiff - src/input/stream.c
* es_out: select es from current program only.
[vlc] / src / input / stream.c
index 6d447b4b86cb31651527c422ab5b2efa18c1837f..9f0c7d1fbb6973096c280cfc29585a8ceaca9b12 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * stream.c
  *****************************************************************************
- * Copyright (C) 1999-2001 VideoLAN
- * $Id: stream.c,v 1.2 2003/08/14 11:25:56 sigmunau Exp $
+ * Copyright (C) 1999-2004 VideoLAN
+ * $Id: stream.c,v 1.11 2004/01/16 11:12:16 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -27,6 +27,7 @@
 
 #include "ninput.h"
 
+#define MAX_LINE 1024
 /****************************************************************************
  * stream_* :
  * XXX for now it's just a wrapper
@@ -48,7 +49,7 @@ struct stream_t
 /**
  * Create a "stream_t *" from an "input_thread_t *".
  */
-stream_t    *stream_OpenInput( input_thread_t *p_input )
+stream_t *stream_OpenInput( input_thread_t *p_input )
 {
     stream_t *s;
 
@@ -64,18 +65,20 @@ stream_t    *stream_OpenInput( input_thread_t *p_input )
 /**
  * Destroy a previously created "stream_t *" instance.
  */
-void        stream_Release( stream_t *s )
+void stream_Release( stream_t *s )
 {
     vlc_object_destroy( s );
 }
 
 /**
- * Similar to #stream_Control(), but takes a va_list and not variable arguments.
+ * Similar to #stream_Control(), but takes a va_list and not variable
+ * arguments.
  */
-int         stream_vaControl( stream_t *s, int i_query, va_list args )
+int stream_vaControl( stream_t *s, int i_query, va_list args )
 {
     vlc_bool_t *p_b;
     int64_t    *p_i64, i64;
+    int        *p_int;
 
     switch( i_query )
     {
@@ -99,7 +102,8 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
             p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
 
             vlc_mutex_lock( &s->p_input->stream.stream_lock );
-            *p_b = s->p_input->stream.b_seekable && s->p_input->stream.i_method == INPUT_METHOD_FILE;
+            *p_b = s->p_input->stream.b_seekable &&
+                   s->p_input->stream.i_method == INPUT_METHOD_FILE;
             vlc_mutex_unlock( &s->p_input->stream.stream_lock );
             return VLC_SUCCESS;
 
@@ -120,7 +124,7 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
                   s->p_input->stream.p_selected_area->i_size < i64 ) )
             {
                 vlc_mutex_unlock( &s->p_input->stream.stream_lock );
-                msg_Err( s, "seek out of bound" );
+                msg_Warn( s, "seek out of bound" );
                 return VLC_EGENERIC;
             }
             vlc_mutex_unlock( &s->p_input->stream.stream_lock );
@@ -133,7 +137,7 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
             if( s->p_input->stream.b_seekable &&
                 ( s->p_input->stream.i_method == INPUT_METHOD_FILE ||
                   i64 - s->p_input->stream.p_selected_area->i_tell < 0 ||
-                  i64 - s->p_input->stream.p_selected_area->i_tell > 1024 ) )
+                  i64 - s->p_input->stream.p_selected_area->i_tell > 4096 ) )
             {
                 input_AccessReinit( s->p_input );
                 s->p_input->pf_seek( s->p_input, i64 );
@@ -142,16 +146,20 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
 
             if( i64 - s->p_input->stream.p_selected_area->i_tell > 0 )
             {
-                data_packet_t   *p_data;
-                int             i_skip = i64 - s->p_input->stream.p_selected_area->i_tell;
+                data_packet_t *p_data;
+                int i_skip = i64 - s->p_input->stream.p_selected_area->i_tell;
 
-                msg_Warn( s, "will skip %d bytes, slow", i_skip );
+                if( i_skip > 1000 )
+                {
+                    msg_Warn( s, "will skip %d bytes, slow", i_skip );
+                }
 
                 while (i_skip > 0 )
                 {
                     int i_read;
 
-                    i_read = input_SplitBuffer( s->p_input, &p_data, __MIN( 4096, i_skip ) );
+                    i_read = input_SplitBuffer( s->p_input, &p_data,
+                                 __MIN( (int)s->p_input->i_bufsize, i_skip ) );
                     if( i_read < 0 )
                     {
                         return VLC_EGENERIC;
@@ -165,7 +173,11 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
                     }
                 }
             }
+            return VLC_SUCCESS;
 
+        case STREAM_GET_MTU:
+            p_int = (int*) va_arg( args, int * );
+            *p_int = s->p_input->i_mtu;
             return VLC_SUCCESS;
 
         default:
@@ -179,7 +191,7 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
  * possible "i_query" value and format arguments.  Return VLC_SUCCESS
  * if ... succeed ;) and VLC_EGENERIC if failed or unimplemented
  */
-int         stream_Control( stream_t *s, int i_query, ... )
+int stream_Control( stream_t *s, int i_query, ... )
 {
     va_list args;
     int     i_result;
@@ -197,7 +209,7 @@ int         stream_Control( stream_t *s, int i_query, ... )
  * value is the real numbers of bytes read/skip. If this value is less
  * than i_read that means that it's the end of the stream.
  */
-int         stream_Read( stream_t *s, void *p_data, int i_data )
+int stream_Read( stream_t *s, void *p_data, int i_data )
 {
     uint8_t       *p = (uint8_t*)p_data;
     data_packet_t *p_packet;
@@ -222,9 +234,14 @@ int         stream_Read( stream_t *s, void *p_data, int i_data )
     {
         int i_count;
 
-        i_count = input_SplitBuffer( s->p_input, &p_packet, __MIN( i_data, 4096 ) );
+        i_count = input_SplitBuffer( s->p_input, &p_packet,
+                      __MIN( i_data, (int)s->p_input->i_bufsize ) );
+
         if( i_count <= 0 )
         {
+            if( i_count == 0 )
+                input_DeletePacket( s->p_input->p_method_data, p_packet );
+
             return i_read;
         }
 
@@ -245,17 +262,75 @@ int         stream_Read( stream_t *s, void *p_data, int i_data )
 
 /**
  * Store in pp_peek a pointer to the next "i_peek" bytes in the stream
- * The return value is the real numbers of valid bytes, if it's less
- * or equal to 0, *pp_peek is invalid.  XXX: it's a pointer to
- * internal buffer and it will be invalid as soons as other stream_*
- * functions are called.  be 0 (then *pp_peek isn't valid).  XXX: due
- * to input limitation, it could be less than i_peek without meaning
+ * \return The real numbers of valid bytes, if it's less
+ * or equal to 0, *pp_peek is invalid.
+ * \note pp_peek is a pointer to internal buffer and it will be invalid as
+ * soons as other stream_* functions are called.
+ * \note Due to input limitation, it could be less than i_peek without meaning
  * the end of the stream (but only when you have i_peek >=
  * p_input->i_bufsize)
  */
-int         stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data )
+int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_peek )
+{
+    return input_Peek( s->p_input, pp_peek, i_peek );
+}
+
+/**
+ * Read "i_size" bytes and store them in a block_t. If less than "i_size"
+ * bytes are available then return what is left and if nothing is availble,
+ * return NULL.
+ */
+block_t *stream_Block( stream_t *s, int i_size )
+{
+    block_t *p_block;
+
+    if( i_size <= 0 ) return NULL;
+    if( !(p_block = block_New( s->p_input, i_size ) ) ) return NULL;
+
+    p_block->i_buffer = stream_Read( s, p_block->p_buffer, i_size );
+    if( !p_block->i_buffer )
+    {
+        block_Release( p_block );
+        p_block = NULL;
+    }
+
+    return p_block;
+}
+
+/**
+ * Read from the stream untill first newline.
+ * \param s Stream handle to read from
+ * \return A null-terminated string. This must be freed,
+ */
+char *stream_ReadLine( stream_t *s )
 {
-    return input_Peek( s->p_input, pp_peek, i_data );
+    uint8_t *p_data;
+    char    *p_line;
+    int      i_data;
+    int      i = 0;
+    i_data = stream_Peek( s, &p_data, MAX_LINE );
+    msg_Dbg( s->p_input, "i_data %d", i_data );
+    while( i < i_data && p_data[i] != '\n' )
+    {
+        i++;
+    }
+    if( i_data <= 0 )
+    {
+        return NULL;
+    }
+    else
+    {
+        p_line = malloc( i + 1 );
+        if( p_line == NULL )
+        {
+            msg_Err( s->p_input, "Out of memory" );
+            return NULL;
+        }
+        i = stream_Read( s, p_line, i + 1 );
+        p_line[ i - 1 ] = '\0';
+        msg_Dbg( s->p_input, "found %d chars long line", i );
+        return p_line;
+    }
 }
 
 /**
@@ -264,7 +339,7 @@ int         stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data )
  * you need to fill i_dts, i_pts, ... ) If only less than "i_size"
  * bytes are available NULL is returned.
  */
-pes_packet_t    *stream_PesPacket( stream_t *s, int i_data )
+pes_packet_t *stream_PesPacket( stream_t *s, int i_data )
 {
     pes_packet_t  *p_pes;
     data_packet_t *p_packet;
@@ -278,8 +353,7 @@ pes_packet_t    *stream_PesPacket( stream_t *s, int i_data )
     if( i_data <= 0 )
     {
         p_pes->p_first =
-            p_pes->p_last  =
-                input_NewPacket( s->p_input->p_method_data, 0 );
+            p_pes->p_last = input_NewPacket( s->p_input->p_method_data, 0 );
         p_pes->i_nb_data = 1;
         return p_pes;
     }
@@ -288,7 +362,8 @@ pes_packet_t    *stream_PesPacket( stream_t *s, int i_data )
     {
         int i_read;
 
-        i_read = input_SplitBuffer( s->p_input, &p_packet, __MIN( i_data, 4096 ) );
+        i_read = input_SplitBuffer( s->p_input, &p_packet,
+                     __MIN( i_data, (int)s->p_input->i_bufsize ) );
         if( i_read <= 0 )
         {
             /* should occur only with EOF and max allocation reached 
@@ -309,13 +384,61 @@ pes_packet_t    *stream_PesPacket( stream_t *s, int i_data )
         p_pes->p_last = p_packet;
         p_pes->i_nb_data++;
         p_pes->i_pes_size += i_read;
-        i_data            -= i_read;
+        i_data -= i_read;
     }
 
     return p_pes;
 }
 
+/**
+ * Read i_size into a data_packet_t. If b_force is not set, fewer bytes can
+ * be returned. You should always set b_force, unless you know what you are
+ * doing.
+ */
+data_packet_t *stream_DataPacket( stream_t *s, int i_size, vlc_bool_t b_force )
+{
+    data_packet_t *p_pk;
+    int           i_read;
+
+    if( i_size <= 0 )
+    {
+        p_pk = input_NewPacket( s->p_input->p_method_data, 0 );
+        if( p_pk )
+        {
+            p_pk->p_payload_end = p_pk->p_payload_start;
+        }
+        return p_pk;
+    }
+
+    i_read = input_SplitBuffer( s->p_input, &p_pk, i_size );
+    if( i_read <= 0 )
+    {
+        return NULL;
+    }
 
+    /* Should be really rare, near 0 */
+    if( i_read < i_size && b_force )
+    {
+        data_packet_t *p_old = p_pk;
+        int           i_missing = i_size - i_read;
 
+        p_pk = input_NewPacket( s->p_input->p_method_data, i_size );
+        if( p_pk == NULL )
+        {
+            input_DeletePacket( s->p_input->p_method_data, p_old );
+            return NULL;
+        }
+        p_pk->p_payload_end = p_pk->p_payload_start + i_size;
+        memcpy( p_pk->p_payload_start, p_old->p_payload_start, i_read );
+        input_DeletePacket( s->p_input->p_method_data, p_old );
 
+        if( stream_Read( s, &p_pk->p_payload_start[i_read], i_missing )
+            < i_missing )
+        {
+            input_DeletePacket( s->p_input->p_method_data, p_pk );
+            return NULL;
+        }
+    }
 
+    return p_pk;
+}