Commit f67cdb74 authored by Frédéric Yhuel's avatar Frédéric Yhuel Committed by Jean-Baptiste Kempf

Smooth Streaming: clean / factorize code

and prepare subtitle support
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent f2cc02bf
...@@ -140,14 +140,8 @@ static int sms_Download( stream_t *s, chunk_t *chunk, char *url ) ...@@ -140,14 +140,8 @@ static int sms_Download( stream_t *s, chunk_t *chunk, char *url )
stream_Delete( p_ts ); stream_Delete( p_ts );
vlc_mutex_lock( &p_sys->download.lock_wait ); vlc_mutex_lock( &p_sys->download.lock_wait );
int index = es_cat_to_index( chunk->type );
if( chunk->type == AUDIO_ES ) p_sys->download.lead[index] += chunk->duration;
p_sys->download.alead += chunk->duration;
else if( chunk->type == VIDEO_ES )
p_sys->download.vlead += chunk->duration;
else if( chunk->type == SPU_ES )
p_sys->download.tlead += chunk->duration;
vlc_mutex_unlock( &p_sys->download.lock_wait ); vlc_mutex_unlock( &p_sys->download.lock_wait );
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -205,12 +199,7 @@ static int get_new_chunks( stream_t *s, chunk_t *ck ) ...@@ -205,12 +199,7 @@ static int get_new_chunks( stream_t *s, chunk_t *ck )
UUID_t uuid; UUID_t uuid;
TfrfBoxDataFields_t *tfrf_df; TfrfBoxDataFields_t *tfrf_df;
if( ck->type == AUDIO_ES ) sms = SMS_GET_SELECTED_ST( ck->type );
sms = p_sys->astream;
else if ( ck->type == VIDEO_ES )
sms = p_sys->vstream;
else
return 0;
SMS_GET4BYTES( size ); SMS_GET4BYTES( size );
SMS_GETFOURCC( type ); SMS_GETFOURCC( type );
...@@ -307,6 +296,7 @@ static int build_smoo_box( stream_t *s, uint8_t *smoo_box ) ...@@ -307,6 +296,7 @@ static int build_smoo_box( stream_t *s, uint8_t *smoo_box )
for( int i = 0; i < 3; i++ ) for( int i = 0; i < 3; i++ )
{ {
sms = NULL; sms = NULL;
int cat = UNKNOWN_ES;
stra_box = smoo_box + i * STRA_SIZE; stra_box = smoo_box + i * STRA_SIZE;
stra_box[26] = (STRA_SIZE & 0xff00)>>8; stra_box[26] = (STRA_SIZE & 0xff00)>>8;
...@@ -322,21 +312,9 @@ static int build_smoo_box( stream_t *s, uint8_t *smoo_box ) ...@@ -322,21 +312,9 @@ static int build_smoo_box( stream_t *s, uint8_t *smoo_box )
((uint32_t *)stra_box)[10] = bswap32( 0x96c7bf25 ); ((uint32_t *)stra_box)[10] = bswap32( 0x96c7bf25 );
((uint32_t *)stra_box)[11] = bswap32( 0xf97e2447 ); ((uint32_t *)stra_box)[11] = bswap32( 0xf97e2447 );
if( i == 0) cat = index_to_es_cat( i );
{ stra_box[48] = cat;
stra_box[48] = VIDEO_ES; sms = SMS_GET_SELECTED_ST( cat );
sms = p_sys->vstream;
}
else if( i == 1 )
{
stra_box[48] = AUDIO_ES;
sms = p_sys->astream;
}
else if( i == 2 )
{
stra_box[48] = SPU_ES;
sms = p_sys->tstream;
}
stra_box[49] = 0; /* reserved */ stra_box[49] = 0; /* reserved */
if( sms == NULL ) if( sms == NULL )
...@@ -359,6 +337,8 @@ static int build_smoo_box( stream_t *s, uint8_t *smoo_box ) ...@@ -359,6 +337,8 @@ static int build_smoo_box( stream_t *s, uint8_t *smoo_box )
((uint32_t *)stra_box)[23] = bswap32( qlvl->AudioTag ); ((uint32_t *)stra_box)[23] = bswap32( qlvl->AudioTag );
((uint16_t *)stra_box)[48] = bswap16( qlvl->nBlockAlign ); ((uint16_t *)stra_box)[48] = bswap16( qlvl->nBlockAlign );
if( !qlvl->CodecPrivateData )
continue;
stra_box[98] = stra_box[99] = stra_box[100] = 0; /* reserved */ stra_box[98] = stra_box[99] = stra_box[100] = 0; /* reserved */
assert( strlen( qlvl->CodecPrivateData ) < 512 ); assert( strlen( qlvl->CodecPrivateData ) < 512 );
stra_box[101] = strlen( qlvl->CodecPrivateData ) / 2; stra_box[101] = strlen( qlvl->CodecPrivateData ) / 2;
...@@ -396,16 +376,8 @@ static int Download( stream_t *s, sms_stream_t *sms ) ...@@ -396,16 +376,8 @@ static int Download( stream_t *s, sms_stream_t *sms )
{ {
stream_sys_t *p_sys = s->p_sys; stream_sys_t *p_sys = s->p_sys;
int64_t start_time; int index = es_cat_to_index( sms->type );
int64_t start_time = p_sys->download.lead[index];
if( sms->type == AUDIO_ES )
start_time = p_sys->download.alead;
else if ( sms->type == VIDEO_ES )
start_time = p_sys->download.vlead;
else
{
return VLC_EGENERIC;
}
quality_level_t *qlevel = get_qlevel( sms, sms->download_qlvl ); quality_level_t *qlevel = get_qlevel( sms, sms->download_qlvl );
if( unlikely( !qlevel ) ) if( unlikely( !qlevel ) )
...@@ -485,21 +457,15 @@ static int Download( stream_t *s, sms_stream_t *sms ) ...@@ -485,21 +457,15 @@ static int Download( stream_t *s, sms_stream_t *sms )
chunk->sequence, sms->name, qlevel->Bitrate ); chunk->sequence, sms->name, qlevel->Bitrate );
uint64_t actual_lead = chunk->start_time + chunk->duration; uint64_t actual_lead = chunk->start_time + chunk->duration;
if( sms->type == AUDIO_ES ) int ind = es_cat_to_index( sms->type );
{ p_sys->download.ck_index[ind] = chunk->sequence;
p_sys->download.aindex = chunk->sequence; p_sys->download.lead[ind] = __MIN( p_sys->download.lead[ind], actual_lead );
p_sys->download.alead = __MIN( p_sys->download.alead, actual_lead );
} if( sms->type == VIDEO_ES ||
else if( sms->type == VIDEO_ES ) ( !SMS_GET_SELECTED_ST( VIDEO_ES ) && sms->type == AUDIO_ES ) )
{
p_sys->download.vindex = chunk->sequence;
p_sys->download.vlead = __MIN( p_sys->download.vlead, actual_lead );
p_sys->playback.toffset = __MIN( p_sys->playback.toffset, (uint64_t)chunk->start_time );
}
else if( sms->type == SPU_ES )
{ {
p_sys->download.sindex = chunk->sequence; p_sys->playback.toffset = __MIN( p_sys->playback.toffset,
p_sys->download.tlead = __MIN( p_sys->download.tlead, actual_lead ); (uint64_t)chunk->start_time );
} }
unsigned dur_ms = __MAX( 1, duration / 1000 ); unsigned dur_ms = __MAX( 1, duration / 1000 );
...@@ -555,30 +521,49 @@ static inline int64_t get_lead( stream_t *s ) ...@@ -555,30 +521,49 @@ static inline int64_t get_lead( stream_t *s )
{ {
stream_sys_t *p_sys = s->p_sys; stream_sys_t *p_sys = s->p_sys;
int64_t lead = 0; int64_t lead = 0;
int64_t alead = p_sys->download.lead[es_cat_to_index( AUDIO_ES )];
if( p_sys->vstream && p_sys->astream ) int64_t vlead = p_sys->download.lead[es_cat_to_index( VIDEO_ES )];
lead = __MIN( p_sys->download.vlead, p_sys->download.alead ); bool video = SMS_GET_SELECTED_ST( VIDEO_ES ) ? true : false;
else if( p_sys->vstream ) bool audio = SMS_GET_SELECTED_ST( AUDIO_ES ) ? true : false;
lead = p_sys->download.vlead;
if( video && audio )
lead = __MIN( vlead, alead );
else if( video )
lead = vlead;
else else
lead = p_sys->download.alead; lead = alead;
lead -= p_sys->playback.toffset; lead -= p_sys->playback.toffset;
return lead; return lead;
} }
static int next_track( stream_t *s )
{
stream_sys_t *p_sys = s->p_sys;
uint64_t tmp, min = 0;
int cat, ret = UNKNOWN_ES;
for( int i = 0; i < 3; i++ )
{
tmp = p_sys->download.lead[i];
cat = index_to_es_cat( i );
if( (!min || tmp < min) && SMS_GET_SELECTED_ST( cat ) )
{
min = tmp;
ret = cat;
}
}
return ret;
}
void* sms_Thread( void *p_this ) void* sms_Thread( void *p_this )
{ {
stream_t *s = (stream_t *)p_this; stream_t *s = (stream_t *)p_this;
stream_sys_t *p_sys = s->p_sys; stream_sys_t *p_sys = s->p_sys;
sms_stream_t *sms = NULL;
chunk_t *chunk;
int canc = vlc_savecancel(); int canc = vlc_savecancel();
sms_stream_t *vsms = p_sys->vstream;
sms_stream_t *asms = p_sys->astream;
if( !vsms && !asms )
goto cancel;
/* We compute the average bandwidth of the 4 last downloaded /* We compute the average bandwidth of the 4 last downloaded
* chunks, but feel free to replace '4' by whatever you wish */ * chunks, but feel free to replace '4' by whatever you wish */
p_sys->bws = sms_queue_init( 4 ); p_sys->bws = sms_queue_init( 4 );
...@@ -595,57 +580,31 @@ void* sms_Thread( void *p_this ) ...@@ -595,57 +580,31 @@ void* sms_Thread( void *p_this )
p_sys->download.next_chunk_offset = init_ck->size; p_sys->download.next_chunk_offset = init_ck->size;
chunk_t *audio_chunk, *video_chunk; /* XXX Sometimes, the video stream is cut into pieces of one exact length,
if( vsms )
video_chunk = vlc_array_item_at_index( vsms->chunks, 0 );
if( asms )
audio_chunk = vlc_array_item_at_index( asms->chunks, 0 );
if( (vsms && !video_chunk) || (asms && !audio_chunk) )
goto cancel;
/* Sometimes, the video stream is cut into pieces of one exact length,
* while the audio stream fragments can't be made to match exactly, * while the audio stream fragments can't be made to match exactly,
* and for some reason the n^th advertised video fragment is related to * and for some reason the n^th advertised video fragment is related to
* the n+1^th advertised audio chunk or vice versa */ * the n+1^th advertised audio chunk or vice versa */
if( asms && vsms )
{
int64_t amid, vmid;
amid = audio_chunk->duration / 2;
vmid = video_chunk->duration / 2;
if( audio_chunk->start_time > video_chunk->start_time + vmid ) int64_t start_time = 0, lead = 0;
{
video_chunk = vlc_array_item_at_index( vsms->chunks, 1 );
}
else if( video_chunk->start_time > audio_chunk->start_time + amid )
{
audio_chunk = vlc_array_item_at_index( asms->chunks, 1 );
}
}
if( p_sys->b_live ) for( int i = 0; i < 3; i++ )
{ {
p_sys->download.vlead = vsms ? sms = SMS_GET_SELECTED_ST( index_to_es_cat( i ) );
video_chunk->start_time + p_sys->timescale / 1000 : 0; if( sms )
p_sys->download.alead = asms ?
audio_chunk->start_time + p_sys->timescale / 1000 : 0;
}
if( vsms && Download( s, vsms ) != VLC_SUCCESS )
{ {
chunk = vlc_array_item_at_index( sms->chunks, 0 );
p_sys->download.lead[i] = chunk->start_time + p_sys->timescale / 1000;
if( !start_time )
start_time = chunk->start_time;
if( Download( s, sms ) != VLC_SUCCESS )
goto cancel; goto cancel;
} }
if( asms && Download( s, asms ) != VLC_SUCCESS )
{
goto cancel;
} }
int64_t lead = 0;
int64_t start_time = vsms ? video_chunk->start_time : audio_chunk->start_time;
while( 1 ) while( 1 )
{ {
/* XXX replace magic number 20 by a value depending on /* XXX replace magic number 10 by a value depending on
* LookAheadFragmentCount and DVRWindowLength */ * LookAheadFragmentCount and DVRWindowLength */
vlc_mutex_lock( &p_sys->download.lock_wait ); vlc_mutex_lock( &p_sys->download.lock_wait );
...@@ -655,13 +614,9 @@ void* sms_Thread( void *p_this ) ...@@ -655,13 +614,9 @@ void* sms_Thread( void *p_this )
break; break;
} }
bool no_more_chunks = !p_sys->b_live &&
(!vsms || p_sys->download.vindex >= vsms->vod_chunks_nb - 1) &&
(!asms || p_sys->download.aindex >= asms->vod_chunks_nb - 1);
lead = get_lead( s ); lead = get_lead( s );
while( lead > 10 * p_sys->timescale + start_time || no_more_chunks ) while( lead > 10 * p_sys->timescale + start_time || NO_MORE_CHUNKS )
{ {
vlc_cond_wait( &p_sys->download.wait, &p_sys->download.lock_wait ); vlc_cond_wait( &p_sys->download.wait, &p_sys->download.lock_wait );
lead = get_lead( s ); lead = get_lead( s );
...@@ -690,8 +645,11 @@ void* sms_Thread( void *p_this ) ...@@ -690,8 +645,11 @@ void* sms_Thread( void *p_this )
p_sys->download.chunks = vlc_array_new(); p_sys->download.chunks = vlc_array_new();
p_sys->playback.toffset = p_sys->time_pos; p_sys->playback.toffset = p_sys->time_pos;
p_sys->download.vlead = p_sys->download.alead = p_sys->time_pos; for( int i = 0; i < 3; i++ )
p_sys->download.aindex = p_sys->download.vindex = 0; {
p_sys->download.lead[i] = p_sys->time_pos;
p_sys->download.ck_index[i] = 0;
}
p_sys->download.next_chunk_offset = 0; p_sys->download.next_chunk_offset = 0;
p_sys->playback.boffset = 0; p_sys->playback.boffset = 0;
...@@ -709,16 +667,9 @@ void* sms_Thread( void *p_this ) ...@@ -709,16 +667,9 @@ void* sms_Thread( void *p_this )
} }
vlc_mutex_unlock( &p_sys->download.lock_wait ); vlc_mutex_unlock( &p_sys->download.lock_wait );
if( !vsms || (asms && p_sys->download.alead < p_sys->download.vlead) ) sms = SMS_GET_SELECTED_ST( next_track( s ) );
{ if( Download( s, sms ) != VLC_SUCCESS )
if( Download( s, asms ) != VLC_SUCCESS ) goto cancel;
break;
}
else if( !asms || (vsms && p_sys->download.vlead <= p_sys->download.alead ) )
{
if( Download( s, vsms ) != VLC_SUCCESS )
break;
}
} }
cancel: cancel:
......
...@@ -404,8 +404,10 @@ static int Open( vlc_object_t *p_this ) ...@@ -404,8 +404,10 @@ static int Open( vlc_object_t *p_this )
p_sys->b_cache = false; p_sys->b_cache = false;
p_sys->sms_streams = vlc_array_new(); p_sys->sms_streams = vlc_array_new();
p_sys->selected_st = vlc_array_new();
p_sys->download.chunks = vlc_array_new(); p_sys->download.chunks = vlc_array_new();
if( unlikely( !p_sys->sms_streams || !p_sys->download.chunks ) ) if( unlikely( !p_sys->sms_streams || !p_sys->download.chunks ||
!p_sys->selected_st ) )
{ {
free( p_sys ); free( p_sys );
return VLC_ENOMEM; return VLC_ENOMEM;
...@@ -423,34 +425,14 @@ static int Open( vlc_object_t *p_this ) ...@@ -423,34 +425,14 @@ static int Open( vlc_object_t *p_this )
p_sys->i_tracks = vlc_array_count( p_sys->sms_streams ); p_sys->i_tracks = vlc_array_count( p_sys->sms_streams );
/* FIXME */ /* Choose first video / audio / subtitle stream available */
p_sys->i_selected_tracks = 2; /* one video track and one audio track */ sms_stream_t *tmp = NULL, *selected = NULL;
/* Choose first video stream available */
sms_stream_t *vsms = NULL;
for( unsigned i = 0; i < p_sys->i_tracks; i++ ) for( unsigned i = 0; i < p_sys->i_tracks; i++ )
{ {
vsms = vlc_array_item_at_index( p_sys->sms_streams, i ); tmp = vlc_array_item_at_index( p_sys->sms_streams, i );
if( vsms->type == VIDEO_ES ) selected = SMS_GET_SELECTED_ST( tmp->type );
{ if( !selected )
msg_Dbg( s, "Video stream chosen is %s", vsms->name ); vlc_array_append( p_sys->selected_st, tmp );
p_sys->vstream = vsms;
break;
}
}
/* Choose first audio stream available */
sms_stream_t *asms = NULL;
for( unsigned i = 0; i < p_sys->i_tracks; i++ )
{
asms = vlc_array_item_at_index( p_sys->sms_streams, i );
//if( asms->type == AUDIO_ES && !strcmp( asms->name, "audio_eng" ) )
if( asms->type == AUDIO_ES )
{
msg_Dbg( s, "Audio stream chosen is %s", asms->name );
p_sys->astream = asms;
break;
}
} }
/* Choose lowest quality for the first chunks */ /* Choose lowest quality for the first chunks */
...@@ -498,7 +480,8 @@ static void Close( vlc_object_t *p_this ) ...@@ -498,7 +480,8 @@ static void Close( vlc_object_t *p_this )
vlc_mutex_lock( &p_sys->download.lock_wait ); vlc_mutex_lock( &p_sys->download.lock_wait );
p_sys->b_close = true; p_sys->b_close = true;
/* Negate the condition variable's predicate */ /* Negate the condition variable's predicate */
p_sys->download.vlead = p_sys->download.alead = 0; for( int i = 0; i < 3; i++ )
p_sys->download.lead[i] = 0;
p_sys->playback.toffset = 0; p_sys->playback.toffset = 0;
vlc_cond_signal(&p_sys->download.wait); vlc_cond_signal(&p_sys->download.wait);
vlc_mutex_unlock( &p_sys->download.lock_wait ); vlc_mutex_unlock( &p_sys->download.lock_wait );
...@@ -544,9 +527,7 @@ static chunk_t *get_chunk( stream_t *s, const bool wait ) ...@@ -544,9 +527,7 @@ static chunk_t *get_chunk( stream_t *s, const bool wait )
p_sys->playback.index ); p_sys->playback.index );
return NULL; return NULL;
} }
if( !p_sys->b_live && if( NO_MORE_CHUNKS )
p_sys->download.aindex >= (p_sys->vstream->vod_chunks_nb -1) &&
p_sys->download.vindex >= (p_sys->astream->vod_chunks_nb -1) )
{ {
vlc_mutex_unlock( &p_sys->download.lock_wait ); vlc_mutex_unlock( &p_sys->download.lock_wait );
msg_Info( s, "No more chunks, end of the VOD" ); msg_Info( s, "No more chunks, end of the VOD" );
...@@ -580,7 +561,8 @@ static int sms_Read( stream_t *s, uint8_t *p_read, int i_read ) ...@@ -580,7 +561,8 @@ static int sms_Read( stream_t *s, uint8_t *p_read, int i_read )
if( chunk->read_pos >= (int)chunk->size ) if( chunk->read_pos >= (int)chunk->size )
{ {
if( chunk->type == VIDEO_ES || !p_sys->vstream ) if( chunk->type == VIDEO_ES ||
( !SMS_GET_SELECTED_ST( VIDEO_ES ) && chunk->type == AUDIO_ES ) )
{ {
vlc_mutex_lock( &p_sys->download.lock_wait ); vlc_mutex_lock( &p_sys->download.lock_wait );
p_sys->playback.toffset += chunk->duration; p_sys->playback.toffset += chunk->duration;
...@@ -727,7 +709,8 @@ static int chunk_Seek( stream_t *s, const uint64_t pos ) ...@@ -727,7 +709,8 @@ static int chunk_Seek( stream_t *s, const uint64_t pos )
p_sys->b_tseek = true; p_sys->b_tseek = true;
p_sys->time_pos = p_sys->vod_duration * pos / FAKE_STREAM_SIZE; p_sys->time_pos = p_sys->vod_duration * pos / FAKE_STREAM_SIZE;
p_sys->download.vlead = p_sys->download.alead = 0; for( int i = 0; i < 3; i++ )
p_sys->download.lead[i] = 0;
p_sys->playback.toffset = 0; p_sys->playback.toffset = 0;
vlc_cond_signal( &p_sys->download.wait); vlc_cond_signal( &p_sys->download.wait);
......
...@@ -89,12 +89,9 @@ struct stream_sys_t ...@@ -89,12 +89,9 @@ struct stream_sys_t
char *base_url; /* URL common part for chunks */ char *base_url; /* URL common part for chunks */
vlc_thread_t thread; /* SMS chunk download thread */ vlc_thread_t thread; /* SMS chunk download thread */
vlc_array_t *sms_streams; /* array of sms_stream_t */ vlc_array_t *sms_streams; /* available streams */
sms_stream_t *vstream; /* current video stream */ vlc_array_t *selected_st; /* selected streams */
sms_stream_t *astream; /* current audio stream */
sms_stream_t *tstream; /* current text stream */
unsigned i_tracks; /* Total number of tracks in the Manifest */ unsigned i_tracks; /* Total number of tracks in the Manifest */
unsigned i_selected_tracks;
sms_queue_t *bws; /* Measured bandwidths of the N last chunks */ sms_queue_t *bws; /* Measured bandwidths of the N last chunks */
uint64_t vod_duration; /* total duration of the VOD media */ uint64_t vod_duration; /* total duration of the VOD media */
int64_t time_pos; int64_t time_pos;
...@@ -103,13 +100,10 @@ struct stream_sys_t ...@@ -103,13 +100,10 @@ struct stream_sys_t
/* Download */ /* Download */
struct sms_download_s struct sms_download_s
{ {
uint64_t alead; // how much audio/video/text data is uint64_t lead[3]; /* how much audio/video/text data is available
uint64_t vlead; // available (downloaded), (downloaded), in seconds / TimeScale */
uint64_t tlead; // in seconds / TimeScale
unsigned aindex; /* current audio chunk for download */ unsigned ck_index[3]; /* current chunk for download */
unsigned vindex; /* video */
unsigned sindex; /* spu */
uint64_t next_chunk_offset; uint64_t next_chunk_offset;
vlc_array_t *chunks; /* chunks that have been downloaded */ vlc_array_t *chunks; /* chunks that have been downloaded */
...@@ -164,6 +158,12 @@ struct stream_sys_t ...@@ -164,6 +158,12 @@ struct stream_sys_t
slice += 4; \ slice += 4; \
} while(0) } while(0)
#define SMS_GET_SELECTED_ST( cat ) \
sms_get_stream_by_cat( p_sys->selected_st, cat )
#define NO_MORE_CHUNKS !p_sys->b_live && \
no_more_chunks( p_sys->download.ck_index, p_sys->selected_st )
sms_queue_t *sms_queue_init( const int ); sms_queue_t *sms_queue_init( const int );
int sms_queue_put( sms_queue_t *, const uint64_t ); int sms_queue_put( sms_queue_t *, const uint64_t );
uint64_t sms_queue_avg( sms_queue_t *); uint64_t sms_queue_avg( sms_queue_t *);
...@@ -176,5 +176,9 @@ void chunk_Free( chunk_t *); ...@@ -176,5 +176,9 @@ void chunk_Free( chunk_t *);
sms_stream_t * sms_New( void ); sms_stream_t * sms_New( void );
void sms_Free( sms_stream_t *); void sms_Free( sms_stream_t *);
uint8_t *decode_string_hex_to_binary( const char * ); uint8_t *decode_string_hex_to_binary( const char * );
sms_stream_t * sms_get_stream_by_cat( vlc_array_t *, int );
bool no_more_chunks( unsigned[], vlc_array_t *);
int index_to_es_cat( int );
int es_cat_to_index( int );
#endif #endif
...@@ -202,3 +202,63 @@ uint64_t sms_queue_avg( sms_queue_t *queue ) ...@@ -202,3 +202,63 @@ uint64_t sms_queue_avg( sms_queue_t *queue )
} }
return sum / queue->length; return sum / queue->length;
} }
sms_stream_t * sms_get_stream_by_cat( vlc_array_t *streams, int i_cat )
{
sms_stream_t *ret = NULL;
int count = vlc_array_count( streams );
assert( count >= 0 && count <= 3 );
for( int i = 0; i < count; i++ )
{
ret = vlc_array_item_at_index( streams, i );
if( ret->type == i_cat )
return ret;
}
return NULL;
}
int es_cat_to_index( int i_cat )
{
switch( i_cat )
{
case VIDEO_ES:
return 0;
case AUDIO_ES:
return 1;
case SPU_ES:
return 2;
default:
return -1;
}
}
int index_to_es_cat( int index )
{
switch( index )
{
case 0:
return VIDEO_ES;
case 1:
return AUDIO_ES;
case 2:
return SPU_ES;
default:
return -1;
}
}
bool no_more_chunks( unsigned *indexes, vlc_array_t *streams )
{
sms_stream_t *sms = NULL;
int count = vlc_array_count( streams );
unsigned ck_index;
for( int i = 0; i < count; i++ )
{
sms = vlc_array_item_at_index( streams, i );
ck_index = indexes[es_cat_to_index( sms->type )];
if( ck_index < sms->vod_chunks_nb - 1 )
return false;
}
return true;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment