[vlc-devel] [PATCH V2 13/13] qt: use the new player timer

Thomas Guillem thomas at gllm.fr
Fri Aug 23 16:45:18 CEST 2019


Add a source player timer with a minimum delay of 250ms. This delay could be
even higher, the difference between the audio device clock and the CPU clock
should not need to be corrected that often.

The PlayerController use a QTimer, that is called every 33ms from the
Mainthread in order to update the UI time/slider using
vlc_player_timer_value_Interpolate() from the value sent via the timer update.

Ideally, the QTimer interval should be 17ms (60fps), but the slider update is
taking a lot of CPU. This should be investigated.
---
 .../gui/qt/components/player_controller.cpp   | 119 ++++++++++++------
 .../gui/qt/components/player_controller.hpp   |   1 +
 .../gui/qt/components/player_controller_p.hpp |   8 ++
 3 files changed, 87 insertions(+), 41 deletions(-)

diff --git a/modules/gui/qt/components/player_controller.cpp b/modules/gui/qt/components/player_controller.cpp
index e73fc7e8ab..5c8b8d5b67 100644
--- a/modules/gui/qt/components/player_controller.cpp
+++ b/modules/gui/qt/components/player_controller.cpp
@@ -60,6 +60,7 @@ PlayerControllerPrivate::~PlayerControllerPrivate()
     vlc_player_vout_RemoveListener( m_player, m_player_vout_listener );
     vlc_player_aout_RemoveListener( m_player, m_player_aout_listener );
     vlc_player_RemoveListener( m_player, m_player_listener );
+    vlc_player_RemoveTimer( m_player, m_player_timer );
 }
 
 void PlayerControllerPrivate::UpdateName(input_item_t* media)
@@ -345,16 +346,6 @@ static void on_player_buffering(vlc_player_t *, float new_buffering, void *data)
     });
 }
 
-static void on_player_rate_changed(vlc_player_t *, float new_rate, void *data)
-{
-    PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
-    msg_Dbg( that->p_intf, "on_player_rate_changed %f", new_rate);
-    that->callAsync([that,new_rate](){
-        that->m_rate = new_rate;
-        emit that->q_func()->rateChanged( new_rate );
-    });
-}
-
 static void on_player_capabilities_changed(vlc_player_t *, int old_caps, int new_caps, void *data)
 {
     PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
@@ -387,34 +378,6 @@ static void on_player_capabilities_changed(vlc_player_t *, int old_caps, int new
     //FIXME other events?
 }
 
-static void on_player_position_changed(vlc_player_t *player, vlc_tick_t time, float pos, void *data)
-{
-    PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
-    vlc_tick_t length =  vlc_player_GetLength( player );
-    that->callAsync([that,time,pos,length] () {
-        PlayerController* q = that->q_func();
-        that->m_position = pos;
-        emit q->positionChanged(pos);
-        that->m_time = time;
-        emit q->timeChanged(time);
-        emit that->q_func()->positionUpdated(pos, time, SEC_FROM_VLC_TICK(length) );
-    });
-}
-
-static void on_player_length_changed(vlc_player_t *player, vlc_tick_t new_length, void *data)
-{
-    PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
-    vlc_tick_t time = vlc_player_GetTime( player );
-    float pos = vlc_player_GetPosition( player );
-    that->callAsync([that,new_length,time,pos] () {
-        PlayerController* q = that->q_func();
-        that->m_length = new_length;
-        emit q->lengthChanged(new_length);
-        emit that->q_func()->positionUpdated( pos, time, SEC_FROM_VLC_TICK(new_length) );
-    });
-
-}
-
 static void on_player_track_list_changed(vlc_player_t *, enum vlc_player_list_action action, const struct vlc_player_track *track, void *data)
 {
     PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
@@ -854,6 +817,56 @@ static void on_player_corks_changed(vlc_player_t *, unsigned, void *data)
     msg_Dbg( that->p_intf, "on_player_corks_changed");
 }
 
+static void on_player_timer_update(enum vlc_player_timer_state state,
+                                   const struct vlc_player_timer_value *value,
+                                   void *data)
+{
+    PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
+    that->callAsync([that,state,value_copy = *value](){
+        PlayerController* q = that->q_func();
+        bool changed = false;
+
+        if (value_copy.ts != VLC_TICK_INVALID)
+        {
+            that->m_player_time = value_copy;
+
+            if (that->m_length != that->m_player_time.length)
+            {
+                that->m_length = that->m_player_time.length;
+                emit q->lengthChanged(that->m_length);
+                changed = true;
+            }
+            if (that->m_rate != that->m_player_time.rate)
+            {
+                that->m_rate = that->m_player_time.rate;
+                emit q->rateChanged(that->m_rate);
+                changed = true;
+            }
+        }
+
+        switch (state)
+        {
+            case VLC_PLAYER_TIMER_STATE_PLAYING:
+                if (that->m_player_time_state != state)
+                {
+                    that->m_interpolate_timer.start();
+                    changed = true;
+                }
+                break;
+            case VLC_PLAYER_TIMER_STATE_PAUSED:
+            case VLC_PLAYER_TIMER_STATE_DISCONTINUITY:
+                that->m_interpolate_timer.stop();
+                break;
+            default:
+                break;
+        }
+        that->m_player_time_state = state;
+
+        if (changed)
+            q->interpolateTime();
+    });
+}
+
 } //extern "C"
 
 static const struct vlc_player_cbs player_cbs = {
@@ -861,10 +874,10 @@ static const struct vlc_player_cbs player_cbs = {
     on_player_state_changed,
     on_player_error_changed,
     on_player_buffering,
-    on_player_rate_changed,
+    nullptr, // on_player_rate_changed: handled by on_player_timer_update
     on_player_capabilities_changed,
-    on_player_position_changed,
-    on_player_length_changed,
+    nullptr, // on_player_position_changed: handled by on_player_timer_update
+    nullptr, // on_player_length_changed: handled by on_player_timer_update
     on_player_track_list_changed,
     on_player_track_selection_changed,
     on_player_track_delay_changed,
@@ -903,6 +916,10 @@ static const struct vlc_player_aout_cbs player_aout_cbs = {
     nullptr
 };
 
+static const struct vlc_player_timer_cbs player_timer_cbs = {
+    on_player_timer_update,
+};
+
 PlayerControllerPrivate::PlayerControllerPrivate(PlayerController *playercontroller, intf_thread_t *p_intf)
     : q_ptr(playercontroller)
     , p_intf(p_intf)
@@ -928,10 +945,14 @@ PlayerControllerPrivate::PlayerControllerPrivate(PlayerController *playercontrol
         m_player_listener = vlc_player_AddListener( m_player, &player_cbs, this );
         m_player_aout_listener = vlc_player_aout_AddListener( m_player, &player_aout_cbs, this );
         m_player_vout_listener = vlc_player_vout_AddListener( m_player, &player_vout_cbs, this );
+        m_player_timer = vlc_player_AddTimer( m_player, VLC_PLAYER_TIMER_TYPE_SOURCE,
+                                              VLC_TICK_FROM_MS(250), &player_timer_cbs, this );
     }
 
     QObject::connect( &m_autoscale, &QVLCBool::valueChanged, q_ptr, &PlayerController::autoscaleChanged );
     QObject::connect( &m_audioVisualization, &VLCVarChoiceModel::hasCurrentChanged, q_ptr, &PlayerController::hasAudioVisualizationChanged );
+
+    m_interpolate_timer.setInterval( 33 );
 }
 
 PlayerController::PlayerController( intf_thread_t *_p_intf )
@@ -941,6 +962,7 @@ PlayerController::PlayerController( intf_thread_t *_p_intf )
     /* Audio Menu */
     menusAudioMapper = new QSignalMapper(this);
     CONNECT( menusAudioMapper, mapped(const QString&), this, menusUpdateAudio(const QString&) );
+    CONNECT( &d_ptr->m_interpolate_timer, timeout(), this, interpolateTime() );
 
     input_fetcher_cbs.on_art_fetch_ended = onArtFetchEnded_callback;
 }
