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

Smooth Streaming: play streams with no video (or audio) track.

Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 9eec8037
...@@ -216,7 +216,7 @@ static int LoadInitFrag( demux_t *p_demux, const bool b_smooth ) ...@@ -216,7 +216,7 @@ static int LoadInitFrag( demux_t *p_demux, const bool b_smooth )
if( p_stra && p_stra->data.p_stra->i_track_ID ) if( p_stra && p_stra->data.p_stra->i_track_ID )
p_sys->i_tracks++; p_sys->i_tracks++;
/* Get timescale and duration of the video track; */ /* Get timescale and duration of the video track; */
if( i == 0 ) if( !p_sys->i_timescale )
{ {
p_sys->i_timescale = p_stra->data.p_stra->i_timescale; p_sys->i_timescale = p_stra->data.p_stra->i_timescale;
p_sys->i_duration = p_stra->data.p_stra->i_duration; p_sys->i_duration = p_stra->data.p_stra->i_duration;
......
...@@ -553,6 +553,22 @@ static int Download( stream_t *s, sms_stream_t *sms ) ...@@ -553,6 +553,22 @@ static int Download( stream_t *s, sms_stream_t *sms )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static inline int64_t get_lead( stream_t *s )
{
stream_sys_t *p_sys = s->p_sys;
int64_t lead = 0;
if( p_sys->vstream && p_sys->astream )
lead = __MIN( p_sys->download.vlead, p_sys->download.alead );
else if( p_sys->vstream )
lead = p_sys->download.vlead;
else
lead = p_sys->download.alead;
lead -= p_sys->playback.toffset;
return lead;
}
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;
...@@ -562,7 +578,7 @@ void* sms_Thread( void *p_this ) ...@@ -562,7 +578,7 @@ void* sms_Thread( void *p_this )
sms_stream_t *vsms = p_sys->vstream; sms_stream_t *vsms = p_sys->vstream;
sms_stream_t *asms = p_sys->astream; sms_stream_t *asms = p_sys->astream;
if( !asms || !vsms ) if( !vsms && !asms )
goto cancel; goto cancel;
/* We compute the average bandwidth of the 4 last downloaded /* We compute the average bandwidth of the 4 last downloaded
...@@ -581,43 +597,53 @@ void* sms_Thread( void *p_this ) ...@@ -581,43 +597,53 @@ 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 *video_chunk = vlc_array_item_at_index( vsms->chunks, 0 ); chunk_t *audio_chunk, *video_chunk;
chunk_t *audio_chunk = vlc_array_item_at_index( asms->chunks, 0 ); if( vsms )
if( !video_chunk || !audio_chunk ) 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; goto cancel;
/* Sometimes, the video stream is cut into pieces of one exact length, /* 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 */
int64_t amid = audio_chunk->duration / 2; if( asms && vsms )
int64_t vmid = video_chunk->duration / 2;
if( audio_chunk->start_time > video_chunk->start_time + vmid )
{ {
video_chunk = vlc_array_item_at_index( vsms->chunks, 1 ); int64_t amid, vmid;
} amid = audio_chunk->duration / 2;
else if ( video_chunk->start_time > audio_chunk->start_time + amid ) vmid = video_chunk->duration / 2;
{
audio_chunk = vlc_array_item_at_index( asms->chunks, 1 ); if( audio_chunk->start_time > video_chunk->start_time + vmid )
{
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 ) if( p_sys->b_live )
{ {
p_sys->download.vlead = video_chunk->start_time + p_sys->timescale / 1000; p_sys->download.vlead = vsms ?
p_sys->download.alead = audio_chunk->start_time + p_sys->timescale / 1000; video_chunk->start_time + p_sys->timescale / 1000 : 0;
p_sys->download.alead = asms ?
audio_chunk->start_time + p_sys->timescale / 1000 : 0;
} }
if( Download( s, vsms ) != VLC_SUCCESS ) if( vsms && Download( s, vsms ) != VLC_SUCCESS )
{ {
goto cancel; goto cancel;
} }
if( Download( s, asms ) != VLC_SUCCESS ) if( asms && Download( s, asms ) != VLC_SUCCESS )
{ {
goto cancel; goto cancel;
} }
int64_t lead = 0; int64_t lead = 0;
int64_t start_time = vsms ? video_chunk->start_time : audio_chunk->start_time;
while( 1 ) while( 1 )
{ {
...@@ -631,30 +657,16 @@ void* sms_Thread( void *p_this ) ...@@ -631,30 +657,16 @@ void* sms_Thread( void *p_this )
break; break;
} }
lead = __MIN( p_sys->download.vlead, p_sys->download.alead ) bool no_more_chunks = !p_sys->b_live &&
- p_sys->playback.toffset; (!vsms || p_sys->download.vindex >= vsms->vod_chunks_nb - 1) &&
(!asms || p_sys->download.aindex >= asms->vod_chunks_nb - 1);
while( (lead > 10 * p_sys->timescale + video_chunk->start_time) ||
/* If there is no new chunk to process, we wait */ lead = get_lead( s );
(
!p_sys->b_live && while( lead > 10 * p_sys->timescale + start_time || no_more_chunks )
p_sys->download.aindex >= (asms->vod_chunks_nb -1) &&
p_sys->download.vindex >= (vsms->vod_chunks_nb - 1)
)
)
{ {
#if 0
msg_Info( s, "sms_Thread is waiting!" );
msg_Info( s, "toffset is %"PRIu64" vlead is %"PRIu64", alead is %"PRIu64", "\
"and lead is %"PRIi64,
p_sys->playback.toffset,
p_sys->download.vlead - video_chunk->start_time,
p_sys->download.alead - video_chunk->start_time,
lead );
#endif
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 = __MIN( p_sys->download.vlead, p_sys->download.alead ) lead = get_lead( s );
- p_sys->playback.toffset;
if( p_sys->b_close ) if( p_sys->b_close )
break; break;
...@@ -699,12 +711,12 @@ void* sms_Thread( void *p_this ) ...@@ -699,12 +711,12 @@ void* sms_Thread( void *p_this )
} }
vlc_mutex_unlock( &p_sys->download.lock_wait ); vlc_mutex_unlock( &p_sys->download.lock_wait );
if( p_sys->download.alead < p_sys->download.vlead ) if( !vsms || (asms && p_sys->download.alead < p_sys->download.vlead) )
{ {
if( Download( s, asms ) != VLC_SUCCESS ) if( Download( s, asms ) != VLC_SUCCESS )
break; break;
} }
else if( p_sys->download.vlead <= p_sys->download.alead ) else if( !asms || (vsms && p_sys->download.vlead <= p_sys->download.alead ) )
{ {
if( Download( s, vsms ) != VLC_SUCCESS ) if( Download( s, vsms ) != VLC_SUCCESS )
break; break;
......
...@@ -433,10 +433,10 @@ static int Open( vlc_object_t *p_this ) ...@@ -433,10 +433,10 @@ static int Open( vlc_object_t *p_this )
if( vsms->type == VIDEO_ES ) if( vsms->type == VIDEO_ES )
{ {
msg_Dbg( s, "Video stream chosen is %s", vsms->name ); msg_Dbg( s, "Video stream chosen is %s", vsms->name );
p_sys->vstream = vsms;
break; break;
} }
} }
p_sys->vstream = vsms;
/* Choose first audio stream available */ /* Choose first audio stream available */
sms_stream_t *asms = NULL; sms_stream_t *asms = NULL;
...@@ -447,10 +447,10 @@ static int Open( vlc_object_t *p_this ) ...@@ -447,10 +447,10 @@ static int Open( vlc_object_t *p_this )
if( asms->type == AUDIO_ES ) if( asms->type == AUDIO_ES )
{ {
msg_Dbg( s, "Audio stream chosen is %s", asms->name ); msg_Dbg( s, "Audio stream chosen is %s", asms->name );
p_sys->astream = asms;
break; break;
} }
} }
p_sys->astream = asms;
/* Choose lowest quality for the first chunks */ /* Choose lowest quality for the first chunks */
quality_level_t *wanted, *qlvl; quality_level_t *wanted, *qlvl;
...@@ -579,7 +579,7 @@ static int sms_Read( stream_t *s, uint8_t *p_read, int i_read ) ...@@ -579,7 +579,7 @@ 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 ) if( chunk->type == VIDEO_ES || !p_sys->vstream )
{ {
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;
......
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