]> git.sesse.net Git - vlc/blobdiff - src/input/stream.c
* input_dec: sout uses block_t.
[vlc] / src / input / stream.c
index 08ac2314f6d963420dcd72ab670c1f7dcf98f0ff..ff2f6a6661558d94f875c3b2b05c9bcbcc9bf55a 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * stream.c
  *****************************************************************************
- * Copyright (C) 1999-2001 VideoLAN
- * $Id: stream.c,v 1.1 2003/08/01 00:00:12 fenrir Exp $
+ * Copyright (C) 1999-2004 VideoLAN
+ * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
 #include "ninput.h"
 
 /****************************************************************************
- * stream_* :
- * XXX for now it's just a wrapper
- *
+ * stream_ReadLine:
  ****************************************************************************/
-
-struct stream_t
+/**
+ * Read from the stream untill first newline.
+ * \param s Stream handle to read from
+ * \return A null-terminated string. This must be freed,
+ */
+/* FIXME don't use stupid MAX_LINE -> do the same than net_ReadLine */
+#define MAX_LINE 1024
+char *stream_ReadLine( stream_t *s )
 {
-    VLC_COMMON_MEMBERS
+    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, "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, "out of memory" );
+            return NULL;
+        }
+        i = stream_Read( s, p_line, i + 1 );
+        p_line[ i - 1 ] = '\0';
+        msg_Dbg( s, "found %d chars long line", i );
+        return p_line;
+    }
+}
 
-    input_thread_t *p_input;
 
-};
 
-stream_t    *stream_OpenInput( input_thread_t *p_input )
+/* TODO: one day we should create a special module stream
+ * when we would have a access wrapper, and stream filter
+ * (like caching, progessive, gunzip, ... )
+ */
+
+/* private stream_sys_t for input_Stream* */
+struct stream_sys_t
 {
-    stream_t *s;
+    input_thread_t *p_input;
+};
+
+/* private pf_* functions declarations */
+static int      IStreamRead   ( stream_t *, void *p_read, int i_read );
+static int      IStreamPeek   ( stream_t *, uint8_t **pp_peek, int i_peek );
+static int      IStreamControl( stream_t *, int i_query, va_list );
 
-    s = vlc_object_create( p_input, sizeof( stream_t ) );
+/****************************************************************************
+ * input_StreamNew: create a wrapper for p_input access
+ ****************************************************************************/
+stream_t *input_StreamNew( input_thread_t *p_input )
+{
+    stream_t *s = vlc_object_create( p_input, sizeof( stream_t ) );
     if( s )
     {
-        s->p_input = p_input;
-    }
+        s->pf_block  = NULL;
+        s->pf_read   = IStreamRead;
+        s->pf_peek   = IStreamPeek;
+        s->pf_control= IStreamControl;
 
+        s->p_sys = malloc( sizeof( stream_sys_t ) );
+        s->p_sys->p_input = p_input;
+    }
     return s;
 }
 
-void        stream_Release( stream_t *s )
+/****************************************************************************
+ * input_StreamDelete:
+ ****************************************************************************/
+void input_StreamDelete( stream_t *s )
 {
+    free( s->p_sys );
     vlc_object_destroy( s );
 }
 
