From e9e8be01a4dbd8afb7693a0f431cdd252f42a86a Mon Sep 17 00:00:00 2001 From: Thomas Guillem Date: Fri, 5 Dec 2025 10:24:13 +0100 Subject: [PATCH] player: also notify seek on the smpte_timer --- include/vlc_player.h | 20 +++++++++++++- src/player/player.h | 2 +- src/player/timer.c | 64 +++++++++++++++++++++++++++----------------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/include/vlc_player.h b/include/vlc_player.h index 3f32f4d90b..5cbaee57ae 100644 --- a/include/vlc_player.h +++ b/include/vlc_player.h @@ -3525,7 +3525,7 @@ struct vlc_player_timer_smpte_cbs { /** * Called when a new frame is displayed - + * * @warning The player is not locked from this callback. It is forbidden * to call any player functions from here. * @@ -3542,6 +3542,24 @@ struct vlc_player_timer_smpte_cbs * @see vlc_player_timer_cbs.on_paused */ void (*on_paused)(vlc_tick_t system_date, void *data); + + /** + * Called when the player is seeking or finished seeking (can be NULL). + * + * @warning The player is not locked from this callback. It is forbidden + * to call any player functions from here. + * + * @warning the value is parameter is a timestamp point and not a timecode, + * as this is an approximation. + * + * @note on_update() can be called when seeking. It corresponds to tracks + * updating their points prior to receiving the asynchronous seek event. + * The user could discard them manually. + * + * @param value point of the seek request or NULL when seeking is finished + * @param data opaque pointer set by vlc_player_AddTimer() + */ + void (*on_seek)(const struct vlc_player_timer_point *value, void *data); }; /** diff --git a/src/player/player.h b/src/player/player.h index e727a7feb0..8df05b287a 100644 --- a/src/player/player.h +++ b/src/player/player.h @@ -194,6 +194,7 @@ struct vlc_player_timer_source struct vlc_list listeners; /* list of struct vlc_player_timer_id */ vlc_es_id_t *es; /* weak reference */ struct vlc_player_timer_point point; + bool seeking; union { struct { @@ -231,7 +232,6 @@ struct vlc_player_timer double seek_position; bool paused; bool stopping; - bool seeking; struct vlc_player_timer_source sources[VLC_PLAYER_TIMER_TYPE_COUNT]; #define best_source sources[VLC_PLAYER_TIMER_TYPE_BEST] diff --git a/src/player/timer.c b/src/player/timer.c index 3d1cba9632..b1244f2255 100644 --- a/src/player/timer.c +++ b/src/player/timer.c @@ -41,7 +41,6 @@ vlc_player_ResetTimer(vlc_player_t *player) player->timer.seek_ts = VLC_TICK_INVALID; player->timer.seek_position = -1; player->timer.paused = false; - player->timer.seeking = false; player->timer.stopping = false; vlc_mutex_unlock(&player->timer.lock); @@ -50,15 +49,24 @@ vlc_player_ResetTimer(vlc_player_t *player) static void vlc_player_SendTimerSeek(vlc_player_t *player, struct vlc_player_timer_source *source, - const struct vlc_player_timer_point *point) + const struct vlc_player_timer_point *point, + bool is_smpte) { (void) player; vlc_player_timer_id *timer; vlc_list_foreach(timer, &source->listeners, node) { - if (timer->cbs->on_seek != NULL) - timer->cbs->on_seek(point, timer->data); + if (is_smpte) + { + if (timer->smpte_cbs->on_seek != NULL) + timer->smpte_cbs->on_seek(point, timer->data); + } + else + { + if (timer->cbs->on_seek != NULL) + timer->cbs->on_seek(point, timer->data); + } } } @@ -226,7 +234,6 @@ vlc_player_UpdateTimerEvent(vlc_player_t *player, vlc_es_id_t *es_source, /* Discontinuity is signalled by all output clocks and the input. * discard the event if it was already signalled or not on the good * es_source. */ - struct vlc_player_timer_source *bestsource = &player->timer.best_source; switch (event) { @@ -237,18 +244,16 @@ vlc_player_UpdateTimerEvent(vlc_player_t *player, vlc_es_id_t *es_source, struct vlc_player_timer_source *source = &player->timer.sources[i]; if (source->es != es_source) continue; - /* signal discontinuity only on best source */ - if (bestsource->es == es_source) + + /* There can be several discontinuities on the same source + * for one seek request, hence the need of the + * 'timer.seeking' variable to notify only once the end of + * the seek request. */ + if (source->seeking) { - /* There can be several discontinuities on the same source - * for one seek request, hence the need of the - * 'timer.seeking' variable to notify only once the end of - * the seek request. */ - if (player->timer.seeking) - { - player->timer.seeking = false; - vlc_player_SendTimerSeek(player, bestsource, NULL); - } + source->seeking = false; + vlc_player_SendTimerSeek(player, source, NULL, + i == VLC_PLAYER_TIMER_TYPE_SMPTE); } source->point.system_date = VLC_TICK_INVALID; } @@ -288,8 +293,6 @@ vlc_player_UpdateTimerEvent(vlc_player_t *player, vlc_es_id_t *es_source, vlc_assert_unreachable(); } - - vlc_mutex_unlock(&player->timer.lock); } @@ -330,8 +333,13 @@ vlc_player_UpdateTimerSeekState(vlc_player_t *player, vlc_tick_t time, .system_date = VLC_TICK_MAX, }; - player->timer.seeking = true; - vlc_player_SendTimerSeek(player, source, &point); + source->seeking = true; + vlc_player_SendTimerSeek(player, source, &point, false); + + source = &player->timer.smpte_source; + source->seeking = true; + vlc_player_SendTimerSeek(player, source, &point, true); + vlc_mutex_unlock(&player->timer.lock); } @@ -401,7 +409,7 @@ vlc_player_UpdateTimerBestSource(vlc_player_t *player, vlc_es_id_t *es_source, /* It is possible to receive valid points while seeking. These * points could be updated when the input thread didn't yet process * the seek request. */ - if (!player->timer.seeking) + if (!source->seeking) { /* Reset seek time/position now that we receive a valid point * and seek was processed */ @@ -526,12 +534,19 @@ void vlc_player_RemoveTimerSource(vlc_player_t *player, vlc_es_id_t *es_source) { vlc_mutex_lock(&player->timer.lock); + struct vlc_player_timer_source *bestsource = &player->timer.best_source; + struct vlc_player_timer_source *smptesource = &player->timer.smpte_source; /* Unlikely case where the source ES is deleted while seeking */ - if (player->timer.best_source.es == es_source && player->timer.seeking) + if (bestsource->es == es_source && bestsource->seeking) + { + bestsource->seeking = false; + vlc_player_SendTimerSeek(player, bestsource, NULL, false); + } + if (smptesource->es == es_source && smptesource->seeking) { - player->timer.seeking = false; - vlc_player_SendTimerSeek(player, &player->timer.best_source, NULL); + smptesource->seeking = false; + vlc_player_SendTimerSeek(player, smptesource, NULL, true); } for (size_t i = 0; i < VLC_PLAYER_TIMER_TYPE_COUNT; ++i) @@ -722,6 +737,7 @@ vlc_player_InitTimer(vlc_player_t *player) vlc_list_init(&player->timer.sources[i].listeners); player->timer.sources[i].point.system_date = VLC_TICK_INVALID; player->timer.sources[i].es = NULL; + player->timer.sources[i].seeking = false; } vlc_player_ResetTimer(player); }