[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