Skip to content

Commit f683566

Browse files
authored
Merge pull request #125 from youennf/issue-124
Add API to request key frames
2 parents 4242a87 + ad75548 commit f683566

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

index.bs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ spec:webidl; type:dfn; text:resolve
2626
}
2727
}
2828
</pre>
29+
</pre>
2930
<pre class=link-defaults>
3031
spec:streams; type:interface; text:ReadableStream
3132
</pre>
@@ -140,6 +141,8 @@ As [=writeEncodedData=] ensures that the transform cannot reorder frames, this w
140141

141142
A RTCRtpTransform has two private slots called `[[readable]]` and `[[writable]]`.
142143

144+
Each RTCRtpTransform has an <dfn>association steps</dfn> set, which is empty by default.
145+
143146
The <dfn attribute for="RTCRtpSender,RTCRtpReceiver">transform</dfn> getter steps are:
144147
1. Return [=this=].`[[transform]]`.
145148

@@ -155,6 +158,7 @@ The `transform` setter steps are:
155158
7. Else, run the [=chain transform algorithm=] steps.
156159
8. Set [=this=].`[[pipeToController]]` to |newPipeToController|.
157160
9. Set [=this=].`[[transform]]` to |transform|.
161+
10. Run the steps in the set of [=association steps=] of |transform| with [=this=].
158162

159163
The <dfn>chain transform algorithm</dfn> steps are defined as:
160164
1. If |newPipeToController| is [=AbortSignal/aborted=], abort these steps.
@@ -332,6 +336,8 @@ interface RTCRtpScriptTransformer {
332336
readonly attribute ReadableStream readable;
333337
readonly attribute WritableStream writable;
334338
readonly attribute any options;
339+
Promise&lt;undefined&gt; generateKeyFrame(optional sequence &lt;DOMString&gt; rids);
340+
Promise&lt;undefined&gt; sendKeyFrameRequest();
335341
};
336342

337343
[Exposed=Window]
@@ -365,9 +371,30 @@ The <dfn constructor for="RTCRtpScriptTransform" lt="RTCRtpScriptTransform(worke
365371

366372
// FIXME: Describe error handling (worker closing flag true at RTCRtpScriptTransform creation time. And worker being terminated while transform is processing data).
367373

374+
Each RTCRtpScriptTransform has the following set of [=association steps=], given |rtcObject|:
375+
1. Let |transform| be the {{RTCRtpScriptTransform}} object that owns the [=association steps=].
376+
1. Let |encoder| be |rtcObject|'s encoder if |rtcObject| is a {{RTCRtpSender}} or undefined otherwise.
377+
1. Let |depacketizer| be |rtcObject|'s depacketizer if |rtcObject| is a {{RTCRtpReceiver}} or undefined otherwise.
378+
1. [=Queue a task=] on the DOM manipulation [=task source=] |worker|'s global scope to run the following steps:
379+
1. Let |transformer| be the {{RTCRtpScriptTransformer}} object associated to |transform|.
380+
1. Set |transformer|.`[[encoder]]` to |encoder|.
381+
1. Set |transformer|.`[[depacketizer]]` to |depacketizer|.
382+
383+
The <dfn method for="RTCRtpScriptTransformer">generateKeyFrame(|rids|)</dfn> method steps are:
384+
1. Let |promise| be a new promise.
385+
1. Run the [=generate key frame algorithm=] with |promise|, |this|.`[[encoder]]` and |rids|.
386+
1. Return |promise|.
387+
388+
The <dfn method for="RTCRtpScriptTransformer">sendKeyFrameRequest()</dfn> method steps are:
389+
1. Let |promise| be a new promise.
390+
1. Run the [=send request key frame algorithm=] with |promise| and |this|.`[[depacketizer]]`.
391+
1. Return |promise|.
392+
368393
## Attributes ## {#RTCRtpScriptTransformer-attributes}
369394

370-
A RTCRtpScriptTransformer has three private slots called `[[options]]`, `[[readable]]` and `[[writable]]`.
395+
A {{RTCRtpScriptTransformer}} has the following private slots called `[[depacketizer]]`, `[[encoder]]`, `[[options]]`, `[[readable]]` and `[[writable]]`.
396+
In addition, a {{RTCRtpScriptTransformer}} is always associated with its parent {{RTCRtpScriptTransform}} transform.
397+
This allows algorithms to go from an {{RTCRtpScriptTransformer}} object to its {{RTCRtpScriptTransform}} parent and vice versa.
371398

372399
The <dfn attribute for="RTCRtpScriptTransformer">options</dfn> getter steps are:
373400
1. Return [=this=].`[[options]]`.
@@ -378,6 +405,65 @@ The <dfn attribute for="RTCRtpScriptTransformer">readable</dfn> getter steps are
378405
The <dfn attribute for="RTCRtpScriptTransformer">writable</dfn> getter steps are:
379406
1. Return [=this=].`[[writable]]`.
380407

408+
## KeyFrame Algorithms ## {#KeyFrame-algorithms}
409+
410+
The <dfn>generate key frame algorithm</dfn>, given |promise|, |encoder| and |rids|, is defined by running these steps:
411+
1. If |encoder| is undefined, reject |promise| with {{InvalidStateError}}, abort these steps.
412+
1. If |encoder| is not processing video frames, reject |promise| with {{InvalidStateError}}, abort these steps.
413+
1. If |rids| is defined, validate each of the RID values in |rids|.
414+
If any RID value is invalid, reject |promise| with {{NotAllowedError}} and abort these steps.
415+
1. [=In parallel=], run the following steps:
416+
1. Gather a list of video encoders, named |videoEncoders| from |encoder|.
417+
1. If |rids| is not empty, remove from |videoEncoders| any video encoder that does not match a value in |rids|.
418+
1. If |videoEncoders| is empty, reject |promise| with {{NotFoundError}} and abort these steps.
419+
|videoEncoders| is expected to be empty if the corresponding {{RTCRtpSender}} is not active, or the corresponding {{RTCRtpSender}} track is ended.
420+
1. For each |rid| in |rids|, run the following substeps:
421+
1. Create a pending key frame task called |task| with ||task|.`[[rid]]` set to rid and |task|.`[[promise]]`| set to |promise|.
422+
1. If |encoder|.`[[pendingKeyFrameTasks]]` is undefined, initialize |encoder|.`[[pendingKeyFrameTasks]]` to an empty set.
423+
1. If |encoder|.`[[pendingKeyFrameTasks]]` contains a task which is matching |rid|, remove |rid| from |rids|.
424+
1. Add |task| to |encoder|.`[[pendingKeyFrameTasks]]`.
425+
1. If |rids| is not empty, remove from |videoEncoders| any video encoder that does not match a value in |rids|.
426+
1. For each |videoEncoder| in |videoEncoders|, instruct |videoEncoder| to generate a key frame for the next provided video frame.
427+
428+
For any {{RTCRtpScriptTransformer}} named |transformer|, the following steps are run just before any |frame| is enqueued in |transformer|.`[[readable]]`:
429+
1. Let |encoder| be |transformer|.`[[encoder]]`.
430+
1. If |encoder| or |encoder|.`[[pendingKeyFrameTasks]]` is undefined, abort these steps.
431+
1. If |frame| is not a video key frame, abort these steps.
432+
1. For each |task| in |encoder|.`[[pendingKeyFrameTasks]]`, run the following steps:
433+
1. If |frame| was generated by a video encoder identified by |task|.`[[rid]]`, run the following steps:
434+
1. Remove |task| from |encoder|.`[[pendingKeyFrameTasks]]`.
435+
1. Resolve |task|.`[[promise]]` with undefined.
436+
437+
By resolving the promises just before enqueuing the corresponding key frame in a {{RTCRtpScriptTransformer}}'s readable,
438+
the resolution callbacks of the promises are always executed just before the corresponding key frame is exposed.
439+
If the promise is associated to several rid values, it will be resolved when the first key frame corresponding to one the rid value is enqueued.
440+
441+
The <dfn>send request key frame algorithm</dfn>, given |promise| and |depacketizer|, is defined by running these steps:
442+
1. If |depacketizer| is undefined, reject |promise| with {{InvalidStateError}}, abort these steps.
443+
1. If |depacketizer| is not processing video packets, reject |promise| with {{InvalidStateError}}, abort these steps.
444+
1. [=In parallel=], run the following steps:
445+
1. If sending a Full Intra Request (FIR) by |depacketizer|'s receiver is not deemed appropriate, [=resolve=] |promise| with undefined and abort these steps.
446+
Section 4.3.1 of [[RFC5104]] provides guidelines of how and when it is appropriate to sending a Full Intra Request.
447+
1. Generate a Full Intra Request (FIR) packet as defined in section 4.3.1 of [[RFC5104]] and send it through |depacketizer|'s receiver.
448+
1. [=Resolve=] |promise| with undefined.
449+
450+
# RTCRtpSender extension # {#rtcrtpsender-extension}
451+
452+
An additional API on {{RTCRtpSender}} is added to complement the generation of key frame added to {{RTCRtpScriptTransformer}}.
453+
454+
<pre class="idl">
455+
partial interface RTCRtpSender {
456+
Promise&lt;undefined&gt; generateKeyFrame(optional sequence &lt;DOMString&gt; rids);
457+
};
458+
</pre>
459+
460+
## Extension operation ## {#sender-operation}
461+
462+
The <dfn method for="RTCRtpSender">generateKeyFrame(|rids|)</dfn> method steps are:
463+
464+
1. Let |promise| be a new promise.
465+
1. [=In parallel=], run the [=generate key frame algorithm=] with |promise|, |this|'s encoder and |rids|.
466+
1. Return |promise|.
381467

382468
# Privacy and security considerations # {#privacy}
383469

0 commit comments

Comments
 (0)