]> git.sesse.net Git - vlc/blobdiff - src/input/input_ext-plugins.c
include/ninput.c, src/input/stream.c:
[vlc] / src / input / input_ext-plugins.c
index 2f3e53332b2c260381d9ca0daf7c6f5b645584b7..123cc4c46c3647d1da85dce297af8c80f724b565 100644 (file)
@@ -2,7 +2,7 @@
  * input_ext-plugins.c: useful functions for access and demux plug-ins
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: input_ext-plugins.c,v 1.11 2002/06/01 12:32:01 sam Exp $
+ * $Id: input_ext-plugins.c,v 1.37 2003/08/13 13:54:02 jpsaman Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <string.h>
-#include <errno.h>
-#include <fcntl.h>
 
 #include <vlc/vlc.h>
 
-#ifdef HAVE_SYS_TIME_H
-#    include <sys/time.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#elif defined( _MSC_VER ) && defined( _WIN32 )
-#   include <io.h>
-#endif
-
-#ifdef WIN32
-#   include <winsock2.h>
-#   include <ws2tcpip.h>
-#elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
-#   include <netdb.h>                                         /* hostent ... */
-#   include <sys/socket.h>
-#   include <netinet/in.h>
-#   ifdef HAVE_ARPA_INET_H
-#       include <arpa/inet.h>                    /* inet_ntoa(), inet_aton() */
-#   endif
-#endif
-
-#ifdef WIN32
-#   include <winsock2.h>
-#   include <ws2tcpip.h>
-#elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
-#   include <netdb.h>                                         /* hostent ... */
-#   include <sys/socket.h>
-#   include <netinet/in.h>
-#   ifdef HAVE_ARPA_INET_H
-#       include <arpa/inet.h>                    /* inet_ntoa(), inet_aton() */
-#   endif
-#endif
-
-
-
 #include "stream_control.h"
 #include "input_ext-intf.h"
 #include "input_ext-dec.h"
@@ -91,7 +50,7 @@
 /*****************************************************************************
  * data_buffer_t: shared data type
  *****************************************************************************/
-struct data_buffer_s
+struct data_buffer_t
 {
     data_buffer_t * p_next;
 
@@ -113,7 +72,7 @@ struct                                                                      \
     unsigned int i_depth;                                                   \
 } NAME;
 
-struct input_buffers_s
+struct input_buffers_t
 {
     vlc_mutex_t lock;
     PACKETS_LIFO( pes_packet_t, pes )
@@ -126,19 +85,19 @@ struct input_buffers_s
 /*****************************************************************************
  * input_BuffersInit: initialize the cache structures, return a pointer to it
  *****************************************************************************/
-void * input_BuffersInit( vlc_object_t *p_this )
+void * __input_BuffersInit( vlc_object_t *p_this )
 {
     input_buffers_t * p_buffers = malloc( sizeof( input_buffers_t ) );
 
     if( p_buffers == NULL )
     {
-        return( NULL );
+        return NULL;
     }
 
     memset( p_buffers, 0, sizeof( input_buffers_t ) );
     vlc_mutex_init( p_this, &p_buffers->lock );
 
-    return( p_buffers );
+    return p_buffers;
 }
 
 /*****************************************************************************
@@ -186,7 +145,7 @@ void input_BuffersEnd( input_thread_t * p_input, input_buffers_t * p_buffers )
 
         if( p_buffers->i_allocated )
         {
-            msg_Err( p_input, "%d bytes have not been freed, "
+            msg_Warn( p_input, "%u bytes have not been freed, "
                               "expect memory leak", p_buffers->i_allocated );
         }
 
@@ -199,17 +158,16 @@ void input_BuffersEnd( input_thread_t * p_input, input_buffers_t * p_buffers )
  * input_NewBuffer: return a pointer to a data buffer of the appropriate size
  *****************************************************************************/
 static inline data_buffer_t * NewBuffer( input_buffers_t * p_buffers,
-                                         size_t i_size )
+                                         size_t i_size,
+                                         vlc_bool_t b_forced )
 {
     data_buffer_t * p_buf;
 
     /* Safety check */
-    if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION )
+    if( !b_forced && p_buffers->i_allocated > INPUT_MAX_ALLOCATION )
     {
-//X        intf_Err( "INPUT_MAX_ALLOCATION reached (%d)",
-//X                     p_buffers->i_allocated );
         return NULL;
-    } 
+    }
 
     if( p_buffers->buffers.p_stack != NULL )
     {
@@ -226,7 +184,6 @@ static inline data_buffer_t * NewBuffer( input_buffers_t * p_buffers,
             p_buf = malloc( sizeof(input_buffers_t) + i_size );
             if( p_buf == NULL )
             {
-//X                intf_ErrMsg( "Out of memory" );
                 return NULL;
             }
             p_buf->i_size = i_size;
@@ -239,7 +196,6 @@ static inline data_buffer_t * NewBuffer( input_buffers_t * p_buffers,
         p_buf = malloc( sizeof(input_buffers_t) + i_size );
         if( p_buf == NULL )
         {
-//X            intf_ErrMsg( "Out of memory" );
             return NULL;
         }
         p_buf->i_size = i_size;
@@ -250,7 +206,7 @@ static inline data_buffer_t * NewBuffer( input_buffers_t * p_buffers,
     p_buf->p_next = NULL;
     p_buf->i_refcount = 0;
 
-    return( p_buf );
+    return p_buf;
 }
 
 data_buffer_t * input_NewBuffer( input_buffers_t * p_buffers, size_t i_size )
@@ -258,10 +214,10 @@ data_buffer_t * input_NewBuffer( input_buffers_t * p_buffers, size_t i_size )
     data_buffer_t * p_buf;
 
     vlc_mutex_lock( &p_buffers->lock );
-    p_buf = NewBuffer( p_buffers, i_size );
+    p_buf = NewBuffer( p_buffers, i_size, VLC_FALSE );
     vlc_mutex_unlock( &p_buffers->lock );
 
-    return( p_buf );
+    return p_buf;
 }
 
 /*****************************************************************************
@@ -318,7 +274,6 @@ static inline data_packet_t * ShareBuffer( input_buffers_t * p_buffers,
         p_data = malloc( sizeof(data_packet_t) );
         if( p_data == NULL )
         {
-//X            intf_ErrMsg( "Out of memory" );
             return NULL;
         }
     }
@@ -331,7 +286,7 @@ static inline data_packet_t * ShareBuffer( input_buffers_t * p_buffers,
     p_data->p_payload_end = p_data->p_demux_start + p_buf->i_size;
     p_buf->i_refcount++;
 
-    return( p_data );
+    return p_data;
 }
 
 data_packet_t * input_ShareBuffer( input_buffers_t * p_buffers,
@@ -343,21 +298,24 @@ data_packet_t * input_ShareBuffer( input_buffers_t * p_buffers,
     p_data = ShareBuffer( p_buffers, p_buf );
     vlc_mutex_unlock( &p_buffers->lock );
 
-    return( p_data );
+    return p_data;
 }
 
 /*****************************************************************************
  * input_NewPacket: allocate a packet along with a buffer
  *****************************************************************************/
 static inline data_packet_t * NewPacket( input_buffers_t * p_buffers,
-                                         size_t i_size )
+                                         size_t i_size,
+                                         vlc_bool_t b_forced )
 {
-    data_buffer_t * p_buf = NewBuffer( p_buffers, i_size );
+    data_buffer_t * p_buf;
     data_packet_t * p_data;
 
+    p_buf = NewBuffer( p_buffers, i_size, b_forced );
+
     if( p_buf == NULL )
     {
-        return( NULL );
+        return NULL;
     }
 
     p_data = ShareBuffer( p_buffers, p_buf );
@@ -365,7 +323,7 @@ static inline data_packet_t * NewPacket( input_buffers_t * p_buffers,
     {
         ReleaseBuffer( p_buffers, p_buf );
     }
-    return( p_data );
+    return p_data;
 }
 
 data_packet_t * input_NewPacket( input_buffers_t * p_buffers, size_t i_size )
@@ -373,10 +331,21 @@ data_packet_t * input_NewPacket( input_buffers_t * p_buffers, size_t i_size )
     data_packet_t * p_data;
 
     vlc_mutex_lock( &p_buffers->lock );
-    p_data = NewPacket( p_buffers, i_size );
+    p_data = NewPacket( p_buffers, i_size, VLC_FALSE );
+    vlc_mutex_unlock( &p_buffers->lock );
+
+    return p_data;
+}
+
+data_packet_t * input_NewPacketForce( input_buffers_t * p_buffers, size_t i_size )
+{
+    data_packet_t * p_data;
+
+    vlc_mutex_lock( &p_buffers->lock );
+    p_data = NewPacket( p_buffers, i_size, VLC_TRUE);
     vlc_mutex_unlock( &p_buffers->lock );
 
-    return( p_data );
+    return p_data;
 }
 
 /*****************************************************************************
@@ -434,19 +403,18 @@ static inline pes_packet_t * NewPES( input_buffers_t * p_buffers )
         p_pes = malloc( sizeof(pes_packet_t) );
         if( p_pes == NULL )
         {
-//X            intf_ErrMsg( "Out of memory" );
             return NULL;
         }
     }
 
     p_pes->p_next = NULL;
-    p_pes->b_data_alignment = p_pes->b_discontinuity =
-        p_pes->i_pts = p_pes->i_dts = 0;
+    p_pes->b_data_alignment = p_pes->b_discontinuity = VLC_FALSE;
+    p_pes->i_pts = p_pes->i_dts = 0;
     p_pes->p_first = p_pes->p_last = NULL;
     p_pes->i_pes_size = 0;
     p_pes->i_nb_data = 0;
 
-    return( p_pes );
+    return p_pes;
 }
 
 pes_packet_t * input_NewPES( input_buffers_t * p_buffers )
@@ -457,7 +425,7 @@ pes_packet_t * input_NewPES( input_buffers_t * p_buffers )
     p_pes = NewPES( p_buffers );
     vlc_mutex_unlock( &p_buffers->lock );
 
-    return( p_pes );
+    return p_pes;
 }
 
 /*****************************************************************************
@@ -515,17 +483,30 @@ void input_DeletePES( input_buffers_t * p_buffers, pes_packet_t * p_pes )
 ssize_t input_FillBuffer( input_thread_t * p_input )
 {
     ptrdiff_t i_remains = p_input->p_last_data - p_input->p_current_data;
-    data_buffer_t * p_buf;
+    data_buffer_t * p_buf = NULL;
     ssize_t i_ret;
 
     vlc_mutex_lock( &p_input->p_method_data->lock );
 
-    p_buf = NewBuffer( p_input->p_method_data,
-                       i_remains + p_input->i_bufsize );
-    if( p_buf == NULL )
+    while( p_buf == NULL )
     {
-        return( -1 );
+        p_buf = NewBuffer( p_input->p_method_data,
+                           i_remains + p_input->i_bufsize, VLC_FALSE );
+        if( p_buf == NULL )
+        {
+            vlc_mutex_unlock( &p_input->p_method_data->lock );
+            msg_Err( p_input,
+                     "failed allocating a new buffer (decoder stuck?)" );
+            msleep( INPUT_IDLE_SLEEP );
+
+            if( p_input->b_die || p_input->b_error || p_input->b_eof )
+            {
+                return -1;
+            }
+            vlc_mutex_lock( &p_input->p_method_data->lock );
+        }
     }
+
     p_buf->i_refcount = 1;
 
     if( p_input->p_data_buffer != NULL )
@@ -539,20 +520,28 @@ ssize_t input_FillBuffer( input_thread_t * p_input )
         ReleaseBuffer( p_input->p_method_data, p_input->p_data_buffer );
     }
 
+    p_input->p_data_buffer = p_buf;
+    p_input->p_current_data = (byte_t *)p_buf + sizeof(data_buffer_t);
+    p_input->p_last_data = p_input->p_current_data + i_remains;
+
     /* Do not hold the lock during pf_read (blocking call). */
     vlc_mutex_unlock( &p_input->p_method_data->lock );
 
     i_ret = p_input->pf_read( p_input,
-                             (byte_t *)p_buf + sizeof(data_buffer_t)
-                              + i_remains,
-                             p_input->i_bufsize );
+                              (byte_t *)p_buf + sizeof(data_buffer_t)
+                               + i_remains,
+                              p_input->i_bufsize );
+    if( i_ret < 0 && i_remains == 0 )
+    {
+        /* Our internal buffers are empty, we can signal the error */
+        return -1;
+    }
 
     if( i_ret < 0 ) i_ret = 0;
-    p_input->p_data_buffer = p_buf;
-    p_input->p_current_data = (byte_t *)p_buf + sizeof(data_buffer_t);
-    p_input->p_last_data = p_input->p_current_data + i_remains + i_ret;
 
-    return( (ssize_t)i_remains + i_ret );
+    p_input->p_last_data += i_ret;
+
+    return (ssize_t)i_remains + i_ret;
 }
 
 /*****************************************************************************
@@ -562,22 +551,23 @@ ssize_t input_FillBuffer( input_thread_t * p_input )
  *****************************************************************************/
 ssize_t input_Peek( input_thread_t * p_input, byte_t ** pp_byte, size_t i_size )
 {
-    if( p_input->p_last_data - p_input->p_current_data < i_size )
+    if( p_input->p_last_data - p_input->p_current_data < (ptrdiff_t)i_size )
     {
         /* Go to the next buffer */
         ssize_t i_ret = input_FillBuffer( p_input );
 
-        if( i_size == -1 )
+        if( i_ret < 0 )
         {
-            return( -1 );
+            return -1;
         }
-        else if( i_ret < i_size )
+
+        if( i_ret < (ssize_t)i_size )
         {
             i_size = i_ret;
         }
     }
     *pp_byte = p_input->p_current_data;
-    return( i_size );
+    return i_size;
 }
 
 /*****************************************************************************
@@ -587,21 +577,27 @@ ssize_t input_Peek( input_thread_t * p_input, byte_t ** pp_byte, size_t i_size )
 ssize_t input_SplitBuffer( input_thread_t * p_input,
                            data_packet_t ** pp_data, size_t i_size )
 {
-    if( p_input->p_last_data - p_input->p_current_data < i_size )
+    if( p_input->p_last_data - p_input->p_current_data < (ptrdiff_t)i_size )
     {
         /* Go to the next buffer */
         ssize_t i_ret = input_FillBuffer( p_input );
 
-        if( i_ret == -1 )
+        if( i_ret < 0 )
         {
-            return( -1 );
+            return -1;
         }
-        else if( i_ret < i_size )
+
+        if( i_ret < (ssize_t)i_size )
         {
             i_size = i_ret;
         }
     }
 
+    if ( i_size < 0)
+    {
+        return 0;
+    }
+
     *pp_data = input_ShareBuffer( p_input->p_method_data,
                                   p_input->p_data_buffer );
 
@@ -611,7 +607,12 @@ ssize_t input_SplitBuffer( input_thread_t * p_input,
 
     p_input->p_current_data += i_size;
 
-    return( i_size );
+    /* Update stream position */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.p_selected_area->i_tell += i_size;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    return i_size;
 }
 
 /*****************************************************************************
@@ -619,16 +620,16 @@ ssize_t input_SplitBuffer( input_thread_t * p_input,
  *****************************************************************************/
 int input_AccessInit( input_thread_t * p_input )
 {
-    p_input->p_method_data = input_BuffersInit( p_input->p_this );
-    if( p_input->p_method_data == NULL ) return( -1 );
+    p_input->p_method_data = input_BuffersInit( p_input );
+    if( p_input->p_method_data == NULL ) return -1;
     p_input->p_data_buffer = NULL;
     p_input->p_current_data = NULL;
     p_input->p_last_data = NULL;
-    return( 0 );
+    return 0;
 }
 
 /*****************************************************************************
- * input_AccessReinit: reinit structures after a random seek
+ * input_AccessReinit: reinit structures before a random seek
  *****************************************************************************/
 void input_AccessReinit( input_thread_t * p_input )
 {
@@ -654,155 +655,3 @@ void input_AccessEnd( input_thread_t * p_input )
     input_BuffersEnd( p_input, p_input->p_method_data );
 }
 
-
-/*
- * Optional file descriptor management functions, for use by access plug-ins
- * base on file descriptors (file, udp, http...).
- */
-
-/*****************************************************************************
- * input_FDClose: close the target
- *****************************************************************************/
-void input_FDClose( input_thread_t * p_input )
-{
-    input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
-
-    msg_Info( p_input, "closing `%s/%s:%s'", 
-              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
-    close( p_access_data->i_handle );
-    free( p_access_data );
-}
-
-/*****************************************************************************
- * input_FDNetworkClose: close a network target
- *****************************************************************************/
-void input_FDNetworkClose( input_thread_t * p_input )
-{
-    input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
-
-    msg_Info( p_input, "closing network `%s/%s:%s'", 
-              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
-#ifdef WIN32
-    closesocket( p_access_data->i_handle );
-#else
-    close( p_access_data->i_handle );
-#endif
-
-    free( p_access_data );
-}
-
-/*****************************************************************************
- * input_FDRead: standard read on a file descriptor.
- *****************************************************************************/
-ssize_t input_FDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
-{
-    input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
-    ssize_t i_ret = read( p_access_data->i_handle, p_buffer, i_len );
-    if( i_ret > 0 )
-    {
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-        p_input->stream.p_selected_area->i_tell += i_ret;
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-    }
-    if( i_ret < 0 )
-    {
-        msg_Err( p_input, "read failed (%s)", strerror(errno) );
-    }
-    return( i_ret );
-}
-
-/*****************************************************************************
- * NetworkSelect: Checks whether data is available on a file descriptor
- *****************************************************************************/
-static inline int NetworkSelect( input_thread_t * p_input )
-{
-    input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
-    struct timeval  timeout;
-    fd_set          fds;
-    int             i_ret;
-
-    /* Initialize file descriptor set */
-    FD_ZERO( &fds );
-    FD_SET( p_access_data->i_handle, &fds );
-
-    /* We'll wait 0.5 second if nothing happens */
-    timeout.tv_sec = 0;
-    timeout.tv_usec = 500000;
-    /* Find if some data is available */
-    i_ret = select( p_access_data->i_handle + 1, &fds,
-                     NULL, NULL, &timeout );
-    if( i_ret == -1 && errno != EINTR )
-    {
-        msg_Err( p_input, "network select error (%s)", strerror(errno) );
-    }
-
-    return( i_ret );
-}
-
-/*****************************************************************************
- * input_FDNetworkRead: read on a file descriptor, checking periodically
- * p_input->b_die
- *****************************************************************************/
-ssize_t input_FDNetworkRead( input_thread_t * p_input, byte_t * p_buffer,
-                             size_t i_len )
-{
-    if( NetworkSelect( p_input ) > 0 )
-    {
-        input_socket_t * p_access_data
-                             = (input_socket_t *)p_input->p_access_data;
-
-        ssize_t i_ret = recv( p_access_data->i_handle, p_buffer, i_len, 0 );
-
-        if( i_ret > 0 )
-        {
-            vlc_mutex_lock( &p_input->stream.stream_lock );
-            p_input->stream.p_selected_area->i_tell += i_ret;
-            vlc_mutex_unlock( &p_input->stream.stream_lock );
-        }
-
-        if( i_ret < 0 )
-        {
-            msg_Err( p_input, "recv failed (%s)", strerror(errno) );
-        }
-
-        return( i_ret );
-    }
-    
-    return( 0 );
-}
-
-/*****************************************************************************
- * input_FDSeek: seek to a specific location in a file
- *****************************************************************************/
-void input_FDSeek( input_thread_t * p_input, off_t i_pos )
-{
-#define S p_input->stream
-    input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
-
-    lseek( p_access_data->i_handle, i_pos, SEEK_SET );
-
-    vlc_mutex_lock( &S.stream_lock );
-    S.p_selected_area->i_tell = i_pos;
-    if( S.p_selected_area->i_tell > S.p_selected_area->i_size )
-    {
-        msg_Err( p_input, "seeking too far" );
-        S.p_selected_area->i_tell = S.p_selected_area->i_size;
-    }
-    else if( S.p_selected_area->i_tell < 0 )
-    {
-        msg_Err( p_input, "seeking too early" );
-        S.p_selected_area->i_tell = 0;
-    }
-    vlc_mutex_unlock( &S.stream_lock );
-#undef S
-}
-
-