Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: content steering switching #1427

Merged
merged 24 commits into from
Sep 26, 2023
Merged

Conversation

wseymour15
Copy link
Contributor

@wseymour15 wseymour15 commented Sep 13, 2023

Description

The changes include the logic for switching pathways regarding content steering. All specifications for both DASH and HLS can be found in the resources below. The function of these changes are to ensure that we are communicating with the content steering server, handling the responses, switching playlists based on this data, and ensuring that we follow the requirements of the spec when deciding when/where to switch.

Specific Changes proposed

  • Logic to determine which pathway/serviceLocation should be selected based on priority.
  • Logic to switch media in cases where we want to switch playlists.
  • Logic to exclude playlists when necessary according to the spec.
  • Logic to set timers to retry certain content steering requests.
  • Tests to cover specification

Example Manifests to Test Locally

DASH: https://fastly.content-steering.com/bbb/playlist_steering_fastly_https_cdn-a_cdn-c_cdn-b.mpd
HLS: https://fastly.content-steering.com/bbb_hls/master_steering_fastly_https.m3u8

Specs

https://dashif.org/docs/DASH-IF-CTS-00XX-Content-Steering-Community-Review.pdf
https://developer.apple.com/streaming/HLSContentSteeringSpecification.pdf

Requirements Checklist

  • Feature implemented / Bug fixed
  • If necessary, more likely in a feature request than a bug fix
  • Reviewed by Two Core Contributors

@codecov
Copy link

codecov bot commented Sep 13, 2023

Codecov Report

Merging #1427 (72af63a) into main (86d5327) will increase coverage by 0.17%.
Report is 1 commits behind head on main.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #1427      +/-   ##
==========================================
+ Coverage   85.75%   85.93%   +0.17%     
==========================================
  Files          42       42              
  Lines       10284    10414     +130     
  Branches     2374     2409      +35     
==========================================
+ Hits         8819     8949     +130     
  Misses       1465     1465              
Files Changed Coverage Δ
src/media-groups.js 98.65% <ø> (-0.01%) ⬇️
src/content-steering-controller.js 99.42% <100.00%> (+0.20%) ⬆️
src/dash-playlist-loader.js 90.54% <100.00%> (+0.02%) ⬆️
src/playlist-controller.js 95.80% <100.00%> (+0.44%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@dzianis-dashkevich
Copy link
Contributor

dzianis-dashkevich commented Sep 18, 2023

Curious about the usage of throughput from segmentLoader:

Are we sure we want to use this value?

throughput is the time since all segment-related downloads are done till the time the segment is appended to the buffer (so basically, it is all about decrypt, transmux, and browser append time)

It is not related to network

@dzianis-dashkevich
Copy link
Contributor

Also curious about the usage of segmentLoader in the contentSteeringController:

Do we need segmentLoader as a dependency?
As far as I see, we are using throughput and xhr; both entities can be provided separately in the constructor.

I believe it should be vhs.bandwidth(pure network metric), or vhs.systemBandwidth(network + cpu) instead of segmentLoader.throughput

Copy link
Contributor

@adrums86 adrums86 left a comment

Choose a reason for hiding this comment

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

This looks great, Walter! Per @dzianis-dashkevich's comment, I think he is correct. We will probably want to use bandwidth instead of our internal throughput value.

src/media-groups.js Show resolved Hide resolved
@wseymour15
Copy link
Contributor Author

Do we need segmentLoader as a dependency? As far as I see, we are using throughput and xhr; both entities can be provided separately in the constructor.

@dzianis-dashkevich I believe we need to pass the entire segment loader here because throughput will be changing. If we just pass throughput, it will be a static value. Would you agree with that @adrums86?

@adrums86
Copy link
Contributor

@wseymour15 Thanks for addressing this, yeah that is correct. We need a reference to the actual bandwidth property on the segmentLoader as it's updated during segment requests. Since the segmentLoader also has an xhr reference we can get both by just passing in the segmentLoader.

@dzianis-dashkevich
Copy link
Contributor

@dzianis-dashkevich I believe we need to pass the entire segment loader here because throughput will be changing. If we just pass throughput, it will be a static value. Would you agree with that @adrums86?

@wseymour15, @adrums86

Yes, I understand that :)

Sorry, I didn't express my thoughts fully in my previous messages...
I was referring to a famous OOP quote:

You wanted a banana, but you got a gorilla holding the banana

My point was to provide a bare minimum interface required for a controller to work.

This is a common approach when designing a new entity, you are using a DI for injecting dependencies, but instead of relying on concrete implementation, you invert control by expecting some interface:
Check the Dependency Inversion Principle from SOLID: https://en.wikipedia.org/wiki/Dependency_inversion_principle

So, in this particular use case:
Instead of providing the whole segmentLoader, we can provide: { get bandwidth() { return segmentLoader.bandwith } }

or something like that.

It is a minor thing, and I am ok to keep things as is.

@adrums86
Copy link
Contributor

adrums86 commented Sep 21, 2023

@dzianis-dashkevich Yeah I see what you mean, and I 100% agree. The only reason it was done this way was because we needed xhr as well, sacrificing a bit of principle for less code. I'm cool with passing a getter for the segment loader bandwidth and passing just that and xhr separately.

@dzianis-dashkevich
Copy link
Contributor

+1 from me when all checks will be successful

@adrums86
Copy link
Contributor

@dzianis-dashkevich we decided to remove the segmentLoader parameter and just pass xhr and a bandwidth function, I think it's much better. Thanks for the suggestion.

@wseymour15 wseymour15 merged commit dd5e2af into main Sep 26, 2023
14 checks passed
@wseymour15 wseymour15 deleted the feat-contentSteeringSwitching branch September 26, 2023 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants