- From: Peter Thatcher <pthatcher@google.com>
- Date: Thu, 8 May 2014 08:34:17 -0700
- To: Robin Raymond <robin@hookflash.com>
- Cc: "public-ortc@w3.org" <public-ortc@w3.org>
- Message-ID: <CAJrXDUF0+kCPy6sO0ivcFGVUAM98MRXssr+KnfttxDRi17TCyQ@mail.gmail.com>
FYI, since this is very big, it will take me a while to read through. Plus I'm out all next week on vacation, and then the IETF/W3C interim is the week after. So I might not have a good response for a few weeks. 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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > *Introduction After 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 15:35:31 UTC