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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

make generateKeyFrame take a list of rids and return a promise<undefined> #165

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

fippo
Copy link
Collaborator

@fippo fippo commented Nov 29, 2022

making it request a key frame for each rid or all of them if the list is empty.

Returning a promise resolving with a timestamp is not necessary since requesting a key frame is something the encoder might not be able or willing to satisfy.


馃挜 Error: connect ETIMEDOUT 173.230.149.95:443 馃挜

PR Preview failed to build. (Last tried on Jan 10, 2023, 10:54 AM UTC).

More

PR Preview relies on a number of web services to run. There seems to be an issue with the following one:

馃毃 CSS Spec Preprocessor - CSS Spec Preprocessor is the web service used to build Bikeshed specs.

馃敆 Related URL

If you don't have enough information above to solve the error by yourself (or to understand to which web service the error is related to, if any), please file an issue.

@fippo fippo changed the title make generateKeyFrame take a list of rids and return void make generateKeyFrame take a list of rids and return undefined Nov 29, 2022
making it request a key frame for each rid or all of them if
the list is empty.

Returning a promise resolving with a timestamp is not necessary
since requesting a key frame is something the encoder might
not be able or willing to satisfy.
@fippo
Copy link
Collaborator Author

fippo commented Nov 29, 2022

discussed at the October 2022 meeting: https://www.w3.org/2022/10/18-webrtc-minutes.html#t03

@alvestrand
Copy link
Contributor

Discussed at the December meeting. Needs update to return promise.

@fippo
Copy link
Collaborator Author

fippo commented Dec 14, 2022

updated. @dontcallmedom will need to slap the IPR bot who seems to have forgotten we're friends again ;-)

@dontcallmedom
Copy link
Member

the IPR bot seems to be happy without any slapping involved

@fippo fippo changed the title make generateKeyFrame take a list of rids and return undefined make generateKeyFrame take a list of rids and return a promise<undefined> Dec 15, 2022
1. Instruct the encoder associated with |sender| to generate a key frame for |rids| or all layers when |rids| is empty.
1. Resolve |promise| with `undefined`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to resolve the promise when the key frame is being queued, this is what the current spec is asking and is a nice addition in the case of script transform.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will introduce unnecessary complexity to what was supposed to be as a simple key frame generation mechanism. And will make scenarios involving multiple streams (active, inactive, restricted) not only hard to define in specification, but even more harder to implement in user agents.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This complexity is fairly limited in the case of script transform, please have a look at how this is already implemented in WebKit.
For the sender API, I agree the usefulness is reduced, we could consider relaxing the resolution timing if it proves difficult to implement.

not only hard to define in specification

This is already defined in the spec for the script transform code path.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think anyone considered awaiting useful at TPAC, to quote the minutes:

this can be done by waiting to a keyframe in the stream before doing the key change"

With multiple rids when do you resolve?
On the first keyframe (regardless of layer) or do you wait for all of them? Return an array of promises?
What about cases like turning off the lowest simulcast layer and asking for a keyframe? Surprise (thankfully not returning an RTP timestamp you don't expect anymore).
What if the highest layer is disabled due to bandwidth restrictions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the first keyframe (regardless of layer) or do you wait for all of them? Return an array of promises?

On the first keyframe of any layer would make sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What usecase does resolving on a "random" keyframe solve? Also how do you avoid this keyframe being triggered by another operation such as changing the size?

1. If |rids| is defined, for each |rid| in rids,
1. if |rid| is not associated with |sender|, reject Promise with an {{InvalidAccessError}} and abort these steps.
1. Instruct the encoder associated with |sender| to generate a key frame for |rids| or all layers when |rids| is empty.
1. Resolve |promise| with `undefined`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. this should happen in a "queue a task" or "in parallel", so that it's obviously async
  2. we should guarantee that the promise resolves before the first of the keyframes arrives at the transform.

index.bs Outdated
@@ -658,7 +633,7 @@ partial interface RTCRtpSender {
The <dfn method for="RTCRtpSender">generateKeyFrame(|rids|)</dfn> method steps are:

1. Let |promise| be a new promise.
1. [=In parallel=], run the [=generate key frame algorithm=] with |promise|, |this|'s encoder and |rids|.
1. Run the [=generate key frame algorithm=] with |promise|, |this| and |rids|.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch removes in-parallel, making this algorithm synchronous while still returning a promise, which is an anti-pattern.

We'd need to either restore in-parallel or drop the promise, for this to make sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, three fell in one swoop ;-)

@youennf
Copy link
Collaborator

youennf commented Jan 26, 2023

I'll have a deeper look before next week editor's meeting.

@youennf
Copy link
Collaborator

youennf commented Feb 2, 2023

I had some more thoughts about this.
If the corresponding rid encoding is not active, or if sender is not sending at all (track is null or transceiver current direction is receive only), we probably want to reject.

We do not want to resolve the promise until this check is done, but this check will be done in parallel, close to the encoder for both requestKeyFrame variants. That removes the possibility for resolving the promise as soon as getting a key frame for one of the given rid in the transformer case. Or we would need to wait for the check result to actually start looking at key frames, which is probably not worth the extra work.

the resolution callbacks of the promises are always executed just before the corresponding key frame is exposed.
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.
The <dfn>generate key frame algorithm</dfn>, given |promise|, |sender| and |rids|, is defined by running these steps:
1. If the sender's transceiver kind is not `video`, reject |promise| with an {{OperationError}} and abort these steps.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NoSupportedError would be more adequate maybe?

The <dfn>generate key frame algorithm</dfn>, given |promise|, |sender| and |rids|, is defined by running these steps:
1. If the sender's transceiver kind is not `video`, reject |promise| with an {{OperationError}} and abort these steps.
1. If |rids| is defined, for each |rid| in rids,
1. if |rid| is not associated with |sender|, reject Promise with an {{InvalidAccessError}} and abort these steps.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

associated with is not really clear to me. Maybe we could reuse webrtc-pc terminology. something like if sender's media stack is not configured with |rid| as active,

I also think we should reject if the sender is not actively sending (its track is null or current direction does not include send). I am not exactly sure of which wording to use, maybe something like if sender's media stack is not actively sending media.

It might also more accurate to queue a task to reject the Promise in the Promise realm event task loop, since all of those checks are done close to the encoder.

1. If the sender's transceiver kind is not `video`, reject |promise| with an {{OperationError}} and abort these steps.
1. If |rids| is defined, for each |rid| in rids,
1. if |rid| is not associated with |sender|, reject Promise with an {{InvalidAccessError}} and abort these steps.
1. Instruct the encoder associated with |sender| to generate a key frame for |rids| or all layers when |rids| is empty.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make it clear that the promise gets resolved in the transformer context before any key frame triggered by this step is enqueued in the transformer readable stream. This PR is removing line 633-635 which was a similar statement with stronger-but-no-longer-valid guarantees.

@dontcallmedom-bot
Copy link

This issue was mentioned in WEBRTCWG-2023-05-16 (Page 27)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants