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
This allows manipulation of encoded frames in the media pipeline
97
97
between the processing steps of an {{RTCRtpSender}}'s underlying
98
-
<dfn>encoder</dfn> and <dfn ignore=''>packetizer</dfn>, and/or
98
+
<dfn>encoder</dfn> and <dfn>packetizer</dfn>, and/or
99
99
between an {{RTCRtpReceiver}}'s underlying <dfn>depacketizer</dfn>
100
-
and <dfn ignore=''>decoder</dfn>.
100
+
and <dfn>decoder</dfn>.
101
101
102
102
## Extension operation ## {#operation}
103
103
@@ -108,8 +108,6 @@ argument, ensure that the codec is disabled and produces no output.
108
108
At construction of each {{RTCRtpSender}} or {{RTCRtpReceiver}}, run the following steps:
109
109
1. Initialize [=this=].`[[transform]]` to null.
110
110
1. Initialize [=this=].`[[pipeToController]]` to null.
111
-
1. Initialize [=this=].`[[lastReceivedFrameCounter]]` to <code>0</code>.
112
-
1. Initialize [=this=].`[[lastEnqueuedFrameCounter]]` to <code>0</code>.
113
111
1. [=Queue a task=] to run the following steps:
114
112
1. If [=this=].`[[pipeToController]]` is not null, abort these steps.
115
113
2. Set [=this=].`[[pipeToController]]` to a new {{AbortController}}.
@@ -128,13 +126,14 @@ The User Agent is responsible for doing these adaptations, especially since it c
128
126
For those reasons, streams backpressure is disabled in WebRTC encoded transforms.
129
127
</p>
130
128
131
-
The <dfn abstract-op>readEncodedData</dfn> algorithm is given a |rtcObject| as parameter. It is defined by running the following steps:
132
-
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}}.
133
-
1. Increment |rtcObject|.`[[lastEnqueuedFrameCounter]]` by <code>1</code>.
129
+
The <dfn abstract-op>readEncodedData</dfn> algorithm is given an {{RTCRtpScriptTransformer}}
130
+
|transformer| as parameter. It is defined by running the following steps:
131
+
1. Wait for a frame to be produced by |transformer|.{{[[frameSource]]}}.
132
+
1. Increment |transformer|.`[[lastEnqueuedFrameCounter]]` by <code>1</code>.
134
133
1. Let |frame| be the newly produced frame.
135
-
1. Set |frame|.`[[owner]]` to |rtcObject|.
136
-
1. Set |frame|.`[[counter]]` to |rtcObject|.`[[lastEnqueuedFrameCounter]]`.
137
-
1. If the frame has been produced by a {{RTCRtpReceiver}}:
134
+
1. Set |frame|.`[[owner]]` to |transformer|.{{[[frameSource]]}}.
135
+
1. Set |frame|.`[[counter]]` to |transformer|.{{[[lastEnqueuedFrameCounter]]}}.
136
+
1. If |frame|.`[[owner]]` is a [=depacketizer=]:
138
137
1. If the relevant RTP packet contains the
139
138
[[RTP-EXT-CAPTURE-TIME|RTP Header Extension for Absolute Capture Time]], set |frame|.`[[captureTime]]` to the
140
139
[[RTP-EXT-CAPTURE-TIME#absolute-capture-timestamp|absolute capture timestamp]] field and set |frame|.`[[senderCaptureTimeOffset]]`
@@ -145,30 +144,32 @@ The <dfn abstract-op>readEncodedData</dfn> algorithm is given a |rtcObject| as p
145
144
[[RTP-EXT-CAPTURE-TIME#timestamp-interpolation|timestamp interpolation]] and set |frame|.`[[senderCaptureTimeOffset]]`
146
145
to the most recent value that was present.
147
146
1. Otherwise, set |frame|.`[[captureTime]]` to undefined and set |frame|.`[[senderCaptureTimeOffset]]` to undefined.
148
-
1. If the frame has been produced by a {{RTCRtpSender}}, set |frame|.`[[captureTime]]` to the capture timestamp
147
+
1. If |frame|.`[[owner]]` is an [=encoder=], set |frame|.`[[captureTime]]` to the capture timestamp
149
148
using the methodology described in [[RTP-EXT-CAPTURE-TIME#absolute-capture-timestamp]] and set frame.`[[senderCaptureTimeOffset]]`
150
149
to undefined.
151
-
1. [=ReadableStream/Enqueue=] |frame| in |rtcObject|.`[[readable]]`.
150
+
1. [=ReadableStream/Enqueue=] |frame| into |transformer|.{{[[readable]]}}.
152
151
153
-
The <dfn abstract-op>writeEncodedData</dfn> algorithm is given a |rtcObject| as parameter and a |frame| as input. It is defined by running the following steps:
154
-
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.
155
-
1. If |frame|.`[[counter]]` is equal or smaller than |rtcObject|.`[[lastReceivedFrameCounter]]`, abort these steps and return [=a promise resolved with=] undefined. A processor cannot reorder frames, although it may delay them or drop them.
156
-
1. Set |rtcObject|.`[[lastReceivedFrameCounter]]` to |frame|`[[counter]]`.
152
+
The <dfn abstract-op>writeEncodedData</dfn> algorithm is given an {{RTCRtpScriptTransformer}}
153
+
|transformer| as parameter and a |frame| as input. It is defined by running the following steps:
154
+
1. If |frame|.`[[owner]]` is not equal to |transformer|.{{[[frameSource]]}}, abort these steps and return [=a promise resolved with=] undefined. A processor cannot create frames, or move frames between streams.
155
+
1. If |frame|.`[[counter]]` is equal or smaller than |transformer|.`[[lastReceivedFrameCounter]]`, abort these steps and return [=a promise resolved with=] undefined. A processor cannot reorder frames, although it may delay them or drop them.
156
+
1. Set |transformer|.`[[lastReceivedFrameCounter]]` to |frame|.`[[counter]]`.
157
157
1. Let |data| be |frame|.`[[data]]`.
158
158
1. Let |serializedFrame| be [$StructuredSerializeWithTransfer$](|frame|, « |data| »).
159
159
1. Let |frameCopy| be [$StructuredDeserializeWithTransfer$](|serializedFrame|, |frame|'s [=relevant realm=]).
160
160
1. Enqueue |frameCopy| for processing as if it came directly from the encoded data source, by running one of the following steps:
161
-
* If |rtcObject| is a {{RTCRtpSender}}, enqueue |frameCopy| to |rtcObject|'s packetizer, to be processed [=in parallel=].
162
-
* If |rtcObject| is a {{RTCRtpReceiver}}, enqueue |frameCopy| it to |rtcObject|'s decoder, to be processed [=in parallel=].
161
+
* If |transformer|.{{[[frameSource]]}} is an [=encoder=], enqueue |frameCopy| to its
162
+
associated [=packetizer=], to be processed [=in parallel=].
163
+
* If |transformer|.{{[[frameSource]]}} is a [=depacketizer=], enqueue |frameCopy| to its associated [=decoder=], to be processed [=in parallel=].
163
164
1. Return [=a promise resolved with=] undefined.
164
165
165
-
On sender side, as part of [$readEncodedData$], frames produced by |rtcObject|'s encoder MUST be enqueued in |rtcObject|.`[[readable]]` in the encoder's output order.
166
+
On the sender side, as part of [$readEncodedData$], frames produced by the [=encoder=] MUST be [=ReadableStream/enqueued=] into |transformer|.{{[[readable]]}} in the [=encoder=]'s output order.
166
167
As [$writeEncodedData$] ensures that the transform cannot reorder frames, the encoder's output order is also the order followed by packetizers to generate RTP packets and assign RTP packet sequence numbers.
167
-
The packetizer may expect the transformed data to still conform to the original format, e.g. a series of NAL units separated by Annex B start codes.
168
+
The [=packetizer=] may expect the transformed data to still conform to the original format, e.g. a series of NAL units separated by Annex B start codes.
168
169
169
-
On receiver side, as part of [$readEncodedData$], frames produced by |rtcObject|'s packetizer MUST be enqueued in |rtcObject|.`[[readable]]` in the same encoder's output order.
170
-
To ensure the order is respected, the depacketizer will typically use RTP packet sequence numbers to reorder RTP packets as needed before enqueuing frames in |rtcObject|.`[[readable]]`.
171
-
As [$writeEncodedData$] ensures that the transform cannot reorder frames, this will be the order expected by |rtcObject|'s decoder.
170
+
On the receiver side, as part of [$readEncodedData$], frames produced by the [=depacketizer=] MUST be [=ReadableStream/enqueued=] into |transformer|.{{[[readable]]}} in the same [=encoder=]'s output order.
171
+
To ensure the order is respected, the [=depacketizer=] will typically use RTP packet sequence numbers to reorder RTP packets as needed before [=ReadableStream/enqueuing=] frames into |transformer|.{{[[readable]]}}.
172
+
As [$writeEncodedData$] ensures that the transform cannot reorder frames, this will be the order expected by the [=decoder=].
172
173
173
174
## Extension attribute ## {#attribute}
174
175
@@ -202,7 +203,7 @@ The <dfn abstract-op>chain transform algorithm</dfn> steps are defined as:
202
203
1. If |newPipeToController|'s [=AbortController/signal=] is [=AbortSignal/aborted=], abort these steps.
4. Assert that |newPipeToController| is the same object as |rtcObject|.`[[pipeToController]]`.
206
+
4. [=Assert=] that |newPipeToController| is the same object as |rtcObject|.`[[pipeToController]]`.
206
207
<!-- FIXME: Use pipeTo algorithm when available. -->
207
208
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|'s [=AbortController/signal=].
208
209
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|'s [=AbortController/signal=].
@@ -930,12 +931,10 @@ The <dfn constructor for="RTCRtpScriptTransform" lt="RTCRtpScriptTransform(worke
930
931
931
932
Each {{RTCRtpScriptTransform}} has the following set of [$association steps$], given |rtcObject|:
932
933
1. Let |transform| be the {{RTCRtpScriptTransform}} object that owns the [$association steps$].
933
-
1. Let |encoder| be |rtcObject|'s encoder if |rtcObject| is a {{RTCRtpSender}} or undefined otherwise.
934
-
1. Let |depacketizer| be |rtcObject|'s depacketizer if |rtcObject| is a {{RTCRtpReceiver}} or undefined otherwise.
934
+
1. Let |frameSource| be |rtcObject|'s [=encoder=] if |rtcObject| is an {{RTCRtpSender}} or |rtcObject|'s [=depacketizer=] otherwise.
935
935
1. [=Queue a task=] on the DOM manipulation [=task source=] |worker|'s global scope to run the following steps:
936
936
1. Let |transformer| be the {{RTCRtpScriptTransformer}} object associated to |transform|.
937
-
1. Set |transformer|.`[[encoder]]` to |encoder|.
938
-
1. Set |transformer|.`[[depacketizer]]` to |depacketizer|.
937
+
1. Set |transformer|.{{[[frameSource]]}} to |frameSource|.
A {{RTCRtpScriptTransformer}} has the following private slots called `[[depacketizer]]`, `[[encoder]]`, `[[options]]`, `[[readable]]` and `[[writable]]`.
1044
-
In addition, a {{RTCRtpScriptTransformer}} is always associated with its parent {{RTCRtpScriptTransform}} transform.
1045
-
This allows algorithms to go from an {{RTCRtpScriptTransformer}} object to its {{RTCRtpScriptTransform}} parent and vice versa.
1046
-
1047
1048
The <dfn attribute for="RTCRtpScriptTransformer">options</dfn> getter steps are:
1048
1049
1. Return [=this=].`[[options]]`.
1049
1050
@@ -1082,21 +1083,19 @@ The following event fires on an {{RTCRtpScriptTransformer}}:
1082
1083
1083
1084
The steps that generate an event of type {{KeyFrameRequestEvent}} are as follows:
1084
1085
1085
-
Given a {{RTCRtpScriptTransformer}} |transform|:
1086
-
1087
-
When |transform|'s `[[encoder]]` receives a keyframe request, for instance from an incoming RTCP Picture Loss Indication (PLI)
1086
+
When the [=encoder=] of an associated {{RTCRtpScriptTransformer}} |transformer| receives a keyframe request, for instance from an incoming RTCP Picture Loss Indication (PLI)
1088
1087
or Full Intra Refresh (FIR), queue a task to perform the following steps:
1089
1088
1090
1089
1. Set |rid| to the RID of the appropriate layer, or undefined if the request is not for a specific layer.
1091
-
1. [=Fire an event=] named `keyframerequest` at |transform| using {{KeyFrameRequestEvent}} with its {{Event/cancelable}} attribute initialized to "true", and with {{KeyFrameRequestEvent/rid}} set to |rid|.
1090
+
1. [=Fire an event=] named `keyframerequest` at |transformer| using {{KeyFrameRequestEvent}} with its {{Event/cancelable}} attribute initialized to "true", and with {{KeyFrameRequestEvent/rid}} set to |rid|.
1092
1091
1. If the event's [=Event/canceled flag=] is true, abort these steps.
1093
-
1. Run the [$generate key frame algorithm$] with a new promise, |transform|.`[[encoder]]` and |rid|.
1092
+
1. Run the [$generate key frame algorithm$] with a new promise, |transformer|.`[[frameSource]]` and |rid|.
1094
1093
1095
1094
## KeyFrame Algorithms ## {#KeyFrame-algorithms}
1096
1095
1097
1096
The <dfn abstract-op>generate key frame algorithm</dfn>, given |promise|, |encoder| and |rid|, is defined by running these steps:
1098
-
1. If |encoder| is undefined, reject |promise| with {{InvalidStateError}}, abort these steps.
1099
-
1. If |encoder| does not belong to a video {{RTCRtpReceiver}}, reject |promise| with {{InvalidStateError}}, abort these steps.
1097
+
1. If |encoder| is not an [=encoder=], reject |promise| with {{InvalidStateError}}, abort these steps.
1098
+
1. If |encoder| does not belong to a video {{RTCRtpSender}}, reject |promise| with {{InvalidStateError}}, abort these steps.
1100
1099
1. If |rid| is defined, but does not conform to the grammar requirements specified
1101
1100
in Section 10 of [[!RFC8851]], then reject |promise| with {{TypeError}} and abort
1102
1101
these steps.
@@ -1116,9 +1115,9 @@ The <dfn abstract-op>generate key frame algorithm</dfn>, given |promise|, |encod
1116
1115
1. For each |layer| in |layers| (if any), instruct |encoder| to generate a key frame for its
1117
1116
next provided video frame to that |layer|.
1118
1117
1119
-
For any {{RTCRtpScriptTransformer}}named |transformer|, the following steps are run just before any |frame| is enqueued in |transformer|.`[[readable]]`:
1120
-
1. Let |encoder| be |transformer|.`[[encoder]]`.
1121
-
1. If |encoder| or |encoder|.`[[pendingKeyFrameTasks]]` is undefined, abort these steps.
1118
+
For any [=encoder=] associated with an {{RTCRtpScriptTransformer}} |transformer|, the user agent MUST run the following steps just before any |frame| is [=ReadableStream/enqueued=] into |transformer|.{{[[readable]]}}:
1119
+
1. Let |encoder| be |transformer|.{{[[frameSource]]}}.
1120
+
1. If |encoder|.`[[pendingKeyFrameTasks]]` is undefined, abort these steps.
1122
1121
1. If |frame| is not a video {{RTCEncodedVideoFrameType/"key"}} frame, abort these steps.
1123
1122
1. For each |task| in |encoder|.`[[pendingKeyFrameTasks]]`, run the following steps:
1124
1123
1. If |frame| was generated for a layer [=list/contained=] in |task|.`[[layers]]`,
@@ -1133,7 +1132,7 @@ the resolution callbacks of the promises are always executed just before the cor
1133
1132
If the promise is associated with several layers, it will be resolved once key frames have been enqueued for all of them.
1134
1133
1135
1134
The <dfn abstract-op>send request key frame algorithm</dfn>, given |promise| and |depacketizer|, is defined by running these steps:
1136
-
1. If |depacketizer| is undefined, reject |promise| with {{InvalidStateError}}, abort these steps.
1135
+
1. If |depacketizer| is not a [=depacketizer=], reject |promise| with {{InvalidStateError}}, abort these steps.
1137
1136
1. If |depacketizer| does not belong to a video {{RTCRtpReceiver}}, reject |promise| with {{InvalidStateError}}, abort these steps.
1138
1137
1. [=In parallel=], run the following steps:
1139
1138
1. If sending a Full Intra Request (FIR) by |depacketizer|'s receiver is not deemed appropriate, [=resolve=] |promise| with undefined and abort these steps.
0 commit comments