W3C home > Mailing lists > Public > public-webrtc@w3.org > May 2015

Re: Attributes! (Re: Proposal: Add RtpSenderInit parameter to addTrack.)

From: Peter Thatcher <pthatcher@google.com>
Date: Fri, 1 May 2015 13:00:12 -0700
Message-ID: <CAJrXDUE+eh6VHbwUtXhwUmr4y+hK5R7_2Ka_2VSiW1UCrtA4OA@mail.gmail.com>
To: Jan-Ivar Bruaroey <jib@mozilla.com>
Cc: "Cullen Jennings (fluffy)" <fluffy@cisco.com>, "public-webrtc@w3.org" <public-webrtc@w3.org>
On Fri, May 1, 2015 at 12:39 PM, Jan-Ivar Bruaroey <jib@mozilla.com> wrote:

>  On 5/1/15 1:43 PM, Peter Thatcher wrote:
>
>  I'll repeat some text I wrote previously about replaceTrack:
>
>
>  In the work in the ORTC CG, we chose to follow the .setFoo pattern
> rather than the .foo= for all things, not just setTrack for the following
> reasons:
>
>  1.  It allows return values, async and sync.  You might think you don't
> want one now, but you might want to add one later.
> 2.  It allows async errors.
> 3.  It allows for adding additional parameters.  You might think you don't
> want one now, but you might want to add one later.
>
>
> Is "you" the implementer? If so, then I think this violates the priority
> of constituencies. [1]
>
>   Specifically, in your example:
>
>      var fooParameters = foo.getParameters();
>     fooParameters.bar = "big";
>     fooParameters.fum = " deal";
>     foo.setParameters(fooParameters)
>
>  That's exactly the situation we want to encourage, because it allows and
> encourages the setting of parameters to be atomic.  Doing something like
> this is madness:
>
>  foo.parameters.bar = "big";
> foo.parameters.fum = " deal";
>
>  Because then you have all this half-set stuff and you have to reason
> about what those things mean when half-set.
>
>
> To be clear, we're talking about implicit action from changing a grab-bag
> of *discrete* settings, not splitting atoms.
>
> This is not multi-threaded c++ where how long to wait to respond to a bag
> of discrete changes is tricky. JavaScript is event-driven:
>
>     var foo = {};
>     Promise.resolve(() => log(foo.bar + foo.fum); // ALWAYS emits "big
> deal"!
>     foo.bar = "big";
>     foo.fum = " deal";
>
> which means there's a quite valuable inherent end to any set of sequential
> actions: the completion of the current task. Any update or refresh task
> need only be scheduled after the end of the current task to solve all
> "half-set" problems.
>
> I see no need to coerce discrete changes into atomic bundles (pardon the
> oxymoron) in such a model.
>
>   Finally, I don't think it makes sense to have RtpParameters and
> RtpSenderInit be the same class because there are certain arguments which
> can change (stuff in RtpParameters) and certain arguments which can't
> change (label).  If we put label, for example, into RtpParameters, that
> would imply that it can change via setParameters.  On the other hand, if we
> either want other things in RtpParameters to be unchangable or if we have
> no things we want to have be unchangable (we remove the ability to set the
> label, for example), then RtpParameters could be the same class as
> RtpSenderInit.
>
>
> You misunderstand, I want to replace RtpParameters with attributes on
> RtpSender. E.g.
>

​I think making all the parameters of RtpParameters into attributes of
RtpSender is a terrible idea.  Every time a change to parameters is made,
it's basically telling the RtpSender "stop what you're currently sending,
and send something different", and if the JS is going to change 5 different
things, it wants to change them all at once so that before the call to
setParameters, the RtpSender is sending one thing, and then after the call,
it's sending a different thing.  We don't want a situation where after each
line of JS there's a different things being sent.

For example, look at the RtpParameters in ORTC:

dictionary RTCRtpParameters {
             DOMString                                 muxId = "";
             sequence<
​​
RTCRtpCodecParameters>           codecs;
             sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
             sequence<RTCRtpEncodingParameters>        encodings;
             RTCRtcpParameters                         rtcp;
};

​If the JS wants to change both the codecs and headerExtensions, it doesn't
want to do:

sender.parameters.codecs = newCodecs;
sender.parameters.headerExtensions = newHeaderExtensions;

​Because in between those two lines, you'll end up in a weird state where
you are sending the new codecs but the old header extensions.  And, worse,
what if you setup something invalid on the header extensions, and it throws
an exception?  Now you're doing half old and half new.  And as you expand
it from 2 different settings like this to 5 different things, it gets even
more problematic.

But the problems don't end ther​
​
​e, because the ​objects are more than one level deep.  Imagine the JS does
this:

var first = sender.parameters.codecs.splice(0, 1);
sender.parameters.codecs.push(first);


​Now there's an intermediate state where the codec is missing.  ​
​
​And what if there were only one codec in the list to begin with?  Does the
sender stop sending in the intermediate state?


​And I could come up with a lot more examples.  The point is that there
will be intermediate sender states for every little operation the JS does,
and reasoning about those states is too complex.  It's much easier to have
one atomic operation done via setParameters.​
​






​
​


​


>
> - label would exist as a member in RtpSenderInit and as a readonly
> attribute on RtpSender.
> - voiceActivityDetection would exist as a member in RtpSenderInit and as
> an attribute on RtpSender.
>
> Just like everywhere else the InitDict pattern is used.
>
> .: Jan-Ivar :.
>
> [1]
> http://www.w3.org/TR/html-design-principles/#priority-of-constituencies
>
>
Received on Friday, 1 May 2015 20:01:20 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 15:19:44 UTC