@@ -1363,6 +1385,21 @@ void PlayerController::menusUpdateAudio( const QString& data )
         aout_DeviceSet( aout.get(), qtu(data) );
 }
 
+void PlayerController::interpolateTime()
+{
+    Q_D(PlayerController);
+    vlc_tick_t new_time;
+    if (vlc_player_timer_value_Interpolate(&d->m_player_time, vlc_tick_now(),
+                                          &new_time, &d->m_position) == VLC_SUCCESS)
+    {
+        d->m_time = new_time;
+        emit positionChanged(d->m_position);
+        emit timeChanged(d->m_time);
+        emit positionUpdated(d->m_position, d->m_time, SEC_FROM_VLC_TICK(d->m_length));
+    }
+}
+
+
 //MISC
 
 void PlayerController::setABloopState(ABLoopState state)
diff --git a/modules/gui/qt/components/player_controller.hpp b/modules/gui/qt/components/player_controller.hpp
index f1e17827df..907f39bf4b 100644
--- a/modules/gui/qt/components/player_controller.hpp
+++ b/modules/gui/qt/components/player_controller.hpp
@@ -267,6 +267,7 @@ public slots:
     bool isRewindable() const;
     bool isPausable() const;
     bool isRateChangable() const;
+    void interpolateTime();
 
     //tracks
     TrackListModel* getVideoTracks();
diff --git a/modules/gui/qt/components/player_controller_p.hpp b/modules/gui/qt/components/player_controller_p.hpp
index 653ef46592..254f5f5079 100644
--- a/modules/gui/qt/components/player_controller_p.hpp
+++ b/modules/gui/qt/components/player_controller_p.hpp
@@ -24,6 +24,8 @@
 #include "util/input_models.hpp"
 #include "adapters/var_choice_model.hpp"
 
+#include <QTimer>
+
 class PlayerControllerPrivate {
     Q_DISABLE_COPY(PlayerControllerPrivate)
 public:
@@ -92,6 +94,12 @@ public:
     VLCTick      m_secondarySubtitleDelay = 0;
     float        m_subtitleFPS = 1.0;
 
+    //timer
+    vlc_player_timer_id* m_player_timer = nullptr;
+    struct vlc_player_timer_value m_player_time;
+    enum vlc_player_timer_state m_player_time_state = VLC_PLAYER_TIMER_STATE_DISCONTINUITY;
+    QTimer m_interpolate_timer;
+
     //title/chapters/menu
     TitleListModel m_titleList;
     ChapterListModel m_chapterList;
-- 
2.20.1



More information about the vlc-devel mailing list