-int         stream_vaControl( stream_t *s, int i_query, va_list args )
+
+/****************************************************************************
+ * IStreamControl:
+ ****************************************************************************/
+static int IStreamControl( stream_t *s, int i_query, va_list args )
 {
+    input_thread_t *p_input = s->p_sys->p_input;
+
     vlc_bool_t *p_b;
     int64_t    *p_i64, i64;
+    int        *p_int;
 
     switch( i_query )
     {
         case STREAM_GET_SIZE:
             p_i64 = (int64_t*) va_arg( args, int64_t * );
 
-            vlc_mutex_lock( &s->p_input->stream.stream_lock );
-            *p_i64 = s->p_input->stream.p_selected_area->i_size;
-            vlc_mutex_unlock( &s->p_input->stream.stream_lock );
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            *p_i64 = p_input->stream.p_selected_area->i_size;
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
             return VLC_SUCCESS;
 
         case STREAM_CAN_SEEK:
             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;
-            vlc_mutex_unlock( &s->p_input->stream.stream_lock );
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            *p_b = p_input->stream.b_seekable;
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
             return VLC_SUCCESS;
 
         case STREAM_CAN_FASTSEEK:
             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;
-            vlc_mutex_unlock( &s->p_input->stream.stream_lock );
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            *p_b = p_input->stream.b_seekable &&
+                   p_input->stream.i_method == INPUT_METHOD_FILE;
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
             return VLC_SUCCESS;
 
         case STREAM_GET_POSITION:
             p_i64 = (int64_t*) va_arg( args, int64_t * );
 
-            vlc_mutex_lock( &s->p_input->stream.stream_lock );
-            *p_i64 = s->p_input->stream.p_selected_area->i_tell;
-            vlc_mutex_unlock( &s->p_input->stream.stream_lock );
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            *p_i64 = p_input->stream.p_selected_area->i_tell;
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
             return VLC_SUCCESS;
 
         case STREAM_SET_POSITION:
+        {
+            int64_t i_skip;
             i64 = (int64_t) va_arg( args, int64_t );
 
-            vlc_mutex_lock( &s->p_input->stream.stream_lock );
+            vlc_mutex_lock( &p_input->stream.stream_lock );
             if( i64 < 0 ||
-                ( s->p_input->stream.p_selected_area->i_size > 0 &&
-                  s->p_input->stream.p_selected_area->i_size < i64 ) )
+                ( p_input->stream.p_selected_area->i_size > 0 &&
+                  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" );
+                vlc_mutex_unlock( &p_input->stream.stream_lock );
+                msg_Warn( s, "seek out of bound" );
                 return VLC_EGENERIC;
             }
-            vlc_mutex_unlock( &s->p_input->stream.stream_lock );
 
-            if( i64 == s->p_input->stream.p_selected_area->i_tell )
+            i_skip = i64 - p_input->stream.p_selected_area->i_tell;
+
+            if( i_skip == 0 )
+            {
+                vlc_mutex_unlock( &p_input->stream.stream_lock );
+                return VLC_SUCCESS;
+            }
+
+            if( i_skip > 0 && i_skip < p_input->p_last_data -
+                            p_input->p_current_data - 1 )
             {
+                /* We can skip without reading/seeking */
+                p_input->p_current_data += i_skip;
+                p_input->stream.p_selected_area->i_tell = i64;
+                vlc_mutex_unlock( &p_input->stream.stream_lock );
                 return VLC_SUCCESS;
             }
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-            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 ) )
+            if( p_input->stream.b_seekable &&
+                ( p_input->stream.i_method == INPUT_METHOD_FILE ||
+                  i_skip < 0 || i_skip >= ( p_input->i_mtu > 0 ?
+                                            p_input->i_mtu : 4096 ) ) )
             {
-                input_AccessReinit( s->p_input );
-                s->p_input->pf_seek( s->p_input, i64 );
+                input_AccessReinit( p_input );
+                p_input->pf_seek( p_input, i64 );
                 return VLC_SUCCESS;
             }
 
-            if( i64 - s->p_input->stream.p_selected_area->i_tell > 0 )
+            if( i_skip > 0 )
             {
-                data_packet_t   *p_data;
-                int             i_skip = i64 - s->p_input->stream.p_selected_area->i_tell;
+                data_packet_t *p_data;
 
-                msg_Warn( s, "will skip %d bytes, slow", i_skip );
+                if( i_skip > 1000 )
+                {
+                    msg_Warn( s, "will skip "I64Fd" bytes, slow", i_skip );
+                }
 
-                while (i_skip > 0 )
+                whilei_skip > 0 )
                 {
                     int i_read;
 
-                    i_read = input_SplitBuffer( s->p_input, &p_data, __MIN( 4096, i_skip ) );
+                    i_read = input_SplitBuffer( p_input, &p_data,
+                                 __MIN( (int)p_input->i_bufsize, i_skip ) );
                     if( i_read < 0 )
                     {
                         return VLC_EGENERIC;
                     }
                     i_skip -= i_read;
 
-                    input_DeletePacket( s->p_input->p_method_data, p_data );
+                    input_DeletePacket( p_input->p_method_data, p_data );
                     if( i_read == 0 && i_skip > 0 )
                     {
                         return VLC_EGENERIC;
                     }
                 }
             }
+            return VLC_SUCCESS;
+        }
 
+        case STREAM_GET_MTU:
+            p_int = (int*) va_arg( args, int * );
+            *p_int = p_input->i_mtu;
             return VLC_SUCCESS;
 
         default:
@@ -161,22 +247,13 @@ int         stream_vaControl( stream_t *s, int i_query, va_list args )
     }
 }
 
-int         stream_Control( stream_t *s, int i_query, ... )
-{
-    va_list args;
-    int     i_result;
-
-    va_start( args, i_query );
-    i_result = stream_vaControl( s, i_query, args );
-    va_end( args );
-
-    return i_result;
-}
-
-int         stream_Read( stream_t *s, void *p_data, int i_data )
+/****************************************************************************
+ * IStreamRead:
+ ****************************************************************************/
+static int IStreamRead( stream_t *s, void *p_data, int i_data )
 {
-    uint8_t       *p = (uint8_t*)p_data;
-    data_packet_t *p_packet;
+    input_thread_t *p_input = s->p_sys->p_input;
+    uint8_t *p = (uint8_t*)p_data;
 
     int i_read = 0;
 
@@ -194,89 +271,43 @@ int         stream_Read( stream_t *s, void *p_data, int i_data )
         return i_data;
     }
 
-    while( i_data > 0 && !s->p_input->b_die )
+    while( i_data > 0 && !p_input->b_die )
     {
-        int i_count;
+        ssize_t i_count = p_input->p_last_data - p_input->p_current_data;
 
-        i_count = input_SplitBuffer( s->p_input, &p_packet, __MIN( i_data, 4096 ) );
         if( i_count <= 0 )
         {
-            return i_read;
-        }
+            /* Go to the next buffer */
+            i_count = input_FillBuffer( p_input );
 
-        if( p )
-        {
-            memcpy( p, p_packet->p_payload_start, i_count );
-            p += i_count;
+            if( i_count < 0 ) return -1;
+            else if( i_count == 0 )
+            {
+                /* We reached the EOF */
+                break;
+            }
         }
 
-        input_DeletePacket( s->p_input->p_method_data, p_packet );
-
+        i_count = __MIN( i_data, i_count );
+        memcpy( p, p_input->p_current_data, i_count );
+        p_input->p_current_data += i_count;
+        p += i_count;
         i_data -= i_count;
         i_read += i_count;
+
+        /* Update stream position */
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        p_input->stream.p_selected_area->i_tell += i_count;
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
     }
 
     return i_read;
 }
 
-int         stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data )
+/****************************************************************************
+ * IStreamPeek:
+ ****************************************************************************/
+static int IStreamPeek( stream_t *s, uint8_t **pp_peek, int i_peek )
 {
-    return input_Peek( s->p_input, pp_peek, i_data );
+    return input_Peek( s->p_sys->p_input, pp_peek, i_peek );
 }
-
-
-pes_packet_t    *stream_PesPacket( stream_t *s, int i_data )
-{
-    pes_packet_t  *p_pes;
-    data_packet_t *p_packet;
-
-
-    if( !(p_pes = input_NewPES( s->p_input->p_method_data ) ) )
-    {
-        return NULL;
-    }
-
-    if( i_data <= 0 )
-    {
-        p_pes->p_first =
-            p_pes->p_last  =
-                input_NewPacket( s->p_input->p_method_data, 0 );
-        p_pes->i_nb_data = 1;
-        return p_pes;
-    }
-
-    while( i_data > 0 )
-    {
-        int i_read;
-
-        i_read = input_SplitBuffer( s->p_input, &p_packet, __MIN( i_data, 4096 ) );
-        if( i_read <= 0 )
-        {
-            /* should occur only with EOF and max allocation reached 
-             * it safer to  return an error */
-            /* free pes */
-            input_DeletePES( s->p_input->p_method_data, p_pes );
-            return NULL;
-        }
-
-        if( p_pes->p_first == NULL )
-        {
-            p_pes->p_first = p_packet;
-        }
-        else
-        {
-            p_pes->p_last->p_next = p_packet;
-        }
-        p_pes->p_last = p_packet;
-        p_pes->i_nb_data++;
-        p_pes->i_pes_size += i_read;
-        i_data            -= i_read;
-    }
-
-    return p_pes;
-}
-
-
-
-
-