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

MediaSource in Worker #175

Open
DanielBaulig opened this issue Dec 15, 2016 · 97 comments
Open

MediaSource in Worker #175

DanielBaulig opened this issue Dec 15, 2016 · 97 comments
Assignees
Labels
feature request needs follow-up TPAC-2022-discussion Marked for discussion at TPAC 2022 Media WG meeting Sep 16
Milestone

Comments

@DanielBaulig
Copy link

The Videos team at Facebook has a growing need to move calls to Media Source Extensions off of the main thread and into a Worker. While most parts of your off-the-shelve streaming video player can be implemented in a Worker (fetching and parsing of the manifest as well as selecting and fetching of segments) the calls to and interactions with the Media Source Extensions API (e.g. SourceBuffer.prototype.appendBuffer, SourceBuffer.prototype.remove, etc) remain a bottleneck and have to happen on the main browser rendering thread.

On a sizable and complex web site large blocks of JS execution can regularly block the main thread making videos slow to start playing and causing lots of rebuffering, especially in live videos where you can only buffer ahead very little data. To ensure great web video performance in the long run, even as web apps continue to grow in size and complexity, we believe we need to allow video players to move into Workers and off of the main thread.

We would like to propose this change to the working group and involve other API users as well as implementors in the discussion.

@bmaurer
Copy link

bmaurer commented Dec 15, 2016

#14 also seems relevant here -- based on my reading of that bug it would help with part of this problem (once you fetch a segment you'd pass a stream to that audio to MediaSource and would bypass the main thread, or even a worker thread in terms of getting that data to where it needs to go).

But that still leaves the issue of fetching a manifest and initiating a request for a segment

@jyavenard
Copy link
Member

the calls to and interactions with the Media Source Extensions API (e.g. SourceBuffer.prototype.appendBuffer, SourceBuffer.prototype.remove, etc) remain a bottleneck and have to happen on the main browser rendering thread.

That it's a bottleneck would be mostly a user agent implementation issue.
Those APIs are designed to be asynchronous, they should take no time at all and not block the main thread.
With current Firefox, running those two operations in a worker would make little (or no) performance difference, they are in effect running internally in a worker.

I wish issue #100 progressed further, it would certainly facilitate handling those operations.

@bmaurer
Copy link

bmaurer commented Dec 16, 2016

The issue here isn't the cost of video on the main thread. The issue is that if the main thread is busy with other work (say the javascript needed to render a page) that it can not be responsive to input from the network. This means that the video will be slower to buffer even though the client has been able to get the video over the network.

The goal is for the video loading code to be isolated on a worker thread where it can operate in real time without the risk of latency induced by work on the main thread.

@zhaoz
Copy link

zhaoz commented Jan 10, 2017

We are seeing the same issue on YouTube and I'd like to add our voice to support a solution here as well. Moving append buffer off the main thread would greatly simplify the juggling we need to do to prioritize video playback.

@bmaurer
Copy link

bmaurer commented Jan 11, 2017

It's great to see that youtube has the same take on this issue. Would it be worth taking the next step here and drafting out what a spec change would look like? I think we can model this on the offscreen canvas api (https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/)

var canvas = document.getElementById('myCanvas');
var offscreen = canvas.transferControlToOffscreen();
var worker = new Worker('worker.js');
worker.postMessage({ canvas: offscreen }, [offscreen]);

Essentially MediaSource would offer an API which would pass control of the media source APIs to a worker thread. Any APIs that MediaSource offers (eg to add source buffers) would only be callable from the worker.

MediaSource is a fairly complex API with a number of events / methods. It'd be great to get some feedback from @zhaoz, @DanielBaulig as well as folks who work on browsers and this spec to comment on what kind of threading issues might come up with this API.

@DanielBaulig
Copy link
Author

The main limitation with transferring MediaSource object that I can currently see is that in general most video player implementations heavily depend on certain video node attribute for determining which video segments to fetch and play. These are as far as I can tell primarily video.currentTime, video.paused and video.buffered.
The main thread will need to regularly update the worker with the current values of these for most video player implementations to be able to operate correctly.

However, the API itself could have support for this: the worker could get copies of these values on every event loop exposed. This exposure could happen as part of the transferred MediaSource object, e.g. on a bag of exposed values or directly on the object:

onmessage = function(message) {
  if (message.mediaSource.mediaElementState.paused) {
    // don't do anything while the video is paused
    return;
  }
};

Another problem may be that the main thread indirectly retains a reference to the MediaSource as an object URL on the videos src attribute. I am not sure how this will complicate the safe usage of object URLs.

@bmaurer
Copy link

bmaurer commented Jan 12, 2017

That makes total sense. It does seem like the MediaSource API should be responsible for relaying that information -- accessing it directly from the video element seems like it violates layering and would make the threading far more difficult here.

One other thing we should think about -- maybe this is a totally separate issue -- I worry about the latency of starting the worker, downloading the necessary JS, etc. On Facebook we've found that the amount of JS necessary to have the logic for streaming the video can be pretty high. I wonder if there's a way to allow the server to list the URLs necessary to start streaming so that they can be fetched and inserted into the buffer while the more advanced control starts up.

@DanielBaulig
Copy link
Author

One other thing we should think about -- maybe this is a totally separate issue -- I worry about the latency of starting the worker, downloading the necessary JS, etc. On Facebook we've found that the amount of JS necessary to have the logic for streaming the video can be pretty high. I wonder if there's a way to allow the server to list the URLs necessary to start streaming so that they can be fetched and inserted into the buffer while the more advanced control starts up.

I don't think there's anything preventing video player implementations from doing something like this currently. That said, in the context of a transferable MediaSource, this becomes a little harder. This could potentially mean creating a MediaSource object and several sourceBuffers on the main thread, appending data to the sourceBuffers and only later transferring ownership to the Worker. This transfer won't be simple anymore though since there's a complex mix of objects and possibly tasks that has to be dealt with.

@jyavenard
Copy link
Member

One of the issue in dealing with a sourcebuffer in a worker thread, is how, currently, the source buffer notifies that the current operation has completed: through events fired on the attached media element and which is only ever accessed on the main thread.

So if your main thread is busy, no update/updateend event and you're back to the issue of not being able to keep up with your source buffer.

This problem could be easily worked around if rather than relying on events such as update/updateend to know when you can feed new data to the source buffer we used Promises.
I opened an issue a while back to implement this:
#100

The beauty with SourceBuffer::appendBuffer and SourceBuffer::remove with returning Promises is that it would be fully backward compatible. Once the appendBuffer operation has completed, resolve the Promise and queue update/updateend
Up to the player to use one mechanism or the other, never both.

Making a SourceBuffer usable on a worker thread wouldn't be a too complicated task (famous last words) in gecko, the architecture is already asynchronous and thread-safe.
The interaction with the media element would be the issue.

But if we limit the interaction to the source buffer to appendBuffer and remove operations, and checking of the buffered range to be performed on the source buffers alone, and we use Promises then it should be straight forward.

@wolenetz
Copy link
Member

wolenetz commented May 4, 2017

@#175 (comment), 'updateend' is fired on the SourceBuffer , not HTMLMediaElement. However, readyState transitions (and consequent events like 'loadedmetadata') would occur on the media element on the main thread.

I'm less clear that Promises are required for MSE-on-SW, though I'm not opposed (I just don't want to tangle the two features).

@wolenetz
Copy link
Member

wolenetz commented May 4, 2017

Here's a summary of this issue so far, from my understanding. I have a set of questions, below, for which web author input would be greatly appreciated.

Proposals in [2] and [3] help to limit the scope of this to be specific to just MSE, and not require exposing all of HTMLMediaElement API also to Service Worker (SW):

[2] Proposes that the MediaSource API be made “transferrable” to a SW
[3] Adds that major HTMLMediaElement attributes necessary for MSE API usage be periodically copied from the main thread to SW (perhaps as part of the transferred MediaSource object).

[1] #175
[2] #175 (comment)
[3] #175 (comment)

Questions:

  • Should the “transfer” be allowed on a MediaSource object which has already had SourceBuffers added to it? (This might allow for initial buffering to occur on main thread on page load, while the SW context is still spinning up.) (I’m not clear this will help so much in practice, as some web players already experience high time to first frame due to other activities contending on the main thread immediately on page load.)
  • Is there potential “safe usage of Object URLs” problem with transferring the MediaSource context to a SW? (I would defer to web platform security experts. I suspect that a set of reasonable restrictions/checks on the transfer may be needed. Any suggestions?)
  • What portion of the MediaSource and SourceBuffer API need to be transferred?
  • What portion of the HTMLMediaElement state need to be periodically copied into the transferred MediaSource’s SW context?
  • Precisely when should such state be copied?
  • Are any HTMLMediaElement events needed in the SW context? (This would increase complexity; I’m not certain any are needed in SW context, since the web app could forward these -- though with consequent potentially high latency -- into the SW context itself.)
  • Once transferred to SW, would the original MediaSource be restricted from access from any other context?
  • I assume the HTMLMediaElement itself must provide continued access; though would queries of it like “buffered”, which MSE extends, need to round-trip into the SW context?

-- edit: substitute "Worker" for "Service Worker" in this post, please. I had conflated them.

@DanielBaulig
Copy link
Author

DanielBaulig commented May 5, 2017

Am I assuming correctly that you are using the term Service Worker and the general Worker API interchangeably?

I'll try to answer most of the questions for which I believe I have enough context:

Should the “transfer” be allowed on a MediaSource object which has already had SourceBuffers added to it? (This might allow for initial buffering to occur on main thread on page load, while the SW context is still spinning up.) (I’m not clear this will help so much in practice, as some web players already experience high time to first frame due to other activities contending on the main thread immediately on page load.)

This is probably not necessary. The sourceopen event takes some time to fire and the application probably needs time to load data to append to the source buffers too. If those steps take significantly less time than spinning up the Worker then there may be some room for optimization, but I believe that this is likely better done by improving Worker startup time, than introducing bloat here. This obviously assumes that we do not have to wait for the "sourceopen" event to fire before we can transfer the MediaSource object.

Is there potential “safe usage of Object URLs” problem with transferring the MediaSource context to a SW? (I would defer to web platform security experts. I suspect that a set of reasonable restrictions/checks on the transfer may be needed. Any suggestions?)

I am not sure I can answer this question.

What portion of the MediaSource and SourceBuffer API need to be transferred?

We've spent some time internally thinking about this and we came to the conclusion that the entirety of the SourceBuffer API is probably the minimally viable subset of the API for the application.

Having the MediaSource object itself available is preferred but not necessarily required. We believe though due to the amount of dependencies between the MediaSource object and it's SourceBuffer objects, that transferring the MediaSource object is likely the easier approach from a spec and implementation perspective.

We'd love to hear some thoughts from implementors on this though.

What portion of the HTMLMediaElement state need to be periodically copied into the transferred MediaSource’s SW context?

Are any HTMLMediaElement events needed in the SW context? (This would increase complexity; I’m not certain any are needed in SW context, since the web app could forward these -- though with consequent potentially high latency -- into the SW context itself.)

The Worker would generally require access to information that is helpful in making decisions on how much, how fast and what kind of data to buffer. Generally this could be the current playhead (currentTime), the current state of the video buffer (buffered attribute) and current payback rate (playbackRate), if audio is audible (muted and volume) and probably more.
The exact information here however is highly dependent on the details and sophistication of the application and probably highly vary from application to application. Note also, that a small delay in updating the Worker with this information should not lead to any significant problems for the application. In fact, there are plenty of applications and scenarios conceivable in which no state synchronization at all would be required. I think generally the same is true for any HTMLMediaElement events.

For those reasons and to make the specification and implementation process easier we would probably suggest to leave this synchronization completely up to the application. The application can use postMessage to update any necessary state in the Worker as required.

Once transferred to SW, would the original MediaSource be restricted from access from any other context?

I think that is the current understanding.

I assume the HTMLMediaElement itself must provide continued access; though would queries of it like “buffered”, which MSE extends, need to round-trip into the SW context?

This seems to be more of an implementation / specification related question that I am not entirely sure I am able to give feedback on. My understanding here however is that the buffered attribute both for sourceBuffer as well as the video node already need information from the (already) asynchronous and in a different thread running process of media decoding.

@wolenetz
Copy link
Member

wolenetz commented May 8, 2017

Thanks for your answers - those do help describe the possible feature scope more precisely. w.r.t.:

Am I assuming correctly that you are using the term Service Worker and the general Worker API interchangeably?

You're indeed correct - I had mistakenly constrained the scope too far :). Unless the general Worker API is too broad, let's target it, not just Service Workers.

@wolenetz
Copy link
Member

@#175 (comment):

My understanding here however is that the buffered attribute both for sourceBuffer as well as the video node already need information from the (already) asynchronous and in a different thread running process of media decoding.

Decoding itself doesn't impact buffered ranges (unless there's a decode error and transition of MediaSource readyState to closed.) Rather, operations on the MSE API itself can change the buffered ranges. What I was trying to get at is: what are the potentially required synchronization points between the HTMLMediaElement attached by a transferred MSE worker context? For example:

  • HTMLMediaElement.buffered and duration: If an app synchronously queries the 'buffered' attribute of such an HTMLMediaElement, yet the MSE in worker context is in the process of, or perhaps has recently completed, a SourceBuffer appendBuffer(), SourceBuffer remove(), SourceBuffer mode or timestampOffset change when previously 'ended', MediaSource endOfStream(), or MediaSource set duration operation, is there some guarantee of synchronization of the result of such operation that needs to be handled? What should such a guarantee look like? Note that actual playback/decode doesn't factor into this (buffered time range updates due to appendBuffer()/remove()/duration setting don't require actual decode). I assume there needs to be some specified synchronization of such results; in non-worker/current case, if the SourceBuffer.updating attribute is false across all SourceBuffers in the attached MediaSource, then the buffered range query on the parent media element should be stable and correct. Is some similar guarantee required in the worker case?

  • HTMLMediaElement.seekable and set/clearLiveSeekableRanges (also involves HTMLMediaElement.buffered state): ditto: should there be some guarantee of synchronization with the worker before a query of seekable can be satisfied?

  • Worker MediaSource.buffered (potential new API method): Note that the worker context can itself inspect and intersect manually the SourceBuffer buffered ranges to mimic what the parent element's logic would do. Should the transferred MSE API provide such copy of the parent media element's logic that can be processed without synchronizing state with the parent media element?

@bmaurer
Copy link

bmaurer commented Jun 27, 2017

These are great questions. I think my intuition is that generally the worker thread which holds the MSE will be communicating with the main thread, eg via postMessage. I think it would make sense to enforce logical causality. For example, if you call appendBuffer, then send a message to the main thread the result of that appendBuffer should be observable when processing the send message.

I agree that MediaSource.buffered probably makes sense -- there's no need to query the main thread for this information.

@wolenetz
Copy link
Member

For example, if you call appendBuffer, then send a message to the main thread the result of that appendBuffer should be observable when processing the send message.

To be clear, I assume you mean more like "if you call appendBuffer, and upon later receiving updateend you send a message to the main thread, the result of the appendBuffer should be visible on the main thread when processing the receipt of that message." Please correct me if I misunderstand :)

@wolenetz
Copy link
Member

Also, does it make sense to use such a transferred MSE API from a Service Worker context (I don't think so, because such a context is independent of a web page, and therefore from a DOM containing a media element). ISTM, this makes sense from a web worker context, not from SW context.

@bmaurer
Copy link

bmaurer commented Jun 27, 2017

To be clear, I assume you mean more like "if you call appendBuffer, and upon later receiving updateend you send a message to the main thread, the result of the appendBuffer should be visible on the main thread when processing the receipt of that message." Please correct me if I misunderstand :)

yep, exactly.

Also, does it make sense to use such a transferred MSE API from a Service Worker context (I don't think so, because such a context is independent of a web page, and therefore from a DOM containing a media element). ISTM, this makes sense from a web worker context, not from SW context.

By worker I meant web worker here

@DanielBaulig
Copy link
Author

I agree with what @bmaurer said: maintaining logical causality with postMessage probably makes sense.

If we are considering replicating the buffered HTMLMediaElement extension on MediaSource - which I totally think makes sense -, we should probably do the same thing for seekable.

@wolenetz
Copy link
Member

Thanks for your responses to my questions. Here's my newbie-to-workers question: can a Worker do a fetch that is intercepted by a Service Worker, thereby enabling a combination of offline MSE-in-Worker being fed by data provided by the Service Worker? Where are known gaps in spec or implementation to accomplish such a scenario (other than, of course, this issue's MSE-in-Worker discussion :) )?

@kentuckyfriedtakahe
Copy link

I'm with @jyavenard thinking that adding #100 while workerising SourceBuffer would be worthwhile. It may be timely because the worker codepath may end up being a fork of the non-worker path. I'd like to hear from @bmaurer and @zhaoz about whether this will make the player implementation simpler or better.

@bakulf
Copy link

bakulf commented Sep 7, 2017

I would like to share my point of view about the transferring of MediaSource and SourceBuffer objects to workers. If I have understood the spec correctly, a normal use of a MediaSource is via HTMLMediaElement.src = URL.createObjectURL(MS). The output of URL.createObjectURL() is a DOMString, fully cloneable via postMessage().

Would be probably cleaner to expose MediaSource and SourceBuffer constructors to workers.
A worker can create a MediaSource and SourceBuffer(s) then, simply send a blob URL to the window: worker.onmessage = e => { mediaElement.src = e.data; }

The change I propose is mark MediaSource interface in this way:

[Constructor, Exposed=(Window,Worker)]
interface MediaSource {...

same for SourceBuffer.

Note that SourceBuffer supports the appending of ArrayBuffer and ArrayBufferView. Both are already transferable to workers.
Another important point, maybe the most important, so far, EventTargets are not transferable to workers because EventHandler cannot be handled correctly when the object is transferred.

@alastor0325
Copy link

Agree with comment, it would be easy if we restrict the media source and source buffer could only be used in one thread all the time and disallow them being transferrable.

If they’re transferable, how should the behavior of event handlers be defined? It seems a difficult problem, and the spec doesn't mention anything about it.

eg.
If I transfer an media source before its “onsourceopen” be called, which thread the event should be dispatched?
If the source buffer can also be transferred, whether we can transfer multiple source buffers to multiple workers?
…e.t.c

If what I understand it correctly, the usage scenario would like the following.

First, we create both media source and source buffer on the WT, and send the URL back to MT after wrapping media source as URL. After the media source is attached successfully to media element, “sourceopen” would be triggered on WT. Next, MT should send the video URL to WT, then all things could be done independently inside the WT from fetching data to appending data into buffer (and with some new API for getting the status of media element).

Please correct me if I was wrong and welcome to propose other possible scenarios.

@DanielBaulig
Copy link
Author

I see the intentions here and agree that this would make several aspects easier. The only concern I have is that this would add a significant amount of additional startup time.

On top of the time it takes to complete sourceopen, now we may also have to wait for a Worker to spin up and a message to be sent form the Worker to the main thread (which may be busy doing other stuff). All these things will have to happen in sequence and it will require two dedicated time slices on the main thread to complete.

In a scenario with a transferable MediaSource, waiting for sourceopen and the bootstrapping of the Worker can happen in parallel and the Worker will not have to round trip back to the main thread to complete the transaction reducing the main thread time slices require to one.

The biggest risks associated with moving MSE into Workers from a product perspective is probably the startup latency. The solution as suggested in #175 (comment) increases this risk significantly.

@alastor0325
Copy link

This might be a stupid question, why couldn't we bootstrap worker in advance, before starting playing video?

Can we bootstrap worker in the beginning? and then use postMessage() to notify worker to return the URL of media source when we would start MSE soon?

In a scenario with a transferable MediaSource, waiting for sourceopen and the bootstrapping of the Worker can happen in parallel and the Worker will not have to round trip back to the main thread to complete the transaction reducing the main thread time slices require to one.

If we can start worker in advance, the following might be the possible use case. In this case, MT only need one time slice to handle the message sent from WT.

worker.postMessage(url /* used for fetching on WT */);
worker.onMessage = e => { mediaElement.src = e.data; };

@alastor0325
Copy link

The main problem to make media source transferable is "how to handle the event handler of transferable object", because it's undefined behavior.

I think this topic is out of the media scope, and I would like to know how strong intention we want to go with this direction? If do so, we need to discuss and modify with worker's working group and make sure the behavior can be well defined.

However, it might be take a long time, and @bakulf, who is our worker expert, also suggest don't try to transfer an object with event handler.

@DanielBaulig
Copy link
Author

@alastor0325 We can only bootstrap the Worker ahead of time, if we have an opportunity to do so. If the first thing we are doing on a blank page load is to create and assign a MediaSource, there's no way for us to bootstrap a Worker ahead of time.

In addition to that, creating the object URL on the Worker thread will require us to touch the main thread twice. Consider the following example:

    /* main thread code */
    // first main thread execution
    const video = document.querySelector('video');
    const worker = new Worker('mse_worker.js');
    worker.addEventListener('message', (event) => {
      // second main thread execution
      video.src = event.data;
    });

But if we can create the MediaSource on the main thread, we only need one time slice on the main thread:

    /* main thread code */
    // first main thread execution
    const video = document.querySelector('video');
    const worker = new Worker('mse_worker.js');
    const ms = new MediaSource();
    const url = window.URL.createObjectURL(ms);
    video.src = url;
    worker.postMessage(ms, [ ms ]);

We don't need a second time slice on the main thread before we can start loading video.

Talking to some folks at Mozilla, they wanted to look into why the sourceopen event even is required/asynchronous in the first place.

Another option could be to require transferring of the MediaSource to the Worker before the URL assignment happens. In that case any events firing on the MediaSource could be deterministically scheduled to execute on the Worker instead of the main thread.

Lastly, I could imagine something TransferableMediaSource, that internally does all the steps MediaSource would do upon creation, but doesn't expose any external API interface except for a getMediaSource() method. After the method was called, the TransferableMediaSource looses it's ability to be transferred.
This could be created on the main thread, assigned to the video node's src through an Object URL and then transferred to the Worker, where the Worker would call getMediaSource to obtain a reference on the "true", underlying MediaSource.

@jyavenard
Copy link
Member

Why not only having the source buffers in a worker?
They really are the only ones we care about when it comes to feeding data fast enough.

@alastor0325
Copy link

@DanielBaulig I think it's a good idea to have "TransferableMediaSource", it could fix the problem about the event handler and also it would only need one time slice on the main thread.

In addition, you've mention we would need something like "mediaSource.mediaElementState" which can be reflected the status of media element. Maybe we could start to define the specific attributes which we need.

@DanielBaulig
Copy link
Author

In addition, you've mention we would need something like "mediaSource.mediaElementState" which can be reflected the status of media element. Maybe we could start to define the specific attributes which we need.

For the most part I think it's sufficient to provide these media element states via postMessage to the worker at a regular rate.

Unless the platform can significantly improve update performance or maybe even provide thread-safe, but otherwise real-time variations of these, I don't think they are of highest priority.

The most important states/properties are probably currentTime and error. Virtually any media related property can be useful though to optimize certain conditions, prevent over- or underfetching and allow for a more consistent player and data fetching state (e.g. buffered, playbackRate, paused, seeking, ended, readyState, duration).

Why not only having the source buffers in a worker?
They really are the only ones we care about when it comes to feeding data fast enough.

Generally this is correct. I remember that this was brought up before as an option, but I'm not entirely sure what the arguments against it were. There's definitely the limitation of having to touch the main thread twice though (you have to wait for 'sourceopen' to fire before you can create SourceBuffer instances), but I believe the major concern was about how to model the APIs around this, since SourceBuffers are exposed on several MediaSource APIs and all of them would become invalid when the SourceBuffer is transferred into a Worker.

@johnBartos
Copy link

LGTM from our app's perspective, as long as typeof MediaSourceHandle === function on the main thread. We'd like some way to check if MSEIW is supported before we set up our worker.

@wolenetz
Copy link
Member

wolenetz commented Sep 9, 2022

@#175 (comment) thanks for your input. We're currently considering two options: Change from exception to null value for the 'handle' attribute when accessed on a main thread MediaSource, or change visibility of that handle getter to only be visible on the dedicated worker context (for now at least). I presume we'll disallow exception even in the latter case.

Either way, it looks like, on main thread (or on worker thread), MediaSource.canConstructInDedicatedWorker === true will remain the overall feature detection for MSE-in-Workers, and, when it's true, both dedicated worker and main thread contexts should have typeof MediaSourceHandle === 'function' on conforming implementations.

@wolenetz wolenetz added the TPAC-2022-discussion Marked for discussion at TPAC 2022 Media WG meeting Sep 16 label Sep 16, 2022
@wolenetz
Copy link
Member

From discussion during Media Working Group meeting at TPAC 2022 today, both @jernoble and @dontcallmedom also supported the visibility restriction option for the handle getter. I presented both options (null with custom spec replacement for [SameObject], or just exposed=dedicatedworker -- neither can throw exception).

I'll update (or just abandon/replace) the PR #316 to instead do visibility restriction of that getter, without exception throwing.

wolenetz added a commit that referenced this issue Sep 21, 2022
Removes the MediaSource handle attribute visibility from the main Window
context, leaving it visible only in dedicated worker contexts. Also
removes the conditional throwing of NotSupportedError exceptions on
getting this attribute's value if the implementation doesn't support
that.

Overall, this change is to undo the backwards incompatibility issue
found when older versions of MSE web app libraries enumerated main
thread MediaSource attribute values, hitting exception in the Chromium
feature implementation through milestone 107. This change replaces that
with simpler and safer visibility restriction of this getter to just the
context where it must be supported if the implementation supports
MSE-in-Workers.

Note, this change replaces the alternative fix discussed in
w3c/media-source PR #316.

Reference feature tracking spec issue for MSE-in-Workers w3c/media-source issue #175.
@wolenetz
Copy link
Member

wolenetz commented Oct 3, 2022

In Chrome, the feature has been fixed to behave per #317 and builds of Chrome >= 108.0.5334.0 should include it enabled by default. See also the Chromium feature tracking issue 878133.

mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
Adds a readonly, boolean-valued, static attribute named
`canConstructInDedicatedWorker` to the MediaSource interface.
Currently, this attribute is only visible to web apps if the
RunTimeEnabledFeature "MediaSourceInWorkers" is enabled. When visible,
this attribute always returns true.

The primary goal of having this attribute is to enable web app's main
thread to proactively determine whether or not MSE is supported from a
dedicated worker context *before* deciding whether or not to create or
try using MSE from such a context.

As an initial example of this use case, the existing MSE-in-Workers
web_tests are updated to use this new attribute's existence and value
to fail-fast rather than potentially flakily fail (e.g. previously, the
...worker-terminate test might flakily pass/fail some of its test cases
on implementations lacking MSE-in-Workers support if the test completed
before handling receipt of error message from worker.)

A further test is added to ensure that, if the attribute is missing or
exists but is not `true`, a dedicated worker does not have ability to
construct a MediaSource instance. See also
w3c/media-source#175 for further discussion
which led to this new attribute.

BUG=878133

Change-Id: I697ca6adc5b5dc65d5c5084ff67a541430a9237b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2487834
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: Will Cassella <cassew@google.com>
Cr-Commit-Position: refs/heads/master@{#819564}
GitOrigin-RevId: 27d63ac81be017698d0b799365cd2ef4cbdd8813
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
Adds core MediaSourceHandle interface and modules implementation.
Later changes will enable apps to get a handle from a dedicated worker
MediaSource, post it to the main thread and attach it to an
HTMLMediaElement via the srcObject attribute; they will also include
test updates.

References:
Full prototype CL:
    https://chromium-review.googlesource.com/c/chromium/src/+/3515334
MSE spec issue:
    w3c/media-source#175
MSE spec feature updates switching from worker MSE attachment via
  object URL to attachment via srcObject MediaSourceHandle:
  * w3c/media-source#305
  * further clarifications in discussion at
    w3c/media-source#306 (comment)

BUG=878133

Change-Id: I9a3b47ea02d2755a9860999e245eafc26f864977
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3687146
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012115}
NOKEYCHECK=True
GitOrigin-RevId: 2813392442e5ff5cc8702a743bdd52a1bab82be4
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
Adds ability for apps to get a MediaSourceHandle from a dedicated worker
MediaSource instance, gated by RuntimeEnabledFeature
"MediaSourceInWorkersUsingHandle". Updates the PassKey required for
creation of a concrete MediaSourceAttachmentSupplement to allow that
only from either URLMediaSource::createObjectURL or the new
MediaSource::getHandle method. This specificity is enabled by a new
AttachmentCreationPassKeyProvider type.
Later changes will enable apps to post the handle to the main thread and
attach it to an HTMLMediaElement via the srcObject attribute; they will
also include test updates.

References:
Full prototype CL:
    https://chromium-review.googlesource.com/c/chromium/src/+/3515334
MSE spec issue:
    w3c/media-source#175
MSE spec feature updates switching from worker MSE attachment via
  object URL to attachment via srcObject MediaSourceHandle:
  * w3c/media-source#305
  * further clarifications in discussion at
    w3c/media-source#306 (comment)

crbug.com/506273 is somewhat related, but not fixed by this change (it
refers to directly setting MediaSource on Window context to the media
element's srcObject attribute.) This change sequence is specific to
enabling MSE-in-Worker attachment via srcObject using a handle object.

BUG=878133,506273

Change-Id: Ic61f4cc4193080bdbc39234b98897d9a789778d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3688613
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: Will Cassella <cassew@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012129}
NOKEYCHECK=True
GitOrigin-RevId: 09e5fb1a68416f65ef2255c846b81a46f6aa8e52
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
Adds ability to serialize a MediaSourceHandleImpl, conditionally failing
with DataCloneError if the handle is_serialized() already or if the
handle is_used() (both of those are initialized to be false
in the new instance created during deserialization.)
Later changes will enable apps to attach the handle to a main thread
HTMLMediaElement via the srcObject attribute; they will also include
test updates.

References:
Full prototype CL:
    https://chromium-review.googlesource.com/c/chromium/src/+/3515334
MSE spec issue:
    w3c/media-source#175
MSE spec feature updates switching from worker MSE attachment via
  object URL to attachment via srcObject MediaSourceHandle:
  * w3c/media-source#305
  * further clarifications in discussion at
    w3c/media-source#306 (comment)

BUG=878133

Change-Id: I19cc8a450423964aef78e8e468776e8cd912503a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3688599
Reviewed-by: Will Cassella <cassew@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012132}
NOKEYCHECK=True
GitOrigin-RevId: d5d391975da969d6242e5785c68609d6cd15fda3
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
Adds ability to attach a dedicated-worker-owned MediaSource to an
HTMLMediaElement using a MediaSourceHandle for that MediaSource instance
that the app has posted over to the main thread and assigned to the
srcObject attribute on the media element. Previously, only a MediaStream
could be set as a srcObject in Chrome. This change adds the relevant
MediaProvider IDL union type and makes it the type of that srcObject
attribute. For historical reasons, the srcObject attribute of an
HTMLMediaElement is implemented in modules as a partial interface; this
change updates that partial interface as well as the media element
implementation to enable the scenario without regressing existing
ability to use MediaStream as media element's srcObject.

The attachment of the worker MediaSource using the handle does not
involve lookup into a URL registry; rather, an internal blob URL is
built into the handle when it was retrieved from the MediaSource and
that URL is used to satisfy existing media element load safety checks as
well as provide the underlying WebMediaPlayer a URL that it can use when
logging to devtools.

Later changes will add further test updates and remove the previous
ability to attach a worker MediaSource using a registered object URL.

References:
Full prototype CL:
    https://chromium-review.googlesource.com/c/chromium/src/+/3515334
MSE spec issue:
    w3c/media-source#175
MSE spec feature updates switching from worker MSE attachment via
  object URL to attachment via srcObject MediaSourceHandle:
  * w3c/media-source#305
  * further clarifications in discussion at
    w3c/media-source#306 (comment)

crbug.com/506273 is somewhat related, but not fixed by this change (it
refers to directly setting MediaSource on Window context to the media
element's srcObject attribute.) This change sequence is specific to
enabling MSE-in-Worker attachment via srcObject using a handle object.

BUG=878133,506273

Change-Id: I86cddd87bafae1c7cbae9e94ea4614418067012f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3688740
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Elad Alon <eladalon@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012202}
NOKEYCHECK=True
GitOrigin-RevId: 756af69b67c9e40e0a0c92cb6c0a911c96ea6835
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
If the MediaSourceInWorkersUsingHandle feature is enabled, this change
prevents successful ability of obtaining an objectURL that would succeed
in loading a worker-owned MediaSource.

It changes the wpt tests to use handle for attachment and verifies
expected new behavior of getHandle and that worker objectURL attachment
fails (these tests run on experimental builds of Chromium with
currently-experimental MediaSourceInWorkersUsingHandle feature enabled,
just like the currently-experimental MediaSourceInWorkers feature.)

References:
Full prototype CL for the parts 1-4 that have already landed:
    https://chromium-review.googlesource.com/c/chromium/src/+/3515334
MSE spec issue:
    w3c/media-source#175
MSE spec feature updates switching from worker MSE attachment via
  object URL to attachment via srcObject MediaSourceHandle:
  * w3c/media-source#305
  * further clarifications in discussion at
    w3c/media-source#306 (comment)

BUG=878133

Change-Id: I60ddca79ee0f95c87b6d84e4f44ad9c283f359a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3698231
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Auto-Submit: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: Will Cassella <cassew@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012712}
NOKEYCHECK=True
GitOrigin-RevId: 6315549b8c2ece3dbbf3062c1a87347589a5e115
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
…bjectURL"

This reverts commit 6315549b8c2ece3dbbf3062c1a87347589a5e115.

Reason for revert: This is causing failures on the WebKit Linux Leak builder
i.e. https://ci.chromium.org/ui/p/chromium/builders/ci/WebKit%20Linux%20Leak/39394/overview

Original change's description:
> MSE-in-Workers: srcObject part 5: Conditionally fail worker objectURL
>
> If the MediaSourceInWorkersUsingHandle feature is enabled, this change
> prevents successful ability of obtaining an objectURL that would succeed
> in loading a worker-owned MediaSource.
>
> It changes the wpt tests to use handle for attachment and verifies
> expected new behavior of getHandle and that worker objectURL attachment
> fails (these tests run on experimental builds of Chromium with
> currently-experimental MediaSourceInWorkersUsingHandle feature enabled,
> just like the currently-experimental MediaSourceInWorkers feature.)
>
> References:
> Full prototype CL for the parts 1-4 that have already landed:
>     https://chromium-review.googlesource.com/c/chromium/src/+/3515334
> MSE spec issue:
>     w3c/media-source#175
> MSE spec feature updates switching from worker MSE attachment via
>   object URL to attachment via srcObject MediaSourceHandle:
>   * w3c/media-source#305
>   * further clarifications in discussion at
>     w3c/media-source#306 (comment)
>
> BUG=878133
>
> Change-Id: I60ddca79ee0f95c87b6d84e4f44ad9c283f359a3
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3698231
> Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
> Auto-Submit: Matthew Wolenetz <wolenetz@chromium.org>
> Reviewed-by: Will Cassella <cassew@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1012712}

Bug: 878133
Change-Id: I1e405ae1de146d1f3183592b00a43bd3c38d849d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3695890
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Nidhi Jaju <nidhijaju@chromium.org>
Owners-Override: Nidhi Jaju <nidhijaju@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012823}
NOKEYCHECK=True
GitOrigin-RevId: f438823c5527e6499b8dedb4eef7bb8ed43f4371
mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
…bjectURL

With the underlying leak fixed by
https://chromium-review.googlesource.com/c/chromium/src/+/3704191, this
change can be relanded now.

Previous revert:
> Revert "MSE-in-Workers: srcObject part 5: Conditionally fail worker objectURL"
>
> This reverts commit 6315549b8c2ece3dbbf3062c1a87347589a5e115.
>
> Reason for revert: This is causing failures on the WebKit Linux Leak builder
> i.e. https://ci.chromium.org/ui/p/chromium/builders/ci/WebKit%20Linux%20Leak/39394/overview
>
> Original change's description:
> > MSE-in-Workers: srcObject part 5: Conditionally fail worker objectURL
> >
> > If the MediaSourceInWorkersUsingHandle feature is enabled, this change
> > prevents successful ability of obtaining an objectURL that would succeed
> > in loading a worker-owned MediaSource.
> >
> > It changes the wpt tests to use handle for attachment and verifies
> > expected new behavior of getHandle and that worker objectURL attachment
> > fails (these tests run on experimental builds of Chromium with
> > currently-experimental MediaSourceInWorkersUsingHandle feature enabled,
> > just like the currently-experimental MediaSourceInWorkers feature.)
> >
> > References:
> > Full prototype CL for the parts 1-4 that have already landed:
> >     https://chromium-review.googlesource.com/c/chromium/src/+/3515334
> > MSE spec issue:
> >     w3c/media-source#175
> > MSE spec feature updates switching from worker MSE attachment via
> >   object URL to attachment via srcObject MediaSourceHandle:
> >   * w3c/media-source#305
> >   * further clarifications in discussion at
> >     w3c/media-source#306 (comment)
> >
> > BUG=878133
> >
> > Change-Id: I60ddca79ee0f95c87b6d84e4f44ad9c283f359a3
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3698231
> > Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
> > Auto-Submit: Matthew Wolenetz <wolenetz@chromium.org>
> > Reviewed-by: Will Cassella <cassew@chromium.org>
> > Cr-Commit-Position: refs/heads/main@{#1012712}
>
> Bug: 878133
> Change-Id: I1e405ae1de146d1f3183592b00a43bd3c38d849d
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3695890
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Commit-Queue: Nidhi Jaju <nidhijaju@chromium.org>
> Owners-Override: Nidhi Jaju <nidhijaju@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1012823}

Bug: 878133
Change-Id: I56e4ecd4d8b58d9d58ed3c575b0fb52f596b6fae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3708465
Reviewed-by: Will Cassella <cassew@chromium.org>
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1014755}
NOKEYCHECK=True
GitOrigin-RevId: 39878163d3ff90baabd342ad784671a4b54262ed
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 8, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 8, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 8, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 8, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 8, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 8, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Feb 9, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
@mwatson2 mwatson2 modified the milestones: V3, V2 Mar 14, 2023
peaBerberian added a commit to canalplus/rx-player that referenced this issue May 17, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Jul 27, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
peaBerberian added a commit to canalplus/rx-player that referenced this issue Aug 7, 2023
This commit adds the `declareInitSegment` and `freeInitSegment` methods
to the RxPlayer's SegmentBuffer abstractions (which is the part of the
code handling the operations on SourceBuffers, such as pushing media and
init segments).

The short term idea is to improve the handling of initialization
segments in the SegmentBuffer.
Until now, each pushed media segment lead to a check that the
initialization segment it relies on is the same than the last one
pushed. To be able to perform that check, a caller need to communicate
again the initialization segment's data each time a chunk is pushed to
the buffer.

This check can be performed efficiently in most cases because we first
check init segment's data equality by reference, which, by pure luck,
should be equal in most cases in the current code. In cases where it
isn't the same reference however, it can lead to a byte-per-byte check,
which should not be an issue in terms of performance in most cases, but
is still an ugly specificity which could be handled in a more optimal
and understandable way.

This commit now allows the definition of a `initSegmentUniqueId`, an
identifier for initialization segments, on SegmentBuffers.
Any pushed segments can then refer to its associated init segment by
indicating which `initSegmentUniqueId` it is linked to.

The SegmentBuffer will ensure behind the hood that the right
initialization segment is pushed before pushing media segments, like
before, excepted that this can now be done just by comparing this
`initSegmentUniqueId` - it also means that the caller is no more
required to keep in memory the data of the loaded initialization
segment, the `SegmentBuffer` is already doing that.
Previously, the initialization segment's data was kept by the
`RepresentationStream`, the abstraction choosing which segments
to load (which is part of the reasons why the reference mostly never
changed).

The declaration and "freeing" of init segment is done through a
`declareInitSegment`/`freeInitSegment` pair of methods on a
`SegmentBuffer`. This sadly means that memory freeing for the
initialization segment is now manual, whereas we just relied on garbage
collection when the initialization segment was directly used.

---

Though mostly, the long term benefit is to implement the hybrid-worker
mode that we plan to have in the future, where buffering is performed in
a WebWorker (thus improving concurrence with an application, with the
goal of preventing both UI stuttering due to heavy player tasks and
rebuffering due to heavy UI tasks).

In the currently-planned long term worker features we would have thus
the following modes:

  - full worker: where both the rebuffering logic and MSE API are called
    in a WebWorker, allowing to avoid UI and media playback blocking
    each other to some extent

    This however requires the
    [MSE-in-Worker](w3c/media-source#175)
    feature to be available in the browser AND it also implies a more
    complex API, notably some callbacks (`manifestLoader`,
    `segmentLoader` and `representationFilter`) which will have to be
    updated.

  - hybrid mode: The buffering logic is mainly performed in a WebWorker
    but MSE API are still in the main thread. This allows e.g. to not
    fight for CPU with the UI to know which segments to download and to
    avoid blocking the UI when the Manifest is being parsed.

    Though the UI blocking could still mean that a loaded segment is
    waiting to be pushed in that mode.

    Because here MSE APIs may have to be called through `postMessage`-style
    message passing, the previous logic of communicating each time the
    same initialization segment each time a segment was pushed, with no
    mean to just move that data (in JavaScript linguo, to "transfer" it)
    was considerably worst than before.
    Relying on a short identifier instead seems a better solution here.

  - normal mode: The current mode where everything stays in main thread.

However it should be noted that all of this long term objective is still
in an higly experimental phase, and the gains are only theoretical for
now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request needs follow-up TPAC-2022-discussion Marked for discussion at TPAC 2022 Media WG meeting Sep 16
Projects
None yet
Development

No branches or pull requests