[vlc-commits] chromecast: use the demux-filter to display the correct playback time
Steve Lhomme
git at videolan.org
Wed Jun 15 01:43:05 CEST 2016
vlc | branch: master | Steve Lhomme <robux4 at videolabs.io> | 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 <jb at videolan.org>
> 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 );
}
More information about the vlc-commits
mailing list