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

feature: add the possibility to rely on managedMediaSource on iOS devices #1562

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from

Conversation

Florent-Bouisset
Copy link
Collaborator

Add the possibility to rely on ManagedMediaSource for devices that has no access to MediaSource such as iOS devices with version > 17.1

In practice that allow devices like iPhone to play DASH content with the RxPlayer.

Note that it is not possible to cast a DASH content with AirPlay, so the RxPlayer disable the possibility to stream to AirPlay by adding the disableRemotePlayback attribute to the video Element when a DASH content is loaded.

#1294

@peaBerberian
Copy link
Collaborator

peaBerberian commented Oct 3, 2024

Aren't there also supplementary events we're supposed to handle as a player with a ManagedMediaSource?
To me that was one of the arguments for it.

I know there's the potentiality of GC at any time, which I think we prefer and already support, and that brings the bufferedchange event which we could use but nothing urgent for that one.
But there's also mainly the stopStreaming / startStreaming events on which we're supposed to pause / resume our [adequately named] stream logic (the loading and pushing segments operations), no?

@peaBerberian peaBerberian added this to the 4.3.0 milestone Oct 4, 2024
@peaBerberian
Copy link
Collaborator

So if I get it, we will not be reacting to startstreaming/endstreaming directly but we'll just check mediaSource.streaming in the next playback observation.

I wonder if it's what we want:

  • For endstreaming, it depends on the philosophy of the event. I'm not sure of what is wanted from us here by reading the spec.
  • For startstreaming, it depends on what the user-agent defined as its [cannot] play uninterrupted and efficiently limit...

@peaBerberian
Copy link
Collaborator

We could also have a supplementary parameter streamingReference everywhere but I understand that it is less nice than having it in a playback observation

@Florent-Bouisset Florent-Bouisset force-pushed the feature/add-managed-media-source branch 2 times, most recently from babacfe to 2fd5e0c Compare October 31, 2024 13:41
*/
if (
"disableRemotePlayback" in videoElement &&
disableRemotePlaybackPreviousValue !== undefined
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why having that condition?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

  • first condition "disableRemotePlayback" in videoElement because on browsers that does not have disableRemotePlayback I don't see the point of setting it.
  • 2nd condition disableRemotePlaybackPreviousValue !== undefined is because typescript don't allow to possibly assign videoElement.disableRemotePlayback to undefined. Because it's typed as disableRemote?: boolean

Copy link
Collaborator

Choose a reason for hiding this comment

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

It was for the second condition.

So it creates a weird situation where we would reset the value UNLESS it was previously set to undefined...

Maybe calling something like removeAttribute in that case is more logical / simpler to understand?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

UNLESS it was previously set to undefined

The property is a boolean so it should never be set to undefined

I can use removeAttribute but this will not reset it to true if that was already true before using the RxPlayer

@Florent-Bouisset
Copy link
Collaborator Author

So if I get it, we will not be reacting to startstreaming/endstreaming directly but we'll just check mediaSource.streaming in the next playback observation.

I wonder if it's what we want:

  • For endstreaming, it depends on the philosophy of the event. I'm not sure of what is wanted from us here by reading the spec.
  • For startstreaming, it depends on what the user-agent defined as its [cannot] play uninterrupted and efficiently limit...

Don't know if the comment is outdated, but it actually send an event streamingChanged and the playbackObserver emit a new observation on the "endstreaming" and "startstreaming" event.
The value is passed down to the representationStream and to the segmentQueue. The next time a segment is intended to be loaded the segmentQueue it check the value on the last observation, so It should be OK.

…ices

add unit test for managed media source

handle start and end stream event from managedMediaSource

fix unit test

react to event endStreaming and startStreaming to immediately trigger a new observation and to download the segments sooner

review feedback

restart Loading queue if it canLoad is updated

add clearSignal to prevent memory leak

remove undefined from canLoad

only set disableRemotePlayback if it's defined by the browser

fmt
* in order to leave the <video> element in the same state has it was set
* by the application before calling the RxPlayer.
*/
if (disableRemotePlaybackPreviousValue !== undefined) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I thought that if videoElement.disableRemotePlayback was defined, it was always a boolean. We already checked that "disableRemotePlayback" in videoElement, so how come disableRemotePlaybackPreviousValue can now be set to undefined for TypeScript?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, done.

* an Airplay source alternative, such as HLS.
* https://github.com/w3c/media-source/issues/320
*/
mediaElement.disableRemotePlayback = true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

We could also put that one inside a if like in the other place no?

* an Airplay source alternative, such as HLS.
* https://github.com/w3c/media-source/issues/320
*/
mediaElement.disableRemotePlayback = true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it possible to just factorize all places where we doing this as it looks fairly similar?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done it

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see the factorized code but why isn't it used here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes I have replaced it once it that file but it was actually used twice, thanks will update it

mediaElement: IMediaElement,
cancellationSignal: CancellationSignal,
) {
if (isManagedMediaSource && "disableRemotePlayback" in mediaElement) {
Copy link
Collaborator

@peaBerberian peaBerberian Nov 12, 2024

Choose a reason for hiding this comment

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

It's a weird combination when I read this to:

  • have a method just called disableRemotePlayback that takes a media element and a cancel signal (which I would assume just disable remote playback until the cancel signal emits I guess)
  • have it inside create_media_source.ts and have it checking isManagedMediaSource (and doing nothing if that isn't the case)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes but the other way around I would need to repeat the condition
if (isManagedMediaSource && "disableRemotePlayback" in mediaElement) every time disableRemotePlayback() is used. I found it to be more factorized like that, do you prefer the other way and repeat the condition?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Or maybe I could rename it so it is more clear that it could disable it or not depending of the type of mediaSource

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.

2 participants