Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ remote-index: index.src.html
--output index.html \
--write-out "%{http_code}" \
--header "Accept: text/plain, text/html" \
-F die-on=warning \
-F [email protected]) && \
[[ "$$HTTP_STATUS" -eq "200" ]]) || ( \
echo ""; cat index.html; echo ""; \
Expand Down
164 changes: 118 additions & 46 deletions index.src.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
spec: media-capabilities; urlPrefix: https://w3c.github.io/media-capabilities/#
type: method; text: decodingInfo(); url: dom-mediacapabilities-decodinginfo
type: attribute; text: powerEfficient; url: dom-mediacapabilitiesinfo-powerefficient

spec: webaudio; urlPrefix: https://www.w3.org/TR/webaudio/
type: dfn; text: acquire the content; url: #acquire-the-content
for: AudioBuffer
type: method; text: copyToChannel(); url: #dom-audiobuffer-copytochannel
</pre>


Expand Down Expand Up @@ -268,21 +273,21 @@
[=Enqueues a control message=] to decode the given |chunk|.

When invoked, run these steps:
1. If {{VideoDecoder/state}} is not `"configured"`, throw an
1. If {{AudioDecoder/state}} is not `"configured"`, throw an
{{InvalidStateError}}.
2. Increment {{VideoDecoder/decodeQueueSize}}.
2. Increment {{AudioDecoder/decodeQueueSize}}.
3. [=Queue a control message=] to decode the |chunk|.

Running a control message to decode the chunk means performing these steps:
1. Attempt to use {{VideoDecoder/[[codec implementation]]}} to decode the
1. Attempt to use {{AudioDecoder/[[codec implementation]]}} to decode the
chunk.
2. If decoding results in an error, queue a task on the [=control thread=]
event loop to run the [=Close VideoDecoder=] algorithm with
event loop to run the [=Close AudioDecoder=] algorithm with
{{EncodingError}}.
3. Queue a task on the [=control thread=] event loop to decrement
{{VideoDecoder/decodeQueueSize}}
{{AudioDecoder/decodeQueueSize}}
4. Let |decoded outputs| be a [=list=] of decoded video data outputs emitted
by {{VideoDecoder/[[codec implementation]]}}.
by {{AudioDecoder/[[codec implementation]]}}.
5. If |decoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output VideoFrames=] algorithm with
|decoded outputs|.
Expand Down Expand Up @@ -365,10 +370,11 @@
<dd>
Run these steps:
1. For each |output| in |outputs|:
1. Let |buffer| be an {{AudioBuffer}} containing the decoded audio data in
|output|.
2. Let |frame| be an {{AudioFrame}} containing |buffer| and a timestamp for
the output.
1. Let |frameInit| be an {{AudioFrameInit}} with the following keys:
1. Let {{AudioFrameInit/buffer}} be an {{AudioBuffer}} containing
the decoded audio data from |output|.
2. Let {{AudioFrameInit/timestamp}} be the timestamp from |output|.
2. Let |frame| be an {{AudioFrame}} constructed with |frameInit|.
3. Invoke {{AudioDecoder/[[output callback]]}} with frame.
</dd>
<dt><dfn>Reset AudioDecoder</dfn></dt>
Expand Down Expand Up @@ -744,24 +750,23 @@
`true`, throw a {{TypeError}}.
2. If {{AudioEncoder/state}} is not `"configured"`, throw an
{{InvalidStateError}}.
3. Let |frameClone| hold the result of running the [=Clone Frame=]
3. Let |frameClone| hold the result of running the [=Clone AudioFrame=]
algorithm with |frame|.
4. Increment {{AudioEncoder/encodeQueueSize}}.
5. [=Queue a control message=] to encode |frameClone|.

Running a control message to encode the frame means performing these steps.
1. Attempt to use {{AudioEncoder/[[codec implementation]]}} to encode
|frameClone|.
the [=frame resource=] described by |frameClone|.
2. If encoding results in an error, queue a task on the [=control thread=]
event loop to run the [=Close AudioEncoder=] algorithm with
{{EncodingError}}.
3. Queue a task on the [=control thread=] event loop to decrement
{{AudioEncoder/encodeQueueSize}}.
4. Let |encoded outputs| be a [=list=] of encoded audio data outputs
emitted by {{AudioEncoder/[[codec implementation]]}}.
5. If |encoded outputs| is not empty, queue a task on the [=control thread=]
event loop to run the [=Output EncodedAudioChunks=] algorithm with
|encoded outputs|.
5. If |encoded outputs| is not empty, queue a task on the
[=control thread=] event loop to run the [=Output EncodedAudioChunks=] algorithm with |encoded outputs|.
</dd>

<dt><dfn method for=AudioEncoder>flush()</dfn></dt>
Expand Down Expand Up @@ -1810,6 +1815,42 @@
====================================================
These interfaces represent unencoded (raw) media.

Memory Model {#raw-media-memory-model}
--------------------------------------

### Background ### {#raw-media-memory-model-background}

This section is non-normative.

Decoded media data (frames) may occupy a large amount of system memory. To
minimize the need for expensive copies, this specification defines a scheme
for reference counting (`frame.clone()` and `frame.close()`).

### Reference Counting ### {#raw-media-memory-model-reference-counting}

A <dfn>frame resource</dfn> is storage for the actual pixel data or the audio
sample data described by a {{VideoFrame}} or {{AudioFrame}}.

The {{AudioFrame}} {{AudioFrame/[[resource reference]]}} and {{VideoFrame}}
{{VideoFrame/[[resource reference]]}} internal slots hold a reference to a
[=frame resource=].

{{VideoFrame}}.{{VideoFrame/clone()}} and
{{AudioFrame}}.{{AudioFrame/clone()}} return new frame objects who's
`[[resource reference]]` points to the same [=frame resource=] as the original
frame.

{{VideoFrame}}.{{VideoFrame/close()}} and {{AudioFrame}}.{{AudioFrame/close()}}
will clear their [[resource reference]] slot, releasing the reference their
[=frame resource=]

A [=frame resource=] must remain alive as long as it continues to be referenced
by a `[[resource reference]]`.

NOTE: When a [=frame resource=] is no longer referenced by a
`[[resource reference]]`, the resource may be destroyed. User agents are
encouraged to destroy such resources quickly to reduce memory pressure and
facilitate resouce reuse.

AudioFrame Interface {#audioframe-interface}
---------------------------------------------
Expand All @@ -1818,8 +1859,11 @@
[Exposed=(Window,DedicatedWorker)]
interface AudioFrame {
constructor(AudioFrameInit init);

readonly attribute unsigned long long timestamp;
readonly attribute AudioBuffer? buffer;

AudioFrame clone();
undefined close();
};

Expand All @@ -1830,49 +1874,77 @@
</xmp>

### Internal Slots ###{#audioframe-internal-slots}
<dl>
<dt><dfn attribute for=AudioFrame>\[[detached]]</dfn></dt>
<dd>
Boolean indicating whether close() was invoked and underlying resources
have been released.
</dd>
</dl>
: <dfn attribute for=AudioFrame>\[[detached]]</dfn>
:: Boolean indicating whether {{AudioFrame/close()}} was invoked.

: <dfn attribute for=AudioFrame>[[resource reference]]</dfn>
:: A reference to a [=frame resource=] that stores the audio sample data for
this frame.

### Constructors ###{#audioframe-constructors}
<dfn constructor for=AudioFrame title="AudioFrame(init)">
AudioFrame(init)
</dfn>
1. Let |frame| be a new {{AudioFrame}} object.
2. Assign `init.timestamp` to `frame.timestamp`.
3. Assign `init.buffer` to `frame.buffer`.
4. Assign `false` to the {{AudioFrame/[[detached]]}} internal slot.
5. Return |frame|.

1. Let |frame| be a new {{AudioFrame}} object, initialized as follows:
1. Assign |init|.{{AudioFrameInit/timestamp}} to {{AudioFrame/timestamp}}.
2. Assign |init|.{{AudioFrameInit/buffer}} to {{AudioFrame/buffer}}.
3. Let |resource| be a new [=frame resource=].
4. [=Acquire the content=] [[WEBAUDIO]] of {{AudioFrame/buffer}} and
assign the acquired content to |resource|.

NOTE: The acquired content stored in |resource| is an immutable
snapshot {{AudioFrameInit/buffer}}'s content. Mutating
{{AudioFrame/buffer}} after construction (e.g. via
{{AudioBuffer/copyToChannel()}}) will have no effect on the
|resource|.

5. Let |resourceReference| be a reference to |resource|.
6. Assign |resourceReference| to {{AudioFrame/[[resource reference]]}}.
7. Assign `false` to the {{AudioFrame/[[detached]]}} internal slot.
2. Return |frame|.

### Attributes ###{#audioframe-attributes}
<dl>
<dt><dfn attribute for=AudioFrame>timestamp</dfn></dt>
<dd>The presentation timestamp, given in microseconds.</dd>
: <dfn attribute for=AudioFrame>timestamp</dfn>
:: The presentation timestamp, given in microseconds.

<dt><dfn attribute for=AudioFrame>buffer</dfn></dt>
<dd>The buffer containing decoded audio data.</dd>
</dl>
: <dfn attribute for=AudioFrame>buffer</dfn>
:: The buffer describing decoded audio data.

NOTE: The backing [=frame resource=] (referenced by
{{AudioFrame/[[resource reference]]}}) is immutable. Mutating
{{AudioFrame/buffer}} after construction (e.g. via
{{AudioBuffer/copyToChannel()}}) will have no effect on the
[=frame resource=].

### Methods ###{#audioframe-methods}
<dl>
<dt><dfn method for=AudioFrame>close()</dfn></dt>
<dd>
Immediately frees [=system resources=]. When invoked, run these steps:
1. Release [=system resources=] for buffer and set its value to null.
2. Assign `true` to the {{AudioFrame/[[detached]]}} internal slot.
: <dfn method for=AudioFrame>clone()</dfn>
:: Creates a new AudioFrame with a reference to the same [=frame resource=].

NOTE: This section needs work. We should use the name and semantics of
VideoFrame destroy(). Similarly, we should add clone() to make a deep
copy.
</dd>
</dl>
When invoked, run these steps:
1. If the value of |frame|'s {{AudioFrame/[[detached]]}} internal slot is
`true`, throw an {{InvalidStateError}} {{DOMException}}.
2. Return the result of running the [=Clone AudioFrame=] algorithm with
[=this=].

: <dfn method for=AudioFrame>close()</dfn>
:: Clears all state and releases the reference to the [=frame resource=].
Close is final.

When invoked, run these steps:
1. Assign `null` to {{AudioFrame/[[resource reference]]}}.
2. Assign `null` to {{AudioFrame/buffer}}.
3. Assign `true` to the {{AudioFrame/[[detached]]}} internal slot.

### Algorithms ### {#audioframe-algorithms}

: <dfn>Clone AudioFrame</dfn> (with |frame|)
:: Run these steps:
1. Let |clone| be a new {{AudioFrame}} initialized as follows:
1. Assign |frame|.{{AudioFrame/[[resource reference]]}} to
{{AudioFrame/[[resource reference]]}}.
2. Assign |frame|.timestamp to {{AudioFrame/timestamp}}.
3. Assign |frame|.buffer to {{AudioFrame/buffer}}.
2. Return |clone|.

VideoFrame Interface {#videoframe-interface}
--------------------------------------------
Expand Down Expand Up @@ -2359,7 +2431,7 @@
operations.

Platform codecs are historically an internal detail of APIs like
{{HTMLMediaElement}}, [[WebAudio]], and [[WebRTC]]. In this way, it has always
{{HTMLMediaElement}}, [[WEBAUDIO]], and [[WebRTC]]. In this way, it has always
been possible to attack the underlying codecs by using malformed media
files/streams and invoking the various API control methods.

Expand Down