Commit 79a1c5ad authored by Thomas Guillem's avatar Thomas Guillem Committed by Jean-Baptiste Kempf

chromecast: rework demux pacing

Pace demux only when the httpd fifo starts to be full.

Replace seek/app_start wait methods by pace() that is interruptible. This fixes
possible deadlock in case of connectivity issue.

(cherry picked from commit 3a151924)
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent a78c362f
......@@ -42,13 +42,15 @@
struct sout_access_out_sys_t
{
intf_sys_t * const m_intf;
httpd_url_t *m_url;
vlc_fifo_t *m_fifo;
block_t *m_header;
bool m_eof;
std::string m_mime;
sout_access_out_sys_t(httpd_host_t *httpd_host, const char *psz_url);
sout_access_out_sys_t(httpd_host_t *httpd_host, intf_sys_t * const intf,
const char *psz_url);
~sout_access_out_sys_t();
void clearUnlocked();
......@@ -62,7 +64,7 @@ struct sout_stream_sys_t
sout_stream_sys_t(httpd_host_t *httpd_host, intf_sys_t * const intf, bool has_video, int port,
const char *psz_default_muxer, const char *psz_default_mime)
: httpd_host(httpd_host)
, access_out_live(httpd_host, "/stream")
, access_out_live(httpd_host, intf, "/stream")
, p_out(NULL)
, default_muxer(psz_default_muxer)
, default_mime(psz_default_mime)
......@@ -316,8 +318,11 @@ static int httpd_url_cb(httpd_callback_sys_t *data, httpd_client_t *cl,
return p_sys->url_cb(cl, answer, query);
}
sout_access_out_sys_t::sout_access_out_sys_t(httpd_host_t *httpd_host, const char *psz_url)
: m_header(NULL)
sout_access_out_sys_t::sout_access_out_sys_t(httpd_host_t *httpd_host,
intf_sys_t * const intf,
const char *psz_url)
: m_intf(intf)
, m_header(NULL)
, m_eof(true)
{
m_fifo = block_FifoNew();
......@@ -404,8 +409,12 @@ int sout_access_out_sys_t::url_cb(httpd_client_t *cl, httpd_message_t *answer,
}
}
}
bool do_unpace = vlc_fifo_GetBytes(m_fifo) < HTTPD_BUFFER_MAX;
vlc_fifo_Unlock(m_fifo);
if (do_unpace)
m_intf->setPacing(false);
answer->i_proto = HTTPD_PROTO_HTTP;
answer->i_version= 0;
answer->i_type = HTTPD_MSG_ANSWER;
......@@ -450,7 +459,11 @@ static ssize_t AccessWrite(sout_access_out_t *p_access, block_t *p_block)
vlc_fifo_Lock(p_sys->m_fifo);
while (vlc_fifo_GetBytes(p_sys->m_fifo) >= HTTPD_BUFFER_MAX)
/* Tell the demux filter to pace when the fifo starts to be full */
bool do_pace = vlc_fifo_GetBytes(p_sys->m_fifo) >= HTTPD_BUFFER_MAX;
/* Drop buffer is the fifo is really full */
while (vlc_fifo_GetBytes(p_sys->m_fifo) >= (HTTPD_BUFFER_MAX * 2))
{
block_t *p_drop = vlc_fifo_DequeueUnlocked(p_sys->m_fifo);
msg_Warn(p_access, "httpd buffer full: dropping %zuB", p_drop->i_buffer);
......@@ -461,6 +474,9 @@ static ssize_t AccessWrite(sout_access_out_t *p_access, block_t *p_block)
vlc_fifo_Unlock(p_sys->m_fifo);
vlc_fifo_Signal(p_sys->m_fifo);
if (do_pace)
p_sys->m_intf->setPacing(true);
return i_len;
}
......@@ -506,6 +522,8 @@ static void AccessClose(vlc_object_t *p_this)
p_sys->m_eof = true;
vlc_fifo_Unlock(p_sys->m_fifo);
vlc_fifo_Signal(p_sys->m_fifo);
p_sys->m_intf->setPacing(false);
}
/*****************************************************************************
......@@ -1185,8 +1203,9 @@ static void Close(vlc_object_t *p_this)
assert(p_sys->streams.empty() && p_sys->out_streams.empty());
httpd_host_t *httpd_host = p_sys->httpd_host;
delete p_sys->p_intf;
intf_sys_t *p_intf = p_sys->p_intf;
delete p_sys;
delete p_intf;
/* Delete last since p_intf and p_sys depends on httpd_host */
httpd_HostDelete(httpd_host);
}
......
......@@ -170,7 +170,11 @@ struct intf_sys_t
void requestPlayerStop();
States state() const;
void setPacing(bool do_pace);
void pace();
int httpd_file_fill( uint8_t *psz_request, uint8_t **pp_data, int *pi_data );
void interrupt_wake_up();
private:
bool handleMessages();
......@@ -211,10 +215,9 @@ private:
static double get_position(void*);
static void set_initial_time( void*, mtime_t time );
static void wait_app_started(void*);
static void pace(void*);
static void request_seek(void*, mtime_t pos);
static void wait_seek_done(void*);
static void set_pause_state(void*, bool paused);
......@@ -232,6 +235,7 @@ private:
mutable vlc_mutex_t m_lock;
vlc_cond_t m_stateChangedCond;
vlc_cond_t m_pace_cond;
vlc_thread_t m_chromecastThread;
ChromecastCommunication m_communication;
......@@ -240,6 +244,8 @@ private:
bool m_request_stop;
bool m_request_load;
bool m_eof;
bool m_pace;
bool m_interrupted;
vlc_meta_t *m_meta;
......
......@@ -42,10 +42,9 @@ typedef struct
double (*pf_get_position)(void*);
void (*pf_set_initial_time)( void*, mtime_t time );
void (*pf_wait_app_started)(void*);
void (*pf_pace)(void*);
void (*pf_request_seek)(void*, mtime_t pos);
void (*pf_wait_seek_done)(void*);
void (*pf_set_pause_state)(void*, bool paused);
......
......@@ -98,6 +98,7 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
, m_request_stop( false )
, m_request_load( false )
, m_eof( false )
, m_pace( false )
, m_meta( NULL )
, m_ctl_thread_interrupt(p_interrupt)
, m_httpd_host(httpd_host)
......@@ -109,6 +110,7 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
{
vlc_mutex_init(&m_lock);
vlc_cond_init( &m_stateChangedCond );
vlc_cond_init( &m_pace_cond );
const char *psz_artmime = "application/octet-stream";
m_httpd_file = httpd_FileNew( m_httpd_host, "/art", psz_artmime, NULL, NULL,
......@@ -123,9 +125,8 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
m_common.pf_get_time = get_time;
m_common.pf_set_length = set_length;
m_common.pf_set_initial_time = set_initial_time;
m_common.pf_wait_app_started = wait_app_started;
m_common.pf_pace = pace;
m_common.pf_request_seek = request_seek;
m_common.pf_wait_seek_done = wait_seek_done;
m_common.pf_set_pause_state = set_pause_state;
m_common.pf_set_meta = set_meta;
......@@ -181,6 +182,7 @@ intf_sys_t::~intf_sys_t()
free( m_art_url );
vlc_cond_destroy(&m_stateChangedCond);
vlc_cond_destroy(&m_pace_cond);
vlc_mutex_destroy(&m_lock);
}
......@@ -344,6 +346,46 @@ bool intf_sys_t::isStateReady() const
}
}
void intf_sys_t::setPacing(bool do_pace)
{
vlc_mutex_lock( &m_lock );
if( m_pace == do_pace )
{
vlc_mutex_unlock( &m_lock );
return;
}
m_pace = do_pace;
vlc_mutex_unlock( &m_lock );
vlc_cond_signal( &m_pace_cond );
}
static void interrupt_wake_up_cb( void *data )
{
intf_sys_t *p_sys = static_cast<intf_sys_t*>((void *)data);
p_sys->interrupt_wake_up();
}
void intf_sys_t::interrupt_wake_up()
{
vlc_mutex_locker locker( &m_lock );
m_interrupted = true;
vlc_cond_signal( &m_pace_cond );
}
void intf_sys_t::pace()
{
vlc_mutex_locker locker(&m_lock);
if( !m_pace )
return;
m_interrupted = false;
vlc_interrupt_register( interrupt_wake_up_cb, this );
while( m_pace && !m_interrupted )
vlc_cond_wait( &m_pace_cond, &m_lock );
vlc_interrupt_unregister();
}
/**
* @brief Process a message received from the Chromecast
* @param msg the CastMessage to process
......@@ -889,40 +931,6 @@ void intf_sys_t::setPauseState(bool paused)
}
}
void intf_sys_t::waitAppStarted()
{
while ( m_state == Connected || m_state == Launching ||
m_state == Authenticating || m_state == Connecting ||
m_state == Stopping )
{
if ( m_state == Connected )
{
msg_Dbg( m_module, "Starting the media receiver application" );
// Don't use setState as we don't want to signal the condition in this case.
m_state = Launching;
m_communication.msgReceiverLaunchApp();
}
msg_Info( m_module, "Waiting for Chromecast media receiver app to be ready: %d", m_state );
vlc_cond_wait(&m_stateChangedCond, &m_lock);
}
msg_Dbg( m_module, "Done waiting for application. transportId: %s", m_appTransportId.c_str() );
}
void intf_sys_t::waitSeekDone()
{
vlc_mutex_locker locker(&m_lock);
while ( m_state == Seeking )
{
#ifndef NDEBUG
msg_Dbg( m_module, "waiting for Chromecast seek" );
#endif
vlc_cond_wait(&m_stateChangedCond, &m_lock);
#ifndef NDEBUG
msg_Dbg( m_module, "finished waiting for Chromecast seek" );
#endif
}
}
bool intf_sys_t::isFinishedPlaying()
{
vlc_mutex_locker locker(&m_lock);
......@@ -1022,11 +1030,10 @@ void intf_sys_t::set_length(void *pt, mtime_t length)
p_this->m_length = length;
}
void intf_sys_t::wait_app_started(void *pt)
void intf_sys_t::pace(void *pt)
{
intf_sys_t *p_this = static_cast<intf_sys_t*>(pt);
vlc_mutex_locker locker( &p_this->m_lock);
p_this->waitAppStarted();
p_this->pace();
}
void intf_sys_t::request_seek(void *pt, mtime_t pos)
......@@ -1035,12 +1042,6 @@ void intf_sys_t::request_seek(void *pt, mtime_t pos)
p_this->requestPlayerSeek(pos);
}
void intf_sys_t::wait_seek_done(void *pt)
{
intf_sys_t *p_this = static_cast<intf_sys_t*>(pt);
p_this->waitSeekDone();
}
void intf_sys_t::set_pause_state(void *pt, bool paused)
{
intf_sys_t *p_this = static_cast<intf_sys_t*>(pt);
......
......@@ -42,8 +42,6 @@ struct demux_sys_t
:p_demux(demux)
,p_renderer(renderer)
,i_length(-1)
,demuxReady(false)
,m_seektime( VLC_TS_INVALID )
,m_enabled( true )
,m_startTime( VLC_TS_INVALID )
{
......@@ -166,7 +164,6 @@ struct demux_sys_t
return false;
/* seeking will be handled with the Chromecast */
m_seektime = i_pos;
p_renderer->pf_request_seek( p_renderer->p_opaque, i_pos );
return true;
......@@ -183,13 +180,8 @@ struct demux_sys_t
if ( !m_enabled )
return demux_Demux( p_demux->p_next );
if (!demuxReady)
{
msg_Dbg(p_demux, "wait to demux");
p_renderer->pf_wait_app_started( p_renderer->p_opaque );
demuxReady = true;
msg_Dbg(p_demux, "ready to demux");
}
p_renderer->pf_pace( p_renderer->p_opaque );
if( m_startTime == VLC_TS_INVALID )
{
if( demux_Control( p_demux->p_next, DEMUX_GET_TIME,
......@@ -198,14 +190,6 @@ struct demux_sys_t
m_startTime );
}
/* hold the data while seeking */
/* wait until the device is buffering for data after the seek command */
if ( m_seektime != VLC_TS_INVALID )
{
p_renderer->pf_wait_seek_done( p_renderer->p_opaque );
m_seektime = VLC_TS_INVALID;
}
return demux_Demux( p_demux->p_next );
}
......@@ -349,10 +333,7 @@ protected:
demux_t * const p_demux;
chromecast_common * p_renderer;
mtime_t i_length;
bool demuxReady;
bool canSeek;
/* seek time kept while waiting for the chromecast to "seek" */
mtime_t m_seektime;
bool m_enabled;
mtime_t m_startTime;
};
......
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