📄 stream.c
字号:
int64_t i_byterate; /* Update stat */ p_sys->stat.i_bytes = tk->i_end - tk->i_start; p_sys->stat.i_read_time = i_date - i_start; i_byterate = ( I64C(1000000) * p_sys->stat.i_bytes ) / (p_sys->stat.i_read_time+1); 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), i_byterate / 1024 ); break; } /* */ i_read = STREAM_CACHE_TRACK_SIZE - tk->i_end; i_read = __MIN( p_sys->stream.i_read_size, i_read ); i_read = AReadStream( s, &tk->p_buffer[tk->i_end], i_read ); if( i_read < 0 ) { msleep( STREAM_DATA_WAIT ); continue; } else if( i_read == 0 ) { /* EOF */ break; } if( i_first == 0 ) { i_first = mdate(); msg_Dbg( s, "received first data for our buffer"); } tk->i_end += i_read; p_sys->stat.i_read_count++; }}/**************************************************************************** * stream_ReadLine: ****************************************************************************//** * Read from the stream untill first newline. * \param s Stream handle to read from * \return A pointer to the allocated output string. You need to free this when you are done. */#define STREAM_PROBE_LINE 2048#define STREAM_LINE_MAX (2048*100)char * stream_ReadLine( stream_t *s ){ char *p_line = NULL; int i_line = 0, i_read = 0; while( i_read < STREAM_LINE_MAX ) { char *psz_eol; uint8_t *p_data; int i_data; int64_t i_pos; /* Probe new data */ i_data = stream_Peek( s, &p_data, STREAM_PROBE_LINE ); if( i_data <= 0 ) break; /* No more data */ /* BOM detection */ i_pos = stream_Tell( s ); if( i_pos == 0 && i_data > 4 ) { 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" ); i_bom_size = 3; } else if( p_data[0] == 0x00 && p_data[1] == 0x00 ) { if( p_data[2] == 0xFE && p_data[3] == 0xFF ) { psz_encoding = strdup( "UTF-32BE" ); s->i_char_width = 4; i_bom_size = 4; } } else if( p_data[0] == 0xFF && p_data[1] == 0xFE ) { if( p_data[2] == 0x00 && p_data[3] == 0x00 ) { psz_encoding = strdup( "UTF-32LE" ); s->i_char_width = 4; s->b_little_endian = VLC_TRUE; i_bom_size = 4; } else { psz_encoding = strdup( "UTF-16LE" ); s->b_little_endian = VLC_TRUE; s->i_char_width = 2; i_bom_size = 2; } } else if( p_data[0] == 0xFE && p_data[1] == 0xFF ) { psz_encoding = strdup( "UTF-16BE" ); s->i_char_width = 2; i_bom_size = 2; } /* Seek past the BOM */ if( i_bom_size ) { stream_Seek( s, i_bom_size ); p_data += i_bom_size; i_data -= i_bom_size; } /* 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 ); if( s->conv == (vlc_iconv_t)-1 ) { 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( s->i_char_width == 1 ) { /* UTF-8: 0A <LF> */ psz_eol = memchr( p_data, '\n', i_data ); } else { 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 <LF> */ while( p <= p_last && ( p[0] != 0x0A || p[1] != 0x00 ) ) p += 2; } else { /* UTF-16BE: 00 0A <LF> */ 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 <LF> */ 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 <LF> */ 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 = (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 ); if( i_data <= 0 ) break; /* Hmmm */ i_line += i_data - s->i_char_width; /* skip \n */; i_read += i_data; /* We have our line */ break; } /* Read data (+1 for easy \0 append) */ p_line = realloc( p_line, i_line + STREAM_PROBE_LINE + s->i_char_width ); i_data = stream_Read( s, &p_line[i_line], STREAM_PROBE_LINE ); if( i_data <= 0 ) break; /* Hmmm */ i_line += i_data; i_read += i_data; } if( i_read > 0 ) { int j; for( j = 0; j < s->i_char_width; j++ ) { p_line[i_line + j] = '\0'; } i_line += s->i_char_width; /* the added \0 */ if( s->i_char_width > 1 ) { size_t i_in = 0, i_out = 0; 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" ); msg_Dbg( s, "original: %d, in %d, out %d", i_line, (int)i_in, (int)i_out ); } if( p_line ) free( p_line ); p_line = psz_new_line; i_line = (size_t)i_line - i_out; /* does not include \0 */ } /* Remove trailing LF/CR */ while( i_line >= 2 && ( p_line[i_line-2] == '\r' || p_line[i_line-2] == '\n') ) i_line--; /* Make sure the \0 is there */ p_line[i_line-1] = '\0'; return p_line; } /* We failed to read any data, probably EOF */ if( p_line ) free( p_line ); if( s->conv != (vlc_iconv_t)(-1) ) vlc_iconv_close( s->conv ); return NULL;}/**************************************************************************** * Access reading/seeking wrappers to handle concatenated streams. ****************************************************************************/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; int i_read_orig = i_read; int i_total; if( !p_sys->i_list ) { i_read = p_access->pf_read( p_access, p_read, i_read ); stats_UpdateInteger( s->p_parent->p_parent , STATS_READ_BYTES, i_read, &i_total ); stats_UpdateFloat( s->p_parent->p_parent , STATS_INPUT_BITRATE, (float)i_total, NULL ); stats_UpdateInteger( s->p_parent->p_parent , STATS_READ_PACKETS, 1, NULL ); return i_read; } i_read = p_sys->p_list_access->pf_read( p_sys->p_list_access, p_read, i_read ); /* If we reached an EOF then switch to the next stream in the list */ if( i_read == 0 && p_sys->i_list_index + 1 < p_sys->i_list ) { char *psz_name = p_sys->list[++p_sys->i_list_index]->psz_path; access_t *p_list_access; msg_Dbg( s, "opening input `%s'", psz_name ); p_list_access = access2_New( s, p_access->psz_access, 0, psz_name, 0 ); if( !p_list_access ) return 0; if( p_sys->p_list_access != p_access ) access2_Delete( p_sys->p_list_access ); p_sys->p_list_access = p_list_access; /* We have to read some data */ return AReadStream( s, p_read, i_read_orig ); } /* Update read bytes in input */ stats_UpdateInteger( s->p_parent->p_parent , STATS_READ_BYTES, i_read, &i_total ); stats_UpdateFloat( s->p_parent->p_parent , STATS_INPUT_BITRATE, (float)i_total, NULL ); stats_UpdateInteger( s->p_parent->p_parent , STATS_READ_PACKETS, 1, NULL ); return i_read;}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; block_t *p_block; vlc_bool_t b_eof; int i_total; 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_block && p_access->p_libvlc->b_stats ) { stats_UpdateInteger( s->p_parent->p_parent, STATS_READ_BYTES, p_block->i_buffer, &i_total ); stats_UpdateFloat( s->p_parent->p_parent , STATS_INPUT_BITRATE, (float)i_total, NULL ); stats_UpdateInteger( s->p_parent->p_parent , STATS_READ_PACKETS, 1, NULL ); } return p_block; } p_block = p_sys->p_list_access->pf_block( p_access ); b_eof = p_sys->p_list_access->info.b_eof; if( pb_eof ) *pb_eof = b_eof; /* If we reached an EOF then switch to the next stream in the list */ if( !p_block && b_eof && p_sys->i_list_index + 1 < p_sys->i_list ) { char *psz_name = p_sys->list[++p_sys->i_list_index]->psz_path; access_t *p_list_access; msg_Dbg( s, "opening input `%s'", psz_name ); p_list_access = access2_New( s, p_access->psz_access, 0, psz_name, 0 ); if( !p_list_access ) return 0; if( p_sys->p_list_access != p_access ) access2_Delete( p_sys->p_list_access ); p_sys->p_list_access = p_list_access; /* We have to read some data */ return AReadBlock( s, pb_eof ); } if( p_block ) { stats_UpdateInteger( s->p_parent->p_parent, STATS_READ_BYTES, p_block->i_buffer, &i_total ); stats_UpdateFloat( s->p_parent->p_parent , STATS_INPUT_BITRATE, (float)i_total, NULL ); stats_UpdateInteger( s->p_parent->p_parent , STATS_READ_PACKETS, 1 , NULL); } return p_block;}static int ASeek( stream_t *s, int64_t i_pos ){ stream_sys_t *p_sys = s->p_sys; access_t *p_access = p_sys->p_access; /* Check which stream we need to access */ if( p_sys->i_list ) { int i; char *psz_name; int64_t i_size = 0; access_t *p_list_access = 0; for( i = 0; i < p_sys->i_list - 1; i++ ) { if( i_pos < p_sys->list[i]->i_size + i_size ) break; i_size += p_sys->list[i]->i_size; } psz_name = p_sys->list[i]->psz_path; if( i != p_sys->i_list_index ) msg_Dbg( s, "opening input `%s'", psz_name ); if( i != p_sys->i_list_index && i != 0 ) { p_list_access = access2_New( s, p_access->psz_access, 0, psz_name, 0 ); } else if( i != p_sys->i_list_index ) { p_list_access = p_access; } if( p_list_access ) { if( p_sys->p_list_access != p_access ) access2_Delete( p_sys->p_list_access ); p_sys->p_list_access = p_list_access; } p_sys->i_list_index = i; return p_sys->p_list_access->pf_seek( p_sys->p_list_access, i_pos - i_size ); } return p_access->pf_seek( p_access, i_pos );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -