X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fstream.c;h=1d71fa9d044149e58d396e117b003a3ca776e654;hb=9025fab9931ecc35fe247b0a63d0cea166dee88d;hp=f7baea1bf93e199bc0000766cf6f3876febec9b9;hpb=2cb472dba008f7d877ffe6bae9c5575253365282;p=vlc diff --git a/src/input/stream.c b/src/input/stream.c index f7baea1bf9..1d71fa9d04 100644 --- a/src/input/stream.c +++ b/src/input/stream.c @@ -23,7 +23,6 @@ #include #include -#include #include "input_internal.h" @@ -192,18 +191,19 @@ static int ASeek( stream_t *s, int64_t i_pos ); ****************************************************************************/ stream_t *__stream_UrlNew( vlc_object_t *p_parent, const char *psz_url ) { - char *psz_access, *psz_demux, *psz_path, *psz_dup; + const char *psz_access, *psz_demux; + char *psz_path; access_t *p_access; stream_t *p_res; if( !psz_url ) return 0; - psz_dup = strdup( psz_url ); + char psz_dup[strlen (psz_url) + 1]; + strcpy (psz_dup, psz_url);; MRLSplit( p_parent, psz_dup, &psz_access, &psz_demux, &psz_path ); /* Now try a real access */ p_access = access2_New( p_parent, psz_access, psz_demux, psz_path, 0 ); - free( psz_dup ); if( p_access == NULL ) { @@ -223,7 +223,7 @@ stream_t *__stream_UrlNew( vlc_object_t *p_parent, const char *psz_url ) stream_t *stream_AccessNew( access_t *p_access, vlc_bool_t b_quick ) { - stream_t *s = vlc_object_create( p_access, VLC_OBJECT_STREAM ); + stream_t *s = vlc_stream_create( VLC_OBJECT(p_access) ); stream_sys_t *p_sys; char *psz_list; @@ -235,7 +235,7 @@ stream_t *stream_AccessNew( access_t *p_access, vlc_bool_t b_quick ) s->pf_block = NULL; s->pf_read = NULL; /* Set up later */ s->pf_peek = NULL; - s->pf_control= AStreamControl; + s->pf_control = AStreamControl; s->pf_destroy = AStreamDestroy; s->p_sys = p_sys = malloc( sizeof( stream_sys_t ) ); @@ -287,7 +287,7 @@ stream_t *stream_AccessNew( access_t *p_access, vlc_bool_t b_quick ) if( psz_name ) { access_t *p_tmp = access2_New( p_access, p_access->psz_access, - 0, psz_name, 0 ); + "", psz_name, 0 ); if( !p_tmp ) { @@ -807,7 +807,7 @@ static int AStreamSeekBlock( stream_t *s, int64_t i_pos ) if( !b_aseek ) { - msg_Err( s, "backward seek impossible (access non seekable)" ); + msg_Err( s, "backward seeking impossible (access not seekable)" ); return VLC_EGENERIC; } @@ -1327,7 +1327,7 @@ static void AStreamPrebufferStream( stream_t *s ) ( (p_access->info.i_title > 1 || p_access->info.i_seekpoint > 1) ? STREAM_CACHE_PREBUFFER_SIZE : STREAM_CACHE_TRACK_SIZE / 3 ); - msg_Dbg( s, "pre buffering" ); + msg_Dbg( s, "pre-buffering..." ); i_start = mdate(); for( ;; ) { @@ -1347,7 +1347,7 @@ static void AStreamPrebufferStream( stream_t *s ) i_byterate = ( I64C(1000000) * p_sys->stat.i_bytes ) / (p_sys->stat.i_read_time+1); - msg_Dbg( s, "prebuffering done "I64Fd" bytes in "I64Fd"s - " + msg_Dbg( s, "pre-buffering done "I64Fd" bytes in "I64Fd"s - " I64Fd" kbytes/s", p_sys->stat.i_bytes, p_sys->stat.i_read_time / I64C(1000000), @@ -1415,7 +1415,7 @@ char * stream_ReadLine( stream_t *s ) { int i_bom_size = 0; char *psz_encoding = NULL; - + if( p_data[0] == 0xEF && p_data[1] == 0xBB && p_data[2] == 0xBF ) { psz_encoding = strdup( "UTF-8" ); @@ -1465,7 +1465,9 @@ char * stream_ReadLine( stream_t *s ) /* Open the converter if we need it */ if( psz_encoding != NULL ) { + input_thread_t *p_input; msg_Dbg( s, "%s BOM detected", psz_encoding ); + p_input = (input_thread_t *)vlc_object_find( s, VLC_OBJECT_INPUT, FIND_PARENT ); if( s->i_char_width > 1 ) { s->conv = vlc_iconv_open( "UTF-8", psz_encoding ); @@ -1474,22 +1476,82 @@ char * stream_ReadLine( stream_t *s ) msg_Err( s, "iconv_open failed" ); } } + if( p_input != NULL) + { + var_Create( p_input, "subsdec-encoding", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); + var_SetString( p_input, "subsdec-encoding", "UTF-8" ); + vlc_object_release( p_input ); + } if( psz_encoding ) free( psz_encoding ); } } if( i_data % s->i_char_width ) { + /* keep i_char_width boundary */ + i_data = i_data - ( i_data % s->i_char_width ); msg_Warn( s, "the read is not i_char_width compatible"); } + if( i_data == 0 ) + break; + /* Check if there is an EOL */ - if( ( psz_eol = memchr( p_data, '\n', i_data ) ) ) + if( s->i_char_width == 1 ) + { + /* UTF-8: 0A */ + psz_eol = memchr( p_data, '\n', i_data ); + } + else { - if( s->b_little_endian == VLC_TRUE && s->i_char_width > 1 ) + uint8_t *p = p_data; + uint8_t *p_last = p + i_data - s->i_char_width; + + if( s->i_char_width == 2 ) + { + if( s->b_little_endian == VLC_TRUE) + { + /* UTF-16LE: 0A 00 */ + while( p <= p_last && ( p[0] != 0x0A || p[1] != 0x00 ) ) + p += 2; + } + else + { + /* UTF-16BE: 00 0A */ + while( p <= p_last && ( p[1] != 0x0A || p[0] != 0x00 ) ) + p += 2; + } + } + else if( s->i_char_width == 4 ) + { + if( s->b_little_endian == VLC_TRUE) + { + /* UTF-32LE: 0A 00 00 00 */ + while( p <= p_last && ( p[0] != 0x0A || p[1] != 0x00 || + p[2] != 0x00 || p[3] != 0x00 ) ) + p += 4; + } + else + { + /* UTF-32BE: 00 00 00 0A */ + while( p <= p_last && ( p[3] != 0x0A || p[2] != 0x00 || + p[1] != 0x00 || p[0] != 0x00 ) ) + p += 4; + } + } + + if( p > p_last ) + { + psz_eol = NULL; + } + else { - psz_eol += ( s->i_char_width - 1 ); + psz_eol = (char *)p + ( s->i_char_width - 1 ); } + } + + if(psz_eol) + { i_data = (psz_eol - (char *)p_data) + 1; p_line = realloc( p_line, i_line + i_data + s->i_char_width ); /* add \0 */ i_data = stream_Read( s, &p_line[i_line], i_data ); @@ -1520,17 +1582,17 @@ char * stream_ReadLine( stream_t *s ) if( s->i_char_width > 1 ) { size_t i_in = 0, i_out = 0; - char * p_in = NULL; + const char * p_in = NULL; char * p_out = NULL; char * psz_new_line = NULL; - + /* iconv */ psz_new_line = malloc( i_line ); - + i_in = i_out = (size_t)i_line; p_in = p_line; p_out = psz_new_line; - + if( vlc_iconv( s->conv, &p_in, &i_in, &p_out, &i_out ) == (size_t)-1 ) { msg_Err( s, "iconv failed" ); @@ -1542,7 +1604,7 @@ char * stream_ReadLine( stream_t *s ) } /* Remove trailing LF/CR */ - while( i_line > 0 && ( p_line[i_line-2] == '\r' || + while( i_line >= 2 && ( p_line[i_line-2] == '\r' || p_line[i_line-2] == '\n') ) i_line--; /* Make sure the \0 is there */ @@ -1564,18 +1626,29 @@ static int AReadStream( stream_t *s, void *p_read, int i_read ) { stream_sys_t *p_sys = s->p_sys; access_t *p_access = p_sys->p_access; + input_thread_t *p_input = NULL; int i_read_orig = i_read; - int i_total; + int i_total = 0; + + if( s->p_parent && s->p_parent->p_parent && + s->p_parent->p_parent->i_object_type == VLC_OBJECT_INPUT ) + p_input = (input_thread_t *)s->p_parent->p_parent; if( !p_sys->i_list ) { i_read = p_access->pf_read( p_access, p_read, i_read ); - stats_UpdateInteger( s->p_parent->p_parent , "read_bytes", i_read ); - stats_GetInteger( s, s->p_parent->p_parent->i_object_id, - "read_bytes", &i_total ); - stats_UpdateFloat( s->p_parent->p_parent , "input_bitrate", - (float)i_total ); - stats_UpdateInteger( s->p_parent->p_parent , "read_packets", 1 ); + if( p_input ) + { + vlc_object_yield( p_input ); + vlc_mutex_lock( &p_input->p->counters.counters_lock ); + stats_UpdateInteger( s, p_input->p->counters.p_read_bytes, i_read, + &i_total ); + stats_UpdateFloat( s, p_input->p->counters.p_input_bitrate, + (float)i_total, NULL ); + stats_UpdateInteger( s, p_input->p->counters.p_read_packets, 1, NULL ); + vlc_mutex_unlock( &p_input->p->counters.counters_lock ); + vlc_object_release( p_input ); + } return i_read; } @@ -1590,7 +1663,7 @@ static int AReadStream( stream_t *s, void *p_read, int i_read ) msg_Dbg( s, "opening input `%s'", psz_name ); - p_list_access = access2_New( s, p_access->psz_access, 0, psz_name, 0 ); + p_list_access = access2_New( s, p_access->psz_access, "", psz_name, 0 ); if( !p_list_access ) return 0; @@ -1604,12 +1677,17 @@ static int AReadStream( stream_t *s, void *p_read, int i_read ) } /* Update read bytes in input */ - stats_UpdateInteger( s->p_parent->p_parent , "read_bytes", i_read ); - stats_GetInteger( s, s->p_parent->p_parent->i_object_id, - "read_bytes", &i_total ); - stats_UpdateFloat( s->p_parent->p_parent , "input_bitrate", - (float)i_total ); - stats_UpdateInteger( s->p_parent->p_parent , "read_packets", 1 ); + if( p_input ) + { + vlc_object_yield( p_input ); + vlc_mutex_lock( &p_input->p->counters.counters_lock ); + stats_UpdateInteger( s, p_input->p->counters.p_read_bytes, i_read, &i_total ); + stats_UpdateFloat( s, p_input->p->counters.p_input_bitrate, + (float)i_total, NULL ); + stats_UpdateInteger( s, p_input->p->counters.p_read_packets, 1, NULL ); + vlc_mutex_unlock( &p_input->p->counters.counters_lock ); + vlc_object_release( p_input ); + } return i_read; } @@ -1617,13 +1695,31 @@ static block_t *AReadBlock( stream_t *s, vlc_bool_t *pb_eof ) { stream_sys_t *p_sys = s->p_sys; access_t *p_access = p_sys->p_access; + input_thread_t *p_input = NULL; block_t *p_block; vlc_bool_t b_eof; + int i_total = 0; + + if( s->p_parent && s->p_parent->p_parent && + s->p_parent->p_parent->i_object_type == VLC_OBJECT_INPUT ) + p_input = (input_thread_t *)s->p_parent->p_parent; if( !p_sys->i_list ) { p_block = p_access->pf_block( p_access ); if( pb_eof ) *pb_eof = p_access->info.b_eof; + if( p_input && p_block && p_access->p_libvlc->b_stats ) + { + vlc_object_yield( p_input ); + vlc_mutex_lock( &p_input->p->counters.counters_lock ); + stats_UpdateInteger( s, p_input->p->counters.p_read_bytes, + p_block->i_buffer, &i_total ); + stats_UpdateFloat( s, p_input->p->counters.p_input_bitrate, + (float)i_total, NULL ); + stats_UpdateInteger( s, p_input->p->counters.p_read_packets, 1, NULL ); + vlc_mutex_unlock( &p_input->p->counters.counters_lock ); + vlc_object_release( p_input ); + } return p_block; } @@ -1639,7 +1735,7 @@ static block_t *AReadBlock( stream_t *s, vlc_bool_t *pb_eof ) msg_Dbg( s, "opening input `%s'", psz_name ); - p_list_access = access2_New( s, p_access->psz_access, 0, psz_name, 0 ); + p_list_access = access2_New( s, p_access->psz_access, "", psz_name, 0 ); if( !p_list_access ) return 0; @@ -1651,7 +1747,22 @@ static block_t *AReadBlock( stream_t *s, vlc_bool_t *pb_eof ) /* We have to read some data */ return AReadBlock( s, pb_eof ); } - + if( p_block ) + { + if( p_input ) + { + vlc_object_yield( p_input ); + vlc_mutex_lock( &p_input->p->counters.counters_lock ); + stats_UpdateInteger( s, p_input->p->counters.p_read_bytes, + p_block->i_buffer, &i_total ); + stats_UpdateFloat( s, p_input->p->counters.p_input_bitrate, + (float)i_total, NULL ); + stats_UpdateInteger( s, p_input->p->counters.p_read_packets, + 1 , NULL); + vlc_mutex_unlock( &p_input->p->counters.counters_lock ); + vlc_object_release( p_input ); + } + } return p_block; } @@ -1681,7 +1792,7 @@ static int ASeek( stream_t *s, int64_t i_pos ) if( i != p_sys->i_list_index && i != 0 ) { p_list_access = - access2_New( s, p_access->psz_access, 0, psz_name, 0 ); + access2_New( s, p_access->psz_access, "", psz_name, 0 ); } else if( i != p_sys->i_list_index ) { @@ -1703,3 +1814,92 @@ static int ASeek( stream_t *s, int64_t i_pos ) return p_access->pf_seek( p_access, i_pos ); } + + +/** + * 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_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) + */ +int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_peek ) +{ + return s->pf_peek( s, pp_peek, i_peek ); +} + +/** + * 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_vaControl( stream_t *s, int i_query, va_list args ) +{ + return s->pf_control( s, i_query, args ); +} + +/** + * Destroy a stream + */ +void stream_Delete( stream_t *s ) +{ + s->pf_destroy( s ); +} + +int stream_Control( stream_t *s, int i_query, ... ) +{ + va_list args; + int i_result; + + if ( s == NULL ) + return VLC_EGENERIC; + + va_start( args, i_query ); + i_result = s->pf_control( s, i_query, args ); + va_end( args ); + return i_result; +} + +/** + * 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 available, + * return NULL. + */ +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; + } +}