Commit 5274b3d1 authored by Laurent Aimar's avatar Laurent Aimar

* stream: added stream_DemuxNew, stream_DemuxSend, stream_DemuxDelete

to chain demuxer.
    - stream_DemuxNew: create a special stream_t, launch a thread that
    will open a demuxer, and call p_demux->pf_demux until asked to die.
    - stream_DemuxSend: append a block to be used by the new demuxer.
    - stream_DemuxDelete : free all data...
parent f1c9b20a
...@@ -236,6 +236,14 @@ static inline block_t *stream_Block( stream_t *s, int i_size ) ...@@ -236,6 +236,14 @@ static inline block_t *stream_Block( stream_t *s, int i_size )
VLC_EXPORT( char *, stream_ReadLine, ( stream_t * ) ); VLC_EXPORT( char *, stream_ReadLine, ( stream_t * ) );
/**
* Create a special stream and a demuxer, this allows chaining demuxers
*/
#define stream_DemuxNew( a, b, c ) __stream_DemuxNew( VLC_OBJECT(a), b, c)
VLC_EXPORT( stream_t *,__stream_DemuxNew, ( vlc_object_t *p_obj, char *psz_demux, es_out_t *out ) );
VLC_EXPORT( void, stream_DemuxSend, ( stream_t *s, block_t *p_block ) );
VLC_EXPORT( void, stream_DemuxDelete,( stream_t *s ) );
/** /**
* @} * @}
*/ */
......
...@@ -76,10 +76,10 @@ char *stream_ReadLine( stream_t *s ) ...@@ -76,10 +76,10 @@ char *stream_ReadLine( stream_t *s )
*/ */
/* private stream_sys_t for input_Stream* */ /* private stream_sys_t for input_Stream* */
struct stream_sys_t typedef struct
{ {
input_thread_t *p_input; input_thread_t *p_input;
}; } input_stream_sys_t;
/* private pf_* functions declarations */ /* private pf_* functions declarations */
static int IStreamRead ( stream_t *, void *p_read, int i_read ); static int IStreamRead ( stream_t *, void *p_read, int i_read );
...@@ -92,6 +92,7 @@ static int IStreamControl( stream_t *, int i_query, va_list ); ...@@ -92,6 +92,7 @@ static int IStreamControl( stream_t *, int i_query, va_list );
stream_t *input_StreamNew( input_thread_t *p_input ) stream_t *input_StreamNew( input_thread_t *p_input )
{ {
stream_t *s = vlc_object_create( p_input, sizeof( stream_t ) ); stream_t *s = vlc_object_create( p_input, sizeof( stream_t ) );
input_stream_sys_t *p_sys;
if( s ) if( s )
{ {
s->pf_block = NULL; s->pf_block = NULL;
...@@ -99,8 +100,8 @@ stream_t *input_StreamNew( input_thread_t *p_input ) ...@@ -99,8 +100,8 @@ stream_t *input_StreamNew( input_thread_t *p_input )
s->pf_peek = IStreamPeek; s->pf_peek = IStreamPeek;
s->pf_control= IStreamControl; s->pf_control= IStreamControl;
s->p_sys = malloc( sizeof( stream_sys_t ) ); p_sys = (input_stream_sys_t*)s->p_sys = malloc( sizeof( input_stream_sys_t ) );
s->p_sys->p_input = p_input; p_sys->p_input = p_input;
} }
return s; return s;
} }
...@@ -120,7 +121,8 @@ void input_StreamDelete( stream_t *s ) ...@@ -120,7 +121,8 @@ void input_StreamDelete( stream_t *s )
****************************************************************************/ ****************************************************************************/
static int IStreamControl( stream_t *s, int i_query, va_list args ) static int IStreamControl( stream_t *s, int i_query, va_list args )
{ {
input_thread_t *p_input = s->p_sys->p_input; input_stream_sys_t * p_sys = (input_stream_sys_t*)s->p_sys;
input_thread_t *p_input = p_sys->p_input;
vlc_bool_t *p_b; vlc_bool_t *p_b;
int64_t *p_i64, i64; int64_t *p_i64, i64;
...@@ -252,7 +254,8 @@ static int IStreamControl( stream_t *s, int i_query, va_list args ) ...@@ -252,7 +254,8 @@ static int IStreamControl( stream_t *s, int i_query, va_list args )
****************************************************************************/ ****************************************************************************/
static int IStreamRead( stream_t *s, void *p_data, int i_data ) static int IStreamRead( stream_t *s, void *p_data, int i_data )
{ {
input_thread_t *p_input = s->p_sys->p_input; input_stream_sys_t * p_sys = (input_stream_sys_t*)s->p_sys;
input_thread_t *p_input = p_sys->p_input;
uint8_t *p = (uint8_t*)p_data; uint8_t *p = (uint8_t*)p_data;
int i_read = 0; int i_read = 0;
...@@ -309,5 +312,277 @@ static int IStreamRead( stream_t *s, void *p_data, int i_data ) ...@@ -309,5 +312,277 @@ static int IStreamRead( stream_t *s, void *p_data, int i_data )
****************************************************************************/ ****************************************************************************/
static int IStreamPeek( stream_t *s, uint8_t **pp_peek, int i_peek ) static int IStreamPeek( stream_t *s, uint8_t **pp_peek, int i_peek )
{ {
return input_Peek( s->p_sys->p_input, pp_peek, i_peek ); input_stream_sys_t * p_sys = (input_stream_sys_t*)s->p_sys;
return input_Peek( p_sys->p_input, pp_peek, i_peek );
} }
/****************************************************************************
* stream_Demux*: create a demuxer for an outpout stream (allow demuxer chain)
****************************************************************************/
typedef struct
{
/* Data buffer */
vlc_mutex_t lock;
int i_buffer;
int i_buffer_size;
uint8_t *p_buffer;
int64_t i_pos;
/* Demuxer */
char *psz_name;
es_out_t *out;
demux_t *p_demux;
} d_stream_sys_t;
static int DStreamRead ( stream_t *, void *p_read, int i_read );
static int DStreamPeek ( stream_t *, uint8_t **pp_peek, int i_peek );
static int DStreamControl( stream_t *, int i_query, va_list );
static int DStreamThread ( stream_t * );
stream_t *__stream_DemuxNew( vlc_object_t *p_obj, char *psz_demux, es_out_t *out )
{
/* We create a stream reader, and launch a thread */
stream_t *s;
d_stream_sys_t *p_sys;
if( psz_demux == NULL || *psz_demux == '\0' )
{
return NULL;
}
s = vlc_object_create( p_obj, sizeof( stream_t ) );
s->pf_block = NULL;
s->pf_read = DStreamRead;
s->pf_peek = DStreamPeek;
s->pf_control= DStreamControl;
p_sys = (d_stream_sys_t*)s->p_sys = malloc( sizeof( d_stream_sys_t) );
vlc_mutex_init( s, &p_sys->lock );
p_sys->i_buffer = 0;
p_sys->i_buffer_size = 1000000;
p_sys->p_buffer = malloc( p_sys->i_buffer_size );
p_sys->i_pos = 0;
p_sys->psz_name = strdup( psz_demux );
p_sys->out = out;
p_sys->p_demux = NULL;
if( vlc_thread_create( s, "stream out", DStreamThread, VLC_THREAD_PRIORITY_INPUT, VLC_FALSE ) )
{
vlc_mutex_destroy( &p_sys->lock );
vlc_object_destroy( s );
free( p_sys );
return NULL;
}
return s;
}
void stream_DemuxSend( stream_t *s, block_t *p_block )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
if( p_block->i_buffer > 0 )
{
vlc_mutex_lock( &p_sys->lock );
/* Realloc if needed */
if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size )
{
if( p_sys->i_buffer_size > 5000000 )
{
vlc_mutex_unlock( &p_sys->lock );
msg_Err( s, "stream_DemuxSend: buffer size > 5000000" );
block_Release( p_block );
return;
}
/* I know, it's more than needed but that's perfect */
p_sys->i_buffer_size += p_block->i_buffer;
/* FIXME won't work with PEEK -> segfault */
p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
msg_Dbg( s, "stream_DemuxSend: realloc to %d", p_sys->i_buffer_size );
}
/* copy data */
memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer );
p_sys->i_buffer += p_block->i_buffer;
vlc_mutex_unlock( &p_sys->lock );
}
block_Release( p_block );
}
void stream_DemuxDelete( stream_t *s )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
s->b_die = VLC_TRUE;
vlc_mutex_lock( &p_sys->lock );
if( p_sys->p_demux )
{
p_sys->p_demux->b_die = VLC_TRUE;
}
vlc_mutex_unlock( &p_sys->lock );
vlc_thread_join( s );
if( p_sys->p_demux )
{
demux2_Delete( p_sys->p_demux );
}
vlc_mutex_destroy( &p_sys->lock );
free( p_sys->psz_name );
free( p_sys->p_buffer );
free( p_sys );
vlc_object_destroy( s );
}
static int DStreamRead ( stream_t *s, void *p_read, int i_read )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
int i_copy;
//msg_Dbg( s, "DStreamRead: wanted %d bytes", i_read );
for( ;; )
{
vlc_mutex_lock( &p_sys->lock );
//msg_Dbg( s, "DStreamRead: buffer %d", p_sys->i_buffer );
if( p_sys->i_buffer >= i_read || s->b_die )
{
break;
}
vlc_mutex_unlock( &p_sys->lock );
msleep( 10000 );
}
//msg_Dbg( s, "DStreamRead: read %d buffer %d", i_read, p_sys->i_buffer );
i_copy = __MIN( i_read, p_sys->i_buffer );
if( i_copy > 0 )
{
if( p_read )
{
memcpy( p_read, p_sys->p_buffer, i_copy );
}
p_sys->i_buffer -= i_copy;
p_sys->i_pos += i_copy;
if( p_sys->i_buffer > 0 )
{
memmove( p_sys->p_buffer, &p_sys->p_buffer[i_copy], p_sys->i_buffer );
}
}
vlc_mutex_unlock( &p_sys->lock );
return i_copy;
}
static int DStreamPeek ( stream_t *s, uint8_t **pp_peek, int i_peek )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
int i_copy;
//msg_Dbg( s, "DStreamPeek: wanted %d bytes", i_peek );
for( ;; )
{
vlc_mutex_lock( &p_sys->lock );
//msg_Dbg( s, "DStreamPeek: buffer %d", p_sys->i_buffer );
if( p_sys->i_buffer >= i_peek || s->b_die )
{
break;
}
vlc_mutex_unlock( &p_sys->lock );
msleep( 10000 );
}
*pp_peek = p_sys->p_buffer;
i_copy = __MIN( i_peek, p_sys->i_buffer );
vlc_mutex_unlock( &p_sys->lock );
return i_copy;
}
static int DStreamControl( stream_t *s, int i_query, va_list args )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
int64_t *p_i64;
vlc_bool_t *p_b;
int *p_int;
switch( i_query )
{
case STREAM_GET_SIZE:
p_i64 = (int64_t*) va_arg( args, int64_t * );
*p_i64 = 0;
return VLC_SUCCESS;
case STREAM_CAN_SEEK:
p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
*p_b = VLC_FALSE;
return VLC_SUCCESS;
case STREAM_CAN_FASTSEEK:
p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
*p_b = VLC_FALSE;
return VLC_SUCCESS;
case STREAM_GET_POSITION:
p_i64 = (int64_t*) va_arg( args, int64_t * );
*p_i64 = p_sys->i_pos;
return VLC_SUCCESS;
case STREAM_SET_POSITION:
return VLC_EGENERIC;
case STREAM_GET_MTU:
p_int = (int*) va_arg( args, int * );
*p_int = 0;
return VLC_SUCCESS;
default:
msg_Err( s, "invalid DStreamControl query=0x%x", i_query );
return VLC_EGENERIC;
}
}
static int DStreamThread ( stream_t *s )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
char *psz_mrl;
demux_t *p_demux;
/* Create the demuxer */
psz_mrl = malloc( strlen( p_sys->psz_name ) + 3 );
sprintf( psz_mrl, "/%s:", p_sys->psz_name );
if( ( p_demux = demux2_New( s, psz_mrl, s, p_sys->out ) ) == NULL )
{
free( psz_mrl );
return VLC_EGENERIC;
}
free( psz_mrl );
vlc_mutex_lock( &p_sys->lock );
p_sys->p_demux = p_demux;
vlc_mutex_unlock( &p_sys->lock );
/* Main loop */
while( !s->b_die && !p_demux->b_die )
{
if( p_demux->pf_demux( p_demux ) <= 0 )
{
break;
}
}
p_demux->b_die = VLC_TRUE;
return VLC_SUCCESS;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment