[vlc-commits] chromecast: rework seek

Thomas Guillem git at videolan.org
Tue Feb 6 18:37:04 CET 2018


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Mon Feb  5 18:44:16 2018 +0100| [82f4830bf59326093f87d9ded6769dfadbbed1c1] | committer: Thomas Guillem

chromecast: rework seek

Don't seek from demux filter but from the the sout. Do it only one time for
every stream ids. Pause the httpd server while seeking in order to prevent the
CC to flush valid post flush buffers.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=82f4830bf59326093f87d9ded6769dfadbbed1c1
---

 modules/stream_out/chromecast/cast.cpp             | 60 ++++++++++++++++++++--
 modules/stream_out/chromecast/chromecast.h         |  9 +++-
 modules/stream_out/chromecast/chromecast_common.h  |  2 -
 modules/stream_out/chromecast/chromecast_ctrl.cpp  | 30 ++++++-----
 modules/stream_out/chromecast/chromecast_demux.cpp | 54 +------------------
 5 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/modules/stream_out/chromecast/cast.cpp b/modules/stream_out/chromecast/cast.cpp
index 71c5448790..9977ddfdf6 100644
--- a/modules/stream_out/chromecast/cast.cpp
+++ b/modules/stream_out/chromecast/cast.cpp
@@ -47,6 +47,8 @@ struct sout_access_out_sys_t
     vlc_fifo_t        *m_fifo;
     block_t           *m_header;
     bool               m_eof;
+    bool               m_flushing;
+    bool               m_seeking;
     std::string        m_mime;
 
     sout_access_out_sys_t(httpd_host_t *httpd_host, intf_sys_t * const intf,
@@ -55,8 +57,10 @@ struct sout_access_out_sys_t
 
     void clearUnlocked();
     void clear();
+    void flush();
     void prepare(sout_stream_t *p_stream, const std::string &mime);
     int url_cb(httpd_client_t *cl, httpd_message_t *answer, const httpd_message_t *query);
+    void seek_done_cb();
 };
 
 struct sout_stream_sys_t
@@ -312,16 +316,24 @@ static int ProxyOpen(vlc_object_t *p_this)
 static int httpd_url_cb(httpd_callback_sys_t *data, httpd_client_t *cl,
                         httpd_message_t *answer, const httpd_message_t *query)
 {
-    sout_access_out_sys_t *p_sys = (sout_access_out_sys_t *) data;
+    sout_access_out_sys_t *p_sys = reinterpret_cast<sout_access_out_sys_t *>(data);
     return p_sys->url_cb(cl, answer, query);
 }
 
+static void on_seek_done_cb(void *data)
+{
+    sout_access_out_sys_t *p_sys = reinterpret_cast<sout_access_out_sys_t *>(data);
+    p_sys->seek_done_cb();
+}
+
 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_flushing(false)
+    , m_seeking(false)
 {
     m_fifo = block_FifoNew();
     if (!m_fifo)
@@ -362,6 +374,19 @@ void sout_access_out_sys_t::clear()
     vlc_fifo_Signal(m_fifo);
 }
 
