Skip to content

Prefer a codec continuity if possible - #1839

Open
peaBerberian wants to merge 1 commit into
devfrom
codec-continuity
Open

Prefer a codec continuity if possible#1839
peaBerberian wants to merge 1 commit into
devfrom
codec-continuity

Conversation

@peaBerberian

@peaBerberian peaBerberian commented Apr 29, 2026

Copy link
Copy Markdown
Collaborator

Current track choice behavior

The track-choice API of the RxPlayer was until now very simple in terms of behavior:

  • Either the application gives an explicit choice, usually by listening to the newAvailablePeriods event (whose first purpose is to indicate that new tracks/qualities choices can be made) and by calling API like setAudioTrack in this handler.

  • Either it doesn't do that and the RxPlayer just defines an order purely based on the content.

    The content itself can indicate priorities explicitly (e.g. the selectionPriority attributes), implicitly (AdaptatationSet with role set to "main") or a third case that I would call "very implicitly": just the order in which they are defined in the Manifest.

That's the sole rules the RxPlayer used for initial track selection, in order of importance (from the most to the least).

Issue

We encountered cases where some multi-Periods Manifest do not indicate a preferred track priority and the application select none. In that case as I wrote earlier we just rely on declaration order in the Manifest (first declared is preferred).

However, those Manifests were not regular in that order, for some Periods in their case you would have AAC, then ec-3 declared, and for other Periods in the same content you would have the reverse.

This led to probably unwanted codec switching, even leading to many case to "reloading" phases, where the screen would switch to black and rebuffer temporarily.

My solution

I propose here a very simple solution both in terms of logic and conceptually: if a track choice has already been made in that content, and if the application did not choose a track for that Period, just stay consistent with the last chosen track (of the current playback session) of the same type in terms of codec: if we last chose ec-3 we continue with ec-3.

There is however a big question and risk with this feature, it is that it supersedes even explicit Manifest hints like DASH' AdaptationSet@selectionPriority.

I'm not sure 100% is what we want here. I'll have to check the spec and see how other players decide before being sure this is the right way.

@peaBerberian
peaBerberian force-pushed the codec-continuity branch 12 times, most recently from 80fdc55 to 90546cf Compare April 29, 2026 10:29
@peaBerberian

peaBerberian commented Apr 29, 2026

Copy link
Copy Markdown
Collaborator Author

I looked at the spec to understand if there's an explicit order for the A/V track choice, especially where selectionPriority sits relative to codec continuity.

Turns out that DASH-IF IOP 5.0 has a dedicated chapter on initial selection for audio tracks in:
https://dashif.org/docs/IOP-Guidelines/DASH-IF-IOP-Part8-v5.1.0.pdf

(chapter 6 Client recommendations)

So basically from what I understand, in order:

  1. We should filter what is not supported support
  2. The language (in case of audio) has priority
  3. Then, and to me that's very ambiguous, we should look at other properties associated to the AdaptationSet. They cite:
    a. Viewpoint
    b. Role
    c. Accessibility
    d. AudioChannelConfiguration
    e. SupplementalProperty and EssentialProperty
    f. Others
  4. Then @selectionPriority
  5. Then, also ambiguous to me, either the "DASH client makes a choice for itself" (implying that step 3 is never "for itself" meaning always external - user or device - explicit reasons?) or random (this one is clear!)

So it depends on the intended "spirit" of step 3, and if DASH' codecs can be considered or not part of "others": codec continuity rely on DASH attributes and not doing it lower the user experience so in some ways it could enter the definition of step 3, but it's not as direct as Accessibility/Viewpoint/Role (e.g. dubbed or not) are...

They probably did not think of that case when writing this.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

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

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 25.78ms -> 26.03ms (-0.244ms, z: 1.53195) 35.70ms -> 35.55ms
seeking 208.45ms -> 203.25ms (5.199ms, z: 0.44952) 18.75ms -> 18.75ms
audio-track-reload 32.33ms -> 32.37ms (-0.036ms, z: 1.64470) 47.40ms -> 47.70ms
cold loading multithread 53.44ms -> 52.72ms (0.721ms, z: 6.91907) 78.15ms -> 77.25ms
seeking multithread 105.90ms -> 109.81ms (-3.910ms, z: 0.32056) 19.95ms -> 19.95ms
audio-track-reload multithread 31.25ms -> 31.27ms (-0.020ms, z: 0.45645) 45.60ms -> 45.60ms
hot loading multithread 20.98ms -> 21.49ms (-0.510ms, z: 1.50731) 30.30ms -> 30.15ms

@canalplus canalplus deleted a comment from github-actions Bot Aug 6, 2026
@Florent-Bouisset

Copy link
Copy Markdown
Collaborator

I looked at the spec to understand if there's an explicit order for the A/V track choice, especially where selectionPriority sits relative to codec continuity.

Turns out that DASH-IF IOP 5.0 has a dedicated chapter on initial selection for audio tracks in: https://dashif.org/docs/IOP-Guidelines/DASH-IF-IOP-Part8-v5.1.0.pdf

(chapter 6 Client recommendations)

So basically from what I understand, in order:

  1. We should filter what is not supported support
  2. The language (in case of audio) has priority
  3. Then, and to me that's very ambiguous, we should look at other properties associated to the AdaptationSet. They cite:
    a. Viewpoint
    b. Role
    c. Accessibility
    d. AudioChannelConfiguration
    e. SupplementalProperty and EssentialProperty
    f. Others
  4. Then @selectionPriority
  5. Then, also ambiguous to me, either the "DASH client makes a choice for itself" (implying that step 3 is never "for itself" meaning always external - user or device - explicit reasons?) or random (this one is clear!)

So it depends on the intended "spirit" of step 3, and if DASH' codecs can be considered or not part of "others": codec continuity rely on DASH attributes and not doing it lower the user experience so in some ways it could enter the definition of step 3, but it's not as direct as Accessibility/Viewpoint/Role (e.g. dubbed or not) are...

They probably did not think of that case when writing this.

Doesn't that go against this:

In addition, the content author may also provide priorities for target versions, if the receivers support multiple of those. The content author may also define priorities in the selection, for example if the client supports multiple capabilities, using the @selectionPriority attribute. Typical examples are that the content is prepared for H.264/AVC and H.265/HEVC capable receivers, and the content author prefers the selection of the H.265/HEVC version as its distribution is more efficient. A device supporting both decoders may then choose the one with higher priority signalled by the content author.

It's from there, https://dashif.org/webRTC/report.html

@peaBerberian

peaBerberian commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

Doesn't that go against this:

Here in this PR we're in the case of a content that had Period already playing before were "codec continuity" (like h264 -> h264) will take precedence over @selectionPriority.

A device supporting both decoders may then choose the one with higher priority signalled by the content author.

The sentence is very loose with thay "may". I don't quite get the "strength" that @selectionPriority is supposed to have, relative to the player optimizing for the experience.
We know it is less strong that explicit track choice from the user (accessibility, lang, role), I wonder if for codec continuity, we aren't in a special common area of priority.

@peaBerberian peaBerberian added the Priority: 2 (Medium) This issue or PR has a medium priority. label Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

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

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 25.87ms -> 26.26ms (-0.394ms, z: 1.01882) 35.70ms -> 35.70ms
seeking 166.06ms -> 174.73ms (-8.665ms, z: 0.19278) 19.20ms -> 19.20ms
audio-track-reload 32.51ms -> 32.54ms (-0.023ms, z: 0.33595) 47.85ms -> 47.70ms
cold loading multithread 53.61ms -> 52.88ms (0.722ms, z: 7.56529) 78.15ms -> 77.00ms
seeking multithread 101.01ms -> 96.97ms (4.034ms, z: 1.23987) 20.40ms -> 20.25ms
audio-track-reload multithread 31.56ms -> 31.44ms (0.114ms, z: 1.70218) 46.20ms -> 46.05ms
hot loading multithread 21.31ms -> 20.95ms (0.358ms, z: 3.26213) 30.45ms -> 30.15ms

@github-actions

Copy link
Copy Markdown

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

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 24.99ms -> 25.03ms (-0.048ms, z: 0.52403) 34.95ms -> 34.95ms
seeking 196.76ms -> 178.06ms (18.700ms, z: 1.09015) 18.90ms -> 19.20ms
audio-track-reload 31.29ms -> 31.36ms (-0.071ms, z: 0.72975) 46.50ms -> 46.50ms
cold loading multithread 52.10ms -> 51.21ms (0.891ms, z: 14.58216) 76.80ms -> 75.60ms
seeking multithread 90.12ms -> 103.47ms (-13.349ms, z: 1.44248) 19.65ms -> 19.65ms
audio-track-reload multithread 30.58ms -> 30.65ms (-0.075ms, z: 1.13551) 44.70ms -> 44.85ms
hot loading multithread 20.41ms -> 20.32ms (0.094ms, z: 0.42386) 29.85ms -> 29.70ms

@peaBerberian

peaBerberian commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

@Florent-Bouisset I dived into this a little more so we can decide what to do with this.

