A clarification on Capabilities, Parameters, createParameters, and filterParameters.

Lately, there seems to be some confusion about what Capabilities,
Parameters, createParameters, and filterParameters are and how they are
meant to be used.  Since I'm the one that first proposed them, I'd like to
clear up what they mean.

Principle #1:  ORTC is a "do what I say" API, and Parameters are how the JS
tells the browser "here's what to do".

All signalling and negotiation ultimately result in the sender saying "send
X" and the receiver saying "receive X", and the Parameters are how the JS
says "X".  For RTP, "X" is RtpParameters, and the methods
are RtpSender.send(RtpParameters) and RtpSender.receive(RtpParameters).

If we get this mechanism right, then all signalling and negotation
mechanisms can be built on top in JS.


Principle #2:  Capablities are how the browser tells the JS "here's what I
can do".

The JS can't tell the browser what to do (well) if it doesn't now what the
browser can do.  That last statement in Principle #1 about the JS being
able to do all the negotiation isn't quite right because it cannot figure
out how to create Parameters correctly if it doesn't know what is allowed
and what isn't.  Thus, we need a way of expressing what the browser can do.
 That's Capabilities.  For RTP, it's RtpCapabilities.

Once we have getCapabilities, send(RtpParameters) and
receive(RtpParameters), we have everything we need in the browser.
 Everything else could be done in JS.


Principle #3:  createParameters is a convenience function to make the
simple use cases simple.

It's nice to have a simple, powerful, low-level API of "here's what I can
do" and "here's what I can do", but for simple use cases, it's a lot of
work to fill in Parameters properly in the first place.  So, we create a
convenience function which works for the simple use cases, so that
developers don't need to fill in the Parameters manually.

Note that we pass the capabilities into the createParameters as a
convenience to 1.  Allow created parameters to match remote capabilities
easily, and 2.  To have a convenient place to turn off certain things.  For
example, if you don't want a specific codec or RTP feature, you can just
remove it from the capabilities before calling createParameters.  At times
this may be more convenient than removing it from the Parameters after
calling createParameters.

It's all about convenience.  We could implement createParameters purely in
JS and leave it out of the browser entirely.  But it's a large benefit for
simple use cases at a small complexity cost, so I think it's worth it.
 More complex use cases can fill in Parameters in more advanced ways
without using createParameters.


Principle #4:  filterParameters is a convenience function to make certain
simple use cases easier.

If endpoints always exchange capabilities and then call createParameters
with their respective capabilities, then filterParameters would never be
needed.  We would only need createParameters.

But sometimes, it's desirable to do signalling/negotiation in one round
trip. And often to this means that the "initiator" must create and send
parameters (sometimes called an "offer") with no knowledge of the
"responder"'s capabilities. At some point, someone (either the initiator or
responder) must alter the parameters according to the capabilities of the
responder before telling the browser "here's what to do".

This could be done entirely in JS, but for simple use cases, that's kind of
a pain, so we introduce a second convenience function: filterParameters.
 It has a simple meaning:

filterParameters(createParameters(), C) == createParameters(C)

In other words, if createParameters() called with no knowledge of
capabilities produces P1, then filterParameters(P1, C) will give the
parameters that createParameters(C) would have returned had the original
caller of createParameters() known the capabilities.  We could call this
createParameters(P, C) instead of filterParameters(P, C), if we think it's
a better name.

That's it.  It's pure convenience and could be done in JS.  If we feel like
the complexity is too difficult to get right in the standard, then we can
remove it from the standard and tell developrs "you have to exchange
capabilities first and pass those down into createParameters or do the
negotiations yourself".


Principle #5:  These 4 things together (Capabilities, Parameters,
createParameters, filterParameters) allow for lots of different
signalling/negotiation mechanisms.  It isn't tied to just one.

Sometimes we are used to a certain signalling/negotiation mechanism (such
as offer/answer), and get all caught up trying to optimize things for the
one we are used to or like.  For example, the WebRTC 1.0 API is heavily
optimized for SDP offer/answer.  This model is the opposite.  It isn't tied
to any signalling/negotiation mechanism.  It allows you to do any, and it
allows you to do many without much inconvenience.

For example, you can:
1.  Exchange capabilities, and then parameters use createParameters (2
round trips, but extremely easy).
2.  Do offer/answer exchanging capabilities and parameters, using
createParameters and filterParameters (1 round trip, but only a little more
complex)
3.  Do offer/answer exchanging only parameters, using createParameters and
filterParameters.
4.  Decide things apriori, create parameters manually, and have zero round
trips of signalling.
5.  Do lots of advanced stuff manually using Capabilities and Parameters
and not use createParameters or filterParameters at all.


Principle #6:  We strike a balance between power, simplicity, and
convenience.

Parameters and Capabilities give the JS all the power it needs.

createParameters and filterParameters give it much convenience at the cost
of some simplicity.

Anything more will need to justify the additional complexity with increases
in power or convenience.  It filterParameters, for example, is too complex
to justify the additional convenience, then we can remove it.



I hope this clears things up.

Received on Friday, 9 May 2014 17:55:32 UTC