X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Finput%2Fdemux.c;h=b014b5a6b7aa0d8ffc7ff29ad94f2340b1d01c5e;hb=01aca2cc006e2c2ef00bc5ca723180e27ab15a76;hp=89808d7c5983db3f8435b3766488c3ecfc7d7a25;hpb=48ec587083c643c70346f2d8b6528f100830f74a;p=vlc diff --git a/src/input/demux.c b/src/input/demux.c index 89808d7c59..b014b5a6b7 100644 --- a/src/input/demux.c +++ b/src/input/demux.c @@ -33,7 +33,7 @@ *****************************************************************************/ 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; @@ -48,8 +48,18 @@ demux_t *__demux2_New( vlc_object_t *p_obj, 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; @@ -72,8 +82,8 @@ demux_t *__demux2_New( vlc_object_t *p_obj, * - 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" }, @@ -89,20 +99,43 @@ demux_t *__demux2_New( vlc_object_t *p_obj, { "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...) */ @@ -112,13 +145,15 @@ demux_t *__demux2_New( vlc_object_t *p_obj, { 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 ) @@ -228,6 +263,7 @@ int demux2_vaControlHelper( stream_t *s, case DEMUX_GET_META: case DEMUX_SET_NEXT_DEMUX_TIME: case DEMUX_GET_TITLE_INFO: + case DEMUX_SET_GROUP: return VLC_EGENERIC; default: @@ -242,10 +278,8 @@ int demux2_vaControlHelper( stream_t *s, 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; @@ -253,6 +287,7 @@ typedef struct 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 ); @@ -261,16 +296,14 @@ 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 ) +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; @@ -281,18 +314,24 @@ stream_t *__stream_DemuxNew( vlc_object_t *p_obj, char *psz_demux, es_out_t *out 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; @@ -301,138 +340,120 @@ stream_t *__stream_DemuxNew( vlc_object_t *p_obj, char *psz_demux, es_out_t *out 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: @@ -456,43 +477,55 @@ static int DStreamControl( stream_t *s, int i_query, va_list args ) 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; }