vlc | branch: master | Thomas Guillem <[email protected]> | 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; }; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
