- From: Erik Lagerway <erik@hookflash.com>
- Date: Wed, 7 May 2014 23:38:00 -0700
- To: Robin Raymond <robin@hookflash.com>
- Cc: "public-ortc@w3.org" <public-ortc@w3.org>
- Message-ID: <CAPF_GTZOtWy8sYYdga7j0oV7AnqncV9CG8F5bWgAmtN1r7b7kg@mail.gmail.com>
Great piece of work here Robin. I like the simplicity in the concepts and thanks for including the SVC use cases! /Erik *Erik Lagerway <http://ca.linkedin.com/in/lagerway> | *Hookflash<http://hookflash.com/>* | 1 (855) Hookflash ext. 2 | Twitter <http://twitter.com/elagerway> | WebRTC.is Blog <http://webrtc.is/> * On Wed, May 7, 2014 at 9:13 PM, Robin Raymond <robin@hookflash.com> wrote: > > I am contributing a proposal on how to resolve an issue discovered in the > usage of "parameters". While the details can always be tweaked, I think it > successfully resolves much of the concern around the level and knowledge > required to configure a "parameters" object for anything other than the > basic use cases. > > In response to this posting: > http://lists.w3.org/Archives/Public/public-ortc/2014May/0007.html > > This also addresses the issue of exchanging detailed parameters over the > wire and instead base parameters based on capabilities. > > I am going to copy the entire proposal below to official contribute the > proposal but for the sake of readability I am also including a link to the > google doc(s). > > Proposal-ORTC Sender / Receiver Capabilities Based Model > > https://docs.google.com/document/d/1htyRaNjXTE_O1GhD8TcLCNXFvVsgszpE8Lqgp3OCHlU/edit?usp=sharing > > Proposal-ORTC Sender / Receiver Use Case [Usage Comparison Analysis] > > https://docs.google.com/document/d/1hdhCHj-gpwv06vIbAftxMG3oZtz7A-nuYsuwQEkTat4/edit?usp=sharing > > > > > Proposal-ORTC Sender / Receiver Capabilities Based Model > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > *IntroductionAfter attempting to write out some use cases using the > existing RTCRtpSender and RTCRtpReciever objects and parameters for ORTC, > some issues were discovered. Specifically, the application developer would > need to have a fair amount of knowledge on exactly how to tweak low level > parameters for anything beyond very simple use cases. For example, setting > up an SVC (Scalable Video Codec) would have required knowing about what > codecs support SVC, how the layering is setup for particular codecs, and > finally setting up specific geometric (or temporal) attributes and layering > relationship details by an application developer.As a result of the lack of > easily configuration of RTP features, the idea came out to give the > application developer "preferences" where the developer could choose what > they want desire with high level knobs and dials and let the engine (which > has explicit knowledge of each codec) configure the low level "parameters" > details according to a developer's wishes. The engine could then return the > closest set of preferences that could be achieved given the capabilities of > the engine and the developer can then choose to proceed or not setting up > media flows using these preferences and constructed parameters.Another > important discovery was made in the process of defining "preferences". If > two ORTC engines were given the same set of preferences and the > capabilities of both sender and receiver, each engine could be made to > construct "compatible" sender and receiver "parameters" details without > ever exchanging the parameter details over the wire. This small realization > about generating "parameters" from capabilities for local consumption by an > engine has a huge impact. This generation removes the need for an engine to > understand and filter settings that it may not understand created by > another engine of unknown origin, which may use proprietary and/or custom > settings. A simple "ignore capabilities you don't understand" rule could > replace complex and cumbersome rules that would be otherwise required if > "parameters" were to be sent over the wire and later filtered using a set > of capabilities.Parameters can be generated based on the union of sender > and receiver capabilities along with application developer preferences > being used as a guideline on how to create the parameters. The engine will > do it’s best to fulfill the preferences and it will return the parameters > that are possible given the union of the capabilities.Two different engines > must be able to compute compatible parameters given all the same > preferences and capabilities. Fortunately, any two engines that understand > the same capabilities can easily follow the same rules to generate > compatible parameters. While the parameters created on the sender and > receiver are required to be "compatible", they need not be identical. The > application developer should call "createParameters(...)" on sender to > create parameters suitable for the sender. The application developer should > call "createParameters(...)" on the receiver to create params suitable for > a receiver. The calculated “parameters” for both sender and receiver have > to be compatible only to the extent that whatever a sender produces a > receiver must be capable of decoding.The application developer has the > option to tweak the detailed parameters output by "createParameters(...)" > but should only do so with extreme caution. The resultant parameters output > by "createParameters(...)" are only meant for local consumption by the > local sender / receiver “start” methods. Sending these created parameters > over the wire is discouraged because implementations may produce objects > which may not be entirely understable by the remote party, even though the > media sent on the wire will be compatible. Differences from Current Sender > / Receiver APIBoth models and APIs are more similar than they are > different. The subtle differences make important behavioural usage > implications.Both models send and receive based upon "parameter" settings. > The difference is in how the "parameters" are generated. The new model > generates the "parameters" based on an exchange of capabilities and the > application developer is given convenient 'knobs' called "preferences" to > perform most common use cases. The "parameters" in the new model are > intended for local consumption only and the application developer is not > required (and actively discouraged) from marshalling these "parameters" > over the wire. The new model proposes marshaling and exchanging > "capabilities" and optionally "preferences" and then generating compatible > "parameters" based on those exchanges.In both models, the application > developer may choose to tweak low level parameters should specific > compatibilities be required. But the "preferences" model allows most > application developers to completely ignore the low level > parameters.Advantages of the New Capabilities ModelOverall the proposed > capabilities based API has strong advantages. Main advantages are: 1. > Simplicity in setup based on "preferences" for the application developer2. > Less brittle designs/implementations since low level parameters are not > exchanged, filtered, and interpreted by different browser engines3. Much > less knowledge (and often no pre-knowledge) is required for the application > developer to take full advantage of a browser's capabilities RTCRtpSender / > RTCRtpReceiverinterface RTCRtpSender { // ... static RTCRtpParameters > createParameters( MediaStreamTrack track, Capabilities receiverCaps, > optional (RTCRtpAudioPreferences or RTCRtpVideoPreferences > or RTCRtpSimulcastPreferences) prefs, optional Capabilities > senderCaps // optional as system can obtain this information ); void > start(RTCRtpParameters params); // ...);interface RTCRtpReceiver { // ... > static RTCRtpParameters createParameters( DOMString kind, > Capabilities senderCaps, optional (RTCRtpAudioPreferences or > RTCRtpVideoPreferences or > RTCRtpSimulcastPreferences) prefs, optional Capabilities > receiverCaps // optional as system can obtain this information ); void > start(RTCRtpParameters params); //...); RTCRtpMediaPreferences// This is > the base dictionary used for both audio and video preferences and > represents// the set of common preferences that are available for both > media types.dictionary RTCRtpMediaPreferences { // If not specified, > system will choose value. If specified, this receiverId will // be > applied to primary SSRC “as is”. If more than one SSRC is needed to encode > // the stream (e.g. FEC, RTX, MST, simulcast), where the meaning of the > RTP packet // with that alternative SSRC cannot be determined by the > media flow itself, the // alternative SSRCs will construct a receiverId > value based upon this receiverId // value. DOMString > receiverId; // This is the primary SSRC to use. Should > alternative SSRCs be required (e.g. FEC, // RTX, MST, simulcast), all > other SSRCs should be assigned sequentially starting // from the chosen > SSRC value. unsigned int ssrc; // For a sender, force the > chosen codec to be the codec within the RTCRtpCapabilities // with this > name. If possible to choose this codec, the system will confirm by // > choosing this codec in the result from "createParameters(...)". // This > value has no meaning for a receiver since a receiver must be capable // > of receiving any of the compatible codecs within the union > RTCRtpCapabilities. // A non specified value indicates the system will > choose the preferred sending // codec. DOMString > codecName; // This value indicates the relative importance of > the media being sent with a // sender versus other media being sent. The > logic is that all sent media with // the same priority will be treated as > having an equal priority. Those with // a greater value will be given a > greater priority and those with a lower value // will be given a lower > priority. The value is relative meaning a value of 2.0 // should be given > roughly 2 times the priority vs a 1.0 value and a value of 4.0 // should > be given roughly 4 times the priority vs a 1.0 value. double > relativePriority = 1.0; // This value indicates the > maximum bit rate the media is allowed to output as // a combined whole > (including all layers, FEC, RTX, etc). The system will filter // out > codecs that are not capable of delivering below this bit rate unless no > // codec is possible in which case the system will chose the minimal > codec bit rate // possible and will override with a different maximum bit > rate in the result of // "createParameters(...)". double > maxBitrate; // engine, keep under this rate > // These values indicates the preferred treatment of FEC/RTX for the RTP > packets. For // audio, some audio codecs have built in FEC/RTX mechanisms > in which case if the // codec is capable, the codec should enable its > FEC/RTX mode if value is set to all // for that codec rather than > creating an additional RTP flow. RTCRtpRecoveryOptions fec = "none"; > RTCRtpRecoveryOptions rtx = "none";};enum RTCRtpRecoveryOptions { > "all", // apply to all layers "base", // only apply for base > (audio will treat "base" as equivalent to "all") "none" // do not > apply to any layer}; RTCRtpAudioPreferencesdictionary > RTCRtpAudioPreferences : RTCRtpMediaPreferences { // If not 0, tells the > engine to pick and configure codecs that are capable of // the minimum of > channels (if possible). If not possible, the minimum number of // > channels will be returned in the result of "createParameters(...)". > unsigned int minChannels = 0; // If not 0, tells the engine to > pick a codec and configure codecs which are // capable of delivering the > minimum Hz rate as indicated. If not possible, the // minimum Hz rate > will be returned in the result of "createParameters(...)" unsigned int > minHzRate = 0; // The engine will choose and configure the codecs > best able to deliver the level // of fidelity requested. > RTCRtpAudioFidelity fidelity = "speech";};enum RTCRtpAudioFidelity { > "speech", // speech only is expected so Hz range only need to support > the vocal range "music", // music is expected, choose stereo compatible > and minimal 32000 Hz "movie" // music / sound effects expected, choose > surround and highest Hz available}; RTCRtpVideoPreferences (and > related)dictionary RTCRtpVideoPreferences : RTCRtpMediaPreferences { // > minFrameRate, minScale, and minQuality each indicate that the engine must > do // it's best effort to keep the frame rate, scale or quality above a > certain minimal // level. When using SVC, these values will hint at the > requirements typically needed // for the base layer. // // > minFrameRate is specified in frames per second. double minFrameRate = > 0; // please engine, keep equal or above this rate // minScale is a > relative value from 0.0 to 1.0 where 1.0 represents full input stream // > width/height is requested and 0.0 represents no minimize size is requested. > // The value of minScale is multiplied by the source video window width > and height // to calculate a minimal width and height that is relative to > source size. double minScale = 0; // please engine, keep equal > or above this scale // Alternatively, a specific fixed minimal width and > height can be requested. double minWidth = 0; // please > engine, keep above X pixels wide double minHeight = 0; // > please engine, keep above Y pixels high // minQuality is a relative value > from 0.0 to 1.0 where 1.0 means maximum output // quality is requested > for a given codec and 0.0 allows any minimal codec quality // output is > deemed acceptable. double minQuality = 0; // please engine, keep > equal or above this quality // The engine needs values to help decide > what to sacrifice when network conditions // are not ideal. The > frameRatePriority, scalePriority, and qualityPriority indicate // the > relative importance of each aspect of the video relative to the other (or > // 0.0 which means the video aspect has no significance (with exclusion > to the minimum // above). The values are relative to each other thus a > value of 2.0 vs 1.0 has // roughly 2 times the importance and a value of > 4.0 vs 1.0 has roughly 4 times the // importance (relatively speaking). > double frameRatePriority = 1.0; // priority of frame rate double > scalePriority = 1.0; // priority of scale double > qualityPriority = 1.0; // priority of quality // If a type of SVC > layering is desired, the frameRateScalabilityOptions, // > scalingScalabilityOptions, and qualityScalabilityOptions should be set to a > // non-null value for each SCV type desired. The details of the // > RTCRtpScalabilityOptions dictionary will indicate the desired details for > // each individual SVC type requested. // // Default of null > indicates no SVC of specific type is requested. RTCRtpScalabilityOptions? > frameRateScalabilityOptions = null; RTCRtpScalabilityOptions? > scalingScalabilityOptions = null; RTCRtpScalabilityOptions? > qualityScalabilityOptions = null;};dictionary RTCRtpScalabilityOptions { > // If the alternative value other than the default value of null is > specified, this // indicates to the engine the precise number of layers > desired (if possible for a // given codec to deliver these layers). If > null, the engine is free to choose // the default layering statically or > dynamically dependent upon the codec // capabilities. unsigned int? > layers = null;}; RTCRtpSimulcastPreferencesdictionary > RTCRtpSimulcastPreferences { // This value indicates the maximum bit rate > all media is allowed to output as // a combined for all simulcast > streams. double? maxBitrate = null; // engine, > keep under this rate sequence<RTCRtpVideoPreferences> > simulcastStreams;};RTCRtpParameters// Typically this object is constructed > by the RTCRtpSender for local consumption by// the RTCRtpSender and by the > RTCRtpReceiver for local consumption by a RTCRtpReceiver.// This is a > "shotgun" object, meaning the developer is given the power of a "shotgun"// > pointed at their feet and they can mess with this object at their own peril > should// they need to modify it for unusual compatibility reasons. Normal > use cases should not// require modifying the values within this structure > and marshalling this structure for// remote consumption by another browser > engine is highly discouraged.dictionary RTCRtpParameters { // When > returned as a result, the system will express the actual chosen preferences > // possible to best fulfill the preferences given the capabilities. In > other words, // the developer can't always get what they want; but if > they try sometimes, they will // get what they need. > (RTCRtpAudioPreferences or RTCRtpVideoPreferences or > RTCRtpSimulcastPreferences) preferences; // the capabilities of both > sender and receiver [value "as is" when passed // > "createParameters(...)]" RTCRtcCapabilities senderCapabilities; > RTCRtcCapabilities receiverCapabilities; // This value contains all the > particularly low level details of how the engine // will encode the media > on the wire. (RTCRtpParameterAudioDetails or > RTCRtpParameterVideoDetails or RTCRtpParameterSimulcastDetails) > details; // The chosen RTP features based upon the union of the > capabilities. Settings rtpFeatures; // The chosen RTP extensions and > configurations based upon the union of // the capabilities. > sequence<RTCRtpHeaderExtensionParameters>? headerExtensions = > null;};RTCRtpParameterDetails// This is the base dictionary of common > parameters needed for both audio and video media// types. Audio and video > will each have their own set of specific parameters depending// upon the > media type.dictionary RTCRtpParameterDetails { DOMString > receiverId = ""; // use this receiver ID for RTP stream ("" = > N/A) unsigned int ssrc = null; // using this SSRC for RTP > stream DOMString fecReceiverId = ""; // use this receiver ID for > FEC RTP ("" = N/A) unsigned int? fecSsrc = null; // using this > SSRC for FEC (null = N/A) Settings fec; // modes > of operation related to FEC DOMString rtxReceiverId = ""; // use > this receiver ID for RTX RTP ("" = N/A) unsigned int? rtxSsrc = null; > // using this SSRC for FEC (null = N/A) Settings rtx; > // modes of operation related to RTX // null for a sender. > For a receiver, this must contain the source SSRC to // use for RTCP > Receiver Reports (RRs). unsigned int? rtcpSsrc = null; // If true, > the engine will mux RTCP with RTP on the same RTCIceTransport. If false, > // the engine will send RTCP reports on the associated RTCP > RTCIceTransport component. boolean rtcpMux = true;}; > RTCRtpParameterAudioDetails (and related)dictionary > RTCRtpParameterAudioDetails : RTCRtpParameterDetails { // Contains a list > of audio codec options per possible to use codecs. The order // of the > codecs is in preferred order. sequence<RTCRtpParameterAudioCodecDetails> > codecDetails;};dictionary RTCRtpParameterCodecDetails { // The name of > the codec as related to the codec name(s) contained within the codecs // > listed within the RTCRtpCapabilities dictionaries. DOMString > codecName; unsigned byte payloadType; // actual payload > type sent on wire Settings formatsParameters; // detailed settings > chosen for related codec};dictionary RTCRtpParameterAudioCodecDetails : > RTCRtpParameterCodecDetails { // nothing anything required at this > time?}; RTCRtpParameterVideoDetails (and related)dictionary > RTCRtpParameterVideoDetails : RTCRtpParameterDetails { double > scale = 1.0; // 0..1 relative scale from source double > frameRate = 1.0; // 0..1 relative frame rate from source > double quality = 1.0; // 0..1 relative quality from source > // Contains a list of video codec options per possible to use codecs. The > order // of the codecs is in preferred order. > sequence<RTCRtpParameterVideoCodecDetails> codecDetails;};dictionary > RTCRtpParameterVideoCodecDetails : RTCRtpParameterCodecDetails { // When > layering is used, this value contains a sequence containing the layer // > information as needed for the related codec. > sequence<RTCRtpParameterVideoLayerDetails>? layers = null;};dictionary > RTCRtpParameterVideoLayerDetails { // Value is set if required for > describing the dependency tree information for // the codec's layers. > DOMString layerId = ""; // Value is null for the base > layer or if dependencies are not needed to be // described (as may be the > case for dynamic SCV codecs). If set, the value // contains a list of > layers this layer is dependent upon (thus allowing a // dependency > tree/graph to be created). sequence<DOMString>? layerIdDependencies = > null; RTCRtpScalabilityType? layerScalabilityType = null; // null would > be for base DOMString receiverId = ""; // use this receiver > ID in layer ("" = N/A) unsigned int? ssrc = null; // if > layer uses its own SSRC (null = N/A) double? frameRate = > null; // framerate for layer (for temporal SVC) double? > scale = null; // scale applied to layer (for spatial > SVC) double? quality = null; // quality applied to layer > (for quality SVC) DOMString fecReceiverId = ""; // receiver > ID for FEC RTP ("" = N/A) unsigned int? fecSsrc = null; // > using this SSRC for FEC (null = N/A) Settings fec; > // modes of operation related to FEC DOMString > rtxReceiverId = ""; // receiver ID for RTX RTP ("" = N/A) > unsigned int? rtxSsrc = null; // using this SSRC for FEC > (null = N/A) Settings rtx; // modes of > operation related to RTX};enum RTCRtpScalabilityType { "temporal", > "spatial", "quality"};RTCRtpParameterSimulcastDetails (and > related)dictionary RTCRtpParameterSimulcastDetails { // This sequence > contains the details of each simulcasted stream when simulcasting // is > used or will contain exactly 1 video stream details when not simulcasting. > sequence<RTCRtpParameterVideoDetails>? simulcastStreams;}; RTCRtpCodec > Dictionary Tweakdictionary RTCRtpCodec { DOMString name = ""; // > Added to be able to pick payload type based upon sender or receiver so they > match // when creating both the sender and receiver parameters. > unsigned byte preferredPayloadType; unsigned int? clockRate = null; > unsigned int? numChannels = 1; Capabilities formats;}; *Proposal-ORTC > Sender / Receiver Use Case [Usage Comparison Analysis] > > Introduction > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > *After attempting to work through examples of code usage using the current > ORTC sender/receiver API, some issues, concerns and deficiencies were > discovered. A retuning of the current model was made to attempt to address > those findings. The differences are illustrated below in code examples > based on various use cases.In the first set of use cases for simple > application usages, there are no advantages to a capabilities model (aside > from the reduction of complexity an engine might need to implement). As the > use cases become more involved, advantages begin to show. In the final > example which illustrates using SVC, the clear advantage of capabilities > and preferences can be demonstrated. Use CasesAlice wishes to send media to > BobCurrent Parameter Based APIStep 1: (Alice)var track = > myObtainMediaTrack();var senderCaps = RTCRtpSender.getCapabilities();var > senderParams = RTCRtpSender.createParameters(track, > senderCaps);mysignal(senderParams);Step 2: (Bob)var senderParams = > mysignal();var receiverCaps = RTPRtcReceiver.getCapabilities();var > receiverParams = RTPRtcReceiver.filterParameters(senderParams, > receiverCaps);var receiver = new > RTCRtpReceiver(...);receiver.start(receiverParams);mysignal(receiverParams);Step > 3: (Alice)var receiverParams = mysignal();var senderParams = > RTPRtcSender.filterParameters(receiverParams, senderCaps);var sender = new > RTCRtpSender(...);sender.start(senderParams);CommentsBecause sender (i.e. > Alice) sent her parameters that contained specific SSRC (and possibly > receiver ID) information in the her sender parameters, the receiver will > latch based upon exact SSRC matching.Proposed Capabilities Based APIStep 1: > (Alice)var senderCaps = > RTCRtpSender.getCapbilities();mysignal(senderCaps);Step 2: (Bob)var > senderCaps = signal();var receiverParams = > RTCRtpReceiver.createParameters("video", senderCaps);var receiver = new > RTCRtpReceiver(...);receiver.start(receiverParams);mysignal(receiverParams.receiverCapabilities);Step > 3: (Alice)var track = myObtainMediaTrack();var receiverCaps = > mysignal();var senderParams = RTCRtpSender.createParameters(track, > receiverCaps);var sender = new > RTCRtpSender(...);sender.start(senderParams);CommentsReceiver (Bob) can > match an incoming stream because the payload types will match and therefore > the incoming stream will latch to the receiver based on payload type alone. > Alice wishes to send media to Bob Using Unhandled EventingCurrent Parameter > Based APIStep 1: (Alice)var track = myObtainMediaTrack();var senderCaps = > RTCRtpSender.getCapabilities();var senderParams = > RTCRtpSender.createParameters(track, > senderCaps);mysignal(senderParams);Step 2: (Bob)var senderParams = > mysignal();var receiverCaps = RTPRtcReceiver.getCapabilities();var > templateReceiverParams = RTPRtcReceiver.filterParameters(senderParams, > receiverCaps);templateReceiverParams.encodings[0].receiverId = > "";templateReceiverParams.encodings[0].ssrc = null;var listener = > RTCRtpListener(...);listener.onunhandledrtp = function(event) { var > receiver = new RTCRtpReceiver(...); > receiver.start(templateReceiverParams);}mysignal(receiverParams);Step 3: > (Alice)var receiverParams = mysignal();var senderParams = > RTPRtcSender.filterParameters(receiverParams, senderCaps);var sender = new > RTCRtpSender(...);sender.start(senderParams);CommentsBecause sender (i.e. > Alice) sent her parameters that contained specific SSRC (and possibly > receiver ID) information in the her sender parameters, the receiver must > override the template receiver params and remove the exact SSRC to attach > the incoming stream by payload type.Proposed Capabilities Based APIStep 1: > (Alice)var senderCaps = > RTCRtpSender.getCapbilities();mysignal(senderCaps);Step 2: (Bob)var > senderCaps = signal();var listener = > RTCRtpListener(...);listener.onunhandledrtp = function(event) { var > receiverParams = RTCRtpReceiver.createParameters("video", senderCaps); var > receiver = new RTCRtpReceiver(...); > receiver.start(receiverParams);}mysignal(receiverParams.receiverCapabilities);Step > 3: (Alice)var track = myObtainMediaTrack();var receiverCaps = > mysignal();var senderParams = RTCRtpSender.createParameters(track, > receiverCaps);var sender = new > RTCRtpSender(...);sender.start(senderParams);CommentsReceiver (Bob) can > match an incoming stream because the payload types will match and therefore > the incoming stream will latch to the receiver based on payload type > alone.Alice / Bob simultaneously exchange information in parallelTo avoid > requiring a sequential offer / answer exchange, Alice and Bob wish to > simultaneously exchange their RTC information to receiver media from the > other party.Current Parameter Based APIStep 1: (Alice / Bob)// [Alice]var > aliceTrack = myObtainMediaTrack();var aliceSenderCaps = > RTCRtpSender.getCapabilities();var aliceSenderParams = > RTCRtpSender.createParameters(aliceTrack, aliceSenderCaps);var > aliceReceiverCaps = RTCRtpReceiver.getCapabilities();var > aliceReceiverParams = RTCRtpReceiver.createParameters("video", > aliceReceiverCaps);mysignal(aliceSenderParams);mysignal(aliceReceiverParams);// > [Bob]var bobTrack = myObtainMediaTrack();var bobSenderCaps = > RTCRtpSender.getCapabilities();var bobSenderParams = > RTCRtpSender.createParameters(bobTrack, bobSenderCaps);var bobReceiverCaps > = RTCRtpReceiver.getCapabilities();var bobReceiverParams = > RTCRtpReceiver.createParameters("video", > bobReceiverCaps);mysignal(bobSenderParams);mysignal(bobReceiverParams);Step > 2: (Alice / Bob)// [Alice]var bobSenderParams = mysignal();var > bobReceiverParams = mysignal();bobSenderParmas = > RTCRtpReceiver.filterParams(bobSenderParams, > aliceReceiverCaps);bobSenderParmas.encodings[0].receiverId = > "";bobSenderParmas.encodings[0].ssrc = null;bobSenderParams = > myFixPayloadTypes(bobSenderParmas, aliceReceiverParams);var aliceReceiver = > new > RTCRtpReceiver(...);aliceReceiver.receive(bobSenderParams);bobReceiverParams > = RTCRtpSender.filterParams(bobReceiverParams, aliceSenderCaps);var > aliceSender = new RTCRtpSender(...);aliceSender.send(bobReceiverParams);// > [Bob]var aliceSenderParams = mysignal();var aliceReceiverParams = > mysignal();aliceSenderParmas = > RTCRtpReceiver.filterParams(aliceSenderParams, > bobReceiverCaps);aliceSenderParmas.encodings[0].receiverId = > "";aliceSenderParmas.encodings[0].ssrc = null;aliceSenderParams = > myFixPayloadTypes(aliceSenderParmas, bobReceiverParams);var bobReceiver = > new > RTCRtpReceiver(...);bobReceiver.receive(aliceSenderParams);aliceReceiverParams > = RTCRtpSender.filterParams(aliceReceiverParams, aliceSenderCaps);var > bobSender = new > RTCRtpSender(...);bobSender.send(aliceReceiverParams);//---------------------------------// > [Alice and Bob need this method]function myFixPayloadTypes(senderParams, > originalReceiverParams) { // TODO: loop through sender params and then > secondarily loop through // original receiver params and set the sender > payload type based upon // what is found in the receiver params. // ... > return myFixedSenderParams;}CommentsThe sender includes exact SSRC > information and signals that to the remote receiver. The issue is the > actual sender is going to base it's sending params upon the receiver params > of the remote party which do not contain a specific SSRC (or contains a > different SSRC). Thus the SSRC has to be stripped from the received sender > params or they will not match and the receiver won't latch onto the > incoming stream as the latching must occur by payload type instead.The > secondary problem is that the sender is actually using the payload types as > defined by the remote party's receiver but the receiver is basing the > payload types based upon the remote party's sender. This means the payload > types might mismatch and the latching based on payload types may not occur. > To fix this problem the web developer has to fix either the sender's > payload types or the receiver's payload type.Proposed Capabilities Based > APIStep 1: (Alice / Bob)// [Alice]var aliceSenderCaps = > RTCRtpSender.getCapbilities();var aliceReceiverCaps = > RTCRtpReceiver.getCapabilities();mysignal(aliceSenderCaps);mysignal(aliceReceiverCaps);// > [Bob]var bobSenderCaps = RTCRtpSender.getCapbilities();var bobReceiverCaps > = > RTCRtpReceiver.getCapabilities();mysignal(bobSenderCaps);mysignal(bobReceiverCaps);Step > 2: (Alice / Bob)// [Alice]var bobSenderCaps = mysignal();var > bobReceiverCaps = mysignal();var aliceTrack = myObtainMediaTrack();var > aliceReceiverParams = RTCRtpReceiver.createParameters("video", > bobSenderCaps);var aliceReceiver = new > RTCRtpReceiver(...);aliceReceiver.receiver(aliceReceiverParams);var > aliceSenderParams = RTCRtpSender.createParameters(aliceTrack, > bobReceiverCaps);var aliceSender = new > RTCRtpSender(...);aliceSender.send(aliceSenderParams);// [Bob]var > aliceSenderCaps = mysignal();var aliceReceiverCaps = mysignal();var > bobTrack = myObtainMediaTrack();var bobReceiverParams = > RTCRtpReceiver.createParameters("video", aliceSenderCaps);var bobReceiver = > new RTCRtpReceiver(...);bobReceiver.receiver(bobReceiverParams);var > bobSenderParams = RTCRtpSender.createParameters(bobTrack, > aliceReceiverCaps);var bobSender = new > RTCRtpSender(...);bobSender.send(bobSenderParams);CommentsThe receiver is > able to latch onto the sender based on payload type alone. Unlike the > current API, there's no need to strip SSRCs and no need to fiddle and fix > the payload type. The code is cleaner and clearer as to what's going on and > does not presume the application level programmer has to know why payload > types need to match or why SSRCs need to be stripped.Alice wants to use a > SVC (Scalable Video Codec) to send to BobThis is for illustration purposes > only. Typical benefits of SVC are greater in conference scenarios rather > than traditional point to point scenarios. However, this scenario can > presume that an intermedia conferencing bridge would be between Alice and > Bob.Current Parameter Based APIStep 1: (Alice)var senderCaps = > RTCRtpSender.getCapabilities();mySignal(senderCaps);Step 2: (Bob)var > senderCaps = mysignal();var receiverCaps = > RTPRtcReceiver.getCapabilities();var receiverParams = > RTPRtcReceiver.createParameters("video", receiverCaps);var receiverParams = > RTPRtcReceiver.filterParams(senderCaps);var receiverParams = > mySetupSVC(receiverParams);var receiver = new > RTCRtpReceiver(...);receiver.start(receiverParams);mysignal(receiverParams);function > mySetupSVC(receiverParams) { // 1. search the receiver params for a codec > capable of SVC based on pre-knowledge // of the codec types // 2. > setup SVC params based on codec's capabilities // TODO - step 1 - code > needs to be added here to do this logic var chosenCodec = "h264svc"; // > hard code for now // TODO: Not sure this code is even right. How does this > layer scale even work? // How is temporal and spatial layering defined > together? Don't see a knob for // setting up temporal SVC… > receiverParams.receiverId = "foo"; receiverParams.encodings[0] = { > "codecName": chosenCodec, "scale": 0.125, "encodingId": "0" }; > receiverParams.encodings[1] = { "scale": 0.25, > "dependencyEncodingIds": {"0"} }; receiverParams.encodings[2] = { > "scale": 0.5, "dependencyEncodingIds": {"0", "1"} };}Step 3: > (Alice)var receiverParams = mysignal();var senderParams = > RTPRtcSender.filterParameters(receiverParams, senderCaps);var track = > myObtainMediaTrack();var sender = new RTCRtpSender(track, > ...);sender.start(senderParams);CommentsThe application developer has to > have a ton of presumed knowledge about available codecs, codec capabilities > and needs to have a deep understanding of how the engine interprets the > layering information. The sender cannot setup the SVC parameters desired > because it doesn't know the receiver capabilities.The sample above may not > work for SVC codecs which put each layer on a unique SSRC because the > receiver did not necessarily pre-dictate the expected SSRCs on each layer > so the application developer would have to handle this situation too and > assign SSRCs for each layer manually based on knowledge that the codec > behaves in this manner.The method to setup temporal or quality SVC is > unclear. Appropriate parameter knobs for the application developer appear > to be missing.Proposed Capabilities Based APIStep 1: (Alice)var senderCaps > = RTCRtpSender.getCapbilities();var senderPrefs = { "receiverId": "foo", > "frameRateScalabilityOptions": {"layers": 2}, > "scalingScalabilityOptions": {"layers": > 2},};mysignal(senderCaps);mysignal(senderPrefs);Step 2: (Bob)var senderCaps > = signal();var senderPrefs = signal();var receiverParams = > RTCRtpReceiver.createParameters("video", senderCaps, senderPrefs);var > receiver = new > RTCRtpReceiver(...);receiver.start(receiverParams);mysignal(receiverParams.receiverCapabilities);Step > 3: (Alice)var track = myObtainMediaTrack();var receiverCaps = > mysignal();var senderParams = RTCRtpSender.createParameters(track, > receiverCaps, senderPrefs);var sender = new RTCRtpSender(track, > ...);sender.start(senderParams);CommentsThe application developer doesn't > require pre-knowledge of the codecs. The developer can quickly and easily > specify the types of SVC properties desired with much simpler knobs. The > developer doesn't have to worry if a codec is assigning each layer a unique > SSRC or not of if the layering ends up being dynamic or > not.ConclusionOverall the proposed capabilities based API has strong > advantages. Main advantages are: 1. Simplicity in setup based on > "preferences" for the application developer2. Less brittle > designs/implementations since low level parameters are not exchanged, > filtered, and interpreted by different browser engines3. Much less > knowledge (and often no pre-knowledge) is required for the application > developer to take full advantage of a browser's capabilitiesThere's no > strong reason to maintain the current API. The biggest difference will be > that browsers will need to generate compatible parameters based on > capabilities but that also comes at a big advantage of the browser engines > not needing to interpreting and filtering low level parameters from other > browser engines. Both new and current use low level parameters to receive > or send information so that design aspect remains unchanged.Advantages of > Current Parameter Based API 1. Browser engines do not need to generate > parameter from capabilities in a "compatible" manner (although low level > parameters do need to be filtered in a "compatible" manner so this is not a > strong advantage).Disadvantages of Current Parameter Based API 1. > Application developer needs pre-knowledge of SVC codecs to be able to chose > and setup their properties based upon pre-knowledge of codec capabilities2. > Application developer needs deep understanding of how layering works to > setup the layering properties correctly3. Browser engines need to agree on > how to filter low level parameters based upon capabilities in a consistent > manner across browsers to ensure compatibility4. Browser engines need to > agree how to interpret low level parameter objects that were generated by > other browsers (or other applications)5. Low level parameter based > exchanges introduce greater brittleness between browsers since extending > the parameters details could mean breaking existing implementations > (instead of capabilities which are typically ignored when not understood)6. > Less innovation / greater brittleness for anything that requires parameter > object extensions since many browsers as well as applications will be > fiddling, exchanging, and filtering these low level parameter objects.7. > Simulcasting with layering doesn't appear to be supported or it's not > obvious how to set up those scenarios.8. Unclear how to mix and match > different SVC modes (e.g. temporal, spatial, and quality)9. The application > developer is uncertain based upon their preferences what the browser engine > is capable of delivering (without deep understanding of all codecs and > their properties).10. Header extensions will need manual setup by the > application developer despite not knowing that codecs or the engines might > need certain extensions to take advantage of codec features or browser > engine features.Advantages Proposed Capabilities Based API 1. Application > developer can easily setup SVC without needing detailed understanding2. > Typical and even advanced use cases do not require a deep understand of RTC > to be able to take advantages of capabilities3. Less brittle > implementations as low level parameter objects are only consumed local by > the browsers that generate them or only in situations where specific > compatibilities with legacy systems are required which the default > generated low level properties read would not be compatible.4. Simulcast > with layering is supported5. Easy for application developer to mix and > match different SVC modes (e.g. temporal, spatial, and quality)6. Easy to > extend support for alternative SVC scalability modes (e.g. colour depth, > sharpness, ROI)7. Application developer knows what the browser engine is > capable of delivering given a set of preferences (from resultant > preferences as returned from "createParameters(...)"8. Header extensions > can be automatically set up based on needs and capabilities of the > browser's RTP engines and codecs.Disadvantages Proposed Capabilities Based > API 1. Browser engines need to agree on how to compute "compatible" > parameters for a given codec and media preferences. The rules for > generation of parameters must be clear.Equal Capabilities of Current and > Proposed Based API 1. Application developer can always tweak low level > properties on an "as needed" basis for compatibility2. Both new and current > proposals send and receive based on lower level parameters (this does not > change).* > > > > >
Received on Thursday, 8 May 2014 06:38:35 UTC