Commit f3f41176 authored by Laurent Aimar's avatar Laurent Aimar

* all: make stream_t using function pointers (needed to have multiple

 implementations, not yet used).
parent 33464f10
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000, 2003 VideoLAN
* $Id: input_ext-intf.h,v 1.102 2003/12/03 13:27:51 rocky Exp $
* $Id: input_ext-intf.h,v 1.103 2004/01/26 20:48:09 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -26,6 +26,7 @@
#ifndef _VLC_INPUT_EXT_INTF_H
#define _VLC_INPUT_EXT_INTF_H 1
#include "vlc_block.h"
#include "ninput.h"
/*
......@@ -237,9 +238,8 @@ struct stream_descriptor_t
int b_new_mute; /* int because it can be -1 */
vlc_cond_t stream_wait; /* interface -> input in case of a
* status change request */
/* Demultiplexer data */
stream_sys_t * p_demux_data;
void * p_demux_data;
/* Programs descriptions */
unsigned int i_pgrm_number; /* size of the following array */
......
......@@ -3,7 +3,7 @@
* but exported to plug-ins
*****************************************************************************
* Copyright (C) 1999-2002 VideoLAN
* $Id: input_ext-plugins.h,v 1.46 2003/11/30 22:47:55 gbazin Exp $
* $Id: input_ext-plugins.h,v 1.47 2004/01/26 20:48:09 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -71,6 +71,9 @@ void input_EscapeAudioDiscontinuity( input_thread_t * );
es_out_t *input_EsOutNew( input_thread_t * );
void input_EsOutDelete( es_out_t * );
stream_t *input_StreamNew( input_thread_t * );
void input_StreamDelete( stream_t * );
/*****************************************************************************
* Prototypes from input_clock.c
*****************************************************************************/
......
......@@ -2,7 +2,7 @@
* ninput.h
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ninput.h,v 1.25 2004/01/21 17:01:54 fenrir Exp $
* $Id: ninput.h,v 1.26 2004/01/26 20:48:09 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -121,41 +121,121 @@ enum stream_query_e
STREAM_GET_MTU, /**< arg1= int * res=cannot fail (0 if no sense)*/
};
/* Stream */
VLC_EXPORT( stream_t *, stream_OpenInput, ( input_thread_t * ) );
VLC_EXPORT( void, stream_Release, ( stream_t * ) );
VLC_EXPORT( int, stream_vaControl, ( stream_t *, int i_query, va_list ) );
VLC_EXPORT( int, stream_Control, ( stream_t *, int i_query, ... ) );
VLC_EXPORT( int, stream_Read, ( stream_t *, void *p_read, int i_read ) );
VLC_EXPORT( int, stream_Peek, ( stream_t *, uint8_t **pp_peek, int i_peek ) );
VLC_EXPORT( char *, stream_ReadLine, ( stream_t * ) );
VLC_EXPORT( block_t *, stream_Block, ( stream_t *, int i_size ) );
/**
* stream_t definition
*/
struct stream_t
{
VLC_COMMON_MEMBERS
block_t *(*pf_block) ( stream_t *, int i_size );
int (*pf_read) ( stream_t *, void *p_read, int i_read );
int (*pf_peek) ( stream_t *, uint8_t **pp_peek, int i_peek );
int (*pf_control)( stream_t *, int i_query, va_list );
stream_sys_t *p_sys;
};
/**
* Try to read "i_read" bytes into a buffer pointed by "p_read". If
* "p_read" is NULL then data are skipped instead of read. The return
* 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.
*/
static inline int stream_Read( stream_t *s, void *p_read, int i_read )
{
return s->pf_read( s, p_read, i_read );
}
/**
* Store in pp_peek a pointer to the next "i_peek" bytes in the stream
* \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)
*/
static inline int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_peek )
{
return s->pf_peek( s, pp_peek, i_peek );
}
static int64_t inline stream_Tell( stream_t *s )
/**
* Use to control the "stream_t *". Look at #stream_query_e for
* possible "i_query" value and format arguments. Return VLC_SUCCESS
* if ... succeed ;) and VLC_EGENERIC if failed or unimplemented
*/
static inline int stream_vaControl( stream_t *s, int i_query, va_list args )
{
return s->pf_control( s, i_query, args );
}
static inline int stream_Control( stream_t *s, int i_query, ... )
{
va_list args;
int i_result;
va_start( args, i_query );
i_result = s->pf_control( s, i_query, args );
va_end( args );
return i_result;
}
static inline int64_t stream_Tell( stream_t *s )
{
int64_t i_pos;
stream_Control( s, STREAM_GET_POSITION, &i_pos );
return i_pos;
}
static int64_t inline stream_Size( stream_t *s )
static inline int64_t stream_Size( stream_t *s )
{
int64_t i_pos;
stream_Control( s, STREAM_GET_SIZE, &i_pos );
return i_pos;
}
static int inline stream_MTU( stream_t *s )
static inline int stream_MTU( stream_t *s )
{
int i_mtu;
return stream_Control( s, STREAM_GET_POSITION, &i_mtu );
stream_Control( s, STREAM_GET_MTU, &i_mtu );
return i_mtu;
}
static int inline stream_Seek( stream_t *s, int64_t i_pos )
static inline int stream_Seek( stream_t *s, int64_t i_pos )
{
return stream_Control( s, STREAM_SET_POSITION, i_pos );
}
/**
* 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.
*/
static inline block_t *stream_Block( stream_t *s, int i_size )
{
if( i_size <= 0 ) return NULL;
if( s->pf_block )
{
return s->pf_block( s, i_size );
}
else
{
/* emulate block read */
block_t *p_bk = block_New( s, i_size );
if( p_bk )
{
p_bk->i_buffer = stream_Read( s, p_bk->p_buffer, i_size );
if( p_bk->i_buffer > 0 )
{
return p_bk;
}
}
if( p_bk ) block_Release( p_bk );
return NULL;
}
}
VLC_EXPORT( char *, stream_ReadLine, ( stream_t * ) );
/**
* @}
*/
......@@ -165,7 +245,6 @@ static int inline stream_Seek( stream_t *s, int64_t i_pos )
* @{
*/
struct demux_t
{
VLC_COMMON_MEMBERS
......
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.105 2004/01/25 21:39:37 gbazin Exp $
* $Id: vlc_common.h,v 1.106 2004/01/26 20:48:09 fenrir Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -222,7 +222,6 @@ typedef struct es_sys_t es_sys_t;
typedef struct pgrm_descriptor_t pgrm_descriptor_t;
typedef struct pgrm_sys_t pgrm_sys_t;
typedef struct stream_descriptor_t stream_descriptor_t;
typedef struct stream_sys_t stream_sys_t;
/* Format */
typedef struct audio_format_t audio_format_t;
......@@ -232,7 +231,8 @@ typedef struct es_format_t es_format_t;
typedef struct video_palette_t video_palette_t;
/* NInput */
typedef struct stream_t stream_t;
typedef struct stream_sys_t stream_sys_t;
typedef struct stream_t stream_t;
typedef struct es_out_t es_out_t;
typedef struct es_out_id_t es_out_id_t;
typedef struct es_out_sys_t es_out_sys_t;
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998-2004 VideoLAN
* $Id: input.c,v 1.279 2004/01/26 20:26:54 gbazin Exp $
* $Id: input.c,v 1.280 2004/01/26 20:48:10 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -736,7 +736,7 @@ static int InitThread( input_thread_t * p_input )
}
/* Create the stream_t facilities */
p_input->s = stream_OpenInput( p_input );
p_input->s = input_StreamNew( p_input );
if( p_input->s == NULL )
{
/* should never occur yet */
......@@ -768,7 +768,7 @@ static int InitThread( input_thread_t * p_input )
msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
p_input->psz_access, p_input->psz_demux, p_input->psz_name );
stream_Release( p_input->s );
input_StreamDelete( p_input->s );
module_Unneed( p_input, p_input->p_access );
if ( p_input->stream.p_sout != NULL )
{
......@@ -945,7 +945,7 @@ static void EndThread( input_thread_t * p_input )
}
/* Destroy the stream_t facilities */
if( p_input->s ) stream_Release( p_input->s );
if( p_input->s ) input_StreamDelete( p_input->s );
/* Destroy es out */
if( p_input->p_es_out ) input_EsOutDelete( p_input->p_es_out );
......
......@@ -2,7 +2,7 @@
* stream.c
*****************************************************************************
* Copyright (C) 1999-2004 VideoLAN
* $Id: stream.c,v 1.13 2004/01/25 17:16:06 zorglub Exp $
* $Id: stream.c,v 1.14 2004/01/26 20:48:10 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -27,55 +27,101 @@
#include "ninput.h"
#define MAX_LINE 1024
/****************************************************************************
* stream_* :
* XXX for now it's just a wrapper
*
* stream_ReadLine:
****************************************************************************/
/**
* Handle to a stream.
* Read from the stream untill first newline.
* \param s Stream handle to read from
* \return A null-terminated string. This must be freed,
*/
struct stream_t
/* 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;
}
}
/** pointer to the input thread */
input_thread_t *p_input;
};
/**
* Create a "stream_t *" from an "input_thread_t *".
/* TODO: one day we should create a special module stream
* when we would have a access wrapper, and stream filter
* (like caching, progessive, gunzip, ... )
*/
stream_t *stream_OpenInput( input_thread_t *p_input )
/* 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;
}
/**
* Destroy a previously created "stream_t *" instance.
*/
void stream_Release( stream_t *s )
/****************************************************************************
* input_StreamDelete:
****************************************************************************/
void input_StreamDelete( stream_t *s )
{
free( s->p_sys );
vlc_object_destroy( s );
}
/**
* 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 )
/****************************************************************************
* 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;
......@@ -85,34 +131,34 @@ int stream_vaControl( stream_t *s, int i_query, va_list args )
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:
......@@ -120,42 +166,42 @@ int stream_vaControl( stream_t *s, int i_query, va_list args )
i64 = (int64_t) va_arg( args, int64_t );
int64_t i_skip;
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 );
vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Warn( s, "seek out of bound" );
return VLC_EGENERIC;
}
i_skip = 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( &s->p_input->stream.stream_lock );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return VLC_SUCCESS;
}
if( i_skip > 0 && i_skip < s->p_input->p_last_data -
s->p_input->p_current_data - 1 )
if( i_skip > 0 && i_skip < p_input->p_last_data -
p_input->p_current_data - 1 )
{
/* We can skip without reading/seeking */
s->p_input->p_current_data += i_skip;
s->p_input->stream.p_selected_area->i_tell = i64;
vlc_mutex_unlock( &s->p_input->stream.stream_lock );
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( &s->p_input->stream.stream_lock );
vlc_mutex_unlock( &p_input->stream.stream_lock );
if( s->p_input->stream.b_seekable &&
( s->p_input->stream.i_method == INPUT_METHOD_FILE ||
i_skip < 0 || i_skip >= ( s->p_input->i_mtu > 0 ?
s->p_input->i_mtu : 4096 ) ) )
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;
}
......@@ -172,15 +218,15 @@ int stream_vaControl( stream_t *s, int i_query, va_list args )
{
int i_read;
i_read = input_SplitBuffer( s->p_input, &p_data,
__MIN( (int)s->p_input->i_bufsize, 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;
......@@ -192,7 +238,7 @@ int stream_vaControl( stream_t *s, int i_query, va_list args )
case STREAM_GET_MTU:
p_int = (int*) va_arg( args, int * );
*p_int = s->p_input->i_mtu;
*p_int = p_input->i_mtu;
return VLC_SUCCESS;
default:
......@@ -201,31 +247,12 @@ int stream_vaControl( stream_t *s, int i_query, va_list args )
}
}
/**
* Use to control the "stream_t *". Look at #stream_query_e for
* 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, ... )
{
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;
}
/**
* Try to read "i_read" bytes into a buffer pointed by "p_read". If
* "p_read" is NULL then data are skipped instead of read. The return
* 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 )
/****************************************************************************
* IStreamRead:
****************************************************************************/
static int IStreamRead( stream_t *s, void *p_data, int i_data )
{
input_thread_t *p_input = s->p_sys->p_input;
uint8_t *p = (uint8_t*)p_data;
data_packet_t *p_packet;
......@@ -245,17 +272,17 @@ 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;
i_count = input_SplitBuffer( s->p_input, &p_packet,
__MIN( i_data, (int)s->p_input->i_bufsize ) );
i_count = input_SplitBuffer( p_input, &p_packet,
__MIN( i_data, (int)p_input->i_bufsize ) );
if( i_count <= 0 )
{
if( i_count == 0 )
input_DeletePacket( s->p_input->p_method_data, p_packet );
input_DeletePacket( p_input->p_method_data, p_packet );
return i_read;
}
......@@ -266,7 +293,7 @@ int stream_Read( stream_t *s, void *p_data, int i_data )
p += i_count;
}
input_DeletePacket( s->p_input->p_method_data, p_packet );
input_DeletePacket( p_input->p_method_data, p_packet );
i_data -= i_count;
i_read += i_count;
......@@ -274,76 +301,10 @@ int stream_Read( stream_t *s, void *p_data, int i_data )
return i_read;
}
/**
* Store in pp_peek a pointer to the next "i_peek" bytes in the stream
* \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_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 )
/****************************************************************************
* IStreamPeek:
****************************************************************************/
static int IStreamPeek( stream_t *s, uint8_t **pp_peek, int i_peek )
{