Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
f573990e by Pierre Lamot at 2026-01-20T15:24:08+01:00
player: fix initial seeking in AB loop policy
When setting AB loop, if the player is already in the interval, we shouldn't
seek to the A point
- - - - -
608b85a6 by Pierre Lamot at 2026-01-20T15:24:08+01:00
test: player: abloop: display test purpose in the logs
- - - - -
b5928fa3 by Pierre Lamot at 2026-01-20T15:24:08+01:00
test: player: abloop: add tests to check initial after setting ABLoop
- - - - -
0ab833bf by Pierre Lamot at 2026-01-20T15:24:08+01:00
player: fix player seeking to AB loop start while paused
- - - - -
3 changed files:
- src/player/input.c
- src/player/player.c
- test/src/player/abloop.c
Changes:
=====================================
src/player/input.c
=====================================
@@ -296,6 +296,7 @@ vlc_player_input_HandleState(struct vlc_player_input *input,
break;
case VLC_PLAYER_STATE_PLAYING:
input->pause_date = VLC_TICK_INVALID;
+ vlc_player_SignalAtoBLoop(player);
vlc_player_UpdateTimerEvent(player, NULL,
VLC_PLAYER_TIMER_EVENT_PLAYING,
input->pause_date);
@@ -311,6 +312,7 @@ vlc_player_input_HandleState(struct vlc_player_input *input,
assert(state_date != VLC_TICK_INVALID);
input->pause_date = state_date;
+ vlc_player_SignalAtoBLoop(player);
vlc_player_UpdateTimerEvent(player, NULL,
VLC_PLAYER_TIMER_EVENT_PAUSED,
input->pause_date);
=====================================
src/player/player.c
=====================================
@@ -195,7 +195,7 @@ vlc_player_GetAtoBLoopDeadline(vlc_player_t *player)
{
struct vlc_player_input *input = vlc_player_get_input_locked(player);
- if (!input || !input->abloop_state[0].set || !input->abloop_state[1].set)
+ if (!input || input->pause_date != VLC_TICK_INVALID ||
!input->abloop_state[0].set || !input->abloop_state[1].set)
return VLC_TICK_MIN;
vlc_tick_t now = vlc_tick_now();
@@ -1609,7 +1609,9 @@ vlc_player_SetAtoBLoopTime(vlc_player_t *player,
vlc_tick_t a_time, vlc_tick_t b
input->abloop_state[1].pos = 0;
input->abloop_state[1].set = true;
- vlc_player_SetTime(player, a_time);
+ vlc_tick_t current = vlc_player_input_GetTime(input, false,
vlc_tick_now());
+ if (current == VLC_TICK_INVALID || current < a_time || current > b_time)
+ vlc_player_SetTime(player, a_time);
vlc_player_SendEvent(player, on_atobloop_changed, VLC_PLAYER_ABLOOP_A,
a_time, 0);
vlc_player_SendEvent(player, on_atobloop_changed, VLC_PLAYER_ABLOOP_B,
b_time, 0);
@@ -1637,7 +1639,9 @@ vlc_player_SetAtoBLoopPosition(vlc_player_t *player,
double a_pos, double b_pos)
input->abloop_state[1].pos = b_pos;
input->abloop_state[1].set = true;
- vlc_player_SetPosition(player, a_pos);
+ double current = vlc_player_input_GetPos(input, false, vlc_tick_now());
+ if (current < a_pos || current > b_pos)
+ vlc_player_SetPosition(player, a_pos);
vlc_player_SendEvent(player, on_atobloop_changed, VLC_PLAYER_ABLOOP_A,
VLC_TICK_INVALID, a_pos);
vlc_player_SendEvent(player, on_atobloop_changed, VLC_PLAYER_ABLOOP_B,
VLC_TICK_INVALID, b_pos);
=====================================
test/src/player/abloop.c
=====================================
@@ -10,6 +10,7 @@
struct abloop_scenario
{
+ const char* title;
bool can_seek;
bool after_1st_buferring;
bool nolength_report;
@@ -131,7 +132,7 @@ test_abloop(struct ctx *ctx)
const struct abloop_scenario scenarios[] =
{
{
- /* Check that b_time past length is handled */
+ .title = "Check that b_time past length is handled",
.can_seek = true, .after_1st_buferring = false,
.check_prev_ts = true,
.length = VLC_TICK_FROM_MS(20000),
@@ -139,7 +140,7 @@ test_abloop(struct ctx *ctx)
.seek_count = 2,
},
{
- /* Check we have the same result if called after buffering */
+ .title = "Check we have the same result if called after
buffering",
.can_seek = true, .after_1st_buferring = true,
.check_prev_ts = true,
.length = VLC_TICK_FROM_MS(20000),
@@ -147,28 +148,28 @@ test_abloop(struct ctx *ctx)
.seek_count = 2,
},
{
- /* Check small A->B loop values */
+ .title = "Check small A->B loop values",
.can_seek = true, .after_1st_buferring = true,
.length = VLC_TICK_FROM_MS(3000),
.a_time = VLC_TICK_FROM_MS(1), .b_time = VLC_TICK_FROM_MS(2),
.seek_count = 4,
},
{
- /* Check with positions */
+ .title = "Check with positions",
.can_seek = true, .after_1st_buferring = true,
.length = VLC_TICK_FROM_MS(3000),
.a_pos = 0.9, .b_pos = 1.0f,
.seek_count = 1,
},
{
- /* Check we have the same result if called after buffering */
+ .title = "Check we have the same result if called after buffering",
.can_seek = true, .after_1st_buferring = false,
.length = VLC_TICK_FROM_MS(3000),
.a_pos = 0.9, .b_pos = 1.0f,
.seek_count = 2,
},
{
- /* Check that seek is triggered by EOF (no reported length) */
+ .title = "Check that seek is triggered by EOF (no reported
length)",
.can_seek = true, .after_1st_buferring = false,
.nolength_report = true,
.length = VLC_TICK_FROM_MS(1000),
@@ -176,7 +177,7 @@ test_abloop(struct ctx *ctx)
.seek_count = 2,
},
{
- /* Check that A->B loop is not triggered */
+ .title= "Check that A->B loop is not triggered",
.can_seek = false, .after_1st_buferring = false,
.nolength_report = true, .wait_stopped = true,
.length = VLC_TICK_FROM_MS(100),
@@ -187,17 +188,171 @@ test_abloop(struct ctx *ctx)
for (size_t i = 0; i < ARRAY_SIZE(scenarios); ++i)
{
- test_log("abloop[%zu]\n", i);
+ test_log("abloop[%zu]: %s\n", i, scenarios[i].title);
test_abloop_scenario(ctx, &scenarios[i]);
}
}
+struct abloop_initial_position_scenario
+{
+ const char* title;
+ bool can_seek;
+ bool nolength_report;
+ vlc_tick_t initial_time;
+ vlc_tick_t expected_initial_time;
+ vlc_tick_t length;
+ vlc_tick_t a_time;
+ vlc_tick_t b_time;
+ double initial_pos;
+ double expected_initial_pos;
+ double a_pos;
+ double b_pos;
+
+};
+
+static void
+test_abloop_initial_position_scenario(struct ctx *ctx, const struct
abloop_initial_position_scenario *scenario)
+{
+ vlc_player_t *player = ctx->player;
+
+ struct media_params params = DEFAULT_MEDIA_PARAMS(scenario->length);
+ params.can_seek = scenario->can_seek;
+ params.track_count[AUDIO_ES] = 1;
+ params.track_count[VIDEO_ES] = 0;
+ params.track_count[SPU_ES] = 0;
+ params.report_length = !scenario->nolength_report;
+ player_set_next_mock_media(ctx, "media1", ¶ms);
+
+ player_start(ctx);
+
+ while (get_buffering_count(ctx) < 1)
+ vlc_player_CondWait(player, &ctx->wait);
+
+ if (scenario->initial_time != VLC_TICK_INVALID)
+ {
+ vlc_player_SetTime(player, scenario->initial_time);
+
+ vec_on_position_changed *vec = &ctx->report.on_position_changed;
+ while (vec->size == 0)
+ vlc_player_CondWait(player, &ctx->wait);
+
+ vlc_tick_t current_time = VEC_LAST(vec).time;
+
+ assert(current_time >= scenario->initial_time);
+ assert(current_time - scenario->initial_time < VLC_TICK_FROM_MS(1000));
+
+ assert(scenario->b_time != VLC_TICK_INVALID);
+ int ret = vlc_player_SetAtoBLoopTime(player, scenario->a_time,
+ scenario->b_time);
+ assert(ret == VLC_SUCCESS);
+
+
+ //wait for the next position report
+ while (vec->size == 1)
+ vlc_player_CondWait(player, &ctx->wait);
+
+
+ current_time = VEC_LAST(vec).time;
+
+ assert(current_time >= scenario->expected_initial_time);
+ assert(current_time - scenario->expected_initial_time <
VLC_TICK_FROM_MS(1000));
+ }
+ else
+ {
+ vlc_player_SetPosition(player, scenario->initial_pos);
+
+ vec_on_position_changed *vec = &ctx->report.on_position_changed;
+ while (vec->size == 0)
+ vlc_player_CondWait(player, &ctx->wait);
+
+ double current_pos = VEC_LAST(vec).pos;
+
+ assert(current_pos >= scenario->initial_pos);
+ assert((current_pos - scenario->initial_pos) < 0.1);
+
+ int ret = vlc_player_SetAtoBLoopPosition(player, scenario->a_pos,
+ scenario->b_pos);
+ assert(ret == VLC_SUCCESS);
+
+
+ //wait for the next position report
+ while (vec->size == 1)
+ vlc_player_CondWait(player, &ctx->wait);
+
+
+ current_pos = VEC_LAST(vec).pos;
+
+ assert(current_pos >= scenario->expected_initial_pos);
+ assert((current_pos - scenario->expected_initial_pos) < 0.1);
+ }
+
+ test_end(ctx);
+}
+
+static void
+test_abloop_initial_position(struct ctx *ctx)
+{
+ const struct abloop_initial_position_scenario scenarios[] =
+ {
+ {
+ .title = "Current time before the interval should seek to
beginning",
+ .can_seek = true,
+ .length = VLC_TICK_FROM_MS(30000),
+ .initial_time = VLC_TICK_FROM_MS(5000), .expected_initial_time =
VLC_TICK_FROM_MS(10000),
+ .a_time = VLC_TICK_FROM_MS(10000), .b_time =
VLC_TICK_FROM_MS(20000),
+ },
+ {
+ .title = "Current time in the interval should not seek",
+ .can_seek = true,
+ .length = VLC_TICK_FROM_MS(30000),
+ .initial_time = VLC_TICK_FROM_MS(15000), .expected_initial_time =
VLC_TICK_FROM_MS(15000),
+ .a_time = VLC_TICK_FROM_MS(10000), .b_time =
VLC_TICK_FROM_MS(20000),
+ },
+ {
+ .title = "Current time after the interval should seek to
beginning",
+ .can_seek = true,
+ .length = VLC_TICK_FROM_MS(30000),
+ .initial_time = VLC_TICK_FROM_MS(25000), .expected_initial_time =
VLC_TICK_FROM_MS(10000),
+ .a_time = VLC_TICK_FROM_MS(10000), .b_time =
VLC_TICK_FROM_MS(20000),
+ },
+ {
+ .title = "Current pos before the interval should seek to
beginning",
+ .can_seek = true,
+ .length = VLC_TICK_FROM_MS(30000),
+ .initial_pos = 0.1, .expected_initial_pos = 0.3,
+ .a_pos = 0.3, .b_pos = 0.6,
+ },
+ {
+ .title = "Current pos in the interval should not seek",
+ .can_seek = true,
+ .length = VLC_TICK_FROM_MS(30000),
+ .initial_pos = 0.4, .expected_initial_pos = 0.4,
+ .a_pos = 0.3, .b_pos = 0.6,
+ },
+ {
+ .title = "Current pos after the interval should seek to beginning",
+ .can_seek = true,
+ .length = VLC_TICK_FROM_MS(30000),
+ .initial_pos = 0.8, .expected_initial_pos = 0.3,
+ .a_pos = 0.3, .b_pos = 0.6,
+ },
+
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(scenarios); ++i)
+ {
+ test_log("abloop_initial_position[%zu]: %s\n", i, scenarios[i].title);
+ test_abloop_initial_position_scenario(ctx, &scenarios[i]);
+ }
+}
+
int
main(void)
{
struct ctx ctx;
ctx_init(&ctx, 0);
test_abloop(&ctx);
+ test_abloop_initial_position(&ctx);
ctx_destroy(&ctx);
return 0;
}
View it on GitLab:
https://code.videolan.org/videolan/vlc/-/compare/abd5e50fefc35d29f143155b2916d0c4965f1a67...0ab833bfbb2012fabfa9f2e308261b8abaed3647
--
View it on GitLab:
https://code.videolan.org/videolan/vlc/-/compare/abd5e50fefc35d29f143155b2916d0c4965f1a67...0ab833bfbb2012fabfa9f2e308261b8abaed3647
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits