* 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"
/*****************************************************************************
* data_buffer_t: shared data type
*****************************************************************************/
-struct data_buffer_s
+struct data_buffer_t
{
data_buffer_t * p_next;
unsigned int i_depth; \
} NAME;
-struct input_buffers_s
+struct input_buffers_t
{
vlc_mutex_t lock;
PACKETS_LIFO( pes_packet_t, pes )
/*****************************************************************************
* 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;
}
/*****************************************************************************
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 );
}
* 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 )
{
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;
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;
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 )
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;
}
/*****************************************************************************
p_data = malloc( sizeof(data_packet_t) );
if( p_data == NULL )
{
-//X intf_ErrMsg( "Out of memory" );
return NULL;
}
}
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,
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 );
{
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 )
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;
}
/*****************************************************************************
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 )
p_pes = NewPES( p_buffers );
vlc_mutex_unlock( &p_buffers->lock );
- return( p_pes );
+ return 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 )
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;
}
/*****************************************************************************
*****************************************************************************/
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;
}
/*****************************************************************************
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 );
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;
}
/*****************************************************************************
*****************************************************************************/
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 )
{
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
-}
-
-