You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
typedef (SFrameTransform or RTCRtpScriptTransform) RTCRtpTransform;
119
+
118
120
// New methods for RTCRtpSender and RTCRtpReceiver
119
121
partial interface RTCRtpSender {
120
122
RTCInsertableStreams createEncodedStreams();
123
+
attribute RTCRtpTransform? transform;
121
124
};
122
125
123
126
partial interface RTCRtpReceiver {
124
127
RTCInsertableStreams createEncodedStreams();
128
+
attribute RTCRtpTransform? transform;
125
129
};
126
130
</pre>
127
131
@@ -134,31 +138,147 @@ argument, ensure that the codec is disabled and produces no output.
134
138
135
139
### Stream creation ### {#stream-creation}
136
140
137
-
Let the {{RTCRtpSender}} or {{RTCRtpReceiver}} have an internal slot,
138
-
`[[Streams]]`, initialized to null.
141
+
At construction of each {{RTCRtpSender}} or {{RTCRtpReceiver}}, run the following steps:
142
+
1. Initialize [=this=].`[[Streams]]` to null.
143
+
2. Initialize [=this=].`[[transform]]` to null.
144
+
3. Initialize [=this=].`[[readable]]` to the result of <a dfn for="ReadableStream">creating</a> a {{ReadableStream}}. `[[readable]]` is provided frames using the [=readEncodedData=] algorithm given |this| as parameter.
145
+
4. Set [=this=].`[[readable]]`.`[[owner]]` to |this|.
146
+
5. Initialize [=this=].`[[writable]]` to the result of [=WritableStream/creating=] a {{WritableStream}}, its [=WritableStream/create/writeAlgorithm=] set to [=writeEncodedData=] given |this| as parameter.
147
+
6. Set [=this=].`[[writable]]`.`[[owner]]` to |this|.
148
+
7. Initialize [=this=].`[[pipeToController]]` to null.
149
+
8. Initialize [=this=].`[[lastReceivedFrameTimestamp]]` to zero.
150
+
9. If the {{RTCPeerConnection}}'s configuration does not have {{RTCConfiguration/encodedInsertableStreams}} set to "true", queue a task to run the following steps:
151
+
1. If [=this=].`[[pipeToController]]` is not null, abort these steps.
152
+
2. Set [=this=].`[[pipeToController]]` to a new {{AbortController}}.
153
+
<!-- FIXME: Use pipeTo algorithm when available. -->
154
+
3. Call <a href="https://streams.spec.whatwg.org/#readable-stream-pipe-to">pipeTo</a> with [=this=].`[[readable]]`, [=this=].`[[writable]]`, preventClose equal to true, preventAbort equal to true, preventCancel equal to true and [=this=].`[[pipeToController]]`.signal.
155
+
156
+
The <dfn method for="RTCRtpSender">createEncodedStreams()</dfn> method steps are:
157
+
158
+
1. If the {{RTCPeerConnection}}'s configuration does not have {{RTCConfiguration/encodedInsertableStreams}} set to "true", throw an "{{InvalidAccessError}}" {{DOMException}} and abort these steps.
159
+
2. If the data source does not permit access, throw an "{{InvalidAccessError}}" {{DOMException}} and abort these steps.
160
+
3. If [=this=].`[[Streams]]` is not null, throw an "{{InvalidAccessError}}" {{DOMException}}.
161
+
4. If [=this=].`[[pipeToController]]` is not null, throw an "{{InvalidAccessError}}" {{DOMException}}.
162
+
5. Set [=this=].`[[Streams]]` to an {{RTCInsertableStreams}} object.
163
+
6. Set [=this=].`[[Streams]]`.{{RTCInsertableStreams/readable}} to [=this=].`[[readable]]`.
164
+
7. Set [=this=].`[[Streams]]`.{{RTCInsertableStreams/writable}} to [=this=].`[[writable]]`.
165
+
8. Enable the encoded data source.
166
+
10. Return [=this=].`[[Streams]]`.
139
167
140
-
When {{RTCRtpSender/createEncodedStreams}}() is
141
-
called, run the following steps:
168
+
### Stream processing ### {#stream-processing}
142
169
143
-
* If the {{RTCPeerConnection}}'s configuration does not have {{RTCConfiguration/encodedInsertableStreams}} set to "true", throw an {{InvalidStateError}} and abort these steps.
144
-
* If the data source does not permit access, throw an {{InvalidAccessError}} and abort these steps.
145
-
* If `[[Streams]]` is not null, throw an {{InvalidStateError}}.
146
-
* Create an {{RTCInsertableStreams}} object |s|.
147
-
* Set |s|.{{RTCInsertableStreams/readable}} to a {{ReadableStream}} representing the encoded data source.
148
-
* Set |s|.{{RTCInsertableStreams/writable}} to a {{WritableStream}} representing the encoded data sink.
149
-
* Enable the encoded data source.
150
-
* Store |s| in the internal slot `[[Streams]]`.
151
-
* Return |s|
170
+
The <dfn>readEncodedData</dfn> algorithm is given a |rtcObject| as parameter. It is defined by running the following steps:
171
+
1. Wait for a frame to be produced by |rtcObject|'s encoder if it is a {{RTCRtpSender}} or |rtcObject|'s packetizer if it is a {{RTCRtpReceiver}}.
172
+
2. Let |frame| be the newly produced frame.
173
+
3. Set |frame|.`[[owner]]` to |rtcObject|.
174
+
4. [=ReadableStream/enqueue=] |frame| in |rtcObject|.`[[readable]]`.
175
+
176
+
The <dfn>writeEncodedData</dfn> algorithm is given a |rtcObject| as parameter and a |frame| as input. It is defined by running the following steps:
177
+
1. If |frame|.`[[owner]]` is not equal to |rtcObject|, abort these steps and return [=a promise resolved with=] undefined. A processor cannot create frames, or move frames between streams.
178
+
2. If the |frame|'s {{RTCEncodedVideoFrame/timestamp}} is equal to or larger than |rtcObject|.`[[lastReceivedFrameTimestamp]]`, abort these steps and return [=a promise resolved with=] undefined. A processor cannot reorder frames, although it may delay them or drop them.
179
+
3. Set |rtcObject|.`[[lastReceivedFrameTimestamp]]` to the |frame|'s {{RTCEncodedVideoFrame/timestamp}}.
180
+
4. Enqueue the frame for processing as if it came directly from the encoded data source, by running one of the following steps:
181
+
* If |rtcObject| is a {{RTCRtpSender}}, enqueue it to |rtcObject|'s packetizer, to be processed [=in parallel=].
182
+
* If |rtcObject| is a {{RTCRtpReceiver}}, enqueue it to |rtcObject|'s decoder, to be processed [=in parallel=].
183
+
5. Return [=a promise resolved with=] undefined.
184
+
185
+
## Extension attribute ## {#attribute}
186
+
187
+
A RTCRtpTransform has two private slots called `[[readable]]` and `[[writable]]`.
188
+
189
+
The <dfn attribute for="RTCRtpSender,RTCRtpReceiver">transform</dfn> getter steps are:
190
+
1. Return [=this=].`[[transform]]`.
191
+
192
+
The `transform` setter steps are:
193
+
2. Let |transform| be the argument to the setter.
194
+
3. Let |checkedTransform| set to |transform| if it is not null or to an [=identity transform stream=] otherwise.
195
+
3. Let |reader| be the result of [=ReadableStream/getting a reader=] for |checkedTransform|.`[[readable]]`.
196
+
4. Let |writer| be the result of [=WritableStream/getting a writer=] for |checkedTransform|.`[[writable]]`.
197
+
5. Initialize |newPipeToController| to a new {{AbortController}}.
198
+
6. If [=this=].`[[pipeToController]]` is not null, run the following steps:
199
+
1. [=AbortSignal/Add=] the [=chain transform algorithm=] to [=this=].`[[pipeToController]]`.signal.
4. Assert that |newPipeToController| is the same object as |rtcObject|.`[[pipeToController]]`.
210
+
<!-- FIXME: Use pipeTo algorithm when available. -->
211
+
5. Call <a href="https://streams.spec.whatwg.org/#readable-stream-pipe-to">pipeTo</a> with |rtcObject|.`[[readable]]`, |checkedTransform|.`[[writable]]`, preventClose equal to false, preventAbort equal to false, preventCancel equal to true and |newPipeToController|.signal.
212
+
6. Call <a href="https://streams.spec.whatwg.org/#readable-stream-pipe-to">pipeTo</a> with |checkedTransform|.`[[readable]]`, |rtcObject|.`[[writable]]`, preventClose equal to true, preventAbort equal to true, preventCancel equal to false and |newPipeToController|.signal.
213
+
214
+
This algorithm is defined so that transforms can be updated dynamically.
215
+
There is no guarantee on which frame will happen the switch from the previous transform to the new transform.
216
+
217
+
If a web application sets the transform synchronously at creation of the {{RTCRtpSender}} (for instance when calling addTrack), the transform will receive the first frame generated by the {{RTCRtpSender}}'s encoder.
218
+
Similarly, if a web application sets the transform synchronously at creation of the {{RTCRtpReceiver}} (for instance when calling addTrack, or at track event handler), the transform will receive the first full frame generated by the {{RTCRtpReceiver}}'s packetizer.
When a frame is produced from the encoded data source, place it on the
156
-
`[[Streams]]`.{{RTCInsertableStreams/readable}}.
240
+
The <dfn constructor for="SFrameTransform" lt="SFrameTransform(options)"><code>new SFrameTransform(<var>options</var>)</code></dfn> constructor steps are:
241
+
1. Let |transformAlgorithm| be an algorithm which takes a |frame| as input and runs the <a href="#sframe-transform-algorithm">SFrame transform algorithm</a> with |this| and |frame|.
242
+
2. Set |this|.`[[transform]]` to the result of [=TransformStream/creating=] a {{TransformStream}}, with [=TransformStream/create/transformAlgorithm=] set to |transformAlgorithm|.
243
+
3. Let |options| be the method's first argument.
244
+
4. Set |this|.`[[role]]` to |options|["{{SFrameTransportOptions/role}}"].
245
+
5. Set |this|.`[[readable]]` to |this|.`[[transform]]`.`[[readable]]`.
246
+
6. Set |this|.`[[writable]]` to |this|.`[[transform]]`.`[[writable]]`.
The SFrame transform algorithm, given |sframe| as a SFrameTransform object and |frame|, runs these steps:
251
+
1. Let |role| be |sframe|.`[[role]]`.
252
+
2. If |frame|.`[[rtcObject]]` is a {{RTCRtpSender}}, set |role| to 'encrypt'.
253
+
3. If |frame|.`[[rtcObject]]` is a {{RTCRtpReceiver}}, set |role| to 'decrypt'.
254
+
4. Let |data| be undefined.
255
+
5. If |frame| is an ArrayBuffer, set |data| to |frame|. // FIXME Support BufferSource
256
+
6. If |frame| is an {{RTCEncodedAudioFrame}}, set |data| to |frame|.{{RTCEncodedAudioFrame/data}}
257
+
7. If |frame| is an {{RTCEncodedVideoFrame}}, set |data| to |frame|.{{RTCEncodedVideoFrame/data}}
258
+
8. If |data| is undefined, abort these steps.
259
+
9. Let |buffer| be the result of running the SFrame algorithm with |data| and |role| as parameters. This algorithm is defined by the <a href="https://datatracker.ietf.org/doc/draft-omara-sframe/">SFrame specification</a>.
260
+
10. If |frame| is an ArrayBuffer, set |frame| to |buffer|.
261
+
11. If |frame| is an {{RTCEncodedAudioFrame}}, set |frame|.{{RTCEncodedAudioFrame/data}} to |buffer|.
262
+
12. If |frame| is an {{RTCEncodedVideoFrame}}, set |frame|.{{RTCEncodedVideoFrame/data}} to |buffer|.
263
+
13. [=ReadableStream/Enqueue=] |frame| in |sframe|.`[[transform]]`.
When a frame appears on the `[[Streams]]`.{{RTCInsertableStreams/writable}}, do the following:
159
-
* Check that the frame is a a valid frame that has been created by the encoded data source; if it is not, discard it. A processor cannot create frames, or move frames between streams.
160
-
* Check that the frame's {{RTCEncodedVideoFrame/timestamp}} is equal to or larger than any previously received frame. A processor cannot reorder frames, although it may delay them or drop them.
161
-
* Process the frame as if it came directly from the encoded data source.
0 commit comments