Skip to content

Fix ordering of a PeriodChange/AdaptationChange couple#1764

Open
peaBerberian wants to merge 1 commit intodevfrom
fix/ordering-periodChange
Open

Fix ordering of a PeriodChange/AdaptationChange couple#1764
peaBerberian wants to merge 1 commit intodevfrom
fix/ordering-periodChange

Conversation

@peaBerberian
Copy link
Collaborator

@peaBerberian peaBerberian commented Nov 12, 2025

New integration tests I've added recently (#1763) led me to a curious RxPlayer behavior: for multithreaded contents, we had two initial textTrackChange (with the payload null) in a row instead of just one.

This exact behavior does not break the API (so it's not a bug), but it was nonetheless not normal, so I looked at it.


Turns out it is linked to a bad ordering in core between the first "PeriodChange" Core message (indicating a Period is currently playing, thus implies that we already chose the audio+video+text tracks) and the last "AdaptationChange" (for audio or video or text type) for that first period.

What happened:

  1. The content begins to be loaded, the RxPlayer setup everything, and start choosing the initial Adaptations (tracks) and Representations.
  2. Once all Adaptation are setup, Core send a PeriodChange message
  3. Then Core sent an AdaptationChange message for the last Adaptation set-up (the text one here)
  4. Main thread receives the PeriodChange message and bubble it to the public API module.
  5. The public API on this event looks at the current audio / video / text tracks for that new Period and send the right ...TrackChange events, then send a periodChange event, as expected
  6. Main thread then receives the AdaptationChange message and also bubble it.
  7. The Public API reacts on this event by sending again textTrackChange for the same text track, because it thinks from the AdaptationChange message that the track just changed, after the PeriodChange

Reversing the ordering (the last AdaptationChange, then PeriodChange) in Core makes more sense (messages are the Core's API, and advertising for a Period change should be done after advertising for all tracks initially choosen for that Period) fixes the issue.

It's very unclear to me if this led to actual bugs later in the RxPlayer. For now the only seen impact was a failing integration test which was voluntarily less "tolerant" than our advertised API.

value.type,
value.period,
value.adaptation,
);
Copy link
Collaborator Author

@peaBerberian peaBerberian Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: I guessed that it was not necessary to check currentLoadCanceller in between the two because sendMessage implies only asynchronous state changes as per our current Core API. Thus a sendMessage call cannot change the world.

If later it turns out that we change the behavior of sendMessage to potentially lead to synchronous change (e.g. if we find out that it improves the perf of a monothreaded scenario), I trust due to the importance of that change that we will think about checking each of its calls and add the check at that point.

@peaBerberian
Copy link
Collaborator Author

I'm now wondering if that simple fix is the right way.
contentTimeBoundariesObserver.onAdaptationChange implies potentially multiple events (such as now advertising a new content duration, e.g. due to a "shorter" video track) where the ordering is unclear to me. I'll think more about it....

New integration tests I've added recently led to a curious behavior: for
multithreaded contents, we had two initial `textTrackChange` (with the
payload `null`) in a row instead of just one.

This exact behavior does not break the API, but it was nonetheless not
normal, so I looked at it.

---

Turns out it is linked to a bad ordering in core between the first
"PeriodChange" Core message (indicating a Period is currently
playing, thus implies that we already chose the audio+video+text
tracks) and the last "AdaptationChange" (for audio or video or text type)
for that first period.

What happened:

1. The content begins to be loaded, the RxPlayer setup everything, and
   start choosing the initial Adaptations (tracks) and Representations.
2. Once all Adaptation are setup, Core send a `PeriodChange` message
3. Then Core sent an `AdaptationChange` message for the last Adaptation
   set-up (the text one here)
4. Main thread receives the `PeriodChange` message and bubble it to the
   public API module.
5. The public API on this event looks at the current audio / video / text
   tracks for that new Period and send the right `...TrackChange` events,
   then send a `periodChange` event, as expected
6. Main thread then receives the `AdaptationChange` message and also
   bubble it.
7. The Public API reacts on this event by sending again `textTrackChange`
   for the same text track, because it thinks from the `AdaptationChange`
   message that the track just changed, after the PeriodChange

---

Reversing the ordering (the last `AdaptationChange`, then `PeriodChange`)
in Core makes more sense (messages are the Core's API, and advertising
for a Period change should be done after advertising for all tracks
initially choosen for that Period) fixes the issue.

It's very unclear to me if this led to actual bugs later in the
RxPlayer. For now the only seen impact was a failing integration tests
which was voluntarily less "tolerant" than our advertised API.
@peaBerberian peaBerberian force-pushed the fix/ordering-periodChange branch from 1ae7f29 to f9b6ccd Compare December 10, 2025 17:26
@github-actions
Copy link

✅ Automated performance checks have passed on commit a8c40327e5a5fbaf86b7caa37cbcdf84240d207a with the base branch dev.

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 21.10ms -> 21.94ms (-0.841ms, z: 0.87850) 29.70ms -> 29.85ms
seeking 12.20ms -> 14.18ms (-1.980ms, z: 0.99391) 12.30ms -> 12.30ms
audio-track-reload 28.76ms -> 28.94ms (-0.178ms, z: 1.51113) 42.15ms -> 42.30ms
cold loading multithread 48.58ms -> 47.82ms (0.764ms, z: 12.31972) 71.70ms -> 70.35ms
seeking multithread 42.17ms -> 53.51ms (-11.340ms, z: 1.38483) 11.25ms -> 11.25ms
audio-track-reload multithread 27.95ms -> 27.89ms (0.062ms, z: 0.11703) 41.10ms -> 41.10ms
hot loading multithread 16.18ms -> 15.95ms (0.226ms, z: 4.00307) 23.70ms -> 23.55ms

@peaBerberian peaBerberian added the Priority: 2 (Medium) This issue or PR has a medium priority. label Dec 17, 2025
@canalplus canalplus deleted a comment from github-actions bot Dec 19, 2025
@canalplus canalplus deleted a comment from github-actions bot Dec 19, 2025
@peaBerberian peaBerberian force-pushed the dev branch 2 times, most recently from d4be192 to 9ad6758 Compare December 19, 2025 19:49
@peaBerberian peaBerberian added this to the 4.5.0 milestone Jan 19, 2026
@peaBerberian peaBerberian force-pushed the dev branch 9 times, most recently from 0142e34 to 1fd9df3 Compare January 27, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority: 2 (Medium) This issue or PR has a medium priority.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant