[vlc-commits] chromecast: rework demux pacing
Thomas Guillem
git at videolan.org
Tue Feb 6 12:51:44 CET 2018
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Feb 6 09:17:16 2018 +0100| [3a1519245d771f2804832bbddc37f6f38f2aa1f8] | committer: Thomas Guillem
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.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3a1519245d771f2804832bbddc37f6f38f2aa1f8
---
modules/stream_out/chromecast/cast.cpp | 31 ++++++--
modules/stream_out/chromecast/chromecast.h | 10 ++-
modules/stream_out/chromecast/chromecast_common.h | 3 +-
modules/stream_out/chromecast/chromecast_ctrl.cpp | 91 +++++++++++-----------
modules/stream_out/chromecast/chromecast_demux.cpp | 23 +-----
5 files changed, 82 insertions(+), 76 deletions(-)
diff --git a/modules/stream_out/chromecast/cast.cpp b/modules/stream_out/chromecast/cast.cpp
index 7dd2705f70..c134d2a79e 100644
--- a/modules/stream_out/chromecast/cast.cpp
+++ b/modules/stream_out/chromecast/cast.cpp
@@ -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)
@@ -314,8 +316,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();
@@ -402,8 +407,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;
@@ -448,7 +457,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);
@@ -459,6 +472,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;
}
@@ -504,6 +520,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);
}
/*****************************************************************************
@@ -1180,8 +1198,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);
}
diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h
index 9918b6e02a..cb0b6b3b23 100644
--- a/modules/stream_out/chromecast/chromecast.h
+++ b/modules/stream_out/chromecast/chromecast.h
@@ -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;
diff --git a/modules/stream_out/chromecast/chromecast_common.h b/modules/stream_out/chromecast/chromecast_common.h
index 38897c0fda..f1ce43c232 100644
--- a/modules/stream_out/chromecast/chromecast_common.h
+++ b/modules/stream_out/chromecast/chromecast_common.h
@@ -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);
diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp
index 486336324a..bc6975f590 100644
--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
@@ -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);
diff --git a/modules/stream_out/chromecast/chromecast_demux.cpp b/modules/stream_out/chromecast/chromecast_demux.cpp
index 8cefd063c1..8872b53661 100644
--- a/modules/stream_out/chromecast/chromecast_demux.cpp
+++ b/modules/stream_out/chromecast/chromecast_demux.cpp
@@ -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 )
{
@@ -165,7 +163,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;
@@ -182,13 +179,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,
@@ -197,14 +189,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 );
}
@@ -323,10 +307,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;
};
More information about the vlc-commits
mailing list