+void sout_access_out_sys_t::flush()
+{
+    vlc_fifo_Lock(m_fifo);
+    block_ChainRelease(vlc_fifo_DequeueAllUnlocked(m_fifo));
+    vlc_fifo_Unlock(m_fifo);
+
+    m_intf->setPacing(false);
+
+    /* Don't seek from here since flush can be called several time (one time
+     * per id). */
+    m_flushing = true;
+}
+
 void sout_access_out_sys_t::prepare(sout_stream_t *p_stream, const std::string &mime)
 {
     var_SetAddress(p_stream->p_sout, SOUT_CFG_PREFIX "access-out-sys", this);
@@ -370,9 +395,19 @@ void sout_access_out_sys_t::prepare(sout_stream_t *p_stream, const std::string &
     clearUnlocked();
     m_mime = mime;
     m_eof = false;
+    m_flushing = false;
+    m_seeking = false;
     vlc_fifo_Unlock(m_fifo);
 }
 
+void sout_access_out_sys_t::seek_done_cb()
+{
+    vlc_fifo_Lock(m_fifo);
+    m_seeking = false;
+    vlc_fifo_Unlock(m_fifo);
+    vlc_fifo_Signal(m_fifo);
+}
+
 int sout_access_out_sys_t::url_cb(httpd_client_t *cl, httpd_message_t *answer,
                                   const httpd_message_t *query)
 {
@@ -386,6 +421,11 @@ int sout_access_out_sys_t::url_cb(httpd_client_t *cl, httpd_message_t *answer,
        && !m_eof)
         vlc_fifo_Wait(m_fifo);
 
+    /* Wait for the seek to be done. This will prevent the CC to flush this
+     * buffer that came after a flush. */
+    while (m_seeking && !m_eof)
+        vlc_fifo_Wait(m_fifo);
+
     /* Handle block headers */
     if (p_block)
     {
@@ -457,6 +497,17 @@ static ssize_t AccessWrite(sout_access_out_t *p_access, block_t *p_block)
 
     vlc_fifo_Lock(p_sys->m_fifo);
 
+    if (p_sys->m_flushing)
+    {
+        p_sys->m_flushing = false;
+        p_sys->m_seeking = true;
+
+        vlc_fifo_Unlock(p_sys->m_fifo);
+        /* TODO: put better timestamp */
+        p_sys->m_intf->requestPlayerSeek(mdate() + INT64_C(1000000));
+        vlc_fifo_Lock(p_sys->m_fifo);
+    }
+
     /* 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;
 
@@ -1029,10 +1080,8 @@ static void Flush( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
     if ( id == NULL || p_sys->drained )
         return;
 
-    /* a seek on the Chromecast flushes its buffers */
-    p_sys->p_intf->requestPlayerSeek( VLC_TS_INVALID );
-
     sout_StreamFlush( p_sys->p_out, id );
+    p_sys->access_out_live.flush();
 }
 
 static int Control(sout_stream_t *p_stream, int i_query, va_list args)
@@ -1148,6 +1197,8 @@ static int Open(vlc_object_t *p_this)
     if (unlikely(p_sys == NULL))
         goto error;
 
+    p_intf->setOnSeekDoneCb(on_seek_done_cb, &p_sys->access_out_live);
+
     /* prevent sout-mux-caching since chromecast-proxy is already doing it */
     var_Create( p_stream->p_sout, "sout-mux-caching", VLC_VAR_INTEGER );
     var_SetInteger( p_stream->p_sout, "sout-mux-caching", 0 );
@@ -1199,6 +1250,7 @@ static void Close(vlc_object_t *p_this)
 
     httpd_host_t *httpd_host = p_sys->httpd_host;
     intf_sys_t *p_intf = p_sys->p_intf;
+    p_intf->setOnSeekDoneCb(NULL, NULL);
     delete p_sys;
     delete p_intf;
     /* Delete last since p_intf and p_sys depends on httpd_host */
diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h
index cb0b6b3b23..201086bc2b 100644
--- a/modules/stream_out/chromecast/chromecast.h
+++ b/modules/stream_out/chromecast/chromecast.h
@@ -148,6 +148,8 @@ private:
     std::string m_serverIp;
 };
 
+typedef void (*on_seek_done_itf)( void *data );
+
 /*****************************************************************************
  * intf_sys_t: description and status of interface
  *****************************************************************************/
@@ -167,6 +169,7 @@ struct intf_sys_t
     void setHasInput(const std::string mime_type = "");
 
     void requestPlayerSeek(mtime_t pos);
+    void setOnSeekDoneCb(on_seek_done_itf on_seek_done, void *on_seek_done_data);
     void requestPlayerStop();
     States state() const;
 
@@ -217,8 +220,6 @@ private:
 
     static void pace(void*);
 
-    static void request_seek(void*, mtime_t pos);
-
     static void set_pause_state(void*, bool paused);
 
     static void set_meta(void*, vlc_meta_t *p_meta);
@@ -238,6 +239,9 @@ private:
     vlc_cond_t   m_pace_cond;
     vlc_thread_t m_chromecastThread;
 
+    on_seek_done_itf m_on_seek_done;
+    void            *m_on_seek_done_data;
+
     ChromecastCommunication m_communication;
     std::queue<QueueableMessages> m_msgQueue;
     States m_state;
@@ -260,6 +264,7 @@ private:
     mtime_t           m_time_playback_started;
     /* local playback time of the input when playback started/resumed */
     mtime_t           m_ts_local_start;
+    mtime_t           m_ts_seek;
     mtime_t           m_length;
 
     /* shared structure with the demux-filter */
diff --git a/modules/stream_out/chromecast/chromecast_common.h b/modules/stream_out/chromecast/chromecast_common.h
index f1ce43c232..c8e1726946 100644
--- a/modules/stream_out/chromecast/chromecast_common.h
+++ b/modules/stream_out/chromecast/chromecast_common.h
@@ -44,8 +44,6 @@ typedef struct
 
     void (*pf_pace)(void*);
 
-    void (*pf_request_seek)(void*, mtime_t pos);
-
     void (*pf_set_pause_state)(void*, bool paused);
 
     void (*pf_set_meta)(void*, vlc_meta_t *p_meta);
diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp
index d88e651e1e..83faa09d51 100644
--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
@@ -47,8 +47,6 @@
 static int httpd_file_fill_cb( httpd_file_sys_t *data, httpd_file_t *http_file,
                           uint8_t *psz_request, uint8_t **pp_data, int *pi_data );
 
-static const mtime_t SEEK_FORWARD_OFFSET = 1000000;
-
 static const char* StateToStr( States s )
 {
     switch (s )
@@ -105,6 +103,7 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
  , m_art_url(NULL)
  , m_time_playback_started( VLC_TS_INVALID )
  , m_ts_local_start( VLC_TS_INVALID )
+ , m_ts_seek( VLC_TS_INVALID )
  , m_length( VLC_TS_INVALID )
  , m_pingRetriesLeft( PING_WAIT_RETRIES )
 {
@@ -126,7 +125,6 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
     m_common.pf_set_length       = set_length;
     m_common.pf_set_initial_time = set_initial_time;
     m_common.pf_pace             = pace;
-    m_common.pf_request_seek     = request_seek;
     m_common.pf_set_pause_state  = set_pause_state;
     m_common.pf_set_meta         = set_meta;
 
@@ -469,16 +467,16 @@ void intf_sys_t::mainLoop()
                     break;
                 case Seek:
                 {
-                    if( !isStatePlaying() || m_mediaSessionId == 0 )
+                    if( !isStatePlaying() || m_mediaSessionId == 0 || m_ts_seek == VLC_TS_INVALID )
                         break;
                     char current_time[32];
-                    mtime_t seek_request_time = mdate() + SEEK_FORWARD_OFFSET;
                     if( snprintf( current_time, sizeof(current_time), "%.3f",
-                                  double( seek_request_time ) / 1000000.0 ) >= (int)sizeof(current_time) )
+                                  double( m_ts_seek ) / 1000000.0 ) >= (int)sizeof(current_time) )
                     {
                         msg_Err( m_module, "snprintf() truncated string for mediaSessionId" );
                         current_time[sizeof(current_time) - 1] = '\0';
                     }
+                    m_ts_seek = VLC_TS_INVALID;
                     /* send a fake time to seek to, to make sure the device flushes its buffers */
                     m_communication.msgPlayerSeek( m_appTransportId, m_mediaSessionId, current_time );
                     setState( Seeking );
@@ -891,6 +889,7 @@ void intf_sys_t::requestPlayerStop()
     vlc_mutex_locker locker(&m_lock);
 
     m_request_load = false;
+    m_ts_seek = VLC_TS_INVALID;
 
     if( !isStatePlaying() )
         return;
@@ -909,11 +908,17 @@ void intf_sys_t::requestPlayerSeek(mtime_t pos)
     vlc_mutex_locker locker(&m_lock);
     if( !isStatePlaying() || m_mediaSessionId == 0 )
         return;
-    if ( pos != VLC_TS_INVALID )
-        m_ts_local_start = pos;
+    m_ts_seek = pos;
     queueMessage( Seek );
 }
 
+void intf_sys_t::setOnSeekDoneCb(on_seek_done_itf on_seek_done, void *on_seek_done_data)
+{
+    vlc_mutex_locker locker(&m_lock);
+    m_on_seek_done = on_seek_done;
+    m_on_seek_done_data = on_seek_done_data;
+}
+
 void intf_sys_t::setPauseState(bool paused)
 {
     msg_Dbg( m_module, "%s state", paused ? "paused" : "playing" );
@@ -991,6 +996,9 @@ void intf_sys_t::setState( States state )
 #ifndef NDEBUG
         msg_Dbg( m_module, "Switching from state %s to %s", StateToStr( m_state ), StateToStr( state ) );
 #endif
+        if (state == Seeking)
+            if (m_on_seek_done != NULL)
+                m_on_seek_done(m_on_seek_done_data);
         m_state = state;
 
         switch( m_state )
@@ -1039,12 +1047,6 @@ void intf_sys_t::pace(void *pt)
     p_this->pace();
 }
 
-void intf_sys_t::request_seek(void *pt, mtime_t pos)
-{
-    intf_sys_t *p_this = static_cast<intf_sys_t*>(pt);
-    p_this->requestPlayerSeek(pos);
-}
-
 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 8872b53661..030712a3ea 100644
--- a/modules/stream_out/chromecast/chromecast_demux.cpp
+++ b/modules/stream_out/chromecast/chromecast_demux.cpp
@@ -150,24 +150,6 @@ struct demux_sys_t
         this->canSeek = canSeek;
     }
 
-    bool seekTo( double pos )
-    {
-        if (i_length == -1)
-            return false;
-        return seekTo( mtime_t( i_length * pos ) );
-    }
-
-    bool seekTo( mtime_t i_pos )
-    {
-        if ( !canSeek )
-            return false;
-
-        /* seeking will be handled with the Chromecast */
-        p_renderer->pf_request_seek( p_renderer->p_opaque, i_pos );
-
-        return true;
-    }
-
     void setLength( mtime_t length )
     {
         this->i_length = length;
@@ -235,45 +217,13 @@ struct demux_sys_t
 
         case DEMUX_SET_POSITION:
         {
-            va_list ap;
-
-            va_copy( ap, args );
-            double pos = va_arg( ap, double );
-            va_end( ap );
-
-            if ( getPlaybackTime() == VLC_TS_INVALID )
-            {
-                msg_Dbg( p_demux_filter, "internal seek to %f when the playback didn't start", pos );
-                break; // seek before device started, likely on-the-fly restart
-            }
-
-            if ( !seekTo( pos ) )
-            {
-                msg_Err( p_demux_filter, "failed to seek to %f", pos );
-                return VLC_EGENERIC;
-            }
+            m_startTime = VLC_TS_INVALID;
             break;
         }
 
         case DEMUX_SET_TIME:
         {
-            va_list ap;
-
-            va_copy( ap, args );
-            mtime_t pos = va_arg( ap, mtime_t );
-            va_end( ap );
-
-            if ( getPlaybackTime() == VLC_TS_INVALID )
-            {
-                msg_Dbg( p_demux_filter, "internal seek to %" PRId64 " when the playback didn't start", pos );
-                break; // seek before device started, likely on-the-fly restart
-            }
-
-            if ( !seekTo( pos ) )
-            {
-                msg_Err( p_demux_filter, "failed to seek to time %" PRId64, pos );
-                return VLC_EGENERIC;
-            }
+            m_startTime = VLC_TS_INVALID;
             break;
         }
         case DEMUX_SET_PAUSE_STATE:



More information about the vlc-commits mailing list