* input_ext-plugins.c: useful functions for access and demux plug-ins
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: input_ext-plugins.c,v 1.1 2002/03/01 00:33:18 massiot Exp $
+ * $Id: input_ext-plugins.c,v 1.19 2002/10/26 15:24:19 gbazin Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* Preamble
*****************************************************************************/
#include <stdlib.h>
-#include <sys/time.h>
+
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
-#include <videolan/vlc.h>
+#include <vlc/vlc.h>
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
# 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
*****************************************************************************/
-typedef struct data_buffer_s
+struct data_buffer_t
{
- struct data_buffer_s * p_next;
+ data_buffer_t * p_next;
/* number of data packets this buffer is referenced from - when it falls
* down to 0, the buffer is freed */
/* size of the current buffer (starting right after this byte) */
size_t i_size;
-} data_buffer_t;
+};
/*****************************************************************************
* input_buffers_t: defines a LIFO per data type to keep
unsigned int i_depth; \
} NAME;
-typedef struct input_buffers_s
+struct input_buffers_t
{
vlc_mutex_t lock;
PACKETS_LIFO( pes_packet_t, pes )
PACKETS_LIFO( data_packet_t, data )
PACKETS_LIFO( data_buffer_t, buffers )
size_t i_allocated;
-} input_buffers_t;
+};
/*****************************************************************************
* input_BuffersInit: initialize the cache structures, return a pointer to it
*****************************************************************************/
-void * input_BuffersInit( void )
+void * __input_BuffersInit( vlc_object_t *p_this )
{
input_buffers_t * p_buffers = malloc( sizeof( input_buffers_t ) );
}
memset( p_buffers, 0, sizeof( input_buffers_t ) );
- vlc_mutex_init( &p_buffers->lock );
+ vlc_mutex_init( p_this, &p_buffers->lock );
return( p_buffers );
}
p_packet = p_next; \
}
-void input_BuffersEnd( input_buffers_t * p_buffers )
+void input_BuffersEnd( input_thread_t * p_input, input_buffers_t * p_buffers )
{
if( p_buffers != NULL )
{
- if( p_main->b_stats )
- {
- intf_StatMsg( "input buffers stats: pes: %d packets",
- p_buffers->pes.i_depth );
- intf_StatMsg( "input buffers stats: data: %d packets",
- p_buffers->data.i_depth );
- intf_StatMsg( "input buffers stats: buffers: %d packets",
- p_buffers->buffers.i_depth );
- }
+ msg_Dbg( p_input, "pes: %d packets", p_buffers->pes.i_depth );
+ msg_Dbg( p_input, "data: %d packets", p_buffers->data.i_depth );
+ msg_Dbg( p_input, "buffers: %d packets", p_buffers->buffers.i_depth );
{
/* Free PES */
if( p_buffers->i_allocated )
{
- intf_ErrMsg( "input buffers error: %d bytes have not been"
- " freed, expect memory leak",
- p_buffers->i_allocated );
+ msg_Err( p_input, "%d bytes have not been freed, "
+ "expect memory leak", p_buffers->i_allocated );
}
vlc_mutex_destroy( &p_buffers->lock );
/*****************************************************************************
* 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 )
+static inline data_buffer_t * NewBuffer( input_buffers_t * p_buffers,
+ size_t i_size )
{
data_buffer_t * p_buf;
/* Safety check */
if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION )
{
- intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)",
- p_buffers->i_allocated );
return NULL;
}
p_buf = malloc( sizeof(input_buffers_t) + i_size );
if( p_buf == NULL )
{
- 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 )
{
- 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 )
/*****************************************************************************
* input_ReleaseBuffer: put a buffer back into the cache
*****************************************************************************/
-static __inline__ void ReleaseBuffer( input_buffers_t * p_buffers,
- data_buffer_t * p_buf )
+static inline void ReleaseBuffer( input_buffers_t * p_buffers,
+ data_buffer_t * p_buf )
{
/* Decrement refcount */
if( --p_buf->i_refcount > 0 )
/*****************************************************************************
* input_ShareBuffer: allocate a data_packet_t pointing to a given buffer
*****************************************************************************/
-static __inline__ data_packet_t * ShareBuffer( input_buffers_t * p_buffers,
- data_buffer_t * p_buf )
+static inline data_packet_t * ShareBuffer( input_buffers_t * p_buffers,
+ data_buffer_t * p_buf )
{
data_packet_t * p_data;
p_data = malloc( sizeof(data_packet_t) );
if( p_data == NULL )
{
- 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,
/*****************************************************************************
* input_NewPacket: allocate a packet along with a buffer
*****************************************************************************/
-static __inline__ data_packet_t * NewPacket( input_buffers_t * p_buffers,
- size_t i_size )
+static inline data_packet_t * NewPacket( input_buffers_t * p_buffers,
+ size_t i_size )
{
- 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 );
+
if( p_buf == NULL )
{
return( NULL );
/*****************************************************************************
* input_DeletePacket: deallocate a packet and its buffers
*****************************************************************************/
-static __inline__ void DeletePacket( input_buffers_t * p_buffers,
- data_packet_t * p_data )
+static inline void DeletePacket( input_buffers_t * p_buffers,
+ data_packet_t * p_data )
{
while( p_data != NULL )
{
/*****************************************************************************
* input_NewPES: return a pointer to a new PES packet
*****************************************************************************/
-static __inline__ pes_packet_t * NewPES( input_buffers_t * p_buffers )
+static inline pes_packet_t * NewPES( input_buffers_t * p_buffers )
{
pes_packet_t * p_pes;
p_pes = malloc( sizeof(pes_packet_t) );
if( p_pes == NULL )
{
- intf_ErrMsg( "Out of memory" );
return NULL;
}
}
* input_DeletePES: put a pes and all data packets and all buffers back into
* the cache
*****************************************************************************/
-static __inline__ void DeletePES( input_buffers_t * p_buffers,
- pes_packet_t * p_pes )
+static inline void DeletePES( input_buffers_t * p_buffers,
+ pes_packet_t * p_pes )
{
while( p_pes != NULL )
{
i_remains + p_input->i_bufsize );
if( p_buf == NULL )
{
- return( -1 );
+ msg_Err( p_input, "failed allocating a new buffer (decoder stuck?)" );
+ return -1;
}
p_buf->i_refcount = 1;
if( p_input->p_data_buffer != NULL )
{
- FAST_MEMCPY( (byte_t *)p_buf + sizeof(data_buffer_t),
- p_input->p_current_data, (size_t)i_remains );
+ if( i_remains )
+ {
+ p_input->p_vlc->pf_memcpy( (byte_t *)p_buf + sizeof(data_buffer_t),
+ p_input->p_current_data,
+ (size_t)i_remains );
+ }
ReleaseBuffer( p_input->p_method_data, p_input->p_data_buffer );
}
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_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;
}
}
+ if ( !i_size )
+ {
+ return 0;
+ }
+
*pp_data = input_ShareBuffer( p_input->p_method_data,
p_input->p_data_buffer );
p_input->p_current_data += 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_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;
ReleaseBuffer( p_input->p_method_data, p_input->p_data_buffer );
}
- input_BuffersEnd( p_input->p_method_data );
+ input_BuffersEnd( p_input, p_input->p_method_data );
}
/*****************************************************************************
* input_FDClose: close the target
*****************************************************************************/
-void input_FDClose( input_thread_t * p_input )
+void __input_FDClose( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
+ 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( vlc_object_t * p_this )
{
+ input_thread_t * p_input = (input_thread_t *)p_this;
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
- intf_WarnMsg( 2, "input: closing `%s/%s:%s'",
- p_input->psz_access, p_input->psz_demux, p_input->psz_name );
+ 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 );
}
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 )
{
- intf_ErrMsg( "input error: read() failed (%s)", strerror(errno) );
+ 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 )
+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;
i_ret = select( p_access_data->i_handle + 1, &fds,
NULL, NULL, &timeout );
- if( i_ret == -1 )
+ if( i_ret == -1 && errno != EINTR )
{
- intf_ErrMsg( "input error: network select error (%s)", strerror(errno) );
+ msg_Err( p_input, "network select error (%s)", strerror(errno) );
}
return( i_ret );
if( i_ret < 0 )
{
- intf_ErrMsg( "input error: recv() failed (%s)", strerror(errno) );
+ msg_Err( p_input, "recv failed (%s)", strerror(errno) );
}
return( i_ret );
*****************************************************************************/
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( &p_input->stream.stream_lock );
- p_input->stream.p_selected_area->i_tell = i_pos;
- vlc_mutex_unlock( &p_input->stream.stream_lock );
+ 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
}