*****************************************************************************/
demux_t *__demux2_New( vlc_object_t *p_obj,
char *psz_access, char *psz_demux, char *psz_path,
- stream_t *s, es_out_t *out )
+ stream_t *s, es_out_t *out, vlc_bool_t b_quick )
{
demux_t *p_demux = vlc_object_create( p_obj, VLC_OBJECT_DEMUX );
char *psz_module;
p_demux->psz_demux = strdup( psz_demux );
p_demux->psz_path = strdup( psz_path );
- msg_Dbg( p_obj, "demux2_New: access='%s' demux='%s' path='%s'",
- p_demux->psz_access, p_demux->psz_demux, p_demux->psz_path );
+ /* Take into account "demux" to be able to do :demux=dump */
+ if( *p_demux->psz_demux == '\0' )
+ {
+ free( p_demux->psz_demux );
+ p_demux->psz_demux = var_GetString( p_obj, "demux" );
+ }
+
+ if( !b_quick )
+ {
+ msg_Dbg( p_obj, "demux2_New: access='%s' demux='%s' path='%s'",
+ p_demux->psz_access, p_demux->psz_demux, p_demux->psz_path );
+ }
p_demux->s = s;
p_demux->out = out;
* - no .mp3, .a52, ... (aac is added as it works only by file ext anyway
* - wav can't be added 'cause of a52 and dts in them as raw audio
*/
- static struct { char *ext; char *demux; } exttodemux[] =
- {
+ static struct { char *ext; char *demux; } exttodemux[] =
+ {
{ "aac", "aac" },
{ "aiff", "aiff" },
{ "asf", "asf" }, { "wmv", "asf" }, { "wma", "asf" },
{ "ogg", "ogg" }, { "ogm", "ogg" },
{ "pva", "pva" },
{ "rm", "rm" },
- { "", "" },
+ { NULL, NULL },
+ };
+ /* Here, we don't mind if it does not work, it must be quick */
+ static struct { char *ext; char *demux; } exttodemux_quick[] =
+ {
+ { "mp3", "mpga" },
+ { "ogg", "ogg" },
+ { "wma", "asf" },
+ { NULL, NULL }
};
char *psz_ext = strrchr( p_demux->psz_path, '.' ) + 1;
int i;
- for( i = 0; exttodemux[i].ext != NULL; i++ )
+ if( !b_quick )
{
- if( !strcasecmp( psz_ext, exttodemux[i].ext ) )
+ for( i = 0; exttodemux[i].ext != NULL; i++ )
{
- psz_module = exttodemux[i].demux;
- break;
+ if( !strcasecmp( psz_ext, exttodemux[i].ext ) )
+ {
+ psz_module = exttodemux[i].demux;
+ break;
+ }
}
}
+ else
+ {
+ for( i = 0; exttodemux_quick[i].ext != NULL; i++ )
+ {
+ if( !strcasecmp( psz_ext, exttodemux_quick[i].ext ) )
+ {
+ psz_module = exttodemux_quick[i].demux;
+ break;
+ }
+ }
+
+ }
}
/* Before module_Need (for var_Create...) */
{
p_demux->p_module =
module_Need( p_demux, "demux2", psz_module,
- !strcmp( psz_module, p_demux->psz_demux ) ? VLC_TRUE : VLC_FALSE );
+ !strcmp( psz_module, p_demux->psz_demux ) ?
+ VLC_TRUE : VLC_FALSE );
}
else
{
p_demux->p_module =
module_Need( p_demux, "access_demux", psz_module,
- !strcmp( psz_module, p_demux->psz_access ) ? VLC_TRUE : VLC_FALSE );
+ !strcmp( psz_module, p_demux->psz_access ) ?
+ VLC_TRUE : VLC_FALSE );
}
if( p_demux->p_module == NULL )
case DEMUX_GET_META:
case DEMUX_SET_NEXT_DEMUX_TIME:
case DEMUX_GET_TITLE_INFO:
+ case DEMUX_SET_GROUP:
return VLC_EGENERIC;
default:
typedef struct
{
/* Data buffer */
- vlc_mutex_t lock;
- int i_buffer;
- int i_buffer_size;
- uint8_t *p_buffer;
+ block_fifo_t *p_fifo;
+ block_t *p_block;
int64_t i_pos;
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 DStreamThread ( stream_t * );
-stream_t *__stream_DemuxNew( vlc_object_t *p_obj, char *psz_demux, es_out_t *out )
+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;
- }
+ if( psz_demux == NULL || *psz_demux == '\0' ) return NULL;
s = vlc_object_create( p_obj, VLC_OBJECT_STREAM );
s->pf_block = NULL;
s->p_sys = malloc( sizeof( d_stream_sys_t) );
p_sys = (d_stream_sys_t*)s->p_sys;
- 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;
+ p_sys->p_block = NULL;
+ p_sys->psz_name = strdup( psz_demux );
+
+ /* decoder fifo */
+ if( ( p_sys->p_fifo = block_FifoNew( s ) ) == NULL )
+ {
+ msg_Err( s, "out of memory" );
+ vlc_object_destroy( s );
+ free( p_sys );
+ return NULL;
+ }
- if( vlc_thread_create( s, "stream out", DStreamThread, VLC_THREAD_PRIORITY_INPUT, VLC_FALSE ) )
+ 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 )
+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 );
+ if( p_block ) block_FifoPut( p_sys->p_fifo, p_block );
}
-void stream_DemuxDelete( stream_t *s )
+void stream_DemuxDelete( stream_t *s )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
+ block_t *p_empty;
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 );
-
+ if( p_sys->p_demux ) p_sys->p_demux->b_die = VLC_TRUE;
+ p_empty = block_New( s, 1 ); p_empty->i_buffer = 0;
+ block_FifoPut( p_sys->p_fifo, p_empty );
vlc_thread_join( s );
- if( p_sys->p_demux )
- {
- demux2_Delete( p_sys->p_demux );
- }
- vlc_mutex_destroy( &p_sys->lock );
+ if( p_sys->p_demux ) demux2_Delete( p_sys->p_demux );
+ if( p_sys->p_block ) block_Release( p_sys->p_block );
+
+ block_FifoRelease( p_sys->p_fifo );
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 )
+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;
+ uint8_t *p_out = p_read;
+ int i_out = 0;
//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 )
+ while( !s->b_die && !s->b_error && i_read )
{
- if( p_read )
+ block_t *p_block = p_sys->p_block;
+ int i_copy;
+
+ if( !p_block )
{
- memcpy( p_read, p_sys->p_buffer, i_copy );
+ p_block = block_FifoGet( p_sys->p_fifo );
+ if( !p_block ) s->b_error = 1;
+ p_sys->p_block = p_block;
}
- p_sys->i_buffer -= i_copy;
- p_sys->i_pos += i_copy;
- if( p_sys->i_buffer > 0 )
+ if( p_block && i_read )
{
- memmove( p_sys->p_buffer, &p_sys->p_buffer[i_copy], p_sys->i_buffer );
+ i_copy = __MIN( i_read, p_block->i_buffer );
+ if( p_out && i_copy ) memcpy( p_out, p_block->p_buffer, i_copy );
+ i_read -= i_copy;
+ i_out += i_copy;
+ p_block->i_buffer -= i_copy;
+ p_block->p_buffer += i_copy;
+
+ if( !p_block->i_buffer )
+ {
+ block_Release( p_block );
+ p_sys->p_block = NULL;
+ }
}
-
}
- vlc_mutex_unlock( &p_sys->lock );
- return i_copy;
+ p_sys->i_pos += i_out;
+ return i_out;
}
-static int DStreamPeek ( stream_t *s, uint8_t **pp_peek, int i_peek )
+
+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;
+ block_t **pp_block = &p_sys->p_block;
+ int i_out = 0;
+ *pp_peek = 0;
//msg_Dbg( s, "DStreamPeek: wanted %d bytes", i_peek );
- for( ;; )
+
+ while( !s->b_die && !s->b_error && i_peek )
{
- 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 )
+ int i_copy;
+
+ if( !*pp_block )
{
- break;
+ *pp_block = block_FifoGet( p_sys->p_fifo );
+ if( !*pp_block ) s->b_error = 1;
+ }
+
+ if( *pp_block && i_peek )
+ {
+ i_copy = __MIN( i_peek, (*pp_block)->i_buffer );
+ i_peek -= i_copy;
+ i_out += i_copy;
+
+ if( i_peek ) pp_block = &(*pp_block)->p_next;
}
- 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 );
+ if( p_sys->p_block )
+ {
+ p_sys->p_block = block_ChainGather( p_sys->p_block );
+ *pp_peek = p_sys->p_block->p_buffer;
+ }
- return i_copy;
+ return i_out;
}
-static int DStreamControl( stream_t *s, int i_query, va_list args )
+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:
return VLC_SUCCESS;
case STREAM_SET_POSITION:
- return VLC_EGENERIC;
+ {
+ int64_t i64 = (int64_t)va_arg( args, int64_t );
+ int i_skip;
+ if( i64 < p_sys->i_pos ) return VLC_EGENERIC;
+ i_skip = i64 - p_sys->i_pos;
+
+ while( i_skip > 0 )
+ {
+ int i_read = DStreamRead( s, NULL, i_skip );
+ if( i_read <= 0 ) return VLC_EGENERIC;
+ i_skip -= i_read;
+ }
+ return VLC_SUCCESS;
+ }
case STREAM_GET_MTU:
p_int = (int*) va_arg( args, int * );
*p_int = 0;
return VLC_SUCCESS;
+ case STREAM_CONTROL_ACCESS:
+ return VLC_EGENERIC;
+
default:
msg_Err( s, "invalid DStreamControl query=0x%x", i_query );
return VLC_EGENERIC;
}
}
-static int DStreamThread ( stream_t *s )
+static int DStreamThread( stream_t *s )
{
d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
- demux_t *p_demux;
+ demux_t *p_demux;
/* Create the demuxer */
-
- if( ( p_demux = demux2_New( s, "", p_sys->psz_name, "", s, p_sys->out ) ) == NULL )
+ if( !(p_demux = demux2_New( s, "", p_sys->psz_name, "", s, p_sys->out,
+ VLC_FALSE )) )
{
return VLC_EGENERIC;
}
- 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;
- }
+ if( p_demux->pf_demux( p_demux ) <= 0 ) break;
}
+
p_demux->b_die = VLC_TRUE;
return VLC_SUCCESS;
}