+
+/****************************************************************************
+ * 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;
+
+ input_thread_t *p_input = (input_thread_t *)s->p_parent->p_parent ;
+ assert( p_input );
+
+ if( !p_sys->i_list )
+ {
+ i_read = p_access->pf_read( p_access, p_read, i_read );
+ vlc_mutex_lock( &p_input->counters.counters_lock );
+ stats_UpdateInteger( s, p_input->counters.p_read_bytes, i_read,
+ &i_total );
+ stats_UpdateFloat( s, p_input->counters.p_input_bitrate,
+ (float)i_total, NULL );
+ stats_UpdateInteger( s, p_input->counters.p_read_packets, 1, NULL );
+ vlc_mutex_unlock( &p_input->counters.counters_lock );
+ 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 */
+ vlc_mutex_lock( &p_input->counters.counters_lock );
+ stats_UpdateInteger( s, p_input->counters.p_read_bytes, i_read, &i_total );
+ stats_UpdateFloat( s, p_input->counters.p_input_bitrate,
+ (float)i_total, NULL );
+ stats_UpdateInteger( s, p_input->counters.p_read_packets, 1, NULL );
+ vlc_mutex_unlock( &p_input->counters.counters_lock );
+ 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;
+
+ input_thread_t *p_input = (input_thread_t *)s->p_parent->p_parent ;
+ assert( p_input );
+
+ 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 )
+ {
+ vlc_mutex_lock( &p_input->counters.counters_lock );
+ stats_UpdateInteger( s, p_input->counters.p_read_bytes,
+ p_block->i_buffer, &i_total );
+ stats_UpdateFloat( s, p_input->counters.p_input_bitrate,
+ (float)i_total, NULL );
+ stats_UpdateInteger( s, p_input->counters.p_read_packets, 1, NULL );
+ vlc_mutex_unlock( &p_input->counters.counters_lock );
+ }
+ 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 )
+ {
+ vlc_mutex_lock( &p_input->counters.counters_lock );
+ stats_UpdateInteger( s, p_input->counters.p_read_bytes,
+ p_block->i_buffer, &i_total );
+ stats_UpdateFloat( s, p_input->counters.p_input_bitrate,
+ (float)i_total, NULL );
+ stats_UpdateInteger( s, p_input->counters.p_read_packets,
+ 1 , NULL);
+ vlc_mutex_unlock( &p_input->counters.counters_lock );
+ }
+ 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 );
+}