To me the specs are too ambiguous (voluntarily or involuntarily I don't know), about the ordering between selectionPriority and heuristics created to maintain smooth playback.

So to break the ambiguity, I thought that the final answer would be to look at what the other DASH players are doing.

So it seems all players I look at agree that @selectionPriority is very secondary

@Florent-Bouisset

Copy link
Copy Markdown
Collaborator

@Florent-Bouisset I dived into this a little more so we can decide what to do with this.

To me the specs are too ambiguous (voluntarily or involuntarily I don't know), about the ordering between selectionPriority and heuristics created to maintain smooth playback.

So to break the ambiguity, I thought that the final answer would be to look at what the other DASH players are doing.

So it seems all players I look at agree that @selectionPriority is very secondary

OK, I think we can adapt the logic for the encountered use case because the spec is a bit vague about what is included in @selectionPriority and the spec does not express that we should strictly follow the order.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

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

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 28.27ms -> 27.64ms (corrected: 2.250ms, A/A bias: -1.619ms, z: 0.29830) 23.30ms -> 23.15ms (corrected: 0.175ms, A/A bias: 0.050ms, z: 1.22206)
seeking 558.90ms -> 528.79ms (corrected: 62.506ms, A/A bias: -32.395ms, z: 1.30866) 1005.10ms -> 1005.00ms (corrected: 0.650ms, A/A bias: -0.500ms, z: 1.26536)
audio-track-reload 23.43ms -> 23.70ms (corrected: -0.164ms, A/A bias: -0.108ms, z: 0.86603) 22.90ms -> 23.10ms (corrected: -0.050ms, A/A bias: -0.225ms, z: 1.44819)
loading over active content 15.82ms -> 16.18ms (corrected: -0.482ms, A/A bias: 0.120ms, z: 0.60622) 14.75ms -> 15.15ms (corrected: -1.975ms, A/A bias: 0.400ms, z: 0.60622)
large multi-period manifest 67.17ms -> 67.34ms (corrected: 2.102ms, A/A bias: -2.266ms, z: 0.05774) 62.25ms -> 61.35ms (corrected: 3.925ms, A/A bias: -1.950ms, z: 0.05774)
cold loading multithread 39.33ms -> 38.65ms (corrected: 0.719ms, A/A bias: -0.038ms, z: 2.19393) 38.75ms -> 38.30ms (corrected: 0.600ms, A/A bias: -0.100ms, z: 3.66136)
seeking multithread 799.80ms -> 827.35ms (corrected: -20.045ms, A/A bias: -7.509ms, z: 0.34641) 1005.90ms -> 1006.00ms (corrected: 0.100ms, A/A bias: -0.200ms, z: 0.23094)
audio-track-reload multithread 23.81ms -> 23.67ms (corrected: -0.097ms, A/A bias: 0.231ms, z: 0.52924) 23.70ms -> 23.40ms (corrected: 0.175ms, A/A bias: 0.100ms, z: 0.12028)
hot loading multithread 14.82ms -> 14.75ms (corrected: 0.093ms, A/A bias: -0.026ms, z: 0.29830) 14.60ms -> 14.60ms (corrected: -0.050ms, A/A bias: 0.050ms, z: 0.20207)

Current track choice behavior
-----------------------------

The track-choice API of the RxPlayer was until now very simple in terms
of behavior:

- Either the application gives an explicit choice, usually by listening to the
  `newAvailablePeriods` event (whose first purpose is to indicate that new
  tracks/qualities choices can be made) and by calling API like
  `setAudioTrack` in this handler.

- Either it doesn't do that and the RxPlayer just defines an order
  purely based on the content.

  The content itself can indicate priorities explicitly (e.g. the
  `selectionPriority` attributes), implicitly (`AdaptatationSet` with
  `role` set to `"main"`) or a third case that I would call "very
  implicitly": just the order in which they are defined in the Manifest.

That's the sole rules the RxPlayer used for initial track selection, in order
of importance (from the most to the least).

Issue
-----

We encountered cases where some multi-Periods Manifest do not indicate a
preferred track priority and the application select none. In that case I
written earlier we just rely on declaration order in the Manifest (first
declared is preferred).

However, thoses Manifest were not regular in that order, for some
Periods in their case you would have AAC, then ec-3 declared, and for
other Periods in the same content you would have the reverse.

This led to probably unwanted codec switching, even leading to many case
to "reloading" phases, where the screen would switch to black and
rebuffer temporarily.

My solution
-----------

I propose here a very simple solution both in terms of logic and
conceptually: if a track choice has already been made in that content,
**and** if the application did not choose a track for that Period, just
stay consistent with the last chosen track of the same type in terms of
codec: if we last chose `ec-3` we continue with `ec-3`.

There is however a big question and risk with this feature, it is that
it supersedes even explicit Manifest hints like DASH'
`AdaptationSet@selectionPriority`.

I'm not sure 100% is what we want here. I'll have to check the
spec and see how other players decide before being sure this is the
right way.
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. waiting-for-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants