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

Refine srcObject's MediaSourceHandle behavior #306

Merged
merged 9 commits into from
Jul 26, 2022
362 changes: 255 additions & 107 deletions media-source-respec.html
Original file line number Diff line number Diff line change
@@ -283,6 +283,13 @@ <h2><dfn>MediaSource</dfn> Object</h2>
<a href="#htmlmediaelement-extensions">HTMLMediaElement Extensions</a> to modify
{{HTMLMediaElement}}.{{HTMLMediaElement/seekable}} behavior.</p>

<p>Each {{MediaSource}} object has a <dfn data-dfn-for="MediaSource">[[\has ever been attached]]</dfn> internal
slot that stores a {{boolean}}. It is initialized to false when the {{MediaSource}} object is created, and is
set true in the extended {{HTMLMediaElement}}'s [=resource fetch algorithm=] as described in the [=attaching to
a media element=] algorithm. The extended [=resource fetch algorithm=] uses this internal slot to conditionally
fail attachment of a {{MediaSource}} using a {{MediaSourceHandle}} set on a {{HTMLMediaElement}}'s
{{HTMLMediaElement/srcObject}} attribute.</p>

<div><pre class="idl">enum ReadyState {
"closed",
"open",
@@ -315,25 +322,50 @@ <h2><dfn>MediaSource</dfn> Object</h2>
<pre class="idl">[Exposed=(Window,DedicatedWorker)]
interface MediaSource : EventTarget {
constructor();
readonly attribute SourceBufferList sourceBuffers;
readonly attribute SourceBufferList activeSourceBuffers;
readonly attribute ReadyState readyState;
attribute unrestricted double duration;
attribute EventHandler onsourceopen;
attribute EventHandler onsourceended;
attribute EventHandler onsourceclose;
static readonly attribute boolean canConstructInDedicatedWorker;
SourceBuffer addSourceBuffer (DOMString type);
undefined removeSourceBuffer (SourceBuffer sourceBuffer);
undefined endOfStream (optional EndOfStreamError error);
undefined setLiveSeekableRange (double start, double end);
undefined clearLiveSeekableRange ();
MediaSourceHandle getHandle ();
static boolean isTypeSupported (DOMString type);
[SameObject] readonly attribute MediaSourceHandle handle;
readonly attribute SourceBufferList sourceBuffers;
readonly attribute SourceBufferList activeSourceBuffers;
readonly attribute ReadyState readyState;
attribute unrestricted double duration;
attribute EventHandler onsourceopen;
attribute EventHandler onsourceended;
attribute EventHandler onsourceclose;
static readonly attribute boolean canConstructInDedicatedWorker;
SourceBuffer addSourceBuffer (DOMString type);
undefined removeSourceBuffer (SourceBuffer sourceBuffer);
undefined endOfStream (optional EndOfStreamError error);
undefined setLiveSeekableRange (double start, double end);
undefined clearLiveSeekableRange ();
static boolean isTypeSupported (DOMString type);
};</pre>
<section>
<h3>Attributes</h3>
<dl class="attributes" data-dfn-for="MediaSource"><dt><dfn><code>sourceBuffers</code></dfn> of type <span class="idlAttrType"><a>SourceBufferList</a></span>, readonly </dt><dd>
<dl class="attributes" data-dfn-for="MediaSource">

<dt><dfn><code>handle</code></dfn> of type <span class="idlAttrType"><a>MediaSourceHandle</a></span>, [SameObject] readonly</dt><dd>

<p>Contains a handle useful for attachment to an {{HTMLMediaElement}} via {{HTMLMediaElement/srcObject}}.
The handle remains the same object for this {{MediaSource}} object across accesses of this attribute, but it
is distinct for each {{MediaSource}} object.</p>
<p>On getting, run the following steps:</p>
<ol>
<li>If the implementation does not support creating a handle for this {{MediaSource}}, then throw a
{{NotSupportedError}} exception and abort these steps.
<p class="note">Implementations MAY choose to only allow handle creation for {{MediaSource}} objects in a
{{DedicatedWorkerGlobalScope}}, as a minimum requirement for enabling attachment of such a {{MediaSource}}
object to an {{HTMLMediaElement}}.</p>
</li>
<li>If the handle for this {{MediaSource}} object has not yet been created, then run the following steps:
<ol>
<li>Let |created handle:MediaSourceHandle| be the result of creating a new
{{MediaSourceHandle}} object and associated resources, linked internally to this
{{MediaSource}}.</li>
<li>Update the attribute to be |created handle|.</li>
</ol>
<li>Return the {{MediaSourceHandle}} object that is this attribute's value.</li>
</ol>

<dt><dfn><code>sourceBuffers</code></dfn> of type <span class="idlAttrType"><a>SourceBufferList</a></span>, readonly </dt><dd>
Contains the list of <a>SourceBuffer</a> objects associated with this <a>MediaSource</a>. When {{MediaSource/readyState}} equals {{ReadyState/""closed""}} this list will be empty. Once {{MediaSource/readyState}} transitions to {{ReadyState/""open""}} SourceBuffer objects can be added to this list by using {{MediaSource/addSourceBuffer()}}.
</dd><dt><dfn><code>activeSourceBuffers</code></dfn> of type <span class="idlAttrType"><a>SourceBufferList</a></span>, readonly </dt><dd>
<p>Contains the subset of {{MediaSource/sourceBuffers}} that are providing the {{VideoTrack/selected}} video track, the
@@ -639,22 +671,6 @@ <h3>Attributes</h3>
</li></ol>
<div><em>No parameters.</em></div><div><em>Return type: </em>{{undefined}}</div></dd>

<dt><dfn><code>getHandle</code></dfn></dt><dd>
<p>Creates a handle useful for attachment to an {{HTMLMediaElement}} via {{HTMLMediaElement/srcObject}}.</p>
<ol class="method-algorithm">
<li>If the implementation does not support creating a handle for this {{MediaSource}}, then throw a
{{NotSupportedError}} exception and abort these steps.
<p class="note">Implementations MAY choose to only allow handle creation for {{MediaSource}} objects in a
{{DedicatedWorkerGlobalScope}}, as a minimum requirement for enabling attachment of such a {{MediaSource}}
object to an {{HTMLMediaElement}}.</p>
<p class="issue">Consider requiring conforming implementations to let such handle be created on a {{Window}}
{{MediaSource}} object, too?</p>
</li>
<li>Create a new {{MediaSourceHandle}} object and associated resources.</li>
<li>Return the new object.</li>
</ol>
<div><em>No parameters.</em></div><div><em>Return type: </em>{{MediaSourceHandle}}</div></dd>

<dt><dfn><code>isTypeSupported</code></dfn>, static</dt><dd>
<p>Check to see whether the <a>MediaSource</a> is capable of creating <a>SourceBuffer</a> objects for the specified MIME type.</p>

@@ -757,83 +773,134 @@ <h4><dfn>Attaching to a media element</dfn></h4>
{{DedicatedWorkerGlobalScope}} for a {{MediaSource}} constructed in that worker, attempting to use that
[=MediaSource object URL=] to attach to a media element using either the {{HTMLMediaElement/src}}
attribute or the src attribute of a &lt;source&gt; inside a media element MUST fail in the media
element's resource selection aglorithm, as extended below.</p>
element's [=resource fetch algorithm=], as extended below.</p>
<p class="note">Extending the object URL attachment mechanism to worker MediaSource object URLs would
further propagate this idiom that is less preferred versus using srcObject, and would unnecessarily
increase user agent interoperability risk and implementation complexity.</p>
</li>
<li>Attaching a {{MediaSource}} that was constructed in a {{DedicatedWorkerGlobalScope}} can be done by
obtaining a handle from it using {{MediaSource/getHandle}}, transferring that {{MediaSourceHandle}} to the
<li>Attaching a {{MediaSource}} that was constructed in a {{DedicatedWorkerGlobalScope}} can only be done by
obtaining a handle from it using {{MediaSource/handle}}, transferring that {{MediaSourceHandle}} to the
{{Window}} context and assigning it to the media element {{HTMLMediaElement/srcObject}} attribute. For the
purposes of aligning this specification with {{HTMLMediaElement}} resource loading and fetching
algorithms, the underlying {{DedicatedWorkerGlobalScope}} {{MediaSource}} is the MediaSource
object mentioned there, and the {{MediaSourceHandle}} object is the media provider object.
<p class="issue">MediaSourceHandle needs to be added to HTMLMediaElement's MediaProvider IDL typedef and
related text involving media provider objects.</p>
</li>
</ul>

<p>If the <a def-id="resource-fetch-algorithm"></a> was invoked with a media provider object that is a
{{MediaSource}} object, a {{MediaSourceHandle}} object or a URL record whose object is a {{MediaSource}}
object, then let mode be local, skip the first step in the <a def-id="resource-fetch-algorithm"></a>
(which may otherwise set mode to remote) and add the steps and clarifications below to the <a
def-id="Otherwise-mode-is-local"></a> section of the <a def-id="resource-fetch-algorithm"></a>.
<p class="note">The <a def-id="resource-fetch-algorithm"></a>'s first step is expected to eventually align with selecting local mode for URL records whose objects are media provider objects. The intent is that if the HTMLMediaElement's <code>src</code> attribute or selected child <code>&lt;source&gt;</code>'s <code>src</code> attribute is a <code>blob:</code> URL matching a [=MediaSource object URL=] when the respective <code>src</code> attribute was last changed, then that MediaSource object is used as the media provider object and current media resource in the local mode logic in the <a def-id="resource-fetch-algorithm"></a>. This also means that the remote mode logic that includes observance of any preload attribute is skipped when a MediaSource object is attached. Even with that eventual change to [[HTML]], the execution of the following steps at the beginning of the local mode logic is still required when the current media resource is a MediaSource object.</p>
<p class="note">Relative to the action which triggered the media element's resource selection algorithm, these steps are asynchronous. The resource fetch algorithm is run after the task that invoked the resource selection algorithm is allowed to continue and a stable state is reached. Implementations may delay the steps in the "<i>Otherwise</i>" clause, below, until the MediaSource object is ready for use.</p>
<dl class="switch">
<dt>If the media provider object is
a URL record whose object is a {{MediaSource}} that was constructed in a {{DedicatedWorkerGlobalScope}},
such as would occur if attempting to use a [=MediaSource object URL=] from a
{{DedicatedWorkerGlobalScope}} {{MediaSource}}
</dt>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the <a def-id="resource-fetch-algorithm"></a>'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dt>If {{MediaSource/readyState}} is NOT set to {{ReadyState/""closed""}}
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the <a def-id="resource-fetch-algorithm"></a>'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dt>Otherwise</dt>
<dd>
<ol>
<li>Set the media element's <a def-id="delaying-the-load-event-flag"></a> to false.</li>
<li>
<dl class="switch">
<dt>If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}, then setup worker
attachment communication and open the {{MediaSource}}:</dt>
<dd><ol>
<li>Set {{HTMLMediaElement/[[channel with worker]]}} to be a new {{MessageChannel}}.</li>
<li>Set {{HTMLMediaElement/[[port to worker]]}} to the {{MessageChannel/port1}} value of
{{HTMLMediaElement/[[channel with worker]]}}.</li>
<li>Execute [=StructuredSerializeWithTransfer=] with the {{MessageChannel/port2}} of
{{HTMLMediaElement/[[channel with worker]]}} as both the value and the sole member of the |transferList|, and let
the result be |serialized port2:MessagePort|.
<li>[=Queue a task=] on the {{MediaSource}}'s {{DedicatedWorkerGlobalScope}} that will
<ol>
<li>Execute [=StructuredDeserializeWithTransfer=] with |serialized port2| and
{{DedicatedWorkerGlobalScope}}'s [=environment settings object/realm=], and set
{{MediaSource/[[port to main]]}} to be the resulting deserialized clone of the transferred
{{MessageChannel/port2}} value of {{HTMLMediaElement/[[channel with worker]]}}.</li>
<p>If the [=resource fetch algorithm=] was invoked with a media provider object that is a {{MediaSource}}
object, a {{MediaSourceHandle}} object or a URL record whose object is a {{MediaSource}} object, then let mode
be local, skip the first step in the [=resource fetch algorithm=] (which may otherwise set mode to remote)
and continue the execution of the [=resource fetch algorithm=].</p>
<p class="note">The first step of the [=resource fetch algorithm=] is expected to eventually align with
selecting local mode for URL records whose objects are media provider objects. The intent is that if the
HTMLMediaElement's <code>src</code> attribute or selected child <code>&lt;source&gt;</code>'s <code>src</code>
attribute is a <code>blob:</code> URL matching a [=MediaSource object URL=] when the respective
<code>src</code> attribute was last changed, then that MediaSource object is used as the media provider object
and current media resource in the local mode logic in the [=resource fetch algorithm=]. This also
means that the remote mode logic that includes observance of any preload attribute is skipped when a
MediaSource object is attached. Even with that eventual change to [[HTML]], the execution of the following
steps at the beginning of the local mode logic is still required when the current media resource is a
MediaSource object.</p>
<p>At the beginning of the "Otherwise (mode is local)" section of the [=resource fetch algorithm=], execute
the additional steps, below.</p>
<p class="note">Relative to the action which triggered the media element's resource selection algorithm, these
steps are asynchronous. The [=resource fetch algorithm=] is run after the task that invoked the resource
selection algorithm is allowed to continue and a stable state is reached. Implementations may delay the steps
in the "<i>Otherwise</i>" clause, below, until the MediaSource object is ready for use.</p>
<ol>
<li>If the [=resource fetch algorithm=] was invoked with a media provider object that is a {{MediaSource}}
object, a {{MediaSourceHandle}} object or a URL record whose object is a {{MediaSource}} object, then:
<dl class="switch">
<dt>If the media provider object is a URL record whose object is a {{MediaSource}} that was constructed
in a {{DedicatedWorkerGlobalScope}}, such as would occur if attempting to use a [=MediaSource object
URL=] from a {{DedicatedWorkerGlobalScope}} {{MediaSource}}
</dt>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the [=resource fetch algorithm=]'s
<a def-id="media-data-processing-steps-list"></a>.
<div class="note">This prevents using [=MediaSource object URLs=] for DedicatedWorker MediaSource
attachments. Transferring {{MediaSource}}.{{MediaSource/handle}} from the DedicatedWorker to the
Window context and assigning it to the media element's {{HTMLMediaElement/srcObject}} attribute is
the only way to attach such a MediaSource.
</div>
</dd>
<dt>If the media provider object is a {{MediaSourceHandle}} whose {{MediaSourceHandle/[[Detached]]}}
internal slot is true</dt>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the [=resource fetch algorithm=]'s
<a def-id="media-data-processing-steps-list"></a>.
</dd>
<dt>If the media provider object is a {{MediaSourceHandle}} whose underlying {{MediaSource}}'s
{{MediaSource/[[has ever been attached]]}} internal slot is true</dt>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the [=resource fetch algorithm=]'s
<a def-id="media-data-processing-steps-list"></a>.
<div class="note">This prevents loading an underlying {{MediaSource}} more than once using a
{{MediaSourceHandle}}, even if the {{MediaSource}} was constructed on {{Window}} and had been loaded
previously using a [=MediaSource object URL=]. This doesn't preclude subsequent use of a
[=MediaSource object URL=] for a {{Window}} {{MediaSource}} from succeeding though.
</div>
</dd>
<dt>If {{MediaSource/readyState}} is NOT set to {{ReadyState/""closed""}}</dt>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the [=resource fetch algorithm=]'s
<a def-id="media-data-processing-steps-list"></a>.</dd>
<dt>Otherwise</dt>
<dd>
<ol>
<li>Set the {{MediaSource}}'s {{MediaSource/[[has ever been attached]]}} internal slot to true.</li>
<li>Set the media element's <a def-id="delaying-the-load-event-flag"></a> to false.</li>
<li>
<dl class="switch">
<dt>If the {{MediaSource}} was constructed in a {{DedicatedWorkerGlobalScope}}, then setup
worker attachment communication and open the {{MediaSource}}:</dt>
<dd><ol>
<li>Set {{HTMLMediaElement/[[channel with worker]]}} to be a new {{MessageChannel}}.</li>
<li>Set {{HTMLMediaElement/[[port to worker]]}} to the {{MessageChannel/port1}} value of
{{HTMLMediaElement/[[channel with worker]]}}.</li>
<li>Execute [=StructuredSerializeWithTransfer=] with the {{MessageChannel/port2}} of
{{HTMLMediaElement/[[channel with worker]]}} as both the value and the sole member of the
|transferList|, and let the result be |serialized port2:MessagePort|.
<li>[=Queue a task=] on the {{MediaSource}}'s {{DedicatedWorkerGlobalScope}} that will
<ol>
<li>Execute [=StructuredDeserializeWithTransfer=] with |serialized port2| and
{{DedicatedWorkerGlobalScope}}'s [=environment settings object/realm=], and set
{{MediaSource/[[port to main]]}} to be the resulting deserialized clone of the
transferred {{MessageChannel/port2}} value of {{HTMLMediaElement/[[channel with
worker]]}}.</li>
<li>Set the {{MediaSource/readyState}} attribute to {{ReadyState/""open""}}.</li>
<li>[=Queue a task=] to [=fire an event=] named {{sourceopen}} at the
<a>MediaSource</a>.</li>
</ol>
</li>
</ol></dd>
<dt>Otherwise, the {{MediaSource}} was constructed in a {{Window}}:</dt>
<dd><ol>
<li>Set {{HTMLMediaElement/[[channel with worker]]}} null.</li>
<li>Set {{HTMLMediaElement/[[port to worker]]}} null.</li>
<li>Set {{MediaSource/[[port to main]]}} null.</li>
<li>Set the {{MediaSource/readyState}} attribute to {{ReadyState/""open""}}.</li>
<li>[=Queue a task=] to [=fire an event=] named {{sourceopen}} at the <a>MediaSource</a>.</li>
</ol>
</li>
</ol></dd>
<dt>Otherwise, the {{MediaSource}} was constructed in a {{Window}}:</dt>
<dd><ol>
<li>Set {{HTMLMediaElement/[[channel with worker]]}} null.</li>
<li>Set {{HTMLMediaElement/[[port to worker]]}} null.</li>
<li>Set {{MediaSource/[[port to main]]}} null.</li>
<li>Set the {{MediaSource/readyState}} attribute to {{ReadyState/""open""}}.</li>
<li>[=Queue a task=] to [=fire an event=] named {{sourceopen}} at the <a>MediaSource</a>.</li>
</ol></dd>
</dl>
<li>Continue the <a def-id="resource-fetch-algorithm"></a> by running the remaining <a def-id="Otherwise-mode-is-local"></a> steps, with these clarifications:
<ol>
<li>Text in the <a def-id="resource-fetch-algorithm"></a> or the <a def-id="media-data-processing-steps-list"></a> that refers to "the download", "bytes received", or "whenever new data for the current media resource becomes available" refers to data passed in via {{SourceBuffer/appendBuffer()}}.</li>
<li>References to HTTP in the <a def-id="resource-fetch-algorithm"></a> and the <a def-id="media-data-processing-steps-list"></a> do not apply because the HTMLMediaElement does not fetch media data via HTTP when a <a>MediaSource</a> is attached.</li>
</ol></dd>
</dl>
<li>Continue the [=resource fetch algorithm=] by running the remaining
<a def-id="Otherwise-mode-is-local"></a> steps, with these requirements:
<ol>
<li>Text in the [=resource fetch algorithm=] or the
<a def-id="media-data-processing-steps-list"></a> that refers to "the download", "bytes
received", or "whenever new data for the current media resource becomes available" refers to
data passed in via {{SourceBuffer/appendBuffer()}}.</li>
<li>References to HTTP in the [=resource fetch algorithm=] and the
<a def-id="media-data-processing-steps-list"></a> shall not apply because the HTMLMediaElement
does not fetch media data via HTTP when a {{MediaSource}} is attached.</li>
</ol>
</li>
</ol>
</li>
</ol>
</dd>
</dl>
<p class="note">An attached MediaSource does not use the remote mode steps in the <a def-id="resource-fetch-algorithm"></a>, so the media element will not fire "suspend" events. Though future versions of this specification will likely remove "progress" and "stalled" events from a media element with an attached MediaSource, user agents conforming to this version of the specification may still fire these two events as these [[HTML]] references changed after implementations of this specification stabilized.</p>
</dd>
</dl>
</li>
</ol>
<p class="note">An attached MediaSource does not use the remote mode steps in the [=resource fetch
algorithm=], so the media element will not fire "suspend" events. Though future versions of this specification
will likely remove "progress" and "stalled" events from a media element with an attached MediaSource, user
agents conforming to this version of the specification may still fire these two events as these [[HTML]]
references changed after implementations of this specification stabilized.</p>
</section>

<section id="mediasource-detach">
@@ -867,7 +934,13 @@ <h4><dfn>Detaching from a media element</dfn></h4>
<li>
[=Queue a task=] to [=fire an event=] named {{sourceclose}} at the <a>MediaSource</a>.</li>
</ol>
<p class="note">Going forward, this algorithm is intended to be externally called and run in any case where the attached <a>MediaSource</a>, if any, must be detached from the media element. It MAY be called on HTMLMediaElement [[HTML]] operations like load() and resource fetch algorithm failures in addition to, or in place of, when the media element transitions to {{HTMLMediaElement/NETWORK_EMPTY}}. Resource fetch algorithm failures are those which abort either the resource fetch algorithm or the resource selection algorithm, with the exception that the "Final step" [[HTML]] is not considered a failure that triggers detachment.</p>
<p class="note">Going forward, this algorithm is intended to be externally called and run in any case where
the attached <a>MediaSource</a>, if any, must be detached from the media element. It MAY be called on
HTMLMediaElement [[HTML]] operations like load() and [=resource fetch algorithm=] failures in addition to, or
in place of, when the media element transitions to {{HTMLMediaElement/NETWORK_EMPTY}}. Resource fetch
algorithm failures are those which abort either the resource fetch algorithm or the resource selection
algorithm, with the exception that the "Final step" [[HTML]] is not considered a failure that triggers
detachment.</p>
</section>

<section id="mediasource-seeking">
@@ -1101,10 +1174,13 @@ <h4><dfn>End of stream</dfn></h4>
<dl class="switch">
<dt>If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute equals
{{HTMLMediaElement/HAVE_NOTHING}}</dt>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the <a def-id="resource-fetch-algorithm"></a>'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dd>Run the <a def-id="media-data-cannot-be-fetched"></a> steps of the [=resource fetch
algorithm=]'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dt>If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is greater than
{{HTMLMediaElement/HAVE_NOTHING}}</dt>
<dd>Run the "<i>If the connection is interrupted after some media data has been received, causing the user agent to give up trying to fetch the resource</i>" steps of the <a def-id="resource-fetch-algorithm"></a>'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dd>Run the "<i>If the connection is interrupted after some media data has been received, causing
the user agent to give up trying to fetch the resource</i>" steps of the [=resource fetch
algorithm=]'s <a def-id="media-data-processing-steps-list"></a>.</dd>
</dl>
</dd>

@@ -1113,10 +1189,13 @@ <h4><dfn>End of stream</dfn></h4>
<dl class="switch">
<dt>If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute equals
{{HTMLMediaElement/HAVE_NOTHING}}</dt>
<dd>Run the "<i>If the media data can be fetched but is found by inspection to be in an unsupported format, or can otherwise not be rendered at all</i>" steps of the <a def-id="resource-fetch-algorithm"></a>'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dd>Run the "<i>If the media data can be fetched but is found by inspection to be in an unsupported
format, or can otherwise not be rendered at all</i>" steps of the [=resource fetch algorithm=]'s
<a def-id="media-data-processing-steps-list"></a>.</dd>
<dt>If the {{HTMLMediaElement}}.{{HTMLMediaElement/readyState}} attribute is greater than
{{HTMLMediaElement/HAVE_NOTHING}}
<dd>Run the <a def-id="media-data-is-corrupted"></a> steps of the <a def-id="resource-fetch-algorithm"></a>'s <a def-id="media-data-processing-steps-list"></a>.</dd>
<dd>Run the <a def-id="media-data-is-corrupted"></a> steps of the [=resource fetch algorithm=]'s
<a def-id="media-data-processing-steps-list"></a>.</dd>
</dl>
</dd>
</dl>
@@ -1160,15 +1239,65 @@ <h2><dfn>MediaSourceHandle</dfn> Object</h2>
<p class="note">This distinct object is necessary to attach a cross-context {{MediaSource}} to a media element
because {{MediaSource}} objects themselves are not transferable since they are event targets.</p>

<p>Each {{MediaSourceHandle}} object has a <dfn data-dfn-for="MediaSourceHandle">[[\has ever been assigned as
srcobject]]</dfn> internal slot that stores a {{boolean}}. It is initialized to false when the
{{MediaSourceHandle}} object is created, is set true in the extended {{HTMLMediaElement}}'s
{{HTMLMediaElement/srcObject}} setter as described in
<a href="#htmlmediaelement-extensions">HTMLMediaElement Extensions</a>, and if true, prevents successful
transfer of the {{MediaSourceHandle}} as described in the [=Transfer=] section.</p>

<p>{{MediaSourceHandle}} objects are {{Transferable}}, each having a <dfn
data-dfn-for="MediaSourceHandle">[[\Detached]]</dfn> internal slot that is used to ensure that once the handle
object instance has been transferred, that instance cannot be transferred again.</p>

<pre class="idl">
[Exposed=(Window,DedicatedWorker)]
[Transferable, Exposed=(Window,DedicatedWorker)]
interface MediaSourceHandle {};</pre>

<section><h2>Transfer</h2>
The {{MediaSourceHandle}} [=transfer steps=] and [=transfer-receiving steps=] require the implementation to
maintain an implicit internal slot referencing the underlying {{MediaSource}} to enable [=attaching to a media
element=] using {{HTMLMediaElement/srcObject}} and consequent setup of an attachment's [=cross-context
communication model=].
<section><h2><dfn>Transfer</dfn></h2>
<p>The {{MediaSourceHandle}} [=transfer steps=] and [=transfer-receiving steps=] require the implementation to
maintain an implicit internal slot referencing the underlying {{MediaSource}} to enable [=attaching to a media
element=] using {{HTMLMediaElement/srcObject}} and consequent setup of an attachment's [=cross-context
communication model=].</p>

<p class="note">
Implementors should be aware that assumption of "move" semantics implied by {{Transferable}} is not always
reality. For example, extensions or internal implementations of postMessage using broadcast may cause
unintended multiple recipients of a transferred {{MediaSourceHandle}}. For this reason, implementations are
guided to not resolve which potential clone of a transferred {{MediaSourceHandle}} is still valid for
attachment until and unless any handle for the underlying {{MediaSource}} object is used in the asynchronous
portion of the media element's resource selection algorithm. This is similar to the existing behavior for
attachment via [=MediaSource object URLs=], which can be cloned easily, where such a URL is valid for at most
one attachment start (across all of its potentially many clones).
</p>

<p>
Implementations MUST support at most one attachment (load) via {{HTMLMediaElement/srcObject}} ever for the
{{MediaSource}} object underlying a {{MediaSourceHandle}}, regardless of potential cloning of the
{{MediaSourceHandle}} due to varying implementations of {{Transferable}}.
<p class="note">See [=attaching to a media element=] for how this is enforced during the asynchronous portion
of the media element's resource selection algorithm.</p>
</p>

<p>{{MediaSourceHandle}} is only exposed on {{Window}} and {{DedicatedWorkerGlobalScope}} contexts, and cannot
successfully transfer between different [=ECMAScript/agent clusters=] [[!ECMASCRIPT]]. Transfer of a
{{MediaSourceHandle}} object can only succeed within the same [=ECMAScript/agent cluster=].
<p class="note">For example, transfer of a {{MediaSourceHandle}} object from either a {{Window}} or
{{DedicatedWorkerGlobalScope}} to either a SharedWorker or a ServiceWorker will not succeed. Developers should
be aware of this difference versus [=MediaSource object URLs=] which are {{DOMString}}s that can be
communicated many ways. Even so, [=attaching to a media element=] using a [=MediaSource object URL=] can only
succeed for a {{MediaSource}} that was constructed in a {{Window}} context. See also the integration of the
[=ECMAScript/agent=] and [=ECMAScript/agent cluster=] formalisms for Web Application APIs [[HTML]] where
related concepts such as [=dedicated worker agents=] are defined.</p>
</p>

<p>[=Transfer steps=] for a {{MediaSourceHandle}} object MUST include the following step:
<ol>
<li>If the {{MediaSourceHandle}}'s {{MediaSourceHandle/[[has ever been assigned as srcobject]]}} internal
slot is true, then the [=transfer steps=] must fail by throwing a {{DataCloneError}} exception.</li>
</ol>
</p>

</section>
</section>

@@ -2592,7 +2721,11 @@ <h3>Event Summary</h3>

<section id="htmlmediaelement-extensions">
<h2>HTMLMediaElement Extensions</h2>
<p>This section specifies what existing attributes on the {{HTMLMediaElement}} MUST return when a <a>MediaSource</a> is attached to the element.</p>
<p>This section specifies what existing {{HTMLMediaElement}}.{{HTMLMediaElement/seekable}} and
{{HTMLMediaElement}}.{{HTMLMediaElement/buffered}} attributes on the {{HTMLMediaElement}} MUST return when a
<a>MediaSource</a> is attached to the element, and what the existing
{{HTMLMediaElement}}.{{HTMLMediaElement/srcObject}} attribute MUST also do when it is set to be a
{{MediaSourceHandle}} object.</p>

<section id="htmlmediaelement-extensions-seekable">
<h3>{{HTMLMediaElement}}.{{HTMLMediaElement/seekable}}</h3>
@@ -2741,6 +2874,21 @@ <h3>{{HTMLMediaElement}}.{{HTMLMediaElement/buffered}}</h3>
</li><li>Return the current value of this attribute.</li>
</ol>
</section>

<section id="htmlmediaelement-extensions-srcobject">
<h3>{{HTMLMediaElement}}.{{HTMLMediaElement/srcObject}}</h3>

<p>If a {{HTMLMediaElement}}.{{HTMLMediaElement/srcObject}} attribute is assigned a {{MediaSourceHandle}},
then set {{MediaSourceHandle/[[has ever been assigned as srcobject]]}} for that {{MediaSourceHandle}} to
true as part of the synchronous steps of the extended {{HTMLMediaElement}}'s {{HTMLMediaElement/srcObject}}
setter that occur before invoking the element's load algorithm.
<p class="note">This prevents transferring that {{MediaSourceHandle}} object ever again, enabling clear
synchronous exception if that is attempted.</p>
<p class="issue">MediaSourceHandle needs to be added to HTMLMediaElement's MediaProvider IDL typedef and
related text involving media provider objects.</p>
</p>

</section>
</section>

<section id="audio-track-extensions">