application that gathering is occurring through an event.  Then, when each new ICE candidate becomes available, the ICE Agent will supply it to the application via an additional event; these candidates will <del> also automatically be added to the local session description. Finally, when all candidates have been gathered, an event will be dispatched to signal that the gathering process is complete. </del>  Note that gathering phases only gather the candidates needed by new/recycled/restarting m= lines; other m= lines continue to use provisional answers, and any previous call leg will be terminated. At some point, the application will end the setup process, perhaps with a timer; at this point, the application could reapply the <del> existing remote description as a final answer. </del>  3.6.2. this, we introduce the concept of "rollback". A rollback discards any proposed changes to the session, returning <del> the state machine to the stable state, and setting the modified local and/or remote description back to their previous values.  Any resources or candidates that were allocated by the abandoned local description are discarded; any media that is received will be processed according to the previous local and remote descriptions. Rollback can only be used to cancel proposed changes; there is no support for rolling back from a stable state to a previous stable state.  Note that this implies that once the answerer has performed setLocalDescription with his answer, this cannot be rolled back. </del>  A rollback is performed by supplying a session description of type "rollback" with empty contents to either setLocalDescription or successfully handle scenarios where the application wants to offer to change from one media format to a different, incompatible format, the PeerConnection must be able to simultaneously support use of both the <del> old and new local descriptions (e.g. support codecs that exist in both descriptions) until a final answer is received, at which point the PeerConnection can fully adopt the new local description, or roll back to the old description if the remote side denied the change. </del>  This API indirectly controls the candidate gathering process.  When a local description is supplied, and the number of transports currently description, the PeerConnection will create transports as needed and begin gathering candidates for them. <del> If setRemoteDescription was previous called with an offer, and </del>  setLocalDescription is called with an answer (provisional or final), and the media directions are compatible, and media are available to send, this will result in the starting of media transmission. 4.1.7. <del> The localDescription method returns a copy of the current local configuration, i.e. what was most recently passed to setLocalDescription, plus any local candidates that have been generated by the ICE Agent. </del>  <del> [[OPEN ISSUE: Do we need to expose accessors for both the current and proposed local description? https://github.com/rtcweb-wg/jsep/ issues/16]] A null object will be returned if the local description has not yet been established. </del>  4.1.8. <del> The remoteDescription method returns a copy of the current remote configuration, i.e. what was most recently passed to setRemoteDescription, plus any remote candidates that have been supplied via processIceMessage. [[OPEN ISSUE: Do we need to expose accessors for both the current and proposed remote description? https://github.com/rtcweb-wg/jsep/ issues/16]] </del>  <del> A null object will be returned if the remote description has not yet been established. </del>  4.1.9.  The canTrickleIceCandidates property indicates whether the remote side supports receiving trickled candidates.  There are three potential values: Trickle on initial offers and Full Trickle on subsequent interactions with a Trickle ICE-compatible agent. <del> 4.1.10. </del>  The setConfiguration method allows the global configuration of the PeerConnection, which was initially set by constructor parameters, to may result in a change to media state if it results in connectivity being established. <del> 4.1.11. </del>  The addIceCandidate method provides a remote candidate to the ICE <del> Agent, which, if parsed successfully, will be added to the remote description according to the rules defined for Trickle ICE. Connectivity checks will be sent to the new candidate. </del>  This call will result in a change to the state of the ICE Agent, and may result in a change to media state if it results in connectivity

I left out the unqualified /, since these are redundant, and only exist in the WebRTC spec as a convenience and for backwards compatibility.
I need to read this carefully at some point but just quickly scanning the diff .. it looks workable. Thanks.
LGTM. I didn't look to see if there were other references to the local/remote desc that need to be updated, but I assume that you already scanned carefully.
I think everything should be covered now. I've gone through twice looking at every place the word "description" is used. Though when talking about rollback, I think "return to the previous description" sounds less confusing than "return to the current description", so I left that wording alone.
LGTM
JSEP S 4.1.7 and 4.1.8 read: " TODO: Do we need to expose accessors for both the current and proposed local description?" and " TODO: Do we need to expose accessors for both the current and proposed remote description?"
DC plan - we add these to W3c spec.
Discussed in DC: Values will be created for surfacing both proposed and current descriptions. Ultimately, this is a matter for the WebRTC group, where the names can be selected and decisions like what to do with existing values can be made.
This is bug URL
Can we close this ?
I would prefer to keep it until the text is written
For the purposes of this comment, let's call the needed APIs .currentLocalDesc and .pendingLocalDesc. On the offerer side, setLocal(desc) updates .pendingLocalDesc to be (desc). On the offerer side, setLocal(rollback) updates .pendingLocalDesc to be NULL. On the answerer side, setRemote(desc) updates .pendingRemoteDesc to be (desc). On the answerer side, setRemote(rollback) updates .pendingRemoteDesc to NULL. On the answerer side, setLocal(desc) updates .currentLocalDesc to be (desc), .currentRemoteDesc to .pendingRemoteDesc, and .pendingRemoteDesc to NULL. On the offerer side, setRemote(desc) updates .currentRemoteDesc to be (desc), .currentLocalDesc to be .pendingLocalDesc, and .pendingLocalDesc to be NULL. Unfortunately, both .pending and .current have slightly different semantics than the existing .local/.remoteDescription properties, so I think we would need to retain .local/remote for now. However, they could be polyfilled as propX = (pendingX) ? pendingX : currentX.
This looks good and need to be clear that some while the pending is out, you need to receive on both current and pending.
Not done yet but started putting this into PC spec on branch URL - have a look and see if it is going the right direction
(Moved my comment to PR)
Hi NAME , why not a simpler 2-arg rather than 3-arg solution? For the purposes of this comment, let's call the needed APIs .localDescription and .stableLocalDescription. On the offerer side, setLocal(desc) updates .localDescription to be (desc). On the offerer side, setLocal(rollback) updates .localDescription to be .stableLocalDescription. On the answerer side, setRemote(desc) updates .remoteDescription to be (desc). On the answerer side, setRemote(rollback) updates .remoteDescription to be .stableRemoteDescription. On the answerer side, setLocal(desc) updates .localDescription and .stableLocalDescription to be (desc), and .stableRemoteDescription to be .remoteDescription. On the offerer side, setRemote(desc) updates .remoteDescription and .stableRemoteDescription to be (desc), and .stableLocalDescription to be .localDescription.
I see what you are trying to do, and I think this would work OK, but the fact that the semantics of .localDescription/.remoteDescription mutate depending on the current state make this confusing. (IOW, sometimes localDescription is the stable desc, sometimes it is the pending desc). I think .current/.pending is the clearest approach, but open to other opinions.
I would argue the semantics don't mutate and their availability transcend state: is the last-set description always is the last negotiated description always
From the point of view of a programmer using the API, I think that what I want to get is the SDP to do with the current negotiation, and the old SDP that I would roll back to. I tend to think of it as old and new. During transition time, the stuff in use is the combination of the old offer/answer pair plus the new offer. The stuff .current/.pending is close enough to this and seems fine to me.
Do you realize you just used "current" to refer to "pending", and "old" to refer to "current"? You want to roll back to the last stable state.
Uh, I used current to refer to old and pending to refer to new.
My point is that these relative words "current" and "pending" are not well-defined, whereas "stable" is. KISS.
I'm not sure stable is a word that makes as much sense as you might hope to developers. It is not used int he SDP or Offer/Answer spec. Anyways, I don't feel strongly about this. None of the names are perfect.
URL
Forgetting about the accessors for a second, the world can be in three basic states. There is an initial offer which has not been answered There is an offer which has been answered and no outstanding offers There is an offer which has been answered and an outstanding offer In the first two cases, there is only one localdesc, which is either answered or not. In the second case, there are two localdescs, one confirmed and one answered or not. As Justin observes, currently localdesc is the most recent description set, regardless of whether it's answered. I find his argument persuasive here. I would prefer that we have two variables: Most recent answered description Most recent non-answered description And in some cases either or both of these can be null. We can obviously keep localdescription around for a while for compat. I don't feel strongly about the names here, so I won't suggest some just yet. Let's agree on the principle one way or the other.
The world can be in four basic states, the fourth being the initial state of no offer at all, which is the only state where "Most recent answered description" would be I hope? This would fit my understanding of "most recent": while it may be initially (meaning "never been set"), it will never go to after that (which would surprise me). I think we're on the same page here. Can "Most recent non-answered description" ever go from non- to ? If it can, then lets avoid the false symmetry with the first one: Most recent answered description, or if never set. Most recent non-answered description if there is one since the last answered description, or . The first one is a.k.a. . The second one is a temporal variable: it'll only ever be non- during re-negotiation, correct? Moreover, during re-negotiation, it's indistinguishable from , do I have that right? So, counting which we have today, why add a redundant third temporal variable that all it brings to the table is that it is outside of renegotiation?
, jan-ivar EMAIL wrote: Yes, then everything is null. No. So, counting localDescription which we have today, we're adding a redundant
What's the value of "most recent non-answered description" after rollback? (matters for the question of whether it can go from non-null to null)
Right, hanging on to a failed description doesn't make much sense, so I see how we got to . So lets not cut it that way. I think a JS writer cares about: the last set value, and the reigning value. Where rollback rolls back failed set values to the known-good reigning value. Having itself be the last-set-value matches most attribute patterns I've seen. (e.g. ).
The problem with this categorization is that in the case of re-offer, there isn't "the reigning value". Rather, the offerer has two values which are simultaneously valid, so I think Justin's approach is superior. In any case, rather than debate this here, let's discuss it at the interim.
So, given what is being discussed here is about PC spec, I'd sort of like to close this and move the conversation over to PC and not jsep.
I agree this overlaps with PC, but given the relevance of this to the overall JSEP O-A model, I think we need to have some description of this in Section 4.1.*
Personal opinion (not claiming to represent any consensus): JSEP needs to describe the procedures followed to get the SDP we want. JSEP shouldn't need to talk about accessors at all; we can leave that to WEBRTC. What's specified in only one place has a greater chance of being consistent.
I find that logic persuasive, in that the accessors are not relevant to the state machine or any other fundamental part of JSEP. That would imply that 4.1.7 and 4.1.8 ought to be removed from this document, and probably also 4.1.9 (canTrickleIceCandidates, another accessor-like API). NAME wdyt?
I can live with that, but I thought that we had agreed previously that JSEP would document this stuff and place requirements on the WebRTC API. , Justin Uberti EMAIL wrote:
It's perfectly reasonable to have a sentence saying "the API will give access to current and pending SDP and whether or not trickleIce is supported". It's when we get the discussion about what the accessor names should be in 2 different places that I feel like we're not using our time optimally.
Well, I suggest we have one discussion and then put it in both places. , Harald Alvestrand <EMAIL
Consensus in W3C was to have two new accessors. This is editor ready.
Resolved by

application that gathering is occurring through an event.  Then, when each new ICE candidate becomes available, the ICE Agent will supply it to the application via an additional event; these candidates will  <ins> also automatically be added to the current and/or pending local session description.  Finally, when all candidates have been gathered, an event will be dispatched to signal that the gathering process is complete. </ins> Note that gathering phases only gather the candidates needed by new/recycled/restarting m= lines; other m= lines continue to use provisional answers, and any previous call leg will be terminated. At some point, the application will end the setup process, perhaps with a timer; at this point, the application could reapply the  <ins> pending remote description as a final answer. </ins> 3.6.2. this, we introduce the concept of "rollback". A rollback discards any proposed changes to the session, returning  <ins> the state machine to the stable state, and setting the pending local and/or remote description back to null.  Any resources or candidates that were allocated by the abandoned local description are discarded; any media that is received will be processed according to the previous local and remote descriptions.  Rollback can only be used to cancel proposed changes; there is no support for rolling back from a stable state to a previous stable state.  Note that this implies that once the answerer has performed setLocalDescription with his answer, this cannot be rolled back. </ins> A rollback is performed by supplying a session description of type "rollback" with empty contents to either setLocalDescription or successfully handle scenarios where the application wants to offer to change from one media format to a different, incompatible format, the PeerConnection must be able to simultaneously support use of both the  <ins> current and pending local descriptions (e.g. support codecs that exist in both descriptions) until a final answer is received, at which point the PeerConnection can fully adopt the pending local description, or roll back to the current description if the remote side denied the change. </ins> This API indirectly controls the candidate gathering process.  When a local description is supplied, and the number of transports currently description, the PeerConnection will create transports as needed and begin gathering candidates for them.  <ins> If setRemoteDescription was previously called with an offer, and </ins> setLocalDescription is called with an answer (provisional or final), and the media directions are compatible, and media are available to send, this will result in the starting of media transmission. 4.1.7.  <ins> The currentLocalDescription method returns a copy of the current negotiated local description - i.e., the local description from the last successful offer/answer exchange - in addition to any local candidates that have been generated by the ICE Agent since the local description was set. </ins>  <ins> A null object will be returned if an offer/answer exchange has not yet been completed. </ins> 4.1.8.  <ins> The pendingLocalDescription method returns a copy of the local description currently in negotiation - i.e., a local offer set without any corresponding remote answer - in addition to any local candidates that have been generated by the ICE Agent since the local description was set. </ins>  <ins> A null object will be returned if the state of the PeerConnection is "stable" or "have-remote-offer". </ins> 4.1.9. <ins> The currentRemoteDescription method returns a copy of the current negotiated remote description - i.e., the remote description from the last successful offer/answer exchange - in addition to any remote candidates that have been supplied via processIceMessage since the remote description was set. A null object will be returned if an offer/answer exchange has not yet been completed. 4.1.10. The pendingRemoteDescription method returns a copy of the remote description currently in negotiation - i.e., a remote offer set without any corresponding local answer - in addition to any remote candidates that have been supplied via processIceMessage since the remote description was set. A null object will be returned if the state of the PeerConnection is "stable" or "have-local-offer". 4.1.11. </ins> The canTrickleIceCandidates property indicates whether the remote side supports receiving trickled candidates.  There are three potential values: Trickle on initial offers and Full Trickle on subsequent interactions with a Trickle ICE-compatible agent.  <ins> 4.1.12. </ins> The setConfiguration method allows the global configuration of the PeerConnection, which was initially set by constructor parameters, to may result in a change to media state if it results in connectivity being established.  <ins> 4.1.13. </ins> The addIceCandidate method provides a remote candidate to the ICE  <ins> Agent, which, if parsed successfully, will be added to the current and/or pending remote description according to the rules defined for Trickle ICE.  Connectivity checks will be sent to the new candidate. </ins> This call will result in a change to the state of the ICE Agent, and may result in a change to media state if it results in connectivity


If an ICE candidate policy is specified, it functions as described in sec.ice-candidate-policy, causing the browser to only surface the <del> permitted candidates to the application, and only use those candidates for connectivity checks.  The set of available policies is as follows: </del>  <del> All candidates will be gathered and used. Candidates with private IP addresses [RFC1918] will be filtered out.  This prevents exposure of internal network details, at the cost of requiring relay usage even for intranet calls, if the NAT does not allow hairpinning as described in [RFC4787], section 6. </del>  the application deploys its relay servers, this could obfuscate location to a metro or possibly even global level. <del> The default ICE candidate policy MUST be set to allow all candidates, as this is generally the desired policy, and also typically reduces use of application TURN server resources significantly. </del>  If a size is specified for the ICE candidate pool, this indicates the number of ICE components to pre-gather candidates for.  Because pre-

LGTM
lgtm
From URL "public" is probably something the browser should control, not the application. "none" was previously removed, but apparently Firefox has implemented it.
Keep in mind that anything less than all means that mobile apps will work better than browser apps. Public tries to just reveal what is already revealed simply by browsing the web with no webrtc.
Right, but that's what "all" does when the browser is configured as recommended by draft-rtcweb-shieh-ip-handling. It's not clear why a "public" mode also needs to exist; the point of this draft is to protect the user from the application, so we can't really give the app the ability to choose whether it wants non-public addresses. I think the real remaining question is whether "none" is worth keeping.
I think the motivation for "none" was a lot stronger when we had automatic gathering prior to setLD() in some situations. Now, it seems like you can just get the same effect by deferring setLD(). I agree that "public" is silly.

If an ICE candidate policy is specified, it functions as described in sec.ice-candidate-policy, causing the browser to only surface the  <ins> permitted candidates (including any internal browser filtering) to the application, and only use those candidates for connectivity checks.  The set of available policies is as follows: </ins>  <ins> All candidates permitted by browser policy will be gathered and used. </ins> the application deploys its relay servers, this could obfuscate location to a metro or possibly even global level.  <ins> The default ICE candidate policy MUST be set to "all" as this is generally the desired policy, and also typically reduces use of application TURN server resources significantly. </ins> If a size is specified for the ICE candidate pool, this indicates the number of ICE components to pre-gather candidates for.  Because pre-


a=imageattr:* recv [x=[16:640],y=[16:360],q=1.0]  3.5.2. RFC6236 defines "a=imageattr" to be an advisory field.  This means of a given MediaStreamTrack, which is producing video of a certain resolution, receives an "a=imageattr recv" attribute, it MUST first check to see if the original resolution meets the criteria specified <del> in the attribute, and transmit it untouched if so.  If the original resolution is too large for the attribute criteria, the sender SHOULD apply downscaling to the output of the MediaStreamTrack in order to satisfy the criteria. </del>  If the receiver requires a minimum resolution which is greater than the native resolution of the video, upscaling is needed, but this may

LGTM
C. Section 3.6.1: As an example, consider a system with a HD-capable, multiformat video decoder, where the application has constrained the received track to at most 360p. In this case, the implemention would generate this attribute: a=imageattr:* recv [x=[16:640],y=[16:360],q=1.0] Maybe this example should discuss the minimal aspect of this. What it really is expressing in that it can handle any resolution between 16x16 pixels up to 640x360 as the longest in respective side. No limitations to any picture aspect ratio. That the examples expresses this is missing in the example text.
I think this is a realistic example, so I suggest we just add more descriptive text.

a=imageattr:* recv [x=[16:640],y=[16:360],q=1.0] <ins> This declaration indicates that the receiver is capable of decoding any image resolution from 16x16 up to 640x360 pixels. </ins> 3.5.2. RFC6236 defines "a=imageattr" to be an advisory field.  This means of a given MediaStreamTrack, which is producing video of a certain resolution, receives an "a=imageattr recv" attribute, it MUST first check to see if the original resolution meets the criteria specified  <ins> in the attribute, and transmit it untouched if so.  Note that when considering a MediaStreamTrack that is producing rotated video, the unrotated resolution MUST be used.  This is required regardless of whether the receiver supports performing receive-side rotation (e.g., through CVO), as it significantly simplifies the matching logic. If the original resolution is too large for the attribute criteria, the sender SHOULD apply downscaling to the output of the MediaStreamTrack in order to satisfy the criteria. </ins> If the receiver requires a minimum resolution which is greater than the native resolution of the video, upscaling is needed, but this may


a nonzero size, any existing candidates will be discarded, and new candidates will be gathered from the new servers. <del> Any changes to the ICE candidate policy also affect the next gathering phase.  If the policy is being made more liberal (i.e., more permitted candidates), and an ICE gathering phase has already started or completed, the 'needs-ice-restart' bit will be set.  If the policy is being made more strict, no ICE restart is needed, and the bit will not be set.  Either way, changes to the policy have no effect on the candidate pool, because pooled candidates are not surfaced to the application until a gathering phase occurs, and so any necessary filtering can still be done on any pooled candidates. </del>  Any changes to the ICE candidate pool size take effect immediately; if increased, additional candidates are pre-gathered;

Also making the "need-ice-restart" bit get set for ANY policy change, rather than just more restrictive changes, to go along with this warning.
Needs merge to master
LGTM
lgtm
LGTM
If a candidate is in use and Policy changes such that this candidate is not longer allowed, do we have text that says to stop using that candidate and restart ice?
yes, I think this is covered in the setConfiguration text. Do you want to look and see if there is anything missing?
The current text says no ICE restart happens here, and it's not clear it should, since the cat is already out of the bag. Eric is going to look at adding a warning mentioning this.
Discussed in Kirkland and we think it is simplest to trigger ICE restart regardless of which way the policy changes.

a nonzero size, any existing candidates will be discarded, and new candidates will be gathered from the new servers.  <ins> Any change to the ICE candidate policy affects the next gathering phase.  If an ICE gathering phase has already started or completed, the 'needs-ice-restart' bit will be set.  Either way, changes to the policy have no effect on the candidate pool, because pooled candidates are not surfaced to the application until a gathering phase occurs, and so any necessary filtering can still be done on any pooled candidates. </ins> Any changes to the ICE candidate pool size take effect immediately; if increased, additional candidates are pre-gathered;


This specification prescribes more specific behavior.  When a sender of a given MediaStreamTrack, which is producing video of a certain <del> resolution, receives an "a=imageattr recv" attribute, it MUST first check to see if the original resolution meets the criteria specified in the attribute, and transmit it untouched if so.  Note that when considering a MediaStreamTrack that is producing rotated video, the unrotated resolution MUST be used.  This is required regardless of whether the receiver supports performing receive-side rotation (e.g., through CVO), as it significantly simplifies the matching logic. If the original resolution is too large for the attribute criteria, </del>  the sender SHOULD apply downscaling to the output of the <del> MediaStreamTrack in order to satisfy the criteria. If the receiver requires a minimum resolution which is greater than the native resolution of the video, upscaling is needed, but this may not be appropriate in all cases.  To address this concern, the application can set an upscaling policy for each sent track.  For this case, if upscaling is permitted by policy, the sender SHOULD apply upscaling in order to provide the desired resolution. Otherwise, the sender MUST NOT apply upscaling.  The sender SHOULD NOT upscale in other cases, even if the policy permits it. </del>  If there is no appropriate and permitted scaling mechanism that <del> allows the received criteria to be satisfied, the sender MUST NOT </del>  transmit the track. In the special case of receiving a maximum resolution of [0, 0], as setRemoteDescription, meaning the PeerConnection is in the "remote- pranswer" or "stable" states, an offer is generated based on the negotiated session descriptions by following the steps mentioned for <del> the "local-offer" state above, along with these exceptions: [OPEN ISSUE: should this be permitted in the remote-pranswer state? https://github.com/rtcweb-wg/jsep/issues/143] </del>  If a m= section exists in the current local description, but does not have an associated local MediaStreamTrack (possibly because

Discusses multiple imageattr; use of different codecs; no aspect ratio handling; preserve aspect ratio when scaling
LGTM
LGTM

This specification prescribes more specific behavior.  When a sender of a given MediaStreamTrack, which is producing video of a certain  <ins> resolution, receives an "a=imageattr recv" attribute, it MUST check to see if the original resolution meets the size criteria specified in the attribute, and adapt the resolution accordingly by scaling (if appropriate).  Note that when considering a MediaStreamTrack that is producing rotated video, the unrotated resolution MUST be used.  This is required regardless of whether the receiver supports performing receive-side rotation (e.g., through CVO), as it significantly simplifies the matching logic. For an "a=imageattr recv" attribute, only size limits are considered. Any other values, e.g. aspect ratio, MUST be ignored. When communicating with a non-JSEP endpoint, multiple relevant "a=imageattr recv" attributes may be received.  If this occurs, attributes other than the one with the highest "q=" value MUST be ignored. If an "a=imageattr recv" attribute references a different video codec than what has been selected for the MediaStreamTrack, it MUST be ignored. If the original resolution matches the size limits in the attribute, the track MUST be transmitted untouched. If the original resolution exceeds the size limits in the attribute, </ins> the sender SHOULD apply downscaling to the output of the  <ins> MediaStreamTrack in order to satisfy the limits.  Downscaling MUST NOT change the track aspect ratio. If the original resolution is less than the size limits in the attribute, upscaling is needed, but this may not be appropriate in all cases.  To address this concern, the application can set an upscaling policy for each sent track.  For this case, if upscaling is permitted by policy, the sender SHOULD apply upscaling in order to provide the desired resolution.  Otherwise, the sender MUST NOT apply upscaling.  The sender SHOULD NOT upscale in other cases, even if the policy permits it.  Upscaling MUST NOT change the track aspect ratio. </ins> If there is no appropriate and permitted scaling mechanism that  <ins> allows the received size limits to be satisfied, the sender MUST NOT </ins> transmit the track. In the special case of receiving a maximum resolution of [0, 0], as setRemoteDescription, meaning the PeerConnection is in the "remote- pranswer" or "stable" states, an offer is generated based on the negotiated session descriptions by following the steps mentioned for  <ins> the "local-offer" state above, along with these exceptions: </ins> If a m= section exists in the current local description, but does not have an associated local MediaStreamTrack (possibly because


Upon receipt of trickled candidates, the receiving application will supply them to its ICE Agent.  This triggers the ICE Agent to start <del> using the new remote candidates for connectivity checks.  If BUNDLE is in use, each candidate is only supplied once, and is associated with the m= section which matches the sender's BUNDLE-tag. </del>  3.4.2.1. Each m= section, provided it is not marked as bundle-only, MUST generate a unique set of ICE credentials and gather its own unique <del> set of ICE candidates.  Bundle-only m= sections MUST NOT have any ICE credentials and MUST NOT gather any candidates. </del>  For DTLS, all m= sections MUST use the certificate for the identity that has been specified for the PeerConnection; as a result, they Each "a=mid" line MUST stay the same. If the m= section is not bundled into another m= section (i.e., it <del> is either not bundled or it is associated with the sender's BUNDLE-tag) each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m= </del>  section is bundled into another m= section, it MUST NOT have any ICE credentials. above. If the m= section is not bundled into another m= section (i.e., it <del> is either not bundled or it is associated with the sender's BUNDLE-tag) each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m= section is bundled into another m= section, it MUST NOT have any ICE credentials. </del>  If the m= section is not bundled into another m= section, for each candidate that has been gathered during the most recent gathering

First cut. Need to update the examples.
Overall LG, a handful of comments
LGTM
lgtm and merged. Will do a new PR to handle minor tweaks
BUNDLE draft 27 (URL) indicates that ICE attributes and candidates in re-offers (and with max-bundle, I'm guessing) should only be in the "m=" line associated with the offerer BUNDLE-tag. In other words, the candidates and ICE parameters are not duplicated unnecessarily across m= sections. We should update JSEP to reflect this.

Upon receipt of trickled candidates, the receiving application will supply them to its ICE Agent.  This triggers the ICE Agent to start  <ins> using the new remote candidates for connectivity checks. When BUNDLE is in use, candidates (both in-SDP and trickle) are only exchanged for and associated with the m= section referenced by the sender's BUNDLE-tag, as described in I-D.ietf-mmusic-sdp-bundle- negotiation </ins> 3.4.2.1. Each m= section, provided it is not marked as bundle-only, MUST generate a unique set of ICE credentials and gather its own unique  <ins> set of ICE candidates.  Bundle-only m= sections MUST NOT contain any ICE credentials and MUST NOT gather any candidates. </ins> For DTLS, all m= sections MUST use the certificate for the identity that has been specified for the PeerConnection; as a result, they Each "a=mid" line MUST stay the same. If the m= section is not bundled into another m= section (i.e., it  <ins> is either not bundled or it possesses the sender's BUNDLE-tag) each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m= </ins> section is bundled into another m= section, it MUST NOT have any ICE credentials. above. If the m= section is not bundled into another m= section (i.e., it  <ins> is either not bundled or it possesses the sender's BUNDLE-tag) each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m= section is bundled into another m= section, it MUST NOT contain any ICE credentials. </ins> If the m= section is not bundled into another m= section, for each candidate that has been gathered during the most recent gathering


Note that gathering phases only gather the candidates needed by new/recycled/restarting m= lines; other m= lines continue to use <del> their existing candidates. </del>  3.4.2. supply them to its ICE Agent.  This triggers the ICE Agent to start using the new remote candidates for connectivity checks. <del> When BUNDLE is in use, candidates (both in-SDP and trickle) are only exchanged for and associated with the m= section referenced by the sender's BUNDLE-tag, as described in I-D.ietf-mmusic-sdp-bundle- negotiation </del> 3.4.2.1. As with session descriptions, the syntax of the IceCandidate object Each "a=mid" line MUST stay the same. <del> If the m= section is not bundled into another m= section (i.e., it is either not bundled or it possesses the sender's BUNDLE-tag) each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless </del>  the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m= <del> section is bundled into another m= section, it MUST NOT have any ICE credentials. </del>  If the m= section is not bundled into another m= section, for each candidate that has been gathered during the most recent gathering values MUST be used, as described in the initial answer section above. <del> If the m= section is not bundled into another m= section (i.e., it is either not bundled or it possesses the sender's BUNDLE-tag) each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m= section is bundled into another m= section, it MUST NOT contain any ICE credentials. </del>  If the m= section is not bundled into another m= section, for each candidate that has been gathered during the most recent gathering

Change position of initial paragraph on handling of bundled m= sections; simplify some text; remove discussion of ICE restart option in answers.
NAME FYI

Note that gathering phases only gather the candidates needed by new/recycled/restarting m= lines; other m= lines continue to use  <ins> their existing candidates.  Also, when bundling is active, candidates are only gathered (and exchanged) for the m= lines referenced in BUNDLE-tags, as described in I-D.ietf-mmusic-sdp-bundle-negotiation. </ins> 3.4.2. supply them to its ICE Agent.  This triggers the ICE Agent to start using the new remote candidates for connectivity checks.  3.4.2.1. As with session descriptions, the syntax of the IceCandidate object Each "a=mid" line MUST stay the same.  <ins> Each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless </ins> the ICE configuration has changed (either changes to the supported STUN/TURN servers, or the ICE candidate policy), or the "IceRestart" option (sec.icerestart was specified.  If the m=  <ins> section is bundled into another m= section, it still MUST NOT contain any ICE credentials. </ins> If the m= section is not bundled into another m= section, for each candidate that has been gathered during the most recent gathering values MUST be used, as described in the initial answer section above.  <ins> Each "a=ice-ufrag" and "a=ice-pwd" line MUST stay the same, unless the m= section is restarting, in which case new ICE credentials must be created as specified in RFC5245, Section 9.2.1.1.  If the m= section is bundled into another m= section, it still MUST NOT contain any ICE credentials. </ins> If the m= section is not bundled into another m= section, for each candidate that has been gathered during the most recent gathering


the remote VAD algorithm. If the "VoiceActivityDetection" option is specified, with a value of <del> "false", the browser MUST NOT omit "CN" codecs.  For codecs that have </del>  their own internal silence suppression support, the appropriate fmtp parameters for that codec MUST be specified to indicate that silence suppression for received audio is not desired.  For example, when

Seems like an important distinction. I went with "MUST NOT emit", though "MUST omit" could work too.
wow lgtm

the remote VAD algorithm. If the "VoiceActivityDetection" option is specified, with a value of  <ins> "false", the browser MUST NOT emit "CN" codecs.  For codecs that have </ins> their own internal silence suppression support, the appropriate fmtp parameters for that codec MUST be specified to indicate that silence suppression for received audio is not desired.  For example, when


and/or pending remote description according to the rules defined for Trickle ICE.  Connectivity checks will be sent to the new candidate.  This call will result in a change to the state of the ICE Agent, and may result in a change to media state if it results in connectivity being established. candidates, as described in Section 5.7 of RFC5245 and start connectivity checks with the appropriate credentials.  If the media section proto value indicates use of RTP: [TODO: header extensions]

Specifically, "addIceCandidate" and "Applying a Remote Description".
I'm fine this however it ends up. I will r+ this and people can merge it once it is done. Thanks
Just adding a still LGTM
lgtm once my comment from today is addressed

and/or pending remote description according to the rules defined for Trickle ICE.  Connectivity checks will be sent to the new candidate. <ins> This method can also be used to provide an end-of-candidates indication (as defined in I-D.ietf-ice-trickle) to the ICE Agent for all media descriptions in the last remote description. </ins> This call will result in a change to the state of the ICE Agent, and may result in a change to media state if it results in connectivity being established. candidates, as described in Section 5.7 of RFC5245 and start connectivity checks with the appropriate credentials. <ins> If an "a=end-of-candidates" attribute is present, process the end- of-candidates indication as described in I-D.ietf-ice-trickle Section 11. </ins> If the media section proto value indicates use of RTP: [TODO: header extensions]


are used in a session.  Note that this filtering is applied on top of any restrictions the browser chooses to enforce regarding which IP addresses are permitted for the application, as discussed in I- <del> D.shieh-rtcweb-ip-handling. </del>  There may also be cases where the application wants to change which types of candidates are used while the session is active.  A prime As an example, consider a system with a HD-capable, multiformat video decoder, where the application has constrained the received track to <del> at most 360p.  In this case, the implemention would generate this </del>  attribute: a=imageattr:* recv [x=[16:640],y=[16:360],q=1.0] Any "a=extmap" lines are parsed as specified in RFC5285, Section 5, and their values are stored. <del> TODO: identity, rtcp-rsize, rtcp-mux, and any other attribs valid at session level. </del>  Once all the session-level lines have been parsed, processing continues with the lines in media sections. If present, a single "a=setup" line is parsed as specified in RFC4145, Section 4, and the setup value is stored. <del> If the "m=" proto value indicates use of RTP, as decribed in the </del>  sec.profile-names section above, the following attribute lines MUST be processed: extension, as described in I-D.ietf-mmusic-msid, Section 3.2. For each specified payload type, establish a mapping between <del> the payload type ID and the actual media format, as descibed in RFC3264.  If any indicated payload type is unknown, this MUST result in an error. </del>  For each specified "rtx" media format, establish a mapping between the RTX payload type and its associated primary payload

This is all strictly editorial and I think if either of you give it a quick scan, you can just merge it
LGTM - will merge

are used in a session.  Note that this filtering is applied on top of any restrictions the browser chooses to enforce regarding which IP addresses are permitted for the application, as discussed in I-  <ins> D.ietf-rtcweb-ip-handling. </ins> There may also be cases where the application wants to change which types of candidates are used while the session is active.  A prime As an example, consider a system with a HD-capable, multiformat video decoder, where the application has constrained the received track to  <ins> at most 360p.  In this case, the implementation would generate this </ins> attribute: a=imageattr:* recv [x=[16:640],y=[16:360],q=1.0] Any "a=extmap" lines are parsed as specified in RFC5285, Section 5, and their values are stored.  <ins> TODO: identity, rtcp-rsize, rtcp-mux, and any other attributes valid at session level. </ins> Once all the session-level lines have been parsed, processing continues with the lines in media sections. If present, a single "a=setup" line is parsed as specified in RFC4145, Section 4, and the setup value is stored.  <ins> If the "m=" proto value indicates use of RTP, as described in the </ins> sec.profile-names section above, the following attribute lines MUST be processed: extension, as described in I-D.ietf-mmusic-msid, Section 3.2. For each specified payload type, establish a mapping between  <ins> the payload type ID and the actual media format, as described in RFC3264.  If any indicated payload type is unknown, this MUST result in an error. </ins> For each specified "rtx" media format, establish a mapping between the RTX payload type and its associated primary payload


D.ietf-ice-trickle, Section 4, is only included if such an option was present in the offer. <del> The next step is to generate lip sync groups as defined in RFC5888, Section 7.  For each MediaStream with more than one referenced RtpTransceiver, a group of type "LS" MUST be added that contains the mid values for each RtpTransceiver added with that MediaStream.  In some cases this may result in adding a mid to a given LS group that was not in that LS group in the associated offer.  Although this is not allowed by RFC5888, it is allowed when implementing this specification.  [[OPEN ISSUE: This is still under discussion.  See: https://github.com/rtcweb-wg/jsep/issues/162.]] </del>  The next step is to generate m= sections for each m= section that is present in the remote offer, as specified in RFC3264, Section 6.  For

Replaces URL
NAME this just flattens all the changes in last PR to the final thin and puts it onto new base with no merge issue. Still needs changes to align with new sender / receiver objects
PTAL
LGTM
LGTM

D.ietf-ice-trickle, Section 4, is only included if such an option was present in the offer.  <ins> The next step is to generate session-level lip sync groups as defined in RFC5888, Section 7.  For each group of type "LS" present in the offer, determine which of the local RtpTransceivers identified by that group's mid values reference a common local MediaStream (as specified in the addTrack and addTransceiver methods).  If at least two such RtpTransceivers exist, a group of type "LS" with the mid values of these RtpTransceivers MUST be added.  Otherwise, this indicates a difference of opinion between the offerer and answerer regarding lip sync status, and as such, the offered group MUST be ignored and no corresponding "LS" group generated. </ins> The next step is to generate m= sections for each m= section that is present in the remote offer, as specified in RFC3264, Section 6.  For


of the corresponding m= section in the current remote description: The m= line and corresponding "a=rtpmap" and "a=fmtp" lines MUST <del> only include codecs present in the remote description. </del>  The RTP header extensions MUST only include those that are present <del> in the remote description. </del>  The RTCP feedback extensions MUST only include those that are <del> present in the remote description. </del>  <del> The "a=rtcp-mux" line MUST only be added if present in the remote description. </del>  <del> The "a=rtcp-rsize" line MUST only be added if present in the remote description. </del>  The "a=group:BUNDLE" attribute MUST include the mid identifiers specified in the bundle group in the most recent answer, minus any m=

…er.
lgtm
Just one observation: If a JSEP implementation offers codec A to an SFU, and the SFU responds with codecs A and B in the answer (which it's allowed to do), with the "most recent answer" wording, that means the JSEP implementation is technically allowed to offer codecs A and B in a subsequent offer. Is that the intention? I'm fine with it, I'm just making sure. This would then be the only way to seamlessly switch to a new codec. For example, after a hardware encoder becomes available.
oh, hmm, I see that is legal in 3264. That wasn't the intention, but let me think about it.
I think the case NAME points out sounds fine.
LGTM but if we end up changing this a bunch I would like to look at it again
The rationale for keeping to the negotiated set was that it becomes ambiguous how to prioritize the codecs in a reoffer. e.g. if you offer ABC and the answer is CB (while supporting DCB), if we keep to the negotiated set then clearly both sides by default should re-offer with CB. Otherwise, it's not clear where A or D should go. In this case, with an A offer and an AB answer, the callee's reoffer would have to be A, and the caller's reoffer could be either A or AB (if B somehow was now available). That is non-ambiguous, and seems fine. Generally, this is a corner case, and as such taking the simplest path seems best.
Section 5.2.2, "Subsequent Offers", says: However, consider a situation where Alice offers codecs and , and Bob answers with only codec , thereby rejecting . If Bob were to now create a subsequent offer, his remote description still contains both and , so he would technically be allowed to offer both codecs, even though was previously rejected. Is this intentional? It seems to go against the spirit of the rule. Perhaps the rule is meant to be "only include codecs present in the current local and remote descriptions". For context, see: URL
Yes, your understanding is correct. The set to be offered should only include the subset of codecs that were negotiated.
Please, let's specify the context of those already negotiated codecs. Is that per m=line? is that per "RTP session" (whatever that means nowadays)? is that per full SDP? If Alice just offers an m=audio line in the initial SDP offer and Bob answers, aren't they allowed to re-offer later with an added m=video line?
Also, are all those rules take into account multi-stream/participants when in a SFU scenario? Alice may join a SFU conference by offering VP8 and H264 for her sending m=video section, and the SFU may reply with just VP8. But later when a new non-VP8 capable peer join the conference, the SFU may want to generate a re-offer for Alice in behalf of Bob with a new m=video line (a=sendonly) having just H264 codec (since Bob). Why is this illegal?
Related issue open in Chromium project: URL
I assumed it meant per m= line, though this should definitely be made clear. If my assumption is correct, there would be no issue in your later comment about an SFU adding a new m= line.
Thanks NAME it makes sense. Hope it's clarified in the spec.
Eric and I discussed today and I think the simplest change is to reference "the codecs present in the most recent answer", since that is the set of negotiated codecs. This should also be extended to the other bullets in 5.2.2 regarding negotiated properties.
NAME NAME have you consider this scenario?: Alice may join a SFU conference by offering VP8 and H264 in her m=video (a=sendrecv), and the SFU may reply with just VP8 to ensure VP8 is used. Later, when a new non-VP8 capable peer joins the conference, the SFU may want to generate a re-offer for Alice by changing the codec to just H264. With your change this is not legal. And I don't agree because it is an artificial limitation. If we play the SDP game we should follow its rules. Does some RFC state that my suggested use case is illegal?
SFUs can do whatever they want. This spec is for JSEP implementations.
NAME please, re-read my concern. It's about a valid SDP received by WebRTC browser.
Nothing prohibits the SFU from re-offering with H.264 + VP8, and the JSEP endpoint will handle this properly when it is received (generating an appropriate answer). The text being discussed here only affects the offers that JSEP generates.
Re-openened due to discution on ietf list
I think re-offer should contain the full set of codecs or this will cause interesting problems with 3pcc or SIP interop. The order of codecs should ideally be the same as currently negotiated to avoid codec flips. Essentially, what this means all supported codecs not currently negotiated should be added to the end of the offer after the currently negotiated ones.
Note that there is a generic problem about what we mean by "codec". For example, assuming we are only allowed to re-offer previously negotiated codecs (e.g. H.264), are we still allowed to re-offer a different H.264 "codec configuration"?
Related: can an endpoint re-offer by introducing new PT values that were not present in previous O/A? URL
So one way to create a re-offer with all the new PT value that got removed in prev O/A is to create a new PC, add all the steams/tracks to it. Then call create offer to create a "fresh" offer and use that for the offer. However, might be a bit complicated with what happens with incoming media, some of it would be incoming on old PC then move to new PC.
This is even more complicated since you are not supposed to re-use the old PT in the new offer for different codecs. Since this is a completely new offer with no information about previously used PT, this restriction is hard to enforce.
Honestly, I don't think such an approach is acceptable.
Hmm - I see your point.
I don't want to renegotiate ICE+DTLS. I just want to add my audio/video on an already connected transport, and make it work :)
From , it appears the decision was to keep the spec as-is (only negotiate a subset), and possibly add an API in the future for adding codecs. Also, non-JSEP endpoints are still allowed to add codecs, which is covered by . So, I think this issue can be closed.
This will definitely break things.
I just listened to the recording, and the conclusion appeared to be "no one in the room objects to this, though some people on the mailing list might, so we'll continue discussion there". Did that discussion never happen? If so, it needs to. I'll reopen.
I do not think discussion ever happened on the list. My issue is that there is no API to generate a new offer which reuses currently negotiated payload types but lists all available codecs. Without this functionality third party call control is impossible to implement and it is impossible to simulate SIP INVITE without the body which will affect interop.
A possible addition to the API to allow reoffer codecs that were excluded previously: URL And the JSEP part: URL
Assigning Peter since his PR seems like the way forward.
I do worry that handling this in an ad hoc fashion is going to bite us, e.g. what if in the future a SFU wants a new offer with all supported RTP header extensions? I'm going to go dig up the initial issue that led to the approach that is currently in the document and see if it helps frame the situation.
TL; DR: After researching this issue, I think we should resolve it by always putting any supported-but-not-previously-negotiated codecs into the offer, but after the previously-negotiated codecs. [I will note that this is what NAME advocated for in August.] Full analysis OK, I trawled through the archives, and to the best of my understanding there are three issues: How to handle the case where EP1 (offerer) supports codecs [A, B, C] (in that preference order) and EP2 (answerer) supports [D, C, B] (in that order). See URL for more info. Interactions with the codec ordering API discussed in and related - how to prevent problems when both sides don't agree on ordering. Unnecessary SDP traffic (resending stuff that won't be used) Turning our attention to 1), we can consider left with the situation where EP1 and EP2 negotiate [B, C], via default 3264 rules, and EP2 now wants to reoffer. Under the current text, EP2 would have to reoffer [B, C], which prevents any change to the codec in use by either side, but doesn't allow for use of D. However, we definitely do not want to reoffer [D, C, B], since that will lead to [C, B] being negotiated, i.e., it will cause a codec switch. That leaves [D, B, C] or [B, C, D] as the only reasonable options to consider, i.e. "put new ones first" or "put new ones last". "New ones first" is complicated if we consider the case where EP2 suddenly supports [D, C, B, A]. Then the offer would become [D, A, B, C], and result in [A, B, C] being negotiated, which is probably not what EP2 wants. "New ones last" results in [B, C, D, A] being offered in the situation above, and [B, C, A] being negotiated. No codec switch occurs, unless explicit priority tweaking is performed. Ergo, "new ones last" seems like a reasonable policy that should address 1). 2) I think can be handled by the solution I am about to propose in . 3) I believe to be of minor importance. In the common case (e.g. when communicating between like endpoints), there will be no changes, and even in interop cases, the difference should be insignificant. Following up on my earlier comment, what about other things that might need to be renegotiated, such as a=rtcp-fb fields, and a=extmap extensions? It seems likely that if we are going to allow new codecs, we need to allow new a=rtcp-fb (which can be associated with a PT). And if we're going to do that, new a=extmap seems largely harmless. However, I think we should draw the line at any changes to TRANSPORT attributes, e.g. a=rtcp-rsize, etc. So the changes to S 5.2.2 would basically just be to incorporate the policy mentioned above into the first 3 bullets on page 45 (and any related changes needed in the subsequent-answer section). The End.
I can live with this. I would note that in bullet 3 above you could also do "B D C" but I think we can agree that that would be silly.
sounds good to me. Lots of SIP stuff does exactly that so I don't foresee any problem wiht his.
I can live with this as well. I just want to remind about two arguments that I got when I proposed this solution: a. Allocating a new codec can consume resources. For instance some video codecs have hardware resources required for their operation which need to be reserved before codec is offered. If codec is offered but never used, this can lead to waste of resources. b. In case of SIP, complete list of codecs is not produced for every offer. It is only produced for the offer which is generated in response to INVITE with no SDP body. Proposed behavior does not allow to exactly match currently implemented SIP end point behavior. As I have stated, I am fine with the proposed solution. I just want to make sure these two arguments do not cause any issues for anybody else.
NAME wdyt about the most recent comment from NAME ? As I see it we can either do what I propose here always, or only upon a createOffer flag (as NAME suggested). Always seems simpler, if we aren't worried about the issues Roman raises.
So what we sorted on editor call is we are going to make this happen by default for now. If a strong use case for having a knob to control it comes up, we can consider that. One point is you can use codec prefs to eliminate codecs so they don't show up in future offers.
NAME can you update your PR to reflect this consensus?
Hi, sorry as I couldn't track all the conclusions in this issue. However I'd like to confirm whether the current Chrome behavior is correct (according to the conclusion above) or not: Chrome is offered with VP8 PT 123. Chrome answers with VP8 PT 123 (including a sending video track) and no other video codecs. Chrome removes the video track from its PeerConnection. Chrome re-adds the same video track into its PeerConnection. Chrome calls . The new offer contains VP8 PT 123, but also VP9 PT 101, H264 etc etc etc. I didn't expect it since the initial SDP O/A did not contain them. Of course, there is a single BUNDLED transport. If this behavior correct and should Chrome fix it?
I think that behavior is correct by the new definition which is roughly reoffers will offer everything the browser can do at that point of time, but will put the stuff currently in use first.
Fine with me :)
Note that removal/readdition from a MediaStream should have no impact on offers/answers. IOW, the case you describe above is essentially: offer with all codecs, answer with just VP8, reoffer contains all codecs.
See also as a trivial followup on this issue.
Which has been merged, bringing this issue, finally, to a close.
What about if the video track I add to the local stream is not the same as the one I previously removed from it? For example, it is a video track retrieved via with different video resolution/constraints settings.
It has no impact. Only tracks given to addTrack or setTrack are used.
I did not understand you, sorry. I know that, according to the new API, changes in the local do not affect what the sends (although current Chrome does not behave like that and reacts on track addition/removal into the ). Thanks.
Just to be 200% sure, I would like to confirm that the following behaviour in Firefox is wrong. The scenario is the same as but now with Firefox: Firefox is offered with VP8 PT 123. Firefox answers with VP8 PT 123 (including a sending video track) and no other video codecs. Firefox removes the video track from its PeerConnection. Firefox adds another local video track into its PeerConnection. Firefox calls . The new offer contains VP8 PT 120 instead of 123 (wrong). Bug/issue detailed here: URL
What exact text do you believe prohibits this?
Per RFC 3264 this is allowed. What is not allowed is to use PT 123 for anything except VP8. Per :
Well, probably nothing prohibits a re-offer to include new PT values pointing to same codec+configurations as previously negotiated. Said that, a re-offer cannot offer a previously used PT for other codec+configuration. So IMHO this could be simplified by mandating reusing same PT values as before.
I'm not seeing a lot of value in requiring JSEP impls to behave this way.
Just noting that if it was a different m line, then it could use any PT it wanted for VP8. And in the above example, it is fine for it to use 120 in the 2nd offer as long as 120 had not previously been used for something other than VP8. To answer EKR question, the only thing of value here is following use case. In offer/answer 1, we have PT 120 => H264 and PT 123 => VP8. If in offer/answer 2 (on same m-lines, same mid, same blah blah blah) we swapped to PT120 => VP8, if we got a late media packet that was sent before the switch, but arrived after the switch, it might get delivered to the VP8 codec when actually it was encoded with H.264. I think that is all the is meant to stop. And I have allwasy viewed that trying to sop this is silly because what is going to happen is that late packet is going to get discarded. If sending a 264 packet to your VP8 codecs causes anything to happen other than it getting discarded, well seem like that is a problem.
The behavior mentioned by NAME does seem complicated, since the offerer needs to decode VP8 on both PT 120 and 123 at least until the O/A completes, but I agree it appears to be legal, and AFAICT it does not create any interoperability problems.
Uh no no. That's not possible. As long as such a m line belongs to the same BUNDLE group, all the m lines in that group are part of the same RTP session [1] and, hence, their PT values must be unique (in the sense that they must point to the same codec+configuration). I already asked about this exact subject several months ago. The given rationale was: "Existing RTP intermediaries [2] may rely on a single 1:1 mapping between PT and codec+configuration when carried over the same IP:port tuple, this is, the same RTP session" Those are the related threads: URL URL URL [1] Future generations may experience difficulties in understanding the concept of "RTP session". [2] Although no one has ever seen them in a WebRTC environment, they may exist.
The sad thing of all of this is that, at the end, for things to work the offerer and re-offerer must always be the same peer.
I think we definitely need to be able to have the reoffer move the media to a different IP since we do that all the time on non webrtc stuff. I might be missing what the issue is here but I want that to work.
Move the m= section into a separate transport just because it includes PT values already present in the other m= sections but pointing to different codec+configurations?
I don't see how any of this is a an issue. The rule is you can't reuse the PT. There's no rule that you can't reuse the codec with a new PT.
That's right, but it's also true that it causes errors in implementations (such as when Firefox renegotiates with Chrome by offering two different PT for Opus and Chrome assumes receipt of just the first PT). Hi, The following scenario causes setLocalDescription() to fail after renegotiation because the re-offerer (Firefox) introduces new codec PT in the same m= line): 1) Chrome calls to Firefox with an audio track. SDP offer (simplified): m=audio 58234 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126 a=setup:actpass a=mid:audio a=sendrecv a=rtcp-mux a=rtpmap:111 opus/48000/2 a=rtcp-fb:111 transport-cc a=fmtp:111 minptime=10;useinbandfec=1 a=rtpmap:103 ISAC/16000 a=rtpmap:104 ISAC/32000 a=rtpmap:9 G722/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:106 CN/32000 a=rtpmap:105 CN/16000 a=rtpmap:13 CN/8000 a=rtpmap:126 telephone-event/8000 2) Firefox SDP answer: m=audio 65515 UDP/TLS/RTP/SAVPF 111 a=recvonly a=fmtp:111 maxplaybackrate=48000;stereo=1 a=mid:audio a=rtcp-mux a=rtpmap:111 opus/48000/2 a=setup:active Firefox has chosen PT 111 (opus). Fine. 3) Firefox re-offers with its own audio track. SDP re-offer: m=audio 65515 UDP/TLS/RTP/SAVPF 109 9 0 8 111 a=sendrecv a=fmtp:111 maxplaybackrate=48000;stereo=1 a=mid:audio a=rtcp-mux a=rtpmap:109 opus/48000/2 a=rtpmap:9 G722/8000/1 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:111 opus/48000/2 a=setup:actpass Here Firefox has introduced a new PT value: 109 (also opus). Note that PT 111 (opus) is still present. 4) Chrome gets the SDP re-offer, calls setRemoteDescription() (success) and calls createAnswer(), which produces the following SDP answer: m=audio 58234 UDP/TLS/RTP/SAVPF 109 9 0 8 a=setup:passive a=mid:audio a=sendrecv a=rtcp-mux a=rtpmap:109 opus/48000/2 a=fmtp:109 minptime=10;useinbandfec=1 a=rtpmap:9 G722/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 Note that Chrome has chosen PT 109 (opus) instead of the previously used PT 111 (opus). 5) Then Chrome calls to setLocalDescription() with such an answer, which produces this error: So my main question is: can an endpoint perform a PeerConnection renegotiation and introduce new PT values within an existing m= line? AFAIR this is NOT valid. If valid, then this is a Chrome bug. If invalid, then this is a Firefox bug. Thanks a lot. Iñaki Baz Castillo

of the corresponding m= section in the current remote description: The m= line and corresponding "a=rtpmap" and "a=fmtp" lines MUST  <ins> only include codecs present in the most recent answer. </ins> The RTP header extensions MUST only include those that are present  <ins> in the most recent answer. </ins> The RTCP feedback extensions MUST only include those that are  <ins> present in the most recent answer. </ins>  <ins> The "a=rtcp-mux" line MUST only be added if present in the most recent answer. </ins>  <ins> The "a=rtcp-rsize" line MUST only be added if present in the most recent answer. </ins> The "a=group:BUNDLE" attribute MUST include the mid identifiers specified in the bundle group in the most recent answer, minus any m=


RFC3264, Section 6., and further processing for this m= section can be skipped. <del> Provided that is not the case, each m= section in the answer should then be generated as specified in RFC3264, Section 6.1.  For the m= line itself, the following rules must be followed: </del>  The port value would normally be set to the port of the default ICE candidate for this m= section, but given that no candidates

LG modulo comment
LGTM
Split from URL Something for the "Setting a remote description section"
(For clarity, the proper outcome is for the answerer to reject the m= line in the offer with no matching codecs, as discussed in IETF 95)
NAME asked about how the sendonly case should be handled. The minutes say but I'm not sure if we need to add any text for this. Peter, do you recall the details here?

RFC3264, Section 6., and further processing for this m= section can be skipped.  <ins> Otherwise, each m= section in the answer should then be generated as specified in RFC3264, Section 6.1.  For the m= line itself, the following rules must be followed: </ins> The port value would normally be set to the port of the default ICE candidate for this m= section, but given that no candidates


The addIceCandidate method provides a remote candidate to the ICE Agent, which, if parsed successfully, will be added to the current and/or pending remote description according to the rules defined for <del> Trickle ICE.  Connectivity checks will be sent to the new candidate. </del>  This method can also be used to provide an end-of-candidates indication (as defined in I-D.ietf-ice-trickle) to the ICE Agent for

Fixes URL
fixed the typos - LGTM
The spec is clear on that the MID has precedence over m= line index when coordinating candidates with m= lines. But it is not clear on what would happen if the MID has a value can't be matched to an m= line (while potentially the m= line index is valid).
I suspect that should result in some sort of invalid value error.
Right, I think we should return an error from addIceCandidate in this case. If you wanted a different result, you should have used the correct mid :-)
I agree to the above, just want it clarified.

The addIceCandidate method provides a remote candidate to the ICE Agent, which, if parsed successfully, will be added to the current and/or pending remote description according to the rules defined for  <ins> Trickle ICE.  If the MID, m-line index, or candidate string provided in the ICE candidate is invalid, an error is generated.  Connectivity checks will be sent to the new candidate. </ins> This method can also be used to provide an end-of-candidates indication (as defined in I-D.ietf-ice-trickle) to the ICE Agent for


I'd suggest that we try to move forward with this and leave the exact ruleset as an open issue pending Peter's investigation.
OK, I updated the PR to have the MST text. I think we had Cullen's r+ so ready to merge?
Merging this and will file an issue on the algorithm.

4.1.2.  <ins> The addTrack method adds a MediaStreamTrack to the PeerConnection, using the MediaStream argument to associate the track with other tracks in the same MediaStream, so that they can be added to the same "LS" group when creating an offer or answer.  addTrack attempts to minimize the number of transceivers as follows: The track will be attached to the first compatible transceiver (of the same media type) which has never had a direction of "sendonly" or "sendrecv".  If no such transceiver exists, then one will be constructed as described in sec.addTransceiver. </ins> 4.1.3.


all streams other than the first will be marked as bundle-only. This policy aims to minimize candidate gathering and maximize multiplexing, at the cost of less compatibility with legacy <del> endpoints. </del>  As it provides the best tradeoff between performance and compatibility with legacy endpoints, the default bundle policy MUST The browser will only gather RTP candidates.  This halves the number of candidates that the offerer needs to gather.  When <del> acting as answerer, the browser will reject any m= section that does not provide an "a=rtcp-mux" attribute. </del>  The default multiplexing policy MUST be set to "require". Implementations MAY choose to reject attempts by the application to there are m= sections, the unmatched RtpTransceivers will need to be associated in a subsequent offer. <del> For each offered m= section, if the associated RtpTransceiver has been stopped, the corresponding m= section in the answer MUST be marked as rejected by setting the port in the m= line to zero, as indicated in RFC3264, Section 6., and further processing for this m= section can be skipped. For each offered m= section, if no supported codec is present in the offer, the corresponding m= section in the answer MUST be marked as </del>  rejected by setting the port in the m= line to zero, as indicated in RFC3264, Section 6., and further processing for this m= section can <del> be skipped. </del>  Otherwise, each m= section in the answer should then be generated as specified in RFC3264, Section 6.1.  For the m= line itself, the

Also restructured the "rejecting media descriptions" sections since there are now four things that can cause it to be rejected.
I think this does a good job clarifying these edge cases and is the behavior we want.
lgtm
LGTM
I just realized this may not be complete. Even if max-bundle is used, shouldn't one media description be accepted? This would ensure the same result regardless of whether the max-bundle endpoint is the offerer or answerer. It would also prevent a remote offer from being rejected if it didn't include a "BUNDLE" group simply because there was only one media description.
Deficiencies should be addressed by this PR (apologies for missing them on the first pass): URL

all streams other than the first will be marked as bundle-only. This policy aims to minimize candidate gathering and maximize multiplexing, at the cost of less compatibility with legacy  <ins> endpoints.  When acting as answerer, the implementation will reject any m= section that is not in a bundle group. </ins> As it provides the best tradeoff between performance and compatibility with legacy endpoints, the default bundle policy MUST The browser will only gather RTP candidates.  This halves the number of candidates that the offerer needs to gather.  When  <ins> acting as answerer, the implementation will reject any m= section that does not contain an "a=rtcp-mux" attribute. </ins> The default multiplexing policy MUST be set to "require". Implementations MAY choose to reject attempts by the application to there are m= sections, the unmatched RtpTransceivers will need to be associated in a subsequent offer.  <ins> For each offered m= section, if any of the following conditions are true, the corresponding m= section in the answer MUST be marked as </ins> rejected by setting the port in the m= line to zero, as indicated in RFC3264, Section 6., and further processing for this m= section can  <ins> be skipped: The associated RtpTransceiver has been stopped. No supported codec is present in the offer. The bundle policy is "max-bundle" and the m= section is not in a bundle group. The RTP/RTCP multiplexing policy is "require" and the m= section doesn't contain an "a=rtcp-mux" attribute. </ins> Otherwise, each m= section in the answer should then be generated as specified in RFC3264, Section 6.1.  For the m= line itself, the


The result is that if there are N distinct media types, then candidates will be gathered for for N media streams.  This policy balances desire to multiplex with the need to ensure basic audio <del> and video can still be negotiated in legacy cases. </del>  all streams other than the first will be marked as bundle-only. This policy aims to minimize candidate gathering and maximize multiplexing, at the cost of less compatibility with legacy <del> endpoints.  When acting as answerer, the implementation will reject any m= section that is not in a bundle group. </del>  As it provides the best tradeoff between performance and compatibility with legacy endpoints, the default bundle policy MUST No supported codec is present in the offer. <del> The bundle policy is "max-bundle" and the m= section is not in a bundle group. </del>  The RTP/RTCP multiplexing policy is "require" and the m= section doesn't contain an "a=rtcp-mux" attribute.

If a non-bundle offer is received, and "max-bundle" is used, the first m= section should be accepted and all others rejected. This will ensure the same result whether or not the "max-bundle" endpoint is the offerer or answerer (ignoring some unlikely corner cases), and will prevent a lone media description from being rejected if the remote offer didn't contain a bundle group simply because it wasn't necessary. Also added equivalent rules for the "balanced" bundle policy.
This LGTM
This isn't exactly what I had in mind for 'balanced', but this might not be an issue in practice. If the answerer needs to handle multiple m= lines that are unbundled, it can set max-compat.
lgtm

The result is that if there are N distinct media types, then candidates will be gathered for for N media streams.  This policy balances desire to multiplex with the need to ensure basic audio  <ins> and video can still be negotiated in legacy cases.  When acting as answerer, if there is no bundle group in the offer, the implementation will reject all but the first m= section of each type. </ins> all streams other than the first will be marked as bundle-only. This policy aims to minimize candidate gathering and maximize multiplexing, at the cost of less compatibility with legacy  <ins> endpoints.  When acting as answerer, if there if no bundle group in the offer, the implementation will reject all but the first m= section. </ins> As it provides the best tradeoff between performance and compatibility with legacy endpoints, the default bundle policy MUST No supported codec is present in the offer.  <ins> The bundle policy is "max-bundle", the m= section is not in a bundle group, and this is not the first m= section. The bundle policy is "balanced", the m= section is not in a bundle group, and this is not the first m= section for this media type. </ins> The RTP/RTCP multiplexing policy is "require" and the m= section doesn't contain an "a=rtcp-mux" attribute.


TIAS = AS * 1000 * 0.95 - 50 * 40 * 8 The 50 is based on 50 packets per second, the 40 is based on an <del> estimate of total header size, the 1000 is to change the unit from kbps to bps and the 0.95 is to allocate 5% to RTCP.  If more accurate control of bandwidth is needed, "TIAS" should be used instead of "AS". </del>  For any "RR" or "RS" bandwidth values, handle as specified in RFC3556, Section 2.

This is an update of Fippo's
See PR
LGTM
lgtm with comma

TIAS = AS * 1000 * 0.95 - 50 * 40 * 8 The 50 is based on 50 packets per second, the 40 is based on an  <ins> estimate of total header size, the 1000 changes the unit from kbps to bps (as required by TIAS) and the 0.95 is to allocate 5% to RTCP.  If more accurate control of bandwidth is needed, "TIAS" should be used instead of "AS". </ins> For any "RR" or "RS" bandwidth values, handle as specified in RFC3556, Section 2.


3.7.  Some call signaling systems allow various types of forking where an SDP Offer may be provided to more than one device.  For example, SIP RFC3261 defines both a "Parallel Search" and "Sequential Search". Start exchanging media with a given remote peer, and free any resources in the offer that are not being used. <del> 3.7.1. </del>  Sequential forking involves a call being dispatched to multiple remote callees, where each callee can accept the call, but only one with a timer; at this point, the application could reapply the pending remote description as a final answer. <del> 3.7.2. </del>  Parallel forking involves a call being dispatched to multiple remote callees, where each callee can accept the call, and multiple

Fixes URL
LGTM
Updated to incorporate feedback from comments. Some more detail needed in the last para, but the narrative should be complete.
PTAL
LGTM
In WebRTC section 5.1, addTransceiver(), it says 'When setRemoteDescription is called with a corresponding remote description that is able to receive multiple RTP encodings as defined in [JSEP], the RTCRtpSender may send multiple RTP encodings and the parameters retrieved via the transceiver’s sender.getParameters() will reflect the encodings negotiated.' It is not obvious what to use as the JSEP reference because there does not seem to be a single place that talks about receipt of multiple encodings.
The specification of signalling that you can recevie multiple encodings seems to belong in either the RID spec or the JSEP spec. A decision was made some time back that WebRTC entities are only required to support receiving one incoming stream, but all the specs need to be clear on what that means in practice.
I think it makes sense for us to add some text in JSEP for this and create a link
The plan is to add a new section in JSEP section 3 that would give an overview of simulcast, perhaps a summary of URL, section 6.2.

3.7. <ins> JSEP supports simulcast of a MediaStreamTrack, where multiple encodings of the source media can be transmitted within the context of a single m= section.  The current JSEP API is designed to allow applications to send simulcasted media but only to receive a single encoding.  This allows for multi-user scenarios where each sending client sends multiple encodings to a server, which then, for each receiving client, chooses the appropriate encoding to forward. Applications request support for simulcast by configuring multiple encodings on an RTPSender, which, upon generation of an offer or answer, are indicated in SDP markings on the corresponding m= section, as described below.  Receivers that understand simulcast and are willing to receive it will also include SDP markings to indicate their support, and JSEP endpoints will use these markings to determine whether simulcast is permitted for a given RTPSender.  If simulcast support is not negotiated, the RTPSender will only use the first configured encoding. Note that the exact simulcast parameters are up to the sending application.  While the aforementioned SDP markings are provided to ensure the remote side can receive and demux multiple simulcast encodings, the specific resolutions and bitrates to be used for each encoding are purely a send-side decision in JSEP. JSEP currently does not provide an API to configure receipt of simulcast.  This means that if simulcast is offered by the remote endpoint, the answer generated by a JSEP endpoint will not indicate support for receipt of simulcast, and as such the remote endpoint will only send a single encoding per m= section.  In addition, when the JSEP endpoint is the answerer, the permitted encodings for the RTPSender must be consistent with the offer, but this information is currently not surfaced through any API.  This means that established simulcast streams will continue to work through a received re-offer, but setting up initial simulcast by way of a received offer requires out-of-band signaling or SDP inspection.  Future versions of this specification may add additional APIs to provide this control. When using JSEP to transmit multiple encodings from a RTPSender, the techniques from I-D.ietf-mmusic-sdp-simulcast and I-D.ietf-mmusic-rid are used.  Specifically, when multiple encodings have been configured for a RTPSender, the m= section for the RTPSender will include an "a=simulcast" attribute, as defined in I-D.ietf-mmusic-sdp-simulcast, Section 6.2, with a "send" simulcast stream description that lists each desired encoding, and no "recv" simulcast stream description. The m= section will also include an "a=rid" attribute for each encoding, as specfied in I-D.ietf-mmusic-rid, Section 4; the use of RID identifiers allows the individual encodings to be disambiguated even though they are all part of the same m= section. 3.8. </ins> Some call signaling systems allow various types of forking where an SDP Offer may be provided to more than one device.  For example, SIP RFC3261 defines both a "Parallel Search" and "Sequential Search". Start exchanging media with a given remote peer, and free any resources in the offer that are not being used.  <ins> 3.8.1. </ins> Sequential forking involves a call being dispatched to multiple remote callees, where each callee can accept the call, but only one with a timer; at this point, the application could reapply the pending remote description as a final answer.  <ins> 3.8.2. </ins> Parallel forking involves a call being dispatched to multiple remote callees, where each callee can accept the call, and multiple


flagged and stored. If present, a single "a=rtcp" attribute MUST be parsed as <del> specified in RFC3605, Section 2.1, but its value is ignored. </del>  If present, a single "a=msid" attribute MUST be parsed as specified in I-D.ietf-mmusic-msid, Section 3.2, and its value

Oh, I see: Issue .
Rewrote to remove some typos, and overall simplification
From the interim, there was some confusion on whether ignoring a=rtcp prohibited unmuxed RTCP; the intention here was that a=rtcp is superfluous because the RTCP port/IP information is carried in a=candidate lines. Suggest we just spell out this rationale explicitly.
That is, unless we use a=rtcp:0 to indicate exclusive.
This appears to be section 5.6.2's statement: If present, a single "a=rtcp" attribute MUST be parsed as specified in [RFC3605], Section 2.1, but its value is ignored. (This is no longer on page 52) Would work?

flagged and stored. If present, a single "a=rtcp" attribute MUST be parsed as  <ins> specified in RFC3605, Section 2.1, but its value is ignored, as this information is superfluous when using ICE. </ins> If present, a single "a=msid" attribute MUST be parsed as specified in I-D.ietf-mmusic-msid, Section 3.2, and its value


Any "a=extmap" lines are parsed as specified in RFC5285, Section 5, and their values are stored. <del> TODO: identity, rtcp-rsize, rtcp-mux, and any other attributes valid at session level. </del> Once all the session-level lines have been parsed, processing continues with the lines in media sections. specified in RFC5761, Section 5.1.1, and its presence or absence flagged and stored.  If present, a single "a=rtcp-rsize" attribute MUST be parsed as specified in RFC5506, Section 5, and its presence or absence flagged and stored.

Not ready yet.
LGTM with editorial comment as above.
Please apply same presence/absence treatment for all
http://rtcweb-URL [TODO: identity, rtcp-rsize, rtcp-mux, and any other attribs valid at session level.]
(session-level, specifically)

Any "a=extmap" lines are parsed as specified in RFC5285, Section 5, and their values are stored.  Once all the session-level lines have been parsed, processing continues with the lines in media sections. specified in RFC5761, Section 5.1.1, and its presence or absence flagged and stored. <ins> If present, a single "a=rtcp-mux-only" attribute MUST be parsed as specified in I-D.ietf-mmusic-mux-exclusive, Section 3, and its presence or absence flagged and stored. </ins> If present, a single "a=rtcp-rsize" attribute MUST be parsed as specified in RFC5506, Section 5, and its presence or absence flagged and stored.


the dummy value "9 IN IP4 0.0.0.0", because no candidates have yet been gathered. <del> A direction attribute for the associated RtpTransceiver as described by sec.offer-dirattr. </del>  For each supported codec, "a=rtpmap" and "a=fmtp" lines, as specified in RFC4566, Section 6.  The audio and video codecs that setting of the "vad" value in the signaling of the client to mixer audio level header extension described in RFC6464, Section 4. <del> 5.2.4. RFC3264 direction attributes (defined in Section 6.1) in offers are chosen according to the states of the RtpSender and RtpReceiver of a given RtpTransceiver, as follows: </del> 5.3. When createAnswer is called, a new SDP description must be created the dummy value "9 IN IP4 0.0.0.0", because no candidates have yet been gathered. <del> A direction attribute for the associated RtpTransceiver described by sec.answer-dirattr. </del>  For each supported codec that is present in the offer, "a=rtpmap" and "a=fmtp" lines, as specified in RFC4566, Section 6, and VoiceActivityDetection to true would result in an answer with CN codecs and "usedtx=0"). <del> 5.3.4. RFC3264 direction attributes (defined in Section 6.1) in answers are chosen according to the direction attribute in the remote offer and the states of the RtpSender and RtpReceiver of the corresponding RtpTransceiver, as follows: </del> 5.4. When a SessionDescription is supplied to setLocalDescription, the

Can you separate this from the ICE changes that are also in this PR?
Oops, yeah
NAME PTAL
LGTM
See URL

the dummy value "9 IN IP4 0.0.0.0", because no candidates have yet been gathered.  <ins> A direction attribute which is the same as that of the associated transceiver. </ins> For each supported codec, "a=rtpmap" and "a=fmtp" lines, as specified in RFC4566, Section 6.  The audio and video codecs that setting of the "vad" value in the signaling of the client to mixer audio level header extension described in RFC6464, Section 4.  5.3. When createAnswer is called, a new SDP description must be created the dummy value "9 IN IP4 0.0.0.0", because no candidates have yet been gathered.  <ins> A direction attribute which is the same as that of the associated transceiver. </ins> For each supported codec that is present in the offer, "a=rtpmap" and "a=fmtp" lines, as specified in RFC4566, Section 6, and VoiceActivityDetection to true would result in an answer with CN codecs and "usedtx=0").  5.4. When a SessionDescription is supplied to setLocalDescription, the


NAME See above
LGTM when outstanding comment addressed
JSEP currently has this: createDataChannel [TODO] We need this text before WGLC, so it's being added to the punchlist.

4.1.4.  <ins> The createDataChannel method creates a data channel and attaches it to the PeerConnection.  If no data channel currently exists for this PeerConnection, then a new offer/answer exchange is required.  All data channels on a given PeerConnection share the same SCTP/DTLS association and therefore the same m= section, so subsequent creation of data channels does not have any impact on the JSEP state. The createDataChannel method also includes a number of arguments which are used by the PeerConnection (e.g., maxPacketLifetime) but are not reflected in the SDP and do not affect the JSEP state. </ins> 4.1.5.


An "a=rtcp-mux" line, as specified in RFC5761, Section 5.1.1.  An "a=rtcp-rsize" line, as specified in RFC5506, Section 5. For each supported RTP header extension, an "a=extmap" line, as The "a=rtcp-mux" line MUST only be added if present in the most recent answer.  The "a=rtcp-rsize" line MUST only be added if present in the most recent answer. m=line MUST be marked as rejected by setting the port in the m= line to zero, as indicated in RFC3264, Section 6.  If present in the offer, an "a=rtcp-rsize" line, as specified in RFC5506, Section 5.

Line 2589: "I don't think this is quite right. I imagine this should probably echo the above, e.g. MUST only be added if present in the most recent answer."
So re-review this one and see if you are OK with it as is.
This seems fine.
JSEP should probably point at the draft and include the attribute on every (applicable) media section.
Agreed

An "a=rtcp-mux" line, as specified in RFC5761, Section 5.1.1. <ins> An "a=rtcp-mux-only" line, as specified in I-D.ietf-mmusic-mux- exclusive Section 4, if and only if the RTP/RTCP multiplexing policy is "require". </ins> An "a=rtcp-rsize" line, as specified in RFC5506, Section 5. For each supported RTP header extension, an "a=extmap" line, as The "a=rtcp-mux" line MUST only be added if present in the most recent answer. <ins> The "a=rtcp-mux-only" line MUST only be added if present in the most recent answer. </ins> The "a=rtcp-rsize" line MUST only be added if present in the most recent answer. m=line MUST be marked as rejected by setting the port in the m= line to zero, as indicated in RFC3264, Section 6. <ins> If present in the offer, an "a=rtcp-mux-only" line, as specified in I-D.ietf-mmusic-mux-exclusive, Section 4.3. </ins> If present in the offer, an "a=rtcp-rsize" line, as specified in RFC5506, Section 5.