vlc | branch: master | Steve Lhomme <[email protected]> | Wed Jun 15 00:37:07 2016 +0200| [f11a78dbc20cf9f920d1e075078e3843b25a6880] | committer: Jean-Baptiste Kempf
chromecast: use the demux-filter to display the correct playback time The device buffers about 8s before starting playing so we wait until the Chromecast starts playing to start a monotone clock in the demux filter. Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f11a78dbc20cf9f920d1e075078e3843b25a6880 --- modules/stream_out/chromecast/chromecast.h | 37 ++++++++++++++++ modules/stream_out/chromecast/chromecast_common.h | 3 ++ modules/stream_out/chromecast/chromecast_ctrl.cpp | 45 +++++++++++++++++++- modules/stream_out/chromecast/chromecast_demux.cpp | 45 ++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h index c764e69..4e10858 100644 --- a/modules/stream_out/chromecast/chromecast.h +++ b/modules/stream_out/chromecast/chromecast.h @@ -182,12 +182,49 @@ private: static void* ChromecastThread(void* p_data); vlc_interrupt_t *p_ctl_thread_interrupt; + mtime_t getPlaybackTimestamp() const + { + switch( receiverState ) + { + case RECEIVER_PLAYING: + return ( mdate() - m_time_playback_started ) + i_ts_local_start; + + case RECEIVER_IDLE: + msg_Dbg(p_module, "receiver idle using buffering time %" PRId64, i_ts_local_start); + break; + case RECEIVER_BUFFERING: + msg_Dbg(p_module, "receiver buffering using buffering time %" PRId64, i_ts_local_start); + break; + case RECEIVER_PAUSED: + msg_Dbg(p_module, "receiver paused using buffering time %" PRId64, i_ts_local_start); + break; + } + return i_ts_local_start; + } + + double getPlaybackPosition( mtime_t i_length ) const + { + if( i_length > 0 && m_time_playback_started != VLC_TS_INVALID) + return (double) getPlaybackTimestamp() / (double)( i_length ); + return 0.0; + } + + /* local date when playback started/resumed, used by monotone clock */ + mtime_t m_time_playback_started; + /* local playback time of the input when playback started/resumed */ + mtime_t i_ts_local_start; + mtime_t i_length; + int recvPacket(bool &b_msgReceived, uint32_t &i_payloadSize, unsigned *pi_received, uint8_t *p_data, bool *pb_pingTimeout, int *pi_wait_delay, int *pi_wait_retries); /* shared structure with the demux-filter */ chromecast_common common; + + static void set_length(void*, mtime_t length); + static mtime_t get_time(void*); + static double get_position(void*); }; #endif /* VLC_CHROMECAST_H */ diff --git a/modules/stream_out/chromecast/chromecast_common.h b/modules/stream_out/chromecast/chromecast_common.h index 2787c13..cfab0bf 100644 --- a/modules/stream_out/chromecast/chromecast_common.h +++ b/modules/stream_out/chromecast/chromecast_common.h @@ -35,6 +35,9 @@ typedef struct { void *p_opaque; + void (*pf_set_length)(void*, mtime_t length); + mtime_t (*pf_get_time)(void*); + double (*pf_get_position)(void*); } chromecast_common; # ifdef __cplusplus diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp index 63096e9..840c043 100644 --- a/modules/stream_out/chromecast/chromecast_ctrl.cpp +++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp @@ -110,11 +110,17 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device , i_requestId(0) , has_input(false) , p_ctl_thread_interrupt(p_interrupt) + , m_time_playback_started( VLC_TS_INVALID ) + , i_ts_local_start( VLC_TS_INVALID ) + , i_length( VLC_TS_INVALID ) { vlc_mutex_init(&lock); vlc_cond_init(&loadCommandCond); common.p_opaque = this; + common.pf_get_position = get_position; + common.pf_get_time = get_time; + common.pf_set_length = set_length; assert( var_Type( p_module->p_parent->p_parent, CC_SHARED_VAR_NAME) == 0 ); if (var_Create( p_module->p_parent->p_parent, CC_SHARED_VAR_NAME, VLC_VAR_ADDRESS ) == VLC_SUCCESS ) @@ -188,6 +194,7 @@ void intf_sys_t::setHasInput( bool b_has_input, const std::string mime_type ) if ( receiverState == RECEIVER_IDLE ) { // we cannot start a new load when the last one is still processing + i_ts_local_start = VLC_TS_0; msgPlayerLoad(); setPlayerStatus(CMD_LOAD_SENT); } @@ -553,17 +560,32 @@ void intf_sys_t::processMessage(const castchannel::CastMessage &msg) case RECEIVER_PLAYING: /* TODO reset demux PCR ? */ setPlayerStatus(CMD_PLAYBACK_SENT); + m_time_playback_started = mdate(); +#ifndef NDEBUG + msg_Dbg( p_module, "Playback started now:%" PRId64 " i_ts_local_start:%" PRId64, m_time_playback_started, i_ts_local_start); +#endif break; case RECEIVER_PAUSED: #ifndef NDEBUG - msg_Dbg( p_module, "Playback paused"); + msg_Dbg( p_module, "Playback paused date_play_start:%" PRId64, m_time_playback_started); +#endif + + if ( m_time_playback_started != VLC_TS_INVALID && oldPlayerState == RECEIVER_PLAYING ) + { + /* this is a pause generated remotely, adjust the playback time */ + i_ts_local_start += mdate() - m_time_playback_started; +#ifndef NDEBUG + msg_Dbg( p_module, "updated i_ts_local_start:%" PRId64, i_ts_local_start); #endif + } + m_time_playback_started = VLC_TS_INVALID; break; case RECEIVER_IDLE: if ( has_input ) setPlayerStatus(NO_CMD_PENDING); + m_time_playback_started = VLC_TS_INVALID; break; } } @@ -571,6 +593,7 @@ void intf_sys_t::processMessage(const castchannel::CastMessage &msg) if ( cmd_status != CMD_LOAD_SENT && receiverState == RECEIVER_IDLE && has_input ) { msg_Dbg( p_module, "the device missed the LOAD command"); + i_ts_local_start = VLC_TS_0; msgPlayerLoad(); setPlayerStatus(CMD_LOAD_SENT); } @@ -952,3 +975,23 @@ void intf_sys_t::requestPlayerSeek() requested_seek = true; notifySendRequest(); } + +mtime_t intf_sys_t::get_time(void *pt) +{ + intf_sys_t *p_this = reinterpret_cast<intf_sys_t*>(pt); + vlc_mutex_locker locker( &p_this->lock ); + return p_this->getPlaybackTimestamp(); +} + +double intf_sys_t::get_position(void *pt) +{ + intf_sys_t *p_this = reinterpret_cast<intf_sys_t*>(pt); + vlc_mutex_locker locker( &p_this->lock ); + return p_this->getPlaybackPosition( p_this->i_length ); +} + +void intf_sys_t::set_length(void *pt, mtime_t length) +{ + intf_sys_t *p_this = reinterpret_cast<intf_sys_t*>(pt); + p_this->i_length = length; +} diff --git a/modules/stream_out/chromecast/chromecast_demux.cpp b/modules/stream_out/chromecast/chromecast_demux.cpp index 870a541..9378a7e 100644 --- a/modules/stream_out/chromecast/chromecast_demux.cpp +++ b/modules/stream_out/chromecast/chromecast_demux.cpp @@ -48,6 +48,25 @@ struct demux_sys_t { } + /** + * @brief getPlaybackTime + * @return the current playback time on the device or VLC_TS_INVALID if unknown + */ + mtime_t getPlaybackTime() + { + return p_renderer->pf_get_time( p_renderer->p_opaque ); + } + + double getPlaybackPosition() + { + return p_renderer->pf_get_position( p_renderer->p_opaque ); + } + + void setLength( mtime_t length ) + { + p_renderer->pf_set_length( p_renderer->p_opaque, length ); + } + int Demux() { return demux_Demux( p_demux->p_next ); @@ -67,6 +86,32 @@ static int Demux( demux_t *p_demux_filter ) static int Control( demux_t *p_demux_filter, int i_query, va_list args) { + demux_sys_t *p_sys = p_demux_filter->p_sys; + + switch (i_query) + { + case DEMUX_GET_POSITION: + *va_arg( args, double * ) = p_sys->getPlaybackPosition(); + return VLC_SUCCESS; + + case DEMUX_GET_TIME: + *va_arg(args, int64_t *) = p_sys->getPlaybackTime(); + return VLC_SUCCESS; + + case DEMUX_GET_LENGTH: + { + int ret; + va_list ap; + + va_copy( ap, args ); + ret = demux_vaControl( p_demux_filter->p_next, i_query, args ); + if( ret == VLC_SUCCESS ) + p_sys->setLength( *va_arg( ap, int64_t * ) ); + va_end( ap ); + return ret; + } + } + return demux_vaControl( p_demux_filter->p_next, i_query, args ); } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
