Commit f11a78db authored by Steve Lhomme's avatar Steve Lhomme Committed by 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's avatarJean-Baptiste Kempf <jb@videolan.org>
parent e56df9fd
......@@ -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 */
......@@ -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
......
......@@ -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;
}
......@@ -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 );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment