<?xml version="1.0" encoding="us-ascii"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<?rfc toc="yes" ?>
<?rfc symrefs="yes" ?>
<?rfc iprnotified="no" ?>
<?rfc strict="yes" ?>
<?rfc compact="yes" ?>
<?rfc sortrefs="yes" ?>
<?rfc colonspace="yes" ?>
<?rfc rfcedstyle="no" ?>
<?rfc docmapping="yes" ?>
<?rfc tocdepth="4"?>
<rfc category="std" docName="draft-ietf-rtcweb-jsep-17"
ipr="trust200902">
  <front>
    <title abbrev="JSEP">Javascript Session Establishment
    Protocol</title>
    <author fullname="Justin Uberti" initials="J." surname="Uberti">
      <organization>Google</organization>
      <address>
        <postal>
          <street>747 6th St S</street>
          <city>Kirkland</city>
          <region>WA</region>
          <code>98033</code>
          <country>USA</country>
        </postal>
        <email>justin@uberti.name</email>
      </address>
    </author>
    <author fullname="Cullen Jennings" initials="C."
    surname="Jennings">
      <organization>Cisco</organization>
      <address>
        <postal>
          <street>400 3rd Avenue SW</street>
          <city>Calgary</city>
          <region>AB</region>
          <code>T2P 4H2</code>
          <country>Canada</country>
        </postal>
        <email>fluffy@iii.ca</email>
      </address>
    </author>
    <author fullname="Eric Rescorla" initials="E.K." surname="Rescorla"
    role="editor">
      <organization>Mozilla</organization>
      <address>
        <postal>
          <street>331 Evelyn Ave</street>
          <city>Mountain View</city>
          <region>CA</region>
          <code>94041</code>
          <country>USA</country>
        </postal>
        <email>ekr@rtfm.com</email>
      </address>
    </author>
    <date />
    <area>RAI</area>
    <abstract>

      <t>This document describes the mechanisms for allowing a
      Javascript application to control the signaling plane of a
      multimedia session via the interface specified in the W3C
      RTCPeerConnection API, and discusses how this relates to existing
      signaling protocols.</t>
    </abstract>
  </front>
  <middle>
    <section title="Introduction" anchor="sec.introduction">

      <t>This document describes how the W3C WEBRTC RTCPeerConnection
      interface
      <xref target="W3C.WD-webrtc-20140617"></xref> is used to control
      the setup, management and teardown of a multimedia session.</t>
      <section title="General Design of JSEP"
      anchor="sec.general-design-of-jsep">

        <t>The thinking behind WebRTC call setup has been to fully
        specify and control the media plane, but to leave the signaling
        plane up to the application as much as possible. The rationale
        is that different applications may prefer to use different
        protocols, such as the existing SIP or Jingle call signaling
        protocols, or something custom to the particular application,
        perhaps for a novel use case. In this approach, the key
        information that needs to be exchanged is the multimedia
        session description, which specifies the necessary transport
        and media configuration information necessary to establish the
        media plane.</t>

        <t>With these considerations in mind, this document describes
        the Javascript Session Establishment Protocol (JSEP) that
        allows for full control of the signaling state machine from
        Javascript. JSEP removes the browser almost entirely from the
        core signaling flow, which is instead handled by the Javascript
        making use of two interfaces: (1) passing in local and remote
        session descriptions and (2) interacting with the ICE state
        machine.</t>

        <t>In this document, the use of JSEP is described as if it
        always occurs between two browsers. Note though in many cases
        it will actually be between a browser and some kind of server,
        such as a gateway or MCU. This distinction is invisible to the
        browser; it just follows the instructions it is given via the
        API.</t>

        <t>JSEP's handling of session descriptions is simple and
        straightforward. Whenever an offer/answer exchange is needed,
        the initiating side creates an offer by calling a createOffer()
        API. The application optionally modifies that offer, and then
        uses it to set up its local config via the
        setLocalDescription() API. The offer is then sent off to the
        remote side over its preferred signaling mechanism (e.g.,
        WebSockets); upon receipt of that offer, the remote party
        installs it using the setRemoteDescription() API.</t>

        <t>To complete the offer/answer exchange, the remote party uses
        the createAnswer() API to generate an appropriate answer,
        applies it using the setLocalDescription() API, and sends the
        answer back to the initiator over the signaling channel. When
        the initiator gets that answer, it installs it using the
        setRemoteDescription() API, and initial setup is complete. This
        process can be repeated for additional offer/answer
        exchanges.</t>

        <t>Regarding ICE
        <xref target="RFC5245"></xref>, JSEP decouples the ICE state
        machine from the overall signaling state machine, as the ICE
        state machine must remain in the browser, because only the
        browser has the necessary knowledge of candidates and other
        transport info. Performing this separation also provides
        additional flexibility; in protocols that decouple session
        descriptions from transport, such as Jingle, the session
        description can be sent immediately and the transport
        information can be sent when available. In protocols that
        don't, such as SIP, the information can be used in the
        aggregated form. Sending transport information separately can
        allow for faster ICE and DTLS startup, since ICE checks can
        start as soon as any transport information is available rather
        than waiting for all of it.</t>

        <t>Through its abstraction of signaling, the JSEP approach does
        require the application to be aware of the signaling process.
        While the application does not need to understand the contents
        of session descriptions to set up a call, the application must
        call the right APIs at the right times, convert the session
        descriptions and ICE information into the defined messages of
        its chosen signaling protocol, and perform the reverse
        conversion on the messages it receives from the other side.</t>

        <t>One way to mitigate this is to provide a Javascript library
        that hides this complexity from the developer; said library
        would implement a given signaling protocol along with its state
        machine and serialization code, presenting a higher level
        call-oriented interface to the application developer. For
        example, libraries exist to adapt the JSEP API into an API
        suitable for a SIP or XMPP. Thus, JSEP provides greater control
        for the experienced developer without forcing any additional
        complexity on the novice developer.</t>
      </section>
      <section title="Other Approaches Considered"
      anchor="sec.other-approaches-consider">

        <t>One approach that was considered instead of JSEP was to
        include a lightweight signaling protocol. Instead of providing
        session descriptions to the API, the API would produce and
        consume messages from this protocol. While providing a more
        high-level API, this put more control of signaling within the
        browser, forcing the browser to have to understand and handle
        concepts like signaling glare. In addition, it prevented the
        application from driving the state machine to a desired state,
        as is needed in the page reload case.</t>

        <t>A second approach that was considered but not chosen was to
        decouple the management of the media control objects from
        session descriptions, instead offering APIs that would control
        each component directly. This was rejected based on a feeling
        that requiring exposure of this level of complexity to the
        application programmer would not be beneficial; it would result
        in an API where even a simple example would require a
        significant amount of code to orchestrate all the needed
        interactions, as well as creating a large API surface that
        needed to be agreed upon and documented. In addition, these API
        points could be called in any order, resulting in a more
        complex set of interactions with the media subsystem than the
        JSEP approach, which specifies how session descriptions are to
        be evaluated and applied.</t>

        <t>One variation on JSEP that was considered was to keep the
        basic session description-oriented API, but to move the
        mechanism for generating offers and answers out of the browser.
        Instead of providing createOffer/createAnswer methods within
        the browser, this approach would instead expose a
        getCapabilities API which would provide the application with
        the information it needed in order to generate its own session
        descriptions. This increases the amount of work that the
        application needs to do; it needs to know how to generate
        session descriptions from capabilities, and especially how to
        generate the correct answer from an arbitrary offer and the
        supported capabilities. While this could certainly be addressed
        by using a library like the one mentioned above, it basically
        forces the use of said library even for a simple example.
        Providing createOffer/createAnswer avoids this problem, but
        still allows applications to generate their own offers/answers
        (to a large extent) if they choose, using the description
        generated by createOffer as an indication of the browser's
        capabilities.</t>
      </section>
    </section>
    <section title="Terminology" anchor="sec.terminology">

      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
      NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
      "OPTIONAL" in this document are to be interpreted as described in

      <xref target="RFC2119"></xref>.</t>
    </section>
    <section title="Semantics and Syntax"
    anchor="sec.semantics-and-syntax">
      <section title="Signaling Model" anchor="sec.signaling-model">

        <t>JSEP does not specify a particular signaling model or state
        machine, other than the generic need to exchange session
        descriptions in the fashion described by
        <xref target="RFC3264"></xref>(offer/answer) in order for both
        sides of the session to know how to conduct the session. JSEP
        provides mechanisms to create offers and answers, as well as to
        apply them to a session. However, the browser is totally
        decoupled from the actual mechanism by which these offers and
        answers are communicated to the remote side, including
        addressing, retransmission, forking, and glare handling. These
        issues are left entirely up to the application; the application
        has complete control over which offers and answers get handed
        to the browser, and when.</t>
        <figure anchor="fig-sigModel" title="JSEP Signaling Model">
          <artwork>
            <![CDATA[
    +-----------+                               +-----------+
    |  Web App  |<--- App-Specific Signaling -->|  Web App  |
    +-----------+                               +-----------+
          ^                                            ^
          |  SDP                                       |  SDP
          V                                            V
    +-----------+                                +-----------+
    |  Browser  |<----------- Media ------------>|  Browser  |
    +-----------+                                +-----------+
]]>
</artwork>
        </figure>
      </section>
      <section title="Session Descriptions and State Machine"
      anchor="sec.session-descriptions-and-">

        <t>In order to establish the media plane, the user agent needs
        specific parameters to indicate what to transmit to the remote
        side, as well as how to handle the media that is received.
        These parameters are determined by the exchange of session
        descriptions in offers and answers, and there are certain
        details to this process that must be handled in the JSEP
        APIs.</t>

        <t>Whether a session description applies to the local side or
        the remote side affects the meaning of that description. For
        example, the list of codecs sent to a remote party indicates
        what the local side is willing to receive, which, when
        intersected with the set of codecs the remote side supports,
        specifies what the remote side should send. However, not all
        parameters follow this rule; for example, the DTLS-SRTP
        parameters
        <xref target="RFC5763"></xref> sent to a remote party indicate
        what certificate the local side will use in DTLS setup, and
        thereby what the remote party should expect to receive; the
        remote party will have to accept these parameters, with no
        option to choose different values.</t>

        <t>In addition, various RFCs put different conditions on the
        format of offers versus answers. For example, an offer may
        propose an arbitrary number of media streams (i.e. m=
        sections), but an answer must contain the exact same number as
        the offer.</t>

        <t>Lastly, while the exact media parameters are only known only
        after an offer and an answer have been exchanged, it is
        possible for the offerer to receive media after they have sent
        an offer and before they have received an answer. To properly
        process incoming media in this case, the offerer's media
        handler must be aware of the details of the offer before the
        answer arrives.</t>

        <t>Therefore, in order to handle session descriptions properly,
        the user agent needs:
        <list style="numbers">

          <t>To know if a session description pertains to the local or
          remote side.</t>

          <t>To know if a session description is an offer or an
          answer.</t>

          <t>To allow the offer to be specified independently of the
          answer.</t>
        </list>JSEP addresses this by adding both setLocalDescription
        and setRemoteDescription methods and having session description
        objects contain a type field indicating the type of session
        description being supplied. This satisfies the requirements
        listed above for both the offerer, who first calls
        setLocalDescription(sdp [offer]) and then later
        setRemoteDescription(sdp [answer]), as well as for the
        answerer, who first calls setRemoteDescription(sdp [offer]) and
        then later setLocalDescription(sdp [answer]).</t>

        <t>JSEP also allows for an answer to be treated as provisional
        by the application. Provisional answers provide a way for an
        answerer to communicate initial session parameters back to the
        offerer, in order to allow the session to begin, while allowing
        a final answer to be specified later. This concept of a final
        answer is important to the offer/answer model; when such an
        answer is received, any extra resources allocated by the caller
        can be released, now that the exact session configuration is
        known. These "resources" can include things like extra ICE
        components, TURN candidates, or video decoders. Provisional
        answers, on the other hand, do no such deallocation results; as
        a result, multiple dissimilar provisional answers can be
        received and applied during call setup.</t>

        <t>In
        <xref target="RFC3264"></xref>, the constraint at the signaling
        level is that only one offer can be outstanding for a given
        session, but at the media stack level, a new offer can be
        generated at any point. For example, when using SIP for
        signaling, if one offer is sent, then cancelled using a SIP
        CANCEL, another offer can be generated even though no answer
        was received for the first offer. To support this, the JSEP
        media layer can provide an offer via the createOffer() method
        whenever the Javascript application needs one for the
        signaling. The answerer can send back zero or more provisional
        answers, and finally end the offer-answer exchange by sending a
        final answer. The state machine for this is as follows:</t>

        <t>
          <figure anchor="fig-state-machine"
          title="JSEP State Machine">
            <artwork>
              <![CDATA[
                    setRemote(OFFER)               setLocal(PRANSWER)
                        /-----\                               /-----\
                        |     |                               |     |
                        v     |                               v     |
         +---------------+    |                +---------------+    |
         |               |----/                |               |----/
         |               | setLocal(PRANSWER)  |               |
         |  Remote-Offer |------------------- >| Local-Pranswer|
         |               |                     |               |
         |               |                     |               |
         +---------------+                     +---------------+
              ^   |                                   |
              |   | setLocal(ANSWER)                  |
setRemote(OFFER)  |                                   |
              |   V                  setLocal(ANSWER) |
         +---------------+                            |
         |               |                            |
         |               |<---------------------------+
         |    Stable     |
         |               |<---------------------------+
         |               |                            |
         +---------------+          setRemote(ANSWER) |
              ^   |                                   |
              |   | setLocal(OFFER)                   |
setRemote(ANSWER) |                                   |
              |   V                                   |
         +---------------+                     +---------------+
         |               |                     |               |
         |               | setRemote(PRANSWER) |               |
         |  Local-Offer  |------------------- >|Remote-Pranswer|
         |               |                     |               |
         |               |----\                |               |----\
         +---------------+    |                +---------------+    |
                        ^     |                               ^     |
                        |     |                               |     |
                        \-----/                               \-----/
                    setLocal(OFFER)               setRemote(PRANSWER)
]]>
</artwork>
          </figure>
        </t>

        <t>Aside from these state transitions there is no other
        difference between the handling of provisional ("pranswer") and
        final ("answer") answers.</t>
      </section>
      <section title="Session Description Format"
      anchor="sec.session-description-forma">

        <t>In the WebRTC specification, session descriptions are
        formatted as SDP messages. While this format is not optimal for
        manipulation from Javascript, it is widely accepted, and
        frequently updated with new features. Any alternate encoding of
        session descriptions would have to keep pace with the changes
        to SDP, at least until the time that this new encoding eclipsed
        SDP in popularity. As a result, JSEP currently uses SDP as the
        internal representation for its session descriptions.</t>

        <t>However, to simplify Javascript processing, and provide for
        future flexibility, the SDP syntax is encapsulated within a
        SessionDescription object, which can be constructed from SDP,
        and be serialized out to SDP. If future specifications agree on
        a JSON format for session descriptions, we could easily enable
        this object to generate and consume that JSON.</t>

        <t>Other methods may be added to SessionDescription in the
        future to simplify handling of SessionDescriptions from
        Javascript. In the meantime, Javascript libraries can be used
        to perform these manipulations.</t>

        <t>Note that most applications should be able to treat the
        SessionDescriptions produced and consumed by these various API
        calls as opaque blobs; that is, the application will not need
        to read or change them.</t>
      </section>
      <section title="Session Description Control"
      anchor="sec.session-description-ctrl">

        <t>In order to give the application control over various common
        session parameters, JSEP provides control surfaces which tell
        the browser how to generate session descriptions. This avoids
        the need for Javascript to modify session descriptions in most
        cases.</t>

        <t>Changes to these objects result in changes to the session
        descriptions generated by subsequent createOffer/Answer
        calls.</t>
        <section title="RtpTransceivers" anchor="sec.rtptransceivers">

          <t>RtpTransceivers allow the application to control the RTP
          media associated with one m= section. Each RtpTransceiver has
          an RtpSender and an RtpReceiver, which an application can use
          to control the sending and receiving of RTP media. The
          application may also modify the RtpTransceiver directly, for
          instance, by stopping it.</t>

          <t>RtpTransceivers generally have a 1:1 mapping with m=
          sections, although there may be more RtpTransceivers than m=
          sections when RtpTransceivers are created but not yet
          associated with a m= section, or if RtpTransceivers have been
          stopped and disassociated from m= sections. An RtpTransceiver
          is never associated with more than one m= section, and once a
          session description is applied, a m= section is always
          associated with exactly one RtpTransceiver.</t>

          <t>RtpTransceivers can be created explicitly by the
          application or implicitly by calling setRemoteDescription
          with an offer that adds new m= sections.</t>
        </section>
        <section title="RtpSenders" anchor="sec.rtpsenders">

          <t>RtpSenders allow the application to control how RTP media
          is sent.</t>
        </section>
        <section title="RtpReceivers" anchor="sec.rtpreceivers">

          <t>RtpReceivers allows the application to control how RTP
          media is received.</t>
        </section>
      </section>
      <section title="ICE" anchor="sec.ice">
        <section title="ICE Gathering Overview"
        anchor="sec.ice-gather-overview">

          <t>JSEP gathers ICE candidates as needed by the application.
          Collection of ICE candidates is referred to as a gathering
          phase, and this is triggered either by the addition of a new
          or recycled m= line to the local session description, or new
          ICE credentials in the description, indicating an ICE
          restart. Use of new ICE credentials can be triggered
          explicitly by the application, or implicitly by the browser
          in response to changes in the ICE configuration.</t>

          <t>When the ICE configuration changes in a way that requires
          a new gathering phase, a 'needs-ice-restart' bit is set. When
          this bit is set, calls to the createOffer API will generate
          new ICE credentials. This bit is cleared by a call to the
          setLocalDescription API with new ICE credentials from either
          an offer or an answer, i.e., from either a local- or
          remote-initiated ICE restart.</t>

          <t>When a new gathering phase starts, the ICE Agent will
          notify the 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 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.</t>

          <t>Note that gathering phases only gather the candidates
          needed by new/recycled/restarting m= lines; other m= lines
          continue to use 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
          <xref target="I-D.ietf-mmusic-sdp-bundle-negotiation" />.</t>
        </section>
        <section title="ICE Candidate Trickling"
        anchor="sec.ice-candidate-trickling">

          <t>Candidate trickling is a technique through which a caller
          may incrementally provide candidates to the callee after the
          initial offer has been dispatched; the semantics of "Trickle
          ICE" are defined in
          <xref target="I-D.ietf-ice-trickle"></xref>. This process
          allows the callee to begin acting upon the call and setting
          up the ICE (and perhaps DTLS) connections immediately,
          without having to wait for the caller to gather all possible
          candidates. This results in faster media setup in cases where
          gathering is not performed prior to initiating the call.</t>

          <t>JSEP supports optional candidate trickling by providing
          APIs, as described above, that provide control and feedback
          on the ICE candidate gathering process. Applications that
          support candidate trickling can send the initial offer
          immediately and send individual candidates when they get the
          notified of a new candidate; applications that do not support
          this feature can simply wait for the indication that
          gathering is complete, and then create and send their offer,
          with all the candidates, at this time.</t>

          <t>Upon receipt of trickled candidates, the receiving
          application will supply them to its ICE Agent. This triggers
          the ICE Agent to start using the new remote candidates for
          connectivity checks.</t>
          <section title="ICE Candidate Format"
          anchor="sec.ice-candidate-format">

            <t>As with session descriptions, the syntax of the
            IceCandidate object provides some abstraction, but can be
            easily converted to and from the SDP candidate lines.</t>

            <t>The candidate lines are the only SDP information that is
            contained within IceCandidate, as they represent the only
            information needed that is not present in the initial offer
            (i.e., for trickle candidates). This information is carried
            with the same syntax as the "candidate-attribute" field
            defined for ICE. For example:</t>
            <figure>
              <artwork>
                <![CDATA[
candidate:1 1 UDP 1694498815 192.0.2.33 10000 typ host
]]>
</artwork>
            </figure>

            <t>The IceCandidate object also contains fields to indicate
            which m= line it should be associated with. The m= line can
            be identified in one of two ways; either by a m= line
            index, or a MID. The m= line index is a zero-based index,
            with index N referring to the N+1th m= line in the SDP sent
            by the entity which sent the IceCandidate. The MID uses the
            "media stream identification" attribute, as defined in
            <xref target="RFC5888"></xref>, Section 4, to identify the
            m= line. JSEP implementations creating an ICE Candidate
            object MUST populate both of these fields, using the MID of
            the associated RtpTransceiver object (which may be locally
            generated by the answerer when interacting with a non-JSEP
            remote endpoint that does not support the MID attribute, as
            discussed in
            <xref target="sec.applying-a-remote-desc" /> below).
            Implementations receiving an ICE Candidate object MUST use
            the MID if present, or the m= line index, if not (the
            non-JSEP remote endpoint case).</t>
          </section>
        </section>
        <section title="ICE Candidate Policy"
        anchor="sec.ice-candidate-policy">

          <t>Typically, when gathering ICE candidates, the browser will
          gather all possible forms of initial candidates - host,
          server reflexive, and relay. However, in certain cases,
          applications may want to have more specific control over the
          gathering process, due to privacy or related concerns. For
          example, one may want to suppress the use of host candidates,
          to avoid exposing information about the local network, or go
          as far as only using relay candidates, to leak as little
          location information as possible (note that these choices
          come with corresponding operational costs). To accomplish
          this, the browser MUST allow the application to restrict
          which ICE candidates 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
          <xref target="I-D.ietf-rtcweb-ip-handling" />.</t>

          <t>There may also be cases where the application wants to
          change which types of candidates are used while the session
          is active. A prime example is where a callee may initially
          want to use only relay candidates, to avoid leaking location
          information to an arbitrary caller, but then change to use
          all candidates (for lower operational cost) once the user has
          indicated they want to take the call. For this scenario, the
          browser MUST allow the candidate policy to be changed in
          mid-session, subject to the aforementioned interactions with
          local policy.</t>

          <t>To administer the ICE candidate policy, the browser will
          determine the current setting at the start of each gathering
          phase. Then, during the gathering phase, the browser MUST NOT
          expose candidates disallowed by the current policy to the
          application, use them as the source of connectivity checks,
          or indirectly expose them via other fields, such as the
          raddr/rport attributes for other ICE candidates. Later, if a
          different policy is specified by the application, the
          application can apply it by kicking off a new gathering phase
          via an ICE restart.</t>
        </section>
        <section title="ICE Candidate Pool"
        anchor="sec.ice-candidate-pool">

          <t>JSEP applications typically inform the browser to begin
          ICE gathering via the information supplied to
          setLocalDescription, as this is where the app specifies the
          number of media streams, and thereby ICE components, for
          which to gather candidates. However, to accelerate cases
          where the application knows the number of ICE components to
          use ahead of time, it may ask the browser to gather a pool of
          potential ICE candidates to help ensure rapid media
          setup.</t>

          <t>When setLocalDescription is eventually called, and the
          browser goes to gather the needed ICE candidates, it SHOULD
          start by checking if any candidates are available in the
          pool. If there are candidates in the pool, they SHOULD be
          handed to the application immediately via the ICE candidate
          event. If the pool becomes depleted, either because a
          larger-than-expected number of ICE components is used, or
          because the pool has not had enough time to gather
          candidates, the remaining candidates are gathered as
          usual.</t>

          <t>One example of where this concept is useful is an
          application that expects an incoming call at some point in
          the future, and wants to minimize the time it takes to
          establish connectivity, to avoid clipping of initial media.
          By pre-gathering candidates into the pool, it can exchange
          and start sending connectivity checks from these candidates
          almost immediately upon receipt of a call. Note though that
          by holding on to these pre-gathered candidates, which will be
          kept alive as long as they may be needed, the application
          will consume resources on the STUN/TURN servers it is
          using.</t>
        </section>
      </section>
      <section anchor="sec.imageattr" title="Video Size Negotiation">

        <t>Video size negotiation is the process through which a
        receiver can use the "a=imageattr" SDP attribute
        <xref target="RFC6236" /> to indicate what video frame sizes it
        is capable of receiving. A receiver may have hard limits on
        what its video decoder can process, or it may wish to constrain
        what it receives due to application preferences, e.g. a
        specific size for the window in which the video will be
        displayed.</t>

        <t>Note that certain codecs support transmission of samples with aspect
        ratios other than 1.0 (i.e., non-square pixels).
        JSEP implementations will not transmit non-square pixels, but SHOULD
        receive and render such video with the correct aspect ratio.
        However, sample aspect ratio has no impact on the size negotiation
        described below; all dimensions assume square pixels.
        </t>

        <section title="Creating an imageattr Attribute">

          <t>In order to determine the limits on what video resolution
          a receiver wants to receive, it will intersect its decoder
          hard limits with any mandatory constraints that have been
          applied to the associated MediaStreamTrack. If the decoder
          limits are unknown, e.g. when using a software decoder, the
          mandatory constraints are used directly. For the answerer,
          these mandatory constraints can be applied to the remote
          MediaStreamTracks that are created by a setRemoteDescription
          call, and will affect the output of the ensuing createAnswer
          call. Any constraints set after setLocalDescription is used
          to set the answer will result in a new offer-answer exchange.
          For the offerer, because it does not know about any remote
          MediaStreamTracks until it receives the answer, the offer can
          only reflect decoder hard limits. If the offerer wishes to
          set mandatory constraints on video resolution, it must do so
          after receiving the answer, and the result will be a new
          offer-answer to communicate them.</t>

          <t>If there are no known decoder limits or mandatory
          constraints, the "a=imageattr" attribute SHOULD be
          omitted.</t>

          <t>Otherwise, an "a=imageattr" attribute is created with
          "recv" direction, and the resulting resolution space formed
          by intersecting the decoder limits and constraints is used to
          specify its minimum and maximum x= and y= values. If the
          intersection is the null set, i.e., there are no resolutions
          that are permitted by both the decoder and the mandatory
          constraints, this SHOULD be represented by x=0 and y=0
          values.</t>

          <t>The rules here express a single set of preferences, and
          therefore, the "a=imageattr" q= value is not important. It
          SHOULD be set to 1.0.</t>

          <t>The "a=imageattr" field is payload type specific. When all
          video codecs supported have the same capabilities, use of a
          single attribute, with the wildcard payload type (*), is
          RECOMMENDED. However, when the supported video codecs have
          differing capabilities, specific "a=imageattr" attributes
          MUST be inserted for each payload type.</t>

          <t>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 implementation would generate this attribute:</t>

          <t>a=imageattr:* recv [x=[16:640],y=[16:360],q=1.0]</t>

          <t>This declaration indicates that the receiver is capable of
          decoding any image resolution from 16x16 up to 640x360
          pixels.</t>
        </section>
        <section title="Interpreting an imageattr Attribute">

          <t>
          <xref target="RFC6236" /> defines "a=imageattr" to be an
          advisory field. This means that it does not absolutely
          constrain the video formats that the sender can use, but
          gives an indication of the preferred values.</t>

          <t>This specification prescribes more specific behavior. When
          a sender of a given MediaStreamTrack, which is producing
          video of a certain 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.</t>

          <t>For the purposes of resolution negotiation, only size limits are
          considered. Any other values, e.g. picture or sample aspect ratio,
          MUST be ignored.</t>

          <t>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.</t>

          <t>If an "a=imageattr recv" attribute references a different
          video codec than what has been selected for the
          MediaStreamTrack, it MUST be ignored.</t>

          <t>If the original resolution matches the size limits in the
          attribute, the track MUST be transmitted untouched.</t>

          <t>If the original resolution exceeds the size limits in the
          attribute, the sender SHOULD apply downscaling to the output
          of the MediaStreamTrack in order to satisfy the limits.
          Downscaling MUST NOT change the track aspect ratio.</t>

          <t>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.</t>

          <t>If there is no appropriate and permitted scaling mechanism
          that allows the received size limits to be satisfied, the
          sender MUST NOT transmit the track.</t>

          <t>If the attribute includes a "sar=" (sample aspect ratio) value set
          to something other than "1.0", indicating the receiver wants to
          receive non-square pixels, this cannot be satisfied and the sender
          MUST NOT transmit the track.</t>

          <t>In the special case of receiving a maximum resolution of
          [0, 0], as described above, the sender MUST NOT transmit the
          track.</t>
        </section>
      </section>
      <section title="Simulcast" anchor="sec.simulcast">

        <t>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.</t>

        <t>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.</t>

        <t>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.</t>

        <t>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.</t>

        <t>When using JSEP to transmit multiple encodings from a
        RTPSender, the techniques from
        <xref target="I-D.ietf-mmusic-sdp-simulcast" /> and
        <xref target="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
        <xref target="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
        <xref target="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.</t>
      </section>
      <section title="Interactions With Forking"
      anchor="sec.interactions-with-forking">

        <t>Some call signaling systems allow various types of forking
        where an SDP Offer may be provided to more than one device. For
        example, SIP
        <xref target="RFC3261"></xref> defines both a "Parallel Search"
        and "Sequential Search". Although these are primarily signaling
        level issues that are outside the scope of JSEP, they do have
        some impact on the configuration of the media plane that is
        relevant. When forking happens at the signaling layer, the
        Javascript application responsible for the signaling needs to
        make the decisions about what media should be sent or received
        at any point of time, as well as which remote endpoint it
        should communicate with; JSEP is used to make sure the media
        engine can make the RTP and media perform as required by the
        application. The basic operations that the applications can
        have the media engine do are:
        <list style="symbols">

          <t>Start exchanging media with a given remote peer, but keep
          all the resources reserved in the offer.</t>

          <t>Start exchanging media with a given remote peer, and free
          any resources in the offer that are not being used.</t>
        </list></t>
        <section title="Sequential Forking"
        anchor="sec.sequential-forking">

          <t>Sequential forking involves a call being dispatched to
          multiple remote callees, where each callee can accept the
          call, but only one active session ever exists at a time; no
          mixing of received media is performed.</t>

          <t>JSEP handles sequential forking well, allowing the
          application to easily control the policy for selecting the
          desired remote endpoint. When an answer arrives from one of
          the callees, the application can choose to apply it either as
          a provisional answer, leaving open the possibility of using a
          different answer in the future, or apply it as a final
          answer, ending the setup flow.</t>

          <t>In a "first-one-wins" situation, the first answer will be
          applied as a final answer, and the application will reject
          any subsequent answers. In SIP parlance, this would be ACK +
          BYE.</t>

          <t>In a "last-one-wins" situation, all answers would be
          applied as 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 pending remote description as a
          final answer.</t>
        </section>
        <section title="Parallel Forking"
        anchor="sec.parallel-forking">

          <t>Parallel forking involves a call being dispatched to
          multiple remote callees, where each callee can accept the
          call, and multiple simultaneous active signaling sessions can
          be established as a result. If multiple callees send media at
          the same time, the possibilities for handling this are
          described in Section 3.1 of
          <xref target="RFC3960"></xref>. Most SIP devices today only
          support exchanging media with a single device at a time, and
          do not try to mix multiple early media audio sources, as that
          could result in a confusing situation. For example, consider
          having a European ringback tone mixed together with the North
          American ringback tone - the resulting sound would not be
          like either tone, and would confuse the user. If the
          signaling application wishes to only exchange media with one
          of the remote endpoints at a time, then from a media engine
          point of view, this is exactly like the sequential forking
          case.</t>

          <t>In the parallel forking case where the Javascript
          application wishes to simultaneously exchange media with
          multiple peers, the flow is slightly more complex, but the
          Javascript application can follow the strategy that
          <xref target="RFC3960"></xref> describes using UPDATE. The
          UPDATE approach allows the signaling to set up a separate
          media flow for each peer that it wishes to exchange media
          with. In JSEP, this offer used in the UPDATE would be formed
          by simply creating a new PeerConnection and making sure that
          the same local media streams have been added into this new
          PeerConnection. Then the new PeerConnection object would
          produce a SDP offer that could be used by the signaling to
          perform the UPDATE strategy discussed in
          <xref target="RFC3960"></xref>.</t>

          <t>As a result of sharing the media streams, the application
          will end up with N parallel PeerConnection sessions, each
          with a local and remote description and their own local and
          remote addresses. The media flow from these sessions can be
          managed by specifying SDP direction attributes in the
          descriptions, or the application can choose to play out the
          media from all sessions mixed together. Of course, if the
          application wants to only keep a single session, it can
          simply terminate the sessions that it no longer needs.</t>
        </section>
      </section>
    </section>
    <section title="Interface" anchor="sec.interface">

      <t>This section details the basic operations that must be present
      to implement JSEP functionality. The actual API exposed in the
      W3C API may have somewhat different syntax, but should map easily
      to these concepts.</t>
      <section title="PeerConnection" anchor="sec.peerconnection">
        <section title="Constructor" anchor="sec.pc-constructor">

          <t>The PeerConnection constructor allows the application to
          specify global parameters for the media session, such as the
          STUN/TURN servers and credentials to use when gathering
          candidates, as well as the initial ICE candidate policy and
          pool size, and also the bundle policy to use.</t>

          <t>If an ICE candidate policy is specified, it functions as
          described in
          <xref target="sec.ice-candidate-policy" />, causing the
          browser to only surface the 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:
          <list style="hanging">
            <t hangText="all:">All candidates permitted by browser
            policy will be gathered and used.</t>

            <t></t>
            <t hangText="relay:">All candidates except relay candidates
            will be filtered out. This obfuscates the location
            information that might be ascertained by the remote peer
            from the received candidates. Depending on how the
            application deploys its relay servers, this could obfuscate
            location to a metro or possibly even global level.</t>
          </list></t>

          <t>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.</t>

          <t>If a size is specified for the ICE candidate pool, this
          indicates the number of ICE components to pre-gather
          candidates for. Because pre-gathering results in utilizing
          STUN/TURN server resources for potentially long periods of
          time, this must only occur upon application request, and
          therefore the default candidate pool size MUST be zero.</t>

          <t>The application can specify its preferred policy regarding
          use of bundle, the multiplexing mechanism defined in
          <xref target="I-D.ietf-mmusic-sdp-bundle-negotiation">
          </xref>. Regardless of policy, the application will always
          try to negotiate bundle onto a single transport, and will
          offer a single bundle group across all media section; use of
          this single transport is contingent upon the answerer
          accepting bundle. However, by specifying a policy from the
          list below, the application can control exactly how
          aggressively it will try to bundle media streams together,
          which affects how it will interoperate with a
          non-bundle-aware endpoint. When negotiating with a
          non-bundle-aware endpoint, only the streams not marked as
          bundle-only streams will be established.</t>

          <t>The set of available policies is as follows:
          <list style="hanging">
            <t hangText="balanced:">The first media section of each
            type (audio, video, or application) will contain transport
            parameters, which will allow an answerer to unbundle that
            section. The second and any subsequent media section of
            each type will be marked bundle-only. 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 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.</t>

            <t></t>
            <t hangText="max-compat:">All media sections will contain
            transport parameters; none will be marked as bundle-only.
            This policy will allow all streams to be received by
            non-bundle-aware endpoints, but require separate candidates
            to be gathered for each media stream.</t>

            <t></t>
            <t hangText="max-bundle:">Only the first media section will
            contain transport parameters; 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 endpoints. When
            acting as answerer, the implementation will reject any m=
            sections other than the first m= section, unless they are
            in the same bundle group as that m= section.</t>
          </list></t>

          <t>As it provides the best tradeoff between performance and
          compatibility with legacy endpoints, the default bundle
          policy MUST be set to "balanced".</t>

          <t>The application can specify its preferred policy regarding
          use of RTP/RTCP multiplexing
          <xref target="RFC5761" /> using one of the following policies:

          <list style="hanging">
            <t hangText="negotiate:">The browser will gather both RTP
            and RTCP candidates but also will offer "a=rtcp-mux", thus
            allowing for compatibility with either multiplexing or
            non-multiplexing endpoints.</t>
            <t hangText="require:">The browser will only gather RTP
            candidates. This halves the number of candidates that the
            offerer needs to gather. When acting as answerer, the
            implementation will reject any m= section that does not
            contain an "a=rtcp-mux" attribute.</t>
          </list></t>

          <t>The default multiplexing policy MUST be set to "require".
          Implementations MAY choose to reject attempts by the
          application to set the multiplexing policy to
          "negotiate".</t>
        </section>
        <section title="addTrack" anchor="sec.addTrack">

          <t>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: If the PeerConnection is in the
          "have-remote-offer" state, the track will be attached to the
          first compatible transceiver that was created by the most
          recent call to setRemoteDescription() and does not have a
          local track. Otherwise, a new transceiver will be created, as
          described in
          <xref target="sec.addTransceiver" />.</t>
        </section>
        <section title="addTransceiver" anchor="sec.addTransceiver">

          <t>The addTransceiver method adds a new RTPTransceiver to the
          PeerConnection. If a MediaStreamTrack argument is provided,
          then the transceiver will be configured with that media type
          and the track will be attached to the transceiver. Otherwise,
          the application MUST explicitly specify the type; this mode
          is useful for creating recvonly transceivers as well as for
          creating transceivers to which a track can be attached at
          some later point.</t>

          <t>At the time of creation, the application can also specify
          a transceiver direction attribute, a set of MediaStreams
          which the transceiver is associated with (allowing LS group
          assignments), and a set of encodings for the media (used for
          simulcast as described in
          <xref target="sec.simulcast" />).</t>
        </section>

        <section title="createDataChannel"
        anchor="sec.createDataChannel">

          <t>The createDataChannel method creates a new 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.</t>

          <t>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.</t>
        </section>
        <section title="createOffer" anchor="sec.createoffer">

          <t>The createOffer method generates a blob of SDP that
          contains a
          <xref target="RFC3264"></xref> offer with the supported
          configurations for the session, including descriptions of the
          media added to this PeerConnection, the codec/RTP/RTCP
          options supported by this implementation, and any candidates
          that have been gathered by the ICE Agent. An options
          parameter may be supplied to provide additional control over
          the generated offer. This options parameter allows an
          application to trigger an ICE restart, for the purpose of
          reestablishing connectivity.</t>

          <t>In the initial offer, the generated SDP will contain all
          desired functionality for the session (functionality that is
          supported but not desired by default may be omitted); for
          each SDP line, the generation of the SDP will follow the
          process defined for generating an initial offer from the
          document that specifies the given SDP line. The exact
          handling of initial offer generation is detailed in
          <xref target="sec.initial-offers" /> below.</t>

          <t>In the event createOffer is called after the session is
          established, createOffer will generate an offer to modify the
          current session based on any changes that have been made to
          the session, e.g., adding or stopping RtpTransceivers, or
          requesting an ICE restart. For each existing stream, the
          generation of each SDP line must follow the process defined
          for generating an updated offer from the RFC that specifies
          the given SDP line. For each new stream, the generation of
          the SDP must follow the process of generating an initial
          offer, as mentioned above. If no changes have been made, or
          for SDP lines that are unaffected by the requested changes,
          the offer will only contain the parameters negotiated by the
          last offer-answer exchange. The exact handling of subsequent
          offer generation is detailed in
          <xref target="sec.subsequent-offers" />. below.</t>

          <t>Session descriptions generated by createOffer must be
          immediately usable by setLocalDescription; if a system has
          limited resources (e.g. a finite number of decoders),
          createOffer should return an offer that reflects the current
          state of the system, so that setLocalDescription will succeed
          when it attempts to acquire those resources. Because this
          method may need to inspect the system state to determine the
          currently available resources, it may be implemented as an
          async operation.</t>

          <t>Calling this method may do things such as generate new ICE
          credentials, but does not result in candidate gathering, or
          cause media to start or stop flowing.</t>
        </section>
        <section title="createAnswer" anchor="sec.createanswer">

          <t>The createAnswer method generates a blob of SDP that
          contains a
          <xref target="RFC3264"></xref> SDP answer with the supported
          configuration for the session that is compatible with the
          parameters supplied in the most recent call to
          setRemoteDescription, which MUST have been called prior to
          calling createAnswer. Like createOffer, the returned blob
          contains descriptions of the media added to this
          PeerConnection, the codec/RTP/RTCP options negotiated for
          this session, and any candidates that have been gathered by
          the ICE Agent. An options parameter may be supplied to
          provide additional control over the generated answer.</t>

          <t>As an answer, the generated SDP will contain a specific
          configuration that specifies how the media plane should be
          established; for each SDP line, the generation of the SDP
          must follow the process defined for generating an answer from
          the document that specifies the given SDP line. The exact
          handling of answer generation is detailed in
          <xref target="sec.generating-an-answer" />. below.</t>

          <t>Session descriptions generated by createAnswer must be
          immediately usable by setLocalDescription; like createOffer,
          the returned description should reflect the current state of
          the system. Because this method may need to inspect the
          system state to determine the currently available resources,
          it may need to be implemented as an async operation.</t>

          <t>Calling this method may do things such as generate new ICE
          credentials, but does not trigger candidate gathering or
          change media state.</t>
        </section>
        <section title="SessionDescriptionType"
        anchor="sec.sessiondescriptiontype">

          <t>Session description objects (RTCSessionDescription) may be
          of type "offer", "pranswer", "answer" or "rollback". These
          types provide information as to how the description parameter
          should be parsed, and how the media state should be
          changed.</t>

          <t>"offer" indicates that a description should be parsed as
          an offer; said description may include many possible media
          configurations. A description used as an "offer" may be
          applied anytime the PeerConnection is in a stable state, or
          as an update to a previously supplied but unanswered
          "offer".</t>

          <t>"pranswer" indicates that a description should be parsed
          as an answer, but not a final answer, and so should not
          result in the freeing of allocated resources. It may result
          in the start of media transmission, if the answer does not
          specify an inactive media direction. A description used as a
          "pranswer" may be applied as a response to an "offer", or an
          update to a previously sent "pranswer".</t>

          <t>"answer" indicates that a description should be parsed as
          an answer, the offer-answer exchange should be considered
          complete, and any resources (decoders, candidates) that are
          no longer needed can be released. A description used as an
          "answer" may be applied as a response to an "offer", or an
          update to a previously sent "pranswer".</t>

          <t>The only difference between a provisional and final answer
          is that the final answer results in the freeing of any unused
          resources that were allocated as a result of the offer. As
          such, the application can use some discretion on whether an
          answer should be applied as provisional or final, and can
          change the type of the session description as needed. For
          example, in a serial forking scenario, an application may
          receive multiple "final" answers, one from each remote
          endpoint. The application could choose to accept the initial
          answers as provisional answers, and only apply an answer as
          final when it receives one that meets its criteria (e.g. a
          live user instead of voicemail).</t>

          <t>"rollback" is a special session description type implying
          that the state machine should be rolled back to the previous
          stable state, as described in
          <xref target="sec.rollback" />. The contents MUST be
          empty.</t>
          <section title="Use of Provisional Answers"
          anchor="sec.use-of-provisional-answer">

            <t>Most web applications will not need to create answers
            using the "pranswer" type. While it is good practice to
            send an immediate response to an "offer", in order to warm
            up the session transport and prevent media clipping, the
            preferred handling for a web application would be to create
            and send an "inactive" final answer immediately after
            receiving the offer. Later, when the called user actually
            accepts the call, the application can create a new
            "sendrecv" offer to update the previous offer/answer pair
            and start the media flow. While this could also be done
            with an inactive "pranswer", followed by a sendrecv
            "answer", the initial "pranswer" leaves the offer-answer
            exchange open, which means that neither side can send an
            updated offer during this time.</t>

            <t>As an example, consider a typical web application that
            will set up a data channel, an audio channel, and a video
            channel. When an endpoint receives an offer with these
            channels, it could send an answer accepting the data
            channel for two-way data, and accepting the audio and video
            tracks as inactive or receive-only. It could then ask the
            user to accept the call, acquire the local media streams,
            and send a new offer to the remote side moving the audio
            and video to be two-way media. By the time the human has
            accepted the call and triggered the new offer, it is likely
            that the ICE and DTLS handshaking for all the channels will
            already have finished.</t>

            <t>Of course, some applications may not be able to perform
            this double offer-answer exchange, particularly ones that
            are attempting to gateway to legacy signaling protocols. In
            these cases, "pranswer" can still provide the application
            with a mechanism to warm up the transport.</t>
          </section>
          <section title="Rollback" anchor="sec.rollback">

            <t>In certain situations it may be desirable to "undo" a
            change made to setLocalDescription or setRemoteDescription.
            Consider a case where a call is ongoing, and one side wants
            to change some of the session parameters; that side
            generates an updated offer and then calls
            setLocalDescription. However, the remote side, either
            before or after setRemoteDescription, decides it does not
            want to accept the new parameters, and sends a reject
            message back to the offerer. Now, the offerer, and possibly
            the answerer as well, need to return to a stable state and
            the previous local/remote description. To support this, we
            introduce the concept of "rollback".</t>

            <t>A rollback discards any proposed changes to the session,
            returning 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.</t>

            <t>A rollback will disassociate any RtpTransceivers that
            were associated with m= sections by the application of the
            rolled-back session description (see
            <xref target="sec.applying-a-remote-desc" /> and
            <xref target="sec.applying-a-local-desc" />). This means
            that some RtpTransceivers that were previously associated
            will no longer be associated with any m= section; in such
            cases, the value of the RtpTransceiver's mid attribute MUST
            be set to null. RtpTransceivers that were created by
            applying a remote offer that was subsequently rolled back
            MUST be removed. However, a RtpTransceiver MUST NOT be
            removed if the RtpTransceiver's RtpSender was activated by
            the addTrack method. This is so that an application may
            call addTrack, then call setRemoteDescription with an
            offer, then roll back that offer, then call createOffer and
            have a m= section for the added track appear in the
            generated offer.</t>

            <t>A rollback is performed by supplying a session
            description of type "rollback" with empty contents to
            either setLocalDescription or setRemoteDescription,
            depending on which was most recently used (i.e. if the new
            offer was supplied to setLocalDescription, the rollback
            should be done using setLocalDescription as well).</t>
          </section>
        </section>
        <section title="setLocalDescription"
        anchor="sec.setlocaldescription">

          <t>The setLocalDescription method instructs the
          PeerConnection to apply the supplied session description as
          its local configuration. The type field indicates whether the
          description should be processed as an offer, provisional
          answer, or final answer; offers and answers are checked
          differently, using the various rules that exist for each SDP
          line.</t>

          <t>This API changes the local media state; among other
          things, it sets up local resources for receiving and decoding
          media. In order to 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 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.</t>

          <t>This API indirectly controls the candidate gathering
          process. When a local description is supplied, and the number
          of transports currently in use does not match the number of
          transports needed by the local description, the
          PeerConnection will create transports as needed and begin
          gathering candidates for them.</t>

          <t>If setRemoteDescription was previously called with an
          offer, and 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.</t>
        </section>
        <section title="setRemoteDescription"
        anchor="sec.setremotedescription">

          <t>The setRemoteDescription method instructs the
          PeerConnection to apply the supplied session description as
          the desired remote configuration. As in setLocalDescription,
          the type field of the description indicates how it should be
          processed.</t>

          <t>This API changes the local media state; among other
          things, it sets up local resources for sending and encoding
          media.</t>

          <t>If setLocalDescription was previously called with an
          offer, and setRemoteDescription 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.</t>
        </section>
        <section title="currentLocalDescription"
        anchor="sec.currentlocaldescription">

          <t>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.</t>

          <t>A null object will be returned if an offer/answer exchange
          has not yet been completed.</t>
        </section>
        <section title="pendingLocalDescription"
        anchor="sec.pendinglocaldescription">

          <t>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.</t>

          <t>A null object will be returned if the state of the
          PeerConnection is "stable" or "have-remote-offer".</t>
        </section>
        <section title="currentRemoteDescription"
        anchor="sec.currentremotedescription">

          <t>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.</t>

          <t>A null object will be returned if an offer/answer exchange
          has not yet been completed.</t>
        </section>
        <section title="pendingRemoteDescription"
        anchor="sec.pendingremotedescription">

          <t>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.</t>

          <t>A null object will be returned if the state of the
          PeerConnection is "stable" or "have-local-offer".</t>
        </section>
        <section title="canTrickleIceCandidates"
        anchor="sec.cantrickle">

          <t>The canTrickleIceCandidates property indicates whether the
          remote side supports receiving trickled candidates. There are
          three potential values:
          <list style="hanging">
            <t hangText="null:">No SDP has been received from the other
            side, so it is not known if it can handle trickle. This is
            the initial value before setRemoteDescription() is
            called.</t>
            <t hangText="true:">SDP has been received from the other
            side indicating that it can support trickle.</t>
            <t hangText="false:">SDP has been received from the other
            side indicating that it cannot support trickle.</t>
          </list></t>

          <t>As described in
          <xref target="sec.ice-candidate-trickling" />, JSEP
          implementations always provide candidates to the application
          individually, consistent with what is needed for Trickle ICE.
          However, applications can use the canTrickleIceCandidates
          property to determine whether their peer can actually do
          Trickle ICE, i.e., whether it is safe to send an initial
          offer or answer followed later by candidates as they are
          gathered. As "true" is the only value that definitively
          indicates remote Trickle ICE support, an application which
          compares canTrickleIceCandidates against "true" will by
          default attempt Half Trickle on initial offers and Full
          Trickle on subsequent interactions with a Trickle
          ICE-compatible agent.</t>
        </section>
        <section title="setConfiguration"
        anchor="sec.setconfiguration">

          <t>The setConfiguration method allows the global
          configuration of the PeerConnection, which was initially set
          by constructor parameters, to be changed during the session.
          The effects of this method call depend on when it is invoked,
          and differ depending on which specific parameters are
          changed:</t>

          <t>
            <list style="symbols">

              <t>Any changes to the STUN/TURN servers to use affect the
              next gathering phase. If an ICE gathering phase has
              already started or completed, the 'needs-ice-restart' bit
              mentioned in
              <xref target="sec.ice-gather-overview" /> will be set.
              This will cause the next call to createOffer to generate
              new ICE credentials, for the purpose of forcing an ICE
              restart and kicking off a new gathering phase, in which
              the new servers will be used. If the ICE candidate pool
              has a nonzero size, any existing candidates will be
              discarded, and new candidates will be gathered from the
              new servers.</t>

              <t>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.</t>

              <t>Any changes to the ICE candidate pool size take effect
              immediately; if increased, additional candidates are
              pre-gathered; if decreased, the now-superfluous
              candidates are discarded.</t>

              <t>The bundle and RTCP-multiplexing policies MUST NOT be
              changed after the construction of the PeerConnection.</t>
            </list>
          </t>

          <t>This call may 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.</t>
        </section>
        <section title="addIceCandidate" anchor="sec.addicecandidate">

          <t>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 Trickle ICE. The pair of MID and ufrag
          is used to determine the m= section and ICE candidate
          generation to which the candidate belongs. If the MID is not
          present, the m= line index is used to look up the locally
          generated MID (see
          <xref target="sec.applying-a-remote-desc" />), which is used
          in place of a supplied MID. If these values or the candidate
          string are invalid, an error is generated.</t>

          <t>The purpose of the ufrag is to resolve ambiguities when
          trickle ICE is in progress during an ICE restart. If the
          ufrag is absent, the candidate MUST be assumed to belong to
          the most recently applied remote description. Connectivity
          checks will be sent to the new candidate.</t>

          <t>This method can also be used to provide an
          end-of-candidates indication to the ICE Agent, as defined in
          <xref target="I-D.ietf-ice-trickle" />). The MID and ufrag
          are used as described above to determine the m= section and
          ICE generation for which candidate gathering is complete. If
          the ufrag is not present, then the end-of-candidates
          indication MUST be assumed to apply to the relevant m=
          section in the most recently applied remote description. If
          neither the MID nor the m= index is present, then the
          indication MUST be assumed to apply to all m= sections in the
          most recently applied remote description.</t>

          <t>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.</t>
        </section>
      </section>
      <section title="RtpTransceiver" anchor="sec.transceiver">
        <section title="stop" anchor="sec.transceiver-stop">
          <t>
            The stop method stops an RtpTransceiver.  This
            will cause future calls to createOffer to generate a zero
            port for the associated m= section.  See below for more
            details.
          </t>
        </section>
        <section title="stopped" anchor="sec.transceiver-stopped">
          <t>
            The stopped method returns "true" if the transceiver has
            been stopped, either by a call to stopTransceiver or by
            applying an answer that rejects the associated m= section, and
            "false" otherwise.
          </t>
          <t>
            A stopped RtpTransceiver does not send any
            outgoing RTP or RTCP or process any incoming RTP
            or RTCP. It cannot be restarted.
          </t>
        </section>
        <section title="setDirection" anchor="sec.transceiver-set-direction">
          <t>
            The setDirection method sets the direction of a transceiver,
            which affects the direction attribute of the associated m=
            section on future calls to createOffer and createAnswer.
          </t>
          <t>
            When creating offers, the transceiver direction is directly
            reflected in the output, even for reoffers. When creating answers,
            the transceiver direction is intersected with the offered direction,
            as explained in the <xref target="sec.generating-an-answer" />
            section below.
          </t>
        </section>
        <section title="setCodecPreferences" anchor="sec.transceiver-set-codec-preferences">
          <t>
            The setCodecPreferences method sets the codec preferences of a
            transceiver, which in turn affect the presence and order of
            codecs of the associated m= section on future calls to
            createOffer and createAnswer. Note that setCodecPreferences
            does not directly affect which codec the implemtation decides
            to send. It only affects which codecs the implementation
            indicates that it prefers to receive, via the offer or answer.
            Even when a codec is excluded by setCodecPreferences, it still
            may be used to send until the next offer/answer exchange
            discards it.
          </t>
          <t>
            The codec preferences of an RtpTransceiver can cause codecs
            to be excluded by subsequent calls to createOffer and
            createAnswer, in which case the corresponding media formats
            in the associated m= section will be excluded. The codec
            preferences cannot add media formats that would otherwise not
            be present. This includes codecs that were not negotiated in a
            previous offer/answer exchange that included the transceiver.
          </t>
          <t>
            The codec preferences of an RtpTransceiver can also determine
            the order of codecs in subsequent calls to createOffer and
            createAnswer, in which case the order of the media formats in
            the associated m= section will match. However, the codec
            preferences cannot change the order of the media formats after
            an answer containing the transceiver has been applied. At this
            point, codecs can only be removed, not reordered.
          </t>
        </section>
      </section>
    </section>
    <section title="SDP Interaction Procedures"
    anchor="sec.sdp-interaction-procedure">

      <t>This section describes the specific procedures to be followed
      when creating and parsing SDP objects.</t>
      <section title="Requirements Overview"
      anchor="sec.requirements-overview">

        <t>JSEP implementations must comply with the specifications
        listed below that govern the creation and processing of offers
        and answers.</t>

        <t>The first set of specifications is the
        "mandatory-to-implement" set. All implementations must support
        these behaviors, but may not use all of them if the remote
        side, which may not be a JSEP endpoint, does not support
        them.</t>

        <t>The second set of specifications is the "mandatory-to-use"
        set. The local JSEP endpoint and any remote endpoint must
        indicate support for these specifications in their session
        descriptions.</t>
        <section title="Implementation Requirements"
        anchor="sec.implementation-requirements">

          <t>This list of mandatory-to-implement specifications is
          derived from the requirements outlined in
          <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>.
          <list style="format R-%d">

            <t>
            <xref target="RFC4566"></xref> is the base SDP specification
            and MUST be implemented.</t>

            <t>
            <xref target="RFC5764"></xref> MUST be supported for
            signaling the UDP/TLS/RTP/SAVPF
            <xref target="RFC5764" />, TCP/DTLS/RTP/SAVPF
            <xref target="I-D.nandakumar-mmusic-proto-iana-registration" />,
            "UDP/DTLS/SCTP"
            <xref target="I-D.ietf-mmusic-sctp-sdp" />, and
            "TCP/DTLS/SCTP"
            <xref target="I-D.ietf-mmusic-sctp-sdp" /> RTP profiles.</t>

            <t>
            <xref target="RFC5245"></xref> MUST be implemented for
            signaling the ICE credentials and candidate lines
            corresponding to each media stream. The ICE implementation
            MUST be a Full implementation, not a Lite
            implementation.</t>

            <t>
            <xref target="RFC5763"></xref> MUST be implemented to signal
            DTLS certificate fingerprints.</t>

            <t>
            <xref target="RFC4568"></xref> MUST NOT be implemented to
            signal SDES SRTP keying information.</t>

            <t>The
            <xref target="RFC5888"></xref> grouping framework MUST be
            implemented for signaling grouping information, and MUST be
            used to identify m= lines via the a=mid attribute.</t>

            <t>
            <xref target="I-D.ietf-mmusic-msid"></xref> MUST be
            supported, in order to signal associations between RTP
            objects and W3C MediaStreams and MediaStreamTracks in a
            standard way.</t>

            <t>The bundle mechanism in
            <xref target="I-D.ietf-mmusic-sdp-bundle-negotiation">
            </xref> MUST be supported to signal the ability to multiplex
            RTP streams on a single UDP port, in order to avoid
            excessive use of port number resources.</t>

            <t>The SDP attributes of "sendonly", "recvonly",
            "inactive", and "sendrecv" from
            <xref target="RFC4566"></xref> MUST be implemented to signal
            information about media direction.</t>

            <t>
            <xref target="RFC5576"></xref> MUST be implemented to signal
            RTP SSRC values and grouping semantics.</t>

            <t>
            <xref target="RFC4585"></xref> MUST be implemented to signal
            RTCP based feedback.</t>

            <t>
            <xref target="RFC5761"></xref> MUST be implemented to signal
            multiplexing of RTP and RTCP.</t>

            <t>
            <xref target="RFC5506"></xref> MUST be implemented to signal
            reduced-size RTCP messages.</t>

            <t>
            <xref target="RFC4588"></xref> MUST be implemented to signal
            RTX payload type associations.</t>

            <t>
            <xref target="RFC3556"></xref> with bandwidth modifiers MAY
            be supported for specifying RTCP bandwidth as a fraction of
            the media bandwidth, RTCP fraction allocated to the senders
            and setting maximum media bit-rate boundaries.</t>

            <t>TODO: any others?</t>
          </list></t>

          <t>As required by
          <xref target="RFC4566"></xref>, Section 5.13, JSEP
          implementations MUST ignore unknown attribute (a=) lines.</t>
        </section>
        <section title="Usage Requirements"
        anchor="sec.usage-requirements">

          <t>All session descriptions handled by JSEP endpoints, both
          local and remote, MUST indicate support for the following
          specifications. If any of these are absent, this omission
          MUST be treated as an error.
          <list style="format R-%d">

            <t>ICE, as specified in
            <xref target="RFC5245"></xref>, MUST be used. Note that the
            remote endpoint may use a Lite implementation;
            implementations MUST properly handle remote endpoints which
            do ICE-Lite.</t>

            <t>DTLS
            <xref target="RFC6347" /> or DTLS-SRTP
            <xref target="RFC5763"></xref>, MUST be used, as
            appropriate for the media type, as specified in
            <xref target="I-D.ietf-rtcweb-security-arch" /></t>
          </list></t>
        </section>
        <section title="Profile Names and Interoperability"
        anchor="sec.profile-names">

          <t>For media m= sections, JSEP endpoints MUST support both
          the "UDP/TLS/ RTP/SAVPF" and "TCP/DTLS/RTP/SAVPF" profiles
          and MUST indicate one of these two profiles for each media m=
          line they produce in an offer. For data m= sections, JSEP
          endpoints must support both the "UDP/DTLS/SCTP" and
          "TCP/DTLS/SCTP" profiles and MUST indicate one of these two
          profiles for each data m= line they produce in an offer.
          Because ICE can select either TCP or UDP transport depending
          on network conditions, both advertisements are consistent
          with ICE eventually selecting either either UDP or TCP.</t>

          <t>Unfortunately, in an attempt at compatibility, some
          endpoints generate other profile strings even when they mean
          to support one of these profiles. For instance, an endpoint
          might generate "RTP/AVP" but supply "a=fingerprint" and
          "a=rtcp-fb" attributes, indicating its willingness to support
          "(UDP,TCP)/TLS/RTP/SAVPF". In order to simplify compatibility
          with such endpoints, JSEP endpoints MUST follow the following
          rules when processing the media m= sections in an offer:</t>

          <t>
            <list style="symbols">

              <t>The profile in any "m=" line in any answer MUST
              exactly match the profile provided in the offer.</t>

              <t>Any profile matching the following patterns MUST be
              accepted: "RTP/[S]AVP[F]" and
              "(UDP/TCP)/TLS/RTP/SAVP[F]"</t>

              <t>Because DTLS-SRTP is REQUIRED, the choice of SAVP or
              AVP has no effect; support for DTLS-SRTP is determined by
              the presence of one or more "a=fingerprint" attribute.
              Note that lack of an "a=fingerprint" attribute will lead
              to negotiation failure.</t>

              <t>The use of AVPF or AVP simply controls the timing
              rules used for RTCP feedback. If AVPF is provided, or an
              "a=rtcp-fb" attribute is present, assume AVPF timing,
              i.e., a default value of "trr-int=0". Otherwise, assume
              that AVPF is being used in an AVP compatible mode and use
              AVP timing, i.e., "trr-int=4".</t>

              <t>For data m= sections, JSEP endpoints MUST support
              receiving the "UDP/ DTLS/SCTP", "TCP/DTLS/SCTP", or
              "DTLS/SCTP" (for backwards compatibility) profiles.</t>
            </list>
          </t>

          <t>Note that re-offers by JSEP endpoints MUST use the correct
          profile strings even if the initial offer/answer exchange
          used an (incorrect) older profile string.</t>
        </section>
      </section>
      <section anchor="sec-create-offer" title="Constructing an Offer">

        <t>When createOffer is called, a new SDP description must be
        created that includes the functionality specified in
        <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>. The exact
        details of this process are explained below.</t>
        <section title="Initial Offers" anchor="sec.initial-offers">

          <t>When createOffer is called for the first time, the result
          is known as the initial offer.</t>

          <t>The first step in generating an initial offer is to
          generate session-level attributes, as specified in
          <xref target="RFC4566"></xref>, Section 5. Specifically:
          <list style="symbols">

            <t>The first SDP line MUST be "v=0", as specified in
            <xref target="RFC4566"></xref>, Section 5.1</t>

            <t>The second SDP line MUST be an "o=" line, as specified
            in
            <xref target="RFC4566"></xref>, Section 5.2. The value of
            the &lt;username&gt; field SHOULD be "-".
            <xref target="RFC3264" /> requires that the &lt;sess-id&gt;
            be representable as a 64-bit signed integer. It is
            RECOMMENDED that the &lt;sess-id&gt; be generated as a
            64-bit quantity with the high bit being sent to zero and
            the remaining 63 bits being cryptographically random. The
            value of the &lt;nettype&gt; &lt;addrtype&gt;
            &lt;unicast-address&gt; tuple SHOULD be set to a
            non-meaningful address, such as IN IP4 0.0.0.0, to prevent
            leaking the local address in this field. As mentioned in
            <xref target="RFC4566"></xref>, the entire o= line needs to
            be unique, but selecting a random number for
            &lt;sess-id&gt; is sufficient to accomplish this.</t>

            <t>The third SDP line MUST be a "s=" line, as specified in
            <xref target="RFC4566"></xref>, Section 5.3; to match the
            "o=" line, a single dash SHOULD be used as the session
            name, e.g. "s=-". Note that this differs from the advice in

            <xref target="RFC4566" /> which proposes a single space, but
            as both "o=" and "s=" are meaningless, having the same
            meaningless value seems clearer.</t>

            <t>Session Information ("i="), URI ("u="), Email Address
            ("e="), Phone Number ("p="), Bandwidth ("b="), Repeat Times
            ("r="), and Time Zones ("z=") lines are not useful in this
            context and SHOULD NOT be included.</t>

            <t>Encryption Keys ("k=") lines do not provide sufficient
            security and MUST NOT be included.</t>

            <t>A "t=" line MUST be added, as specified in
            <xref target="RFC4566"></xref>, Section 5.9; both
            &lt;start-time&gt; and &lt;stop-time&gt; SHOULD be set to
            zero, e.g. "t=0 0".</t>

            <t>An "a=ice-options" line with the "trickle" option MUST
            be added, as specified in
            <xref target="I-D.ietf-ice-trickle"></xref>, Section 4.</t>
          </list></t>

          <t>The next step is to generate m= sections, as specified in
          <xref target="RFC4566" /> Section 5.14. An m= section is
          generated for each RtpTransceiver that has been added to the
          PeerConnection. This is done in the order that their
          associated RtpTransceivers were added to the PeerConnection
          and excludes RtpTransceivers that are stopped and not
          associated with an m= section (either due to an m= section
          being recycled or an RtpTransceiver having been stopped
          before being associated with an m= section) .</t>

          <t>Each m= section, provided it is not marked as bundle-only,
          MUST generate a unique set of ICE credentials and gather its
          own unique set of ICE candidates. Bundle-only m= sections
          MUST NOT contain any ICE credentials and MUST NOT gather any
          candidates.</t>

          <t>For DTLS, all m= sections MUST use all the certificate(s)
          that have been specified for the PeerConnection; as a result,
          they MUST all have the same
          <xref target="I-D.ietf-mmusic-4572-update"></xref> fingerprint
          value(s), or these value(s) MUST be session-level
          attributes.</t>

          <t>Each m= section should be generated as specified in
          <xref target="RFC4566"></xref>, Section 5.14. For the m= line
          itself, the following rules MUST be followed:
          <list style="symbols">

            <t>The port value is set to the port of the default ICE
            candidate for this m= section, but given that no candidates
            have yet been gathered, the "dummy" port value of 9
            (Discard) MUST be used, as indicated in
            <xref target="I-D.ietf-ice-trickle"></xref>, Section
            5.1.</t>

            <t>To properly indicate use of DTLS, the &lt;proto&gt;
            field MUST be set to "UDP/TLS/RTP/SAVPF", as specified in
            <xref target="RFC5764" />, Section 8, if the default
            candidate uses UDP transport, or "TCP/DTLS/RTP/SAVPF", as
            specified in
            <xref target="I-D.nandakumar-mmusic-proto-iana-registration" /> if
            the default candidate uses TCP transport.</t>

            <t>If codec preferences have been set for the associated
            transceiver, media formats MUST be generated in the
            corresponding order, and MUST exclude any codecs not present
            in the codec preferences.</t>

            <t>Unless excluded by the above restrictions, the media
            formats MUST include the mandatory audio/video codecs as
            specified in
            <xref target="I-D.ietf-rtcweb-audio"></xref>(see Section 3)
            and
            <xref target="I-D.ietf-rtcweb-video"></xref>(see Section
            5).</t>
          </list></t>

          <t>The m= line MUST be followed immediately by a "c=" line,
          as specified in
          <xref target="RFC4566"></xref>, Section 5.7. Again, as no
          candidates have yet been gathered, the "c=" line must contain
          the "dummy" value "IN IP4 0.0.0.0", as defined in
          <xref target="I-D.ietf-ice-trickle"></xref>, Section 5.1.</t>

          <t>
          <xref target="I-D.ietf-mmusic-sdp-mux-attributes" /> groups
          SDP attributes into different categories. To avoid
          unnecessary duplication when bundling, Section 8.1 of
          <xref target="I-D.ietf-mmusic-sdp-bundle-negotiation" /> specifies
          that attributes of category IDENTICAL or TRANSPORT should not
          be repeated in bundled m= sections.</t>

          <t>The following attributes, which are of a category other
          than IDENTICAL or TRANSPORT, MUST be included in each m=
          section:</t>

          <t>
            <list style="symbols">

              <t>An "a=mid" line, as specified in
              <xref target="RFC5888"></xref>, Section 4. When
              generating mid values, it is RECOMMENDED that the values
              be 3 bytes or less, to allow them to efficiently fit into
              the RTP header extension defined in
              <xref target="I-D.ietf-mmusic-sdp-bundle-negotiation">
              </xref>, Section 11.</t>

              <t>A direction attribute which is the same as that of the
              associated transceiver.</t>

              <t>For each media format on the m= line,
              "a=rtpmap" and "a=fmtp" lines, as specified in
              <xref target="RFC4566"></xref>, Section 6, and
              <xref target="RFC3264"></xref>, Section 5.1.</t>

              <t>If this m= section is for media with configurable
              frame sizes, e.g. audio, an "a=maxptime" line, indicating
              the smallest of the maximum supported frame sizes out of
              all codecs included above, as specified in
              <xref target="RFC4566"></xref>, Section 6.</t>

              <t>If this m= section is for video media, and there are
              known limitations on the size of images which can be
              decoded, an "a=imageattr" line, as specified in
              <xref target="sec.imageattr"></xref>.</t>

              <t>For each primary codec where RTP retransmission should
              be used, a corresponding "a=rtpmap" line indicating "rtx"
              with the clock rate of the primary codec and an "a=fmtp"
              line that references the payload type of the primary
              codec, as specified in
              <xref target="RFC4588"></xref>, Section 8.1.</t>

              <t>For each supported FEC mechanism, "a=rtpmap" and
              "a=fmtp" lines, as specified in
              <xref target="RFC4566"></xref>, Section 6. The FEC
              mechanisms that MUST be supported are specified in
              <xref target="I-D.ietf-rtcweb-fec"></xref>, Section 6,
              and specific usage for each media type is outlined in
              Sections 4 and 5.</t>

              <t>For each supported RTP header extension, an "a=extmap"
              line, as specified in
              <xref target="RFC5285"></xref>, Section 5. The list of
              header extensions that SHOULD/MUST be supported is
              specified in
              <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>, Section
              5.2. Any header extensions that require encryption MUST
              be specified as indicated in
              <xref target="RFC6904"></xref>, Section 4.</t>

              <t>For each supported RTCP feedback mechanism, an
              "a=rtcp-fb" mechanism, as specified in
              <xref target="RFC4585"></xref>, Section 4.2. The list of
              RTCP feedback mechanisms that SHOULD/MUST be supported is
              specified in
              <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>, Section
              5.1.</t>

              <t>If the bundle policy for this PeerConnection is set to
              "max-bundle", and this is not the first m= section, or
              the bundle policy is set to "balanced", and this is not
              the first m= section for this media type, an
              "a=bundle-only" line.</t>

              <t>If the RtpTransceiver has a sendrecv or sendonly
              direction:
              <list style="symbols">

                <t>An "a=msid" line, as specified in
                <xref target="I-D.ietf-mmusic-msid"></xref>, Section
                2.</t>
              </list></t>

              <t>If the RtpTransceiver has a sendrecv or sendonly
              direction, and the application has specified RID values or
              has specified more than one encoding in the RtpSenders's
              parameters, an "a=rid" line for each encoding specified.
              The "a=rid" line is specified in
              <xref target="I-D.ietf-mmusic-rid"></xref>, and its
              direction MUST be "send". If the application has chosen a
              RID value, it MUST be used as the rid-identifier;
              otherwise a RID value MUST be generated by the
              implementation. When generating RID values, it is
              RECOMMENDED that the values be 3 bytes or less, to allow
              them to efficiently fit into the RTP header extension
              defined in
              <xref target="I-D.ietf-avtext-rid"></xref>, Section 11.
              If no encodings have been specified, or only one encoding
              is specified but without a RID value, then no "a=rid"
              lines are generated.</t>

              <t>If the RtpTransceiver has a sendrecv or sendonly
              direction and more than one "a=rid" line has been generated,
              an "a=simulcast" line, with direction "send", as defined in
              <xref target="I-D.ietf-mmusic-sdp-simulcast"></xref>,
              Section 6.2. The list of RIDs MUST include all of the RID
              identifiers used in the "a=rid" lines for this m=
              section.</t>
            </list>
          </t>

          <t>The following attributes, which are of category IDENTICAL
          or TRANSPORT, MUST appear only in "m=" sections which either
          have a unique address or which are associated with the
          bundle-tag. (In initial offers, this means those "m="
          sections which do not contain an "a=bundle-only"
          attribute.</t>

          <t>
            <list style="symbols">
              <t>"a=ice-ufrag" and "a=ice-pwd" lines, as specified in
              <xref target="RFC5245"></xref>, Section 15.4.</t>

              <t>An "a=fingerprint" line for each of the endpoint's
              certificates, as specified in
              <xref target="RFC4572"></xref>, Section 5; the digest
              algorithm used for the fingerprint MUST match that used
              in the certificate signature.</t>

              <t>An "a=setup" line, as specified in
              <xref target="RFC4145"></xref>, Section 4, and clarified
              for use in DTLS-SRTP scenarios in
              <xref target="RFC5763"></xref>, Section 5. The role value
              in the offer MUST be "actpass".</t>

              <t>An "a=dtls-id" line, as specified in
              <xref target="I-D.ietf-mmusic-dtls-sdp"/> Section 5.2.</t>

              <t>An "a=rtcp" line, as specified in
              <xref target="RFC3605"></xref>, Section 2.1, containing
              the dummy value "9 IN IP4 0.0.0.0", because no candidates
              have yet been gathered.</t>

              <t>An "a=rtcp-mux" line, as specified in
              <xref target="RFC5761"></xref>, Section 5.1.1.</t>

              <t>An "a=rtcp-rsize" line, as specified in
              <xref target="RFC5506"></xref>, Section 5.</t>
            </list>
          </t>

          <t>Lastly, if a data channel has been created, a m= section
          MUST be generated for data. The &lt;media&gt; field MUST be
          set to "application" and the &lt;proto&gt; field MUST be set
          to "UDP/DTLS/SCTP" if the default candidate uses UDP
          transport, or "TCP/DTLS/SCTP" if the default candidate uses
          TCP transport
          <xref target="I-D.ietf-mmusic-sctp-sdp"></xref>. The "fmt"
          value MUST be set to "webrtc-datachannel" as specified in
          <xref target="I-D.ietf-mmusic-sctp-sdp"></xref>, Section
          4.1.</t>

          <t>Within the data m= section, the "a=mid", "a=ice-ufrag",
          "a=ice-pwd", "a=fingerprint", "a=dtls-id", and "a=setup" lines MUST be
          included as mentioned above, along with an
          "a=fmtp:webrtc-datachannel" line and an "a=sctp-port" line
          referencing the SCTP port number as defined in
          <xref target="I-D.ietf-mmusic-sctp-sdp"></xref>, Section
          4.1.</t>

          <t>Once all m= sections have been generated, a session-level
          "a=group" attribute MUST be added as specified in
          <xref target="RFC5888"></xref>. This attribute MUST have
          semantics "bundle", and MUST include the mid identifiers of
          each m= section. The effect of this is that the browser
          offers all m= sections as one bundle group. However, whether
          the m= sections are bundle-only or not depends on the bundle
          policy.</t>

          <t>The next step is to generate session-level lip sync groups
          as defined in
          <xref target="RFC5888" />, Section 7. For each MediaStream
          referenced by more than one RtpTransceiver (by passing those
          MediaStreams as arguments to the addTrack and addTransceiver
          methods), a group of type "LS" MUST be added that contains
          the mid values for each RtpTransceiver.</t>

          <t>Attributes which SDP permits to either be at the session
          level or the media level SHOULD generally be at the media
          level even if they are identical. This promotes readability,
          especially if one of a set of initially identical attributes
          is subsequently changed.</t>

          <t>Attributes other than the ones specified above MAY be
          included, except for the following attributes which are
          specifically incompatible with the requirements of
          <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>, and MUST
          NOT be included:
          <list style="symbols">

            <t>"a=crypto"</t>

            <t>"a=key-mgmt"</t>

            <t>"a=ice-lite"</t>
          </list></t>

          <t>Note that when bundle is used, any additional attributes
          that are added MUST follow the advice in
          <xref target="I-D.ietf-mmusic-sdp-mux-attributes"></xref> on
          how those attributes interact with bundle.</t>

          <t>Note that these requirements are in some cases stricter
          than those of SDP. Implementations MUST be prepared to accept
          compliant SDP even if it would not conform to the
          requirements for generating SDP in this specification.</t>
        </section>
        <section title="Subsequent Offers"
        anchor="sec.subsequent-offers">

          <t>When createOffer is called a second (or later) time, or is
          called after a local description has already been installed,
          the processing is somewhat different than for an initial
          offer.</t>

          <t>If the initial offer was not applied using
          setLocalDescription, meaning the PeerConnection is still in
          the "stable" state, the steps for generating an initial offer
          should be followed, subject to the following restriction:
          <list style="symbols">

            <t>The fields of the "o=" line MUST stay the same except
            for the &lt;session-version&gt; field, which MUST increment
            by one on each call to createOffer if the offer might
            differ from the output of the previous call to createOffer;
            implementations MAY opt to increment
            &lt;session-version&gt; on every call. The value of the
            generated &lt;session-version&gt; is independent of the
            &lt;session-version&gt; of the current local description;
            in particular, in the case where the current version is N,
            an offer is created with version N+1, and then that offer
            is rolled back so that the current version is again N, the
            next generated offer will still have version N+2.</t>
          </list></t>

          <t>Note that if the application creates an offer by reading
          currentLocalDescription instead of calling createOffer, the
          returned SDP may be different than when setLocalDescription
          was originally called, due to the addition of gathered ICE
          candidates, but the &lt;session-version&gt; will not have
          changed. There are no known scenarios in which this causes
          problems, but if this is a concern, the solution is simply to
          use createOffer to ensure a unique
          &lt;session-version&gt;.</t>

          <t>If the initial offer was applied using
          setLocalDescription, but an answer from the remote side has
          not yet been applied, meaning the PeerConnection is still in
          the "local-offer" state, an offer is generated by following
          the steps in the "stable" state above, along with these
          exceptions:
          <list style="symbols">

            <t>The "s=" and "t=" lines MUST stay the same.</t>

            <t>If any RtpTransceiver has been added, and there exists
            an m= section with a zero port in the current local
            description or the current remote description, that m=
            section MUST be recycled by generating an m= section for
            the added RtpTransceiver as if the m= section were being
            added to the session description, placed at the same index
            as the m= section with a zero port.</t>

            <t>If an RtpTransceiver is stopped and is not associated
            with an m= section, an m= section MUST NOT be generated for
            it. This prevents adding back RtpTransceivers whose m=
            sections were recycled and used for a new RtpTransceiver in
            a previous offer/ answer exchange, as described above.</t>

            <t>If an RtpTransceiver has been stopped and is associated
            with an m= section, and the m= section is not being
            recycled as described above, an m= section MUST be
            generated for it with the port set to zero and the
            "a=msid" line removed.</t>

            <t>For RtpTransceivers that are not stopped, the "a=msid"
            line MUST stay the same if
            they are present in the current description.</t>

            <t>Each "m=" and c=" line MUST be filled in with the port,
            protocol, and address of the default candidate for the m=
            section, as described in
            <xref target="RFC5245"></xref>, Section 4.3. If ICE
            checking has already completed for one or more candidate
            pairs and a candidate pair is in active use, then that pair
            MUST be used, even if ICE has not yet completed. Note that
            this differs from the guidance in
            <xref target="RFC5245" />, Section 9.1.2.2, which only
            refers to offers created when ICE has completed. In each
            case, if no RTP candidates have yet been
            gathered, dummy values MUST be used, as described
            above.</t>

            <t>Each "a=mid" line MUST stay the same.</t>

            <t>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 (
            <xref target="sec.icerestart" /> was specified. If the m=
            section is bundled into another m= section, it still MUST
            NOT contain any ICE credentials.</t>

            <t>If the m= section is not bundled into another
            m= section, an "a=rtcp" attribute line MUST be added with
            of the default RTCP candidate, as indicated in
            <xref target="RFC5761"></xref>, section 5.1.3.</t>

            <t>If the m= section is not bundled into another m=
            section, for each candidate that has been gathered during
            the most recent gathering phase (see
            <xref target="sec.ice-gather-overview"></xref>), an
            "a=candidate" line MUST be added, as defined in
            <xref target="RFC5245"></xref>, Section 4.3., paragraph 3.
            If candidate gathering for the section has completed, an
            "a=end-of-candidates" attribute MUST be added, as described
            in
            <xref target="I-D.ietf-ice-trickle"></xref>, Section 9.3.
            If the m= section is bundled into another m= section, both
            "a=candidate" and "a=end-of-candidates" MUST be
            omitted.</t>

            <t>For RtpTransceivers that are still present, the
            "a=msid" line MUST stay the same.</t>

            <t>For RtpTransceivers that are still present, the "a=rid"
            lines MUST stay the same.</t>

            <t>For RtpTransceivers that are still present, any
            "a=simulcast" line MUST stay the same.</t>

            <t>If any RtpTransceiver has been stopped, the port MUST be
            set to zero and the "a=msid"
            line MUST be removed.</t>

            <t>If any RtpTransceiver has been added, and there exists a
            m= section with a zero port in the current local
            description or the current remote description, that m=
            section MUST be recycled by generating a m= section for the
            added RtpTransceiver as if the m= section were being added
            to session description, except that instead of adding it,
            the generated m= section replaces the m= section with a
            zero port.</t>
          </list></t>

          <t>If the initial offer was applied using
          setLocalDescription, and an answer from the remote side has
          been applied using 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 the
          "local-offer" state above.
          </t>

          <t>In addition, for each non-recycled, non-rejected m=
          section in the new offer, the following adjustments are made
          based on the contents of the corresponding m= section in the
          current remote description:
          <list style="symbols">

            <t>The m= line and corresponding "a=rtpmap" and "a=fmtp"
            lines MUST only include codecs present in the most recent
            answer which have not been excluded by the codec preferences
            of the associated transceiver.</t>

            <t>The media formats on the m= line MUST be generated in the
            same order as in the current local description.</t>

            <t>The RTP header extensions MUST only include those that
            are present in the most recent answer.</t>

            <t>The RTCP feedback extensions MUST only include those
            that are present in the most recent answer.</t>

            <t>The "a=rtcp" line MUST only be added if the most recent
            answer did not include an "a=rtcp-mux" line.</t>

            <t>The "a=rtcp-mux" line MUST only be added if present in
            the most recent answer.</t>

            <t>The "a=rtcp-mux-only" line MUST only be added if present
            in the most recent answer.</t>

            <t>The "a=rtcp-rsize" line MUST only be added if present in
            the most recent answer.</t>
          </list></t>

          <t>The "a=group:BUNDLE" attribute MUST include the mid
          identifiers specified in the bundle group in the most recent
          answer, minus any m= sections that have been marked as
          rejected, plus any newly added or re-enabled m= sections. In
          other words, the bundle attribute must contain all m=
          sections that were previously bundled, as long as they are
          still alive, as well as any new m= sections.</t>

          <t>The "LS" groups are generated in the same way as with
          initial offers.</t>
        </section>
        <section title="Options Handling"
        anchor="sec.options-handling1">

          <t>The createOffer method takes as a parameter an
          RTCOfferOptions object. Special processing is performed when
          generating a SDP description if the following options are
          present.</t>
          <section title="IceRestart" anchor="sec.icerestart">

            <t>If the "IceRestart" option is specified, with a value of
            "true", the offer MUST indicate an ICE restart by
            generating new ICE ufrag and pwd attributes, as specified
            in
            <xref target="RFC5245"></xref>, Section 9.1.1.1. If this
            option is specified on an initial offer, it has no effect
            (since a new ICE ufrag and pwd are already generated).
            Similarly, if the ICE configuration has changed, this
            option has no effect, since new ufrag and pwd attributes
            will be generated automatically. This option is primarily
            useful for reestablishing connectivity in cases where
            failures are detected by the application.</t>
          </section>
          <section title="VoiceActivityDetection"
          anchor="sec.voiceactivitydetection1">

            <t>If the "VoiceActivityDetection" option is specified,
            with a value of "true", the offer MUST indicate support for
            silence suppression in the audio it receives by including
            comfort noise ("CN") codecs for each offered audio codec,
            as specified in
            <xref target="RFC3389"></xref>, Section 5.1, except for
            codecs that have their own internal silence suppression
            support. For codecs that have 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 desired. For example,
            when using the Opus codec, the "usedtx=1" parameter would
            be specified in the offer. This option allows the endpoint
            to significantly reduce the amount of audio bandwidth it
            receives, at the cost of some fidelity, depending on the
            quality of the remote VAD algorithm.</t>

            <t>If the "VoiceActivityDetection" option is specified,
            with a value of "false", the browser MUST NOT emit "CN"
            codecs. For codecs that have 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 using the Opus codec, the "usedtx=0" parameter would
            be specified in the offer.</t>

            <t>Note that setting the "VoiceActivityDetection" parameter
            when generating an offer is a request to receive audio with
            silence suppression. It has no impact on whether the local
            endpoint does silence suppression for the audio it
            sends.</t>

            <t>The "VoiceActivityDetection" option does not have any
            impact on the setting of the "vad" value in the signaling
            of the client to mixer audio level header extension
            described in
            <xref target="RFC6464"></xref>, Section 4.</t>
          </section>
        </section>
      </section>
      <section title="Generating an Answer"
      anchor="sec.generating-an-answer">

        <t>When createAnswer is called, a new SDP description must be
        created that is compatible with the supplied remote description
        as well as the requirements specified in
        <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>. The exact
        details of this process are explained below.</t>
        <section title="Initial Answers" anchor="sec.initial-answers">

          <t>When createAnswer is called for the first time after a
          remote description has been provided, the result is known as
          the initial answer. If no remote description has been
          installed, an answer cannot be generated, and an error MUST
          be returned.</t>

          <t>Note that the remote description SDP may not have been
          created by a JSEP endpoint and may not conform to all the
          requirements listed in
          <xref target="sec-create-offer"></xref>. For many cases, this
          is not a problem. However, if any mandatory SDP attributes
          are missing, or functionality listed as mandatory-to-use
          above is not present, this MUST be treated as an error, and
          MUST cause the affected m= sections to be marked as
          rejected.</t>

          <t>The first step in generating an initial answer is to
          generate session-level attributes. The process here is
          identical to that indicated in the Initial Offers section
          above, except that the "a=ice-options" line, with the
          "trickle" option as specified in
          <xref target="I-D.ietf-ice-trickle"></xref>, Section 4, is
          only included if such an option was present in the offer.</t>

          <t>The next step is to generate session-level lip sync groups
          as defined in
          <xref target="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.</t>

          <t>The next step is to generate m= sections for each m=
          section that is present in the remote offer, as specified in
          <xref target="RFC3264"></xref>, Section 6. For the purposes
          of this discussion, any session-level attributes in the offer
          that are also valid as media-level attributes SHALL be
          considered to be present in each m= section.</t>

          <t>The next step is to go through each offered m= section.
          Each offered m= section will have an associated
          RtpTransceiver, as described in
          <xref target="sec.applying-a-remote-desc" />. If there are
          more RtpTransceivers than there are m= sections, the
          unmatched RtpTransceivers will need to be associated in a
          subsequent offer.</t>

          <t>For each offered m= section, if any of the following
          conditions are true, 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
          <xref target="RFC3264"></xref>, Section 6., and further
          processing for this m= section can be skipped:
          <list style="symbols">

            <t>The associated RtpTransceiver has been stopped.</t>

            <t>No supported codec is present in the offer.</t>

            <t>The bundle policy is "max-bundle", and this is not the
            first m= section or in the same bundle group as the first
            m= section.</t>

            <t>The bundle policy is "balanced", and this is not the
            first m= section for this media type or in the same bundle
            group as the first m= section for this media type.</t>

            <t>The RTP/RTCP multiplexing policy is "require" and the m=
            section doesn't contain an "a=rtcp-mux" attribute.</t>
          </list></t>

          <t>Otherwise, each m= section in the answer should then be
          generated as specified in
          <xref target="RFC3264"></xref>, Section 6.1. For the m= line
          itself, the following rules must be followed:
          <list style="symbols">

            <t>The port value would normally be set to the port of the
            default ICE candidate for this m= section, but given that
            no candidates have yet been gathered, the "dummy" port
            value of 9 (Discard) MUST be used, as indicated in
            <xref target="I-D.ietf-ice-trickle"></xref>, Section
            5.1.</t>

            <t>The &lt;proto&gt; field MUST be set to exactly match the
            &lt;proto&gt; field for the corresponding m= line in the
            offer.</t>

            <t>If codec preferences have been set for the associated
            transceiver, media formats MUST be generated in the
            corresponding order, and MUST exclude any codecs not present
            in the codec preferences or not present in the offer.</t>

            <t>Unless excluded by the above restrictions, the media
            formats MUST include the mandatory audio/video codecs as
            specified in
            <xref target="I-D.ietf-rtcweb-audio"></xref>(see Section 3)
            and
            <xref target="I-D.ietf-rtcweb-video"></xref>(see Section
            5).</t>
          </list></t>

          <t>The m= line MUST be followed immediately by a "c=" line,
          as specified in
          <xref target="RFC4566"></xref>, Section 5.7. Again, as no
          candidates have yet been gathered, the "c=" line must contain
          the "dummy" value "IN IP4 0.0.0.0", as defined in
          <xref target="I-D.ietf-ice-trickle"></xref>, Section 5.1.</t>

          <t>If the offer supports bundle, all m= sections to be
          bundled must use the same ICE credentials and candidates; all
          m= sections not being bundled must use unique ICE credentials
          and candidates. Each m= section MUST contain the following
          attributes (which are of attribute types other than IDENTICAL
          and TRANSPORT):
          <list style="symbols">

            <t>If and only if present in the offer, an "a=mid" line, as
            specified in
            <xref target="RFC5888"></xref>, Section 9.1. The "mid"
            value MUST match that specified in the offer.</t>

            <t>A direction attribute, determined by applying the
            rules regarding the offered direction specified
            in <xref target="RFC3264" />, Section 6.1, and then
            intersecting with the direction of the associated
            RtpTransceiver. For example,
            in the case where an m= section is offered as "sendonly",
            and the local transceiver is set to "sendrecv", the
            result in the answer is a "recvonly" direction.</t>

            <t>For each media format on the m= line,
            "a=rtpmap" and "a=fmtp" lines, as specified in
            <xref target="RFC4566"></xref>, Section 6, and
            <xref target="RFC3264"></xref>, Section 6.1.</t>

            <t>If this m= section is for media with configurable frame
            sizes, e.g. audio, an "a=maxptime" line, indicating the
            smallest of the maximum supported frame sizes out of all
            codecs included above, as specified in
            <xref target="RFC4566"></xref>, Section 6.</t>

            <t>If this m= section is for video media, and there are
            known limitations on the size of images which can be
            decoded, an "a=imageattr" line, as specified in
            <xref target="sec.imageattr"></xref>.</t>

            <t>If "rtx" is present in the offer, for each primary codec
            where RTP retransmission should be used, a corresponding
            "a=rtpmap" line indicating "rtx" with the clock rate of the
            primary codec and an "a=fmtp" line that references the
            payload type of the primary codec, as specified in
            <xref target="RFC4588"></xref>, Section 8.1.</t>

            <t>For each supported FEC mechanism, "a=rtpmap" and
            "a=fmtp" lines, as specified in
            <xref target="RFC4566"></xref>, Section 6. The FEC
            mechanisms that MUST be supported are specified in
            <xref target="I-D.ietf-rtcweb-fec"></xref>, Section 6, and
            specific usage for each media type is outlined in Sections
            4 and 5.</t>

            <t>For each supported RTP header extension that is present
            in the offer, an "a=extmap" line, as specified in
            <xref target="RFC5285"></xref>, Section 5. The list of
            header extensions that SHOULD/MUST be supported is
            specified in
            <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>, Section
            5.2. Any header extensions that require encryption MUST be
            specified as indicated in
            <xref target="RFC6904"></xref>, Section 4.</t>

            <t>For each supported RTCP feedback mechanism that is
            present in the offer, an "a=rtcp-fb" mechanism, as
            specified in
            <xref target="RFC4585"></xref>, Section 4.2. The list of
            RTCP feedback mechanisms that SHOULD/MUST be supported is
            specified in
            <xref target="I-D.ietf-rtcweb-rtp-usage"></xref>, Section
            5.1.</t>

            <t>If the RtpTransceiver has a sendrecv or sendonly direction:
            <list style="symbols">

              <t>An "a=msid" line, as specified in
              <xref target="I-D.ietf-mmusic-msid"></xref>, Section
              2.</t>
            </list></t>
          </list></t>

          <t>Each m= section which is not bundled into another m=
          section, MUST contain the following attributes (which are of
          category IDENTICAL or TRANSPORT):</t>

          <t>
            <list style="symbols">

              <t>"a=ice-ufrag" and "a=ice-pwd" lines, as specified in
              <xref target="RFC5245"></xref>, Section 15.4.</t>

              <t>An "a=fingerprint" line for each of the endpoint's
              certificates, as specified in
              <xref target="RFC4572"></xref>, Section 5; the digest
              algorithm used for the fingerprint MUST match that used
              in the certificate signature.</t>

              <t>An "a=setup" line, as specified in
              <xref target="RFC4145"></xref>, Section 4, and clarified
              for use in DTLS-SRTP scenarios in
              <xref target="RFC5763"></xref>, Section 5. The role value
              in the answer MUST be "active" or "passive"; the "active"
              role is RECOMMENDED. The role value MUST be consistent
              with the existing DTLS connection, if one exists and is
              being continued.</t>

              <t>An "a=dtls-id" line, as specified in
              <xref target="I-D.ietf-mmusic-dtls-sdp"/> Section 5.3.</t>

              <t>If present in the offer, an "a=rtcp-mux" line, as
              specified in
              <xref target="RFC5761"></xref>, Section 5.1.1.
              Otherwise, an "a=rtcp" line, as specified in
              <xref target="RFC3605"></xref>, Section 2.1, containing the
              dummy value "9 IN IP4 0.0.0.0" (because no candidates have
              yet been gathered).</t>

              <t>If present in the offer, an "a=rtcp-rsize" line, as
              specified in
              <xref target="RFC5506"></xref>, Section 5.</t>
            </list>
          </t>

          <t>If a data channel m= section has been offered, a m=
          section MUST also be generated for data. The &lt;media&gt;
          field MUST be set to "application" and the &lt;proto&gt; and
          "fmt" fields MUST be set to exactly match the fields in the
          offer.</t>

          <t>Within the data m= section, the "a=mid", "a=ice-ufrag",
          "a=ice-pwd", "a=candidate", "a=fingerprint", "a=dtls-id",
          and "a=setup" lines MUST be included under the conditions described above,
          along with an "a=fmtp:webrtc-datachannel" line and an
          "a=sctp-port" line referencing the SCTP port number as
          defined in
          <xref target="I-D.ietf-mmusic-sctp-sdp"></xref>, Section
          4.1.</t>

          <t>If "a=group" attributes with semantics of "BUNDLE" are
          offered, corresponding session-level "a=group" attributes
          MUST be added as specified in
          <xref target="RFC5888"></xref>. These attributes MUST have
          semantics "BUNDLE", and MUST include the all mid identifiers
          from the offered bundle groups that have not been rejected.
          Note that regardless of the presence of "a=bundle-only" in
          the offer, no m= sections in the answer should have an
          "a=bundle-only" line.</t>

          <t>Attributes that are common between all m= sections MAY be
          moved to session-level, if explicitly defined to be valid at
          session-level.</t>

          <t>The attributes prohibited in the creation of offers are
          also prohibited in the creation of answers.</t>
        </section>
        <section title="Subsequent Answers"
        anchor="sec.subsequent-answers">

          <t>When createAnswer is called a second (or later) time, or
          is called after a local description has already been
          installed, the processing is somewhat different than for an
          initial answer.</t>

          <t>If the initial answer was not applied using
          setLocalDescription, meaning the PeerConnection is still in
          the "have-remote-offer" state, the steps for generating an
          initial answer should be followed, subject to the following
          restriction:
          <list style="symbols">

            <t>The fields of the "o=" line MUST stay the same except
            for the &lt;session-version&gt; field, which MUST increment
            if the session description changes in any way from the
            previously generated answer.</t>
          </list></t>

          <t>If any session description was previously supplied to
          setLocalDescription, an answer is generated by following the
          steps in the "have-remote-offer" state above, along with
          these exceptions:
          <list style="symbols">

            <t>The "s=" and "t=" lines MUST stay the same.</t>

            <t>Each "m=" and c=" line MUST be filled in with the port
            and address of the default candidate for the m= section, as
            described in
            <xref target="RFC5245"></xref>, Section 4.3. Note, however,
            that the m= line protocol need not match the default
            candidate, because this protocol value must instead match
            what was supplied in the offer, as described above.</t>

            <t>The media formats on the m= line MUST be generated in the
            same order as in the current local description.</t>

            <t>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
            <xref target="RFC5245"></xref>, Section 9.2.1.1. If the m=
            section is bundled into another m= section, it still MUST
            NOT contain any ICE credentials.</t>

            <t>If the m= section is not bundled into another m=
            section and RTCP multiplexing is not active, an "a=rtcp" attribute
            line MUST be filled in with the port and address of the default RTCP
            candidate. If no RTCP candidates have yet been gathered, dummy values MUST be
            used, as described in the initial answer section above.</t>

            <t>If the m= section is not bundled into another m=
            section, for each candidate that has been gathered during
            the most recent gathering phase (see
            <xref target="sec.ice-gather-overview"></xref>), an
            "a=candidate" line MUST be added, as defined in
            <xref target="RFC5245"></xref>, Section 4.3., paragraph 3.
            If candidate gathering for the section has completed, an
            "a=end-of-candidates" attribute MUST be added, as described
            in
            <xref target="I-D.ietf-ice-trickle"></xref>, Section 9.3.
            If the m= section is bundled into another m= section, both
            "a=candidate" and "a=end-of-candidates" MUST be
            omitted.</t>

            <t>For RtpTransceivers that are not stopped, the "a=msid"
            line MUST stay the same.</t>
          </list></t>
        </section>
        <section title="Options Handling"
        anchor="sec.options-handling2">

          <t>The createAnswer method takes as a parameter an
          RTCAnswerOptions object. The set of parameters for
          RTCAnswerOptions is different than those supported in
          RTCOfferOptions; the IceRestart option is unnecessary, as ICE
          credentials will automatically be changed for all m= lines
          where the offerer chose to perform ICE restart.</t>

          <t>The following options are supported in
          RTCAnswerOptions.</t>
          <section title="VoiceActivityDetection"
          anchor="sec.voiceactivitydetection2">

            <t>Silence suppression in the answer is handled as
            described in
            <xref target="sec.voiceactivitydetection1"></xref>, with
            one exception: if support for silence suppression was not
            indicated in the offer, the VoiceActivityDetection
            parameter has no effect, and the answer should be generated
            as if VoiceActivityDetection was set to false. This is done
            on a per-codec basis (e.g., if the offerer somehow offered
            support for CN but set "usedtx=0" for Opus, setting
            VoiceActivityDetection to true would result in an answer
            with CN codecs and "usedtx=0").</t>
          </section>
        </section>
      </section>
      <section title="Modifying an Offer or Answer"
      anchor="sec.modifying-sdp">

        <t>The SDP returned from createOffer or createAnswer MUST NOT
        be changed before passing it to setLocalDescription. If precise
        control over the SDP is needed, the aformentioned
        createOffer/createAnswer options or RTPSender APIs MUST be
        used.</t>

        <t>Note that the application MAY modify the SDP to reduce the
        capabilities in the offer it sends to the far side
        (post-setLocalDescription) or the offer that it installs from
        the far side (pre-setRemoteDescription), as long as it remains
        a valid SDP offer and specifies a subset of what was in the
        original offer. This is safe because the answer is not
        permitted to expand capabilities, and therefore will just
        respond to what is present in the offer.</t>

        <t>The application SHOULD NOT modify the SDP in the answer it
        transmits, as the answer contains the negotiated capabilities,
        and this can cause the two sides to have different ideas about
        what exactly was negotiated.</t>

        <t>As always, the application is solely responsible for what it
        sends to the other party, and all incoming SDP will be
        processed by the browser to the extent of its capabilities. It
        is an error to assume that all SDP is well-formed; however, one
        should be able to assume that any implementation of this
        specification will be able to process, as a remote offer or
        answer, unmodified SDP coming from any other implementation of
        this specification.</t>
      </section>
      <section title="Processing a Local Description"
      anchor="sec.processing-a-local-desc">

        <t>When a SessionDescription is supplied to
        setLocalDescription, the following steps MUST be performed:
        <list style="symbols">

          <t>First, the type of the SessionDescription is checked
          against the current state of the PeerConnection:
          <list style="symbols">

            <t>If the type is "offer", the PeerConnection state MUST be
            either "stable" or "have-local-offer".</t>

            <t>If the type is "pranswer" or "answer", the
            PeerConnection state MUST be either "have-remote-offer" or
            "have-local-pranswer".</t>
          </list></t>

          <t>If the type is not correct for the current state,
          processing MUST stop and an error MUST be returned.</t>

          <t>Next, the SessionDescription is parsed into a data
          structure, as described in the
          <xref target="sec.parsing-a-desc" /> section below. If parsing
          fails for any reason, processing MUST stop and an error MUST
          be returned.</t>

          <t>Finally, the parsed SessionDescription is applied as
          described in the
          <xref target="sec.applying-a-local-desc" /> section below.</t>
        </list></t>
      </section>
      <section title="Processing a Remote Description"
      anchor="sec.processing-a-remote-desc">

        <t>When a SessionDescription is supplied to
        setRemoteDescription, the following steps MUST be performed:
        <list style="symbols">

          <t>First, the type of the SessionDescription is checked
          against the current state of the PeerConnection:
          <list style="symbols">

            <t>If the type is "offer", the PeerConnection state MUST be
            either "stable" or "have-remote-offer".</t>

            <t>If the type is "pranswer" or "answer", the
            PeerConnection state MUST be either "have-local-offer" or
            "have-remote-pranswer".</t>
          </list></t>

          <t>If the type is not correct for the current state,
          processing MUST stop and an error MUST be returned.</t>

          <t>Next, the SessionDescription is parsed into a data
          structure, as described in the
          <xref target="sec.parsing-a-desc" /> section below. If parsing
          fails for any reason, processing MUST stop and an error MUST
          be returned.</t>

          <t>Finally, the parsed SessionDescription is applied as
          described in the
          <xref target="sec.applying-a-remote-desc" /> section
          below.</t>
        </list></t>
      </section>
      <section title="Parsing a Session Description"
      anchor="sec.parsing-a-desc">

        <t>When a SessionDescription of any type is supplied to
        setLocal/RemoteDescription, the implementation must parse it
        and reject it if it is invalid. The exact details of this
        process are explained below.</t>

        <t>The SDP contained in the session description object consists
        of a sequence of text lines, each containing a key-value
        expression, as described in
        <xref target="RFC4566" />, Section 5. The SDP is read,
        line-by-line, and converted to a data structure that contains
        the deserialized information. However, SDP allows many types of
        lines, not all of which are relevant to JSEP applications. For
        each line, the implementation will first ensure it is
        syntactically correct according to its defining ABNF, check
        that it conforms to
        <xref target="RFC4566" /> and
        <xref target="RFC3264" /> semantics, and then either parse and
        store or discard the provided value, as described below.</t>

        <t>If any line is not well-formed, or cannot be parsed as
        described, the parser MUST stop with an error and reject the
        session description, even if the value is to be discarded. This
        ensures that implementations do not accidentally misinterpret
        ambiguous SDP.</t>
        <section title="Session-Level Parsing"
        anchor="sec.session-level-parse">

          <t>First, the session-level lines are checked and parsed.
          These lines MUST occur in a specific order, and with a
          specific syntax, as defined in
          <xref target="RFC4566" />, Section 5. Note that while the
          specific line types (e.g. "v=", "c=") MUST occur in the
          defined order, lines of the same type (typically "a=") can
          occur in any order, and their ordering is not meaningful.</t>

          <t>The following non-attribute lines are not meaningful in
          the JSEP context and MAY be discarded once they have been
          checked.
          <list>

            <t>The "c=" line MUST be checked for syntax but its value
            is not used. This supersedes the guidance in
            <xref target="RFC5245" />, Section 6.1, to use
            "ice-mismatch" to indicate mismatches between "c=" and the
            candidate lines; because JSEP always uses ICE,
            "ice-mismatch" is not useful in this context.</t>

            <t>The "i=", "u=", "e=", "p=", "t=", "r=", "z=", and "k="
            lines are not used by this specification; they MUST be
            checked for syntax but their values are not used.</t>
          </list></t>

          <t>The remaining non-attribute lines are processed as
          follows:
          <list>

            <t>The "v=" line MUST have a version of 0, as specified in
            <xref target="RFC4566" />, Section 5.1.</t>

            <t>The "o=" line MUST be parsed as specified in
            <xref target="RFC4566" />, Section 5.2.</t>

            <t>The "b=" line, if present, MUST be parsed as specified
            in
            <xref target="RFC4566" />, Section 5.8, and the bwtype and
            bandwidth values stored.</t>
          </list></t>

          <t>Finally, the attribute lines are processed. Specific
          processing MUST be applied for the following session-level
          attribute ("a=") lines:
          <list style="symbols">

            <t>Any "a=group" lines are parsed as specified in
            <xref target="RFC5888" />, Section 5, and the group's
            semantics and mids are stored.</t>

            <t>If present, a single "a=ice-lite" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.3, and a value
            indicating the presence of ice-lite is stored.</t>

            <t>If present, a single "a=ice-ufrag" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.4, and the ufrag
            value is stored.</t>

            <t>If present, a single "a=ice-pwd" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.4, and the password
            value is stored.</t>

            <t>If present, a single "a=ice-options" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.5, and the set of
            specified options is stored.</t>

            <t>Any "a=fingerprint" lines are parsed as specified in
            <xref target="RFC4572" />, Section 5, and the set of
            fingerprint and algorithm values is stored.</t>

            <t>If present, a single "a=setup" line is parsed as
            specified in
            <xref target="RFC4145" />, Section 4, and the setup value
            is stored.</t>

            <t>If present, a single "a=dtls-id" line is parsed as
            specified in
            <xref target="I-D.ietf-mmusic-dtls-sdp"/> Section 5,
            and the dtls-id value is stored.</t>

            <t>Any "a=extmap" lines are parsed as specified in
            <xref target="RFC5285" />, Section 5, and their values are
            stored.</t>
          </list></t>

          <t>Once all the session-level lines have been parsed,
          processing continues with the lines in media sections.</t>
        </section>
        <section title="Media Section Parsing"
        anchor="sec.media-level-parse">

          <t>Like the session-level lines, the media session lines MUST
          occur in the specific order and with the specific syntax
          defined in
          <xref target="RFC4566" />, Section 5.</t>

          <t>The "m=" line itself MUST be parsed as described in
          <xref target="RFC4566" />, Section 5.14, and the media, port,
          proto, and fmt values stored.</t>

          <t>Following the "m=" line, specific processing MUST be
          applied for the following non-attribute lines:
          <list style="symbols">

            <t>As with the "c=" line at the session level, the "c="
            line MUST be parsed according to
            <xref target="RFC4566" />, Section 5.7, but its value is
            not used.</t>

            <t>The "b=" line, if present, MUST be parsed as specified
            in
            <xref target="RFC4566" />, Section 5.8, and the bwtype and
            bandwidth values stored.</t>
          </list></t>

          <t>Specific processing MUST also be applied for the following
          attribute lines:
          <list style="symbols">

            <t>If present, a single "a=ice-ufrag" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.4, and the ufrag
            value is stored.</t>

            <t>If present, a single "a=ice-pwd" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.4, and the password
            value is stored.</t>

            <t>If present, a single "a=ice-options" line is parsed as
            specified in
            <xref target="RFC5245" />, Section 15.5, and the set of
            specified options is stored.</t>

            <t>Any "a=candidate" attributes MUST be parsed as specified
            in
            <xref target="RFC5245" />, Section 15.1, and their values
            stored.</t>

            <t>Any "a=remote-candidates" attributes MUST be parsed as
            specified in
            <xref target="RFC5245" />, Section 15.2, but their values
            are ignored.</t>

            <t>If present, a single "a=end-of-candidates" attribute
            MUST be parsed as specified in
            <xref target="I-D.ietf-ice-trickle" />, Section 8.2, and
            its presence or absence flagged and stored.</t>

            <t>Any "a=fingerprint" lines are parsed as specified in
            <xref target="RFC4572" />, Section 5, and the set of
            fingerprint and algorithm values is stored.</t>
          </list></t>

          <t>If the "m=" proto value indicates use of RTP, as described
          in the
          <xref target="sec.profile-names" /> section above, the
          following attribute lines MUST be processed:
          <list style="symbols">

            <t>The "m=" fmt value MUST be parsed as specified in
            <xref target="RFC4566" />, Section 5.14, and the individual
            values stored.</t>

            <t>Any "a=rtpmap" or "a=fmtp" lines MUST be parsed as
            specified in
            <xref target="RFC4566" />, Section 6, and their values
            stored.</t>

            <t>If present, a single "a=ptime" line MUST be parsed as
            described in
            <xref target="RFC4566" />, Section 6, and its value
            stored.</t>

            <t>If present, a single "a=maxptime" line MUST be parsed as
            described in
            <xref target="RFC4566" />, Section 6, and its value
            stored.</t>

            <t>If present, a single direction attribute line (e.g.
            "a=sendrecv") MUST be parsed as described in
            <xref target="RFC4566" />, Section 6, and its value
            stored.</t>

            <t>Any "a=ssrc" or "a=ssrc-group" attributes MUST be parsed
            as specified in
            <xref target="RFC5576" />, Sections 4.1-4.2, and their
            values stored.</t>

            <t>Any "a=extmap" attributes MUST be parsed as specified in

            <xref target="RFC5285" />, Section 5, and their values
            stored.</t>

            <t>Any "a=rtcp-fb" attributes MUST be parsed as specified
            in
            <xref target="RFC4585" />, Section 4.2., and their values
            stored.</t>

            <t>If present, a single "a=rtcp-mux" attribute MUST be
            parsed as specified in
            <xref target="RFC5761" />, Section 5.1.1, and its presence
            or absence flagged and stored.</t>

            <t>If present, a single "a=rtcp-mux-only" attribute MUST be
            parsed as specified in
            <xref target="I-D.ietf-mmusic-mux-exclusive" />, Section 3,
            and its presence or absence flagged and stored.</t>

            <t>If present, a single "a=rtcp-rsize" attribute MUST be
            parsed as specified in
            <xref target="RFC5506" />, Section 5, and its presence or
            absence flagged and stored.</t>

            <t>If present, a single "a=rtcp" attribute MUST be parsed
            as specified in
            <xref target="RFC3605" />, Section 2.1, but its value is
            ignored, as this information is superfluous when using
            ICE.</t>

            <t>If present, a single "a=msid" attribute MUST be parsed
            as specified in
            <xref target="I-D.ietf-mmusic-msid" />, Section 3.2, and
            its value stored.</t>

            <t>Any "a=imageattr" attributes MUST be parsed as specified
            in
            <xref target="RFC6236" />, Section 3, and their values
            stored.</t>

            <t>Any "a=rid" lines MUST be parsed as specified in
            <xref target="I-D.ietf-mmusic-rid"></xref>, Section 10, and
            their values stored.</t>

            <t>If present, a single "a=simulcast" line MUST be parsed
            as specified in
            <xref target="I-D.ietf-mmusic-sdp-simulcast"></xref>, and
            its values stored.</t>
          </list></t>

          <t>Otherwise, if the "m=" proto value indicates use of SCTP,
          the following attribute lines MUST be processed:
          <list style="symbols">

            <t>The "m=" fmt value MUST be parsed as specified in
            <xref target="I-D.ietf-mmusic-sctp-sdp" />, Section 4.3,
            and the application protocol value stored.</t>

            <t>An "a=sctp-port" attribute MUST be present, and it MUST
            be parsed as specified in
            <xref target="I-D.ietf-mmusic-sctp-sdp" />, Section 5.2,
            and the value stored.</t>

            <t>If present, a single "a=max-message-size" attribute MUST
            be parsed as specified in
            <xref target="I-D.ietf-mmusic-sctp-sdp" />, Section 6, and
            the value stored. Otherwise, use the specified default.</t>
          </list></t>
        </section>
        <section title="Semantics Verification">

          <t>Assuming parsing completes successfully, the parsed
          description is then evaluated to ensure internal consistency
          as well as proper support for mandatory features.
          Specifically, the following checks are performed:
          <list style="symbols">

            <t>For each m= section, valid values for each of the
            mandatory-to-use features enumerated in
            <xref target="sec.usage-requirements" /> MUST be present.
            These values MAY either be present at the media level, or
            inherited from the session level.
            <list style="symbols">

              <t>ICE ufrag and password values, which MUST comply with
              the size limits specified in
              <xref target="RFC5245" />, Section 15.4.</t>

              <t>dtls-id value, which MUST be set according to
              <xref target="I-D.ietf-mmusic-dtls-sdp"/> Section 5.
              If this is a re-offer and the dtls-id value is different
              from that presently in use, the DTLS connection is not being
              continued and the remote description MUST be part of an
              ICE restart, together with new ufrag and password
              values. If this is an answer, the
              dtls-id value, if present, MUST be the same as in the
              offer.</t>

              <t>DTLS setup value, which MUST be set according to the
              rules specified in <xref target="RFC5763"/>,
              Section 5 and MUST
              be consistent with the selected role of the current DTLS
              connection, if one exists and is being continued.</t>

              <t>DTLS fingerprint values, where at least one
              fingerprint MUST be present.</t>
            </list></t>

            <t>All RID values referenced in an "a=simulcast" line MUST
            exist as "a=rid" lines.</t>

            <t>Each m= section is also checked to ensure prohibited
            features are not used. If this is a local description, the
            "ice-lite" attribute MUST NOT be specified.</t>
          </list></t>

          <t>If this session description is of type "pranswer" or
          "answer", the following additional checks are applied:
          <list style="symbols">

            <t>The session description must follow the rules defined in

            <xref target="RFC3264" />, Section 6, including the
            requirement that the number of m= sections MUST exactly
            match the number of m= sections in the associated
            offer.</t>

            <t>For each m= section, the media type and protocol values
            MUST exactly match the media type and protocol values in
            the corresponding m= section in the associated offer.</t>
          </list></t>
        </section>
      </section>
      <section title="Applying a Local Description"
      anchor="sec.applying-a-local-desc">

        <t>The following steps are performed at the media engine level
        to apply a local description.</t>

        <t>First, the parsed parameters are checked to ensure that they
        have not been altered after their generation in
        createOffer/createAnswer, as discussed in
        <xref target="sec.modifying-sdp" />; otherwise, processing MUST
        stop and an error MUST be returned.</t>

        <t>Next, media sections are processed. For each media section,
        the following steps MUST be performed; if any parameters are
        out of bounds, or cannot be applied, processing MUST stop and
        an error MUST be returned.
        <list style="symbols">

          <t>If this media section is new, begin gathering candidates
          for it, as defined in
          <xref target="RFC5245" />, Section 4.1.1, unless it has been
          marked as bundle-only.</t>

          <t>Or, if the ICE ufrag and password values have changed, and
          it has not been marked as bundle-only, trigger the ICE Agent
          to start an ICE restart, and begin gathering new candidates
          for the media section as described in
          <xref target="RFC5245" />, Section 9.1.1.1. If this
          description is an answer, also start checks on that media
          section as defined in
          <xref target="RFC5245" />, Section 9.3.1.1.</t>

          <t>If the media section proto value indicates use of RTP:
          <list style="symbols">

            <t>If there is no RtpTransceiver associated with this m=
            section (which should only happen when applying an offer),
            find one and associate it with this m= section according to
            the following steps:
            <list style="symbols">

              <t>Find the RtpTransceiver that corresponds to the m=
              section with the same MID in the created offer.</t>

              <t>Set the value of the RtpTransceiver's mid attribute to
              the MID of the m= section.</t>
            </list></t>

            <t>If RTCP mux is indicated, prepare to demux RTP and RTCP
            from the RTP ICE component, as specified in
            <xref target="RFC5761" />, Section 5.1.1. If RTCP mux is
            not indicated, but was indicated in a previous description,
            this MUST result in an error.</t>

            <t>For each specified RTP header extension, establish a
            mapping between the extension ID and URI, as described in
            section 6 of
            <xref target="RFC5285" />. If any indicated RTP header
            extension is not supported, this MUST result in an
            error.</t>

            <t>If the MID header extension is supported, prepare to
            demux RTP data intended for this media section based on the
            MID header extension, as described in
            <xref target="I-D.ietf-mmusic-msid" />, Section 3.2.</t>

            <t>For each specified media format, establish a mapping
            between the payload type and the actual media format, as
            described in
            <xref target="RFC3264" />, Section 6.1. If any indicated
            media format is not supported, this MUST result in an
            error.</t>

            <t>For each specified "rtx" media format, establish a
            mapping between the RTX payload type and its associated
            primary payload type, as described in
            <xref target="RFC4588" />, Sections 8.6 and 8.7. If any
            referenced primary payload types are not present, this MUST
            result in an error.</t>

            <t>If the directional attribute is of type "sendrecv" or
            "recvonly", enable receipt and decoding of media.</t>
          </list></t>
        </list></t>

        <t>Finally, if this description is of type "pranswer" or
        "answer", follow the processing defined in the
        <xref target="sec.applying-an-answer" /> section below.</t>
      </section>
      <section title="Applying a Remote Description"
      anchor="sec.applying-a-remote-desc">

        <t>If the answer contains any "a=ice-options" attributes where
        "trickle" is listed as an attribute, update the PeerConnection
        canTrickle property to be true. Otherwise, set this property to
        false.</t>

        <t>The following steps are performed at the media engine level
        to apply a remote description.</t>

        <t>The following steps MUST be performed for attributes at the
        session level; if any parameters are out of bounds, or cannot
        be applied, processing MUST stop and an error MUST be returned.

        <list style="symbols">

          <t>For any specified "CT" bandwidth value, set this as the
          limit for the maximum total bitrate for all m= sections, as
          specified in Section 5.8 of
          <xref target="RFC4566"></xref>. The implementation can decide
          how to allocate the available bandwidth between m= sections
          to simultaneously meet any limits on individual m= sections,
          as well as this overall session limit.</t>

          <t>For any specified "RR" or "RS" bandwidth values, handle as
          specified in
          <xref target="RFC3556"></xref>, Section 2.</t>

          <t>Any "AS" bandwidth value MUST be ignored, as the meaning
          of this construct at the session level is not well
          defined.</t>
        </list></t>

        <t>For each media section, the following steps MUST be
        performed; if any parameters are out of bounds, or cannot be
        applied, processing MUST stop and an error MUST be returned.
        <list style="symbols">

          <t>If the ICE ufrag or password changed from the previous
          remote description, then an ICE restart is needed, as
          described in Section 9.1.1.1 of
          <xref target="RFC5245" /> If the description is of type
          "offer", mark that an ICE restart is needed. If the
          description is of type "answer" and the current local
          description is also an ICE restart, then signal the ICE agent
          to begin checks as described in Section 9.3.1.1 of
          <xref target="RFC5245" />. An answer MUST change the ufrag
          and password in an answer if and only if ICE is restarting,
          as described in Section 9.2.1.1 of
          <xref target="RFC5245" />.</t>

          <t>Configure the ICE components associated with this media
          section to use the supplied ICE remote ufrag and password for
          their connectivity checks.</t>

          <t>Pair any supplied ICE candidates with any gathered local
          candidates, as described in Section 5.7 of
          <xref target="RFC5245" /> and start connectivity checks with
          the appropriate credentials.</t>

          <t>If an "a=end-of-candidates" attribute is present, process
          the end-of-candidates indication as described in
          <xref target="I-D.ietf-ice-trickle" /> Section 11.</t>

          <t>If the media section proto value indicates use of RTP:
          <list style="symbols">

            <t>If the m= section is being recycled (see
            <xref target="sec.subsequent-offers"></xref>), dissociate
            the currently associated RtpTransceiver by setting its mid
            attribute to null.</t>

            <t>If the m= section is not associated with any
            RtpTransceiver (possibly because it was dissociated in the
            previous step), either find an RtpTransceiver or create one
            according to the following steps:
            <list style="symbols">

              <t>If the m= section is sendrecv or recvonly, and there
              are RtpTransceivers of the same type that were added to
              the PeerConnection by addTrack and are not associated
              with any m= section and are not stopped, find the first
              (according to the canonical order described in
              <xref target="sec.initial-offers" />) such
              RtpTransceiver.</t>

              <t>If no RtpTransceiver was found in the previous step,
              create one with a recvonly direction.</t>

              <t>Associate the found or created RtpTransceiver with the
              m= section by setting the value of the RtpTransceiver's
              mid attribute to the MID of the m= section. If the m=
              section does not include a MID (i.e., the remote side
              does not support the MID extension), generate a value for
              the RtpTransceiver mid attribute, following the guidance
              for "a=mid" mentioned in
              <xref target="sec.initial-offers" />.</t>
            </list></t>

            <t>For each specified media format that is also supported
            by the local implementation, establish a mapping between
            the specified payload type and the media format, as
            described in
            <xref target="RFC3264" />, Section 6.1. Specifically, this
            means that the implementation records the payload type to
            be used in outgoing RTP packets when sending each specified
            media format, as well as the relative preference for each
            format that is indicated in their ordering. If any
            indicated media format is not supported by the local
            implementation, it MUST be ignored.</t>

            <t>For each specified "rtx" media format, establish a
            mapping between the RTX payload type and its associated
            primary payload type, as described in
            <xref target="RFC4588" />, Section 4. If any referenced
            primary payload types are not present, this MUST result in
            an error.</t>

            <t>For each specified fmtp parameter that is supported by
            the local implementation, enable them on the associated
            media formats.</t>

            <t>For each specified RTP header extension that is also
            supported by the local implementation, establish a mapping
            between the extension ID and URI, as described in
            <xref target="RFC5285" />, Section 5. Specifically, this
            means that the implementation records the extension ID to
            be used in outgoing RTP packets when sending each specified
            header extension. If any indicated RTP header extension is
            not supported by the local implementation, it MUST be
            ignored.</t>

            <t>For each specified RTCP feedback mechanism that is
            supported by the local implementation, enable them on the
            associated media formats.</t>

            <t>For any specified "TIAS" bandwidth value, set this value
            as a constraint on the maximum RTP bitrate to be used when
            sending media, as specified in
            <xref target="RFC3890"></xref>. If a "TIAS" value is not
            present, but an "AS" value is specified, generate a "TIAS"
            value using this formula:
            <list style="format">

              <t>TIAS = AS * 1000 * 0.95 - 50 * 40 * 8</t>
            </list>The 50 is based on 50 packets per second, the 40 is
            based on an 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".</t>

            <t>For any "RR" or "RS" bandwidth values, handle as
            specified in
            <xref target="RFC3556"></xref>, Section 2.</t>

            <t>Any specified "CT" bandwidth value MUST be ignored, as
            the meaning of this construct at the media level is not
            well defined.</t>

            <t>If the media section is of type audio:
            <list style="symbols">

              <t>For each specified "CN" media format, enable DTX for
              all supported media formats with the same clockrate,
              as described in <xref target="RFC3389" />,
              Section 5, except for formats that have their own internal DTX
              mechanisms. DTX for such formats (e.g., Opus) is controlled via
              fmtp parameters, as discussed in
              <xref target="sec.voiceactivitydetection1" />.</t>

              <t>For each specified "telephone-event" media format, enable DTMF
              transmission for all supported media formats with the same
              clockrate, as described in <xref target="RFC4733" />, Section
              2.5.1.2. If the application attempts to transmit DTMF when using
              a media format that does not have a corresponding telephone-event
              format, this MUST result in an error.</t>

              <t>For any specified "ptime" value, configure the
              available media formats to use the specified packet size.
              If the specified size is not supported for a media
              format, use the next closest value instead.</t>
            </list></t>
          </list></t>
        </list></t>

        <t>Finally, if this description is of type "pranswer" or
        "answer", follow the processing defined in the
        <xref target="sec.applying-an-answer" /> section below.</t>
      </section>
      <section title="Applying an Answer"
      anchor="sec.applying-an-answer">

        <t>In addition to the steps mentioned above for processing a
        local or remote description, the following steps are performed
        when processing a description of type "pranswer" or
        "answer".</t>

        <t>For each media section, the following steps MUST be
        performed:
        <list style="symbols">

          <t>If the media section has been rejected (i.e. port is set
          to zero in the answer), stop any reception or transmission of
          media for this section, and discard any associated ICE
          components, as described in Section 9.2.1.3 of
          <xref target="RFC5245" />.</t>

          <t>If the remote DTLS fingerprint has been changed or
          the dtls-id has changed, tear down the DTLS connection.
          If a DTLS connection needs to be torn down but the answer
          does not indicate an ICE restart, an error MUST be generated.
          If an ICE restart is performed without a change in dtls-id
          or fingerprint, then the same DTLS connection is continued over
          the new ICE channel.</t>

          <t>If no valid DTLS connection exists, prepare to start a
          DTLS connection, using the specified roles and fingerprints,
          on any underlying ICE components, once they are active.</t>

          <t>If the media section proto value indicates use of RTP:
          <list style="symbols">

            <t>If the media section references any media formats, RTP
            header extensions, or RTCP feedback mechanisms that were
            not present in the corresponding media section in the
            offer, this indicates a negotiation problem and MUST result
            in an error.</t>

            <t>If the media section has RTCP mux enabled, discard any
            RTCP component, and begin or continue muxing RTCP over the
            RTP component, as specified in
            <xref target="RFC5761" />, Section 5.1.3. Otherwise,
            prepare to transmit RTCP over the RTCP component; if no RTCP
            component exists, because RTCP mux was previously enabled, this
            MUST result in an error.</t>

            <t>If the media section has reduced-size RTCP enabled,
            configure the RTCP transmission for this media section to
            use reduced-size RTCP, as specified in
            <xref target="RFC5506" />.</t>

            <t>If the directional attribute in the answer is of type
            "sendrecv" or "sendonly", choose the media format to send as
            the most preferred media format from the remote
            description that is also present in the answer, as
            described in
            <xref target="RFC3264" />, Sections 6.1 and 7, and start
            transmitting RTP media once the underlying transport layers have
            been established. If a SSRC has not already been chosen for this
            outgoing RTP stream, choose a random one.</t>

            <t>The payload type mapping
            from the remote description is used to determine payload
            types for the outgoing RTP streams, including the payload type for
            the send media format chosen above. Any RTP header
            extensions that were negotiated should be included in the
            outgoing RTP streams, using the extension mapping from the
            remote description; if the RID header extension has been
            negotiated, and RID values are specified, include the RID
            header extension in the outgoing RTP streams, as indicated
            in
            <xref target="I-D.ietf-mmusic-rid"></xref>, Section 4.</t>

            <t>If simulcast has been negotiated, send the number of Source RTP
            Streams as specified in
            <xref target="I-D.ietf-mmusic-sdp-simulcast"></xref>,
            Section 6.2.2.</t>

            <t>If the send media format chosen above has a corresponding "rtx"
            media format, or a FEC mechanism has been negotiated, establish a
            Redundancy RTP Stream with a random SSRC for each Source RTP Stream,
            and start or continue transmitting RTX/FEC packets as needed.
            </t>

            <t>If the send media format chosen above has a corresponding "red"
            media format of the same clockrate, allow redundant encoding using
            the specified format for resiliency purposes, as discussed in
            <xref target="I-D.ietf-rtcweb-fec" />, Section 3.2. Note that unlike
            RTX or FEC media formats, the "red" format is transmitted on the
            Source RTP Stream, not the Redundancy RTP Stream.</t>

            <t>Enable the RTCP feedback mechanisms referenced in the media
            section for all Source RTP Streams using the specified
            media formats. Specifically,
            begin or continue sending the requested feedback types and
            reacting to received feedback, as specified in
            <xref target="RFC4585" />, Section 4.2. When sending RTCP feedback,
            use the SSRC of an outgoing Source RTP Stream as the RTCP sender
            SSRC; if no outgoing Source RTP Stream exists, choose a random one.
            </t>

            <t>If the directional attribute is of type "recvonly" or
            "inactive", stop transmitting all RTP media, but continue sending
            RTCP, as described in
            <xref target="RFC3264" />, Section 5.1.</t>
          </list></t>

          <t>If the media section proto value indicates use of SCTP:
          <list style="symbols">

            <t>If no SCTP association yet exists, prepare to initiate a
            SCTP association over the associated ICE component and DTLS
            connection, using the local SCTP port value from the local
            description, and the remote SCTP port value from the remote
            description, as described in
            <xref target="I-D.ietf-mmusic-sctp-sdp" />, Section
            10.2.</t>
          </list></t>
        </list></t>

        <t>If the answer contains valid bundle groups, discard any ICE
        components for the m= sections that will be bundled onto the
        primary ICE components in each bundle, and begin muxing these
        m= sections accordingly, as described in
        <xref target="I-D.ietf-mmusic-sdp-bundle-negotiation" />,
        Section 8.2.</t>
      </section>
    </section>
    <section title="Processing RTP/RTCP packets" anchor="sec.rtp.demux">

      <t>Note: The following algorithm does not yet have WG consensus
      but is included here as something concrete for the working group
      to discuss.</t>

      <t>When an RTP packet is received by a transport and passes SRTP
      authentication, that packet needs to be routed to the correct
      RtpReceiver. For each transport, the following steps MUST be
      followed to prepare to route packets:</t>

      <t>
        <list>

          <t>Construct a table mapping MID to RtpReceiver for each
          RtpReceiver configured to receive from this transport.</t>

          <t>Construct a table mapping incoming SSRC to RtpReceiver
          for each RtpReceiver configured to receive from this
          transport and for each SSRC that RtpReceiver is configured
          to receive. Some of the SSRCs may be present in the m=
          section corresponding to that RtpReceiver in the remote
          description.</t>

          <t>Construct a table mapping outgoing SSRC to RtpSender for
          each RtpSender configured to transmit from this transport
          and for each SSRC that RtpSender is configured to use when
          sending.</t>

          <t>Construct a table mapping payload type to RtpReceiver for
          each RtpReceiver configured to receive from this transport
          and for each payload type that RtpReceiver is configured to
          receive. The payload types of a given RtpReceiver are found
          in the m= section corresponding to that RtpReceiver in the
          local description. If any payload type could map to more
          than one RtpReceiver, map to the RtpReceiver whose m=
          section appears earliest in the local description.</t>
        </list>
      </t>

      <t>As RtpTransceivers (and, thus, RtpReceivers) are added,
      removed, stopped, or reconfigured, the tables above must also be
      updated.</t>

      <t>For each RTP packet received, the following steps MUST be
      followed to route the packet:</t>

      <t>
        <list>
          <t>If the packet has a MID and that MID is not in the table
          mapping MID to RtpReceiver, drop the packet and stop.</t>

          <t>If the packet has a MID and that MID is in the table
          mapping MID to RtpReceiver, update the incoming SSRC mapping
          table to include an entry that maps the packet's SSRC to the
          RtpReceiver for that MID.</t>

          <t>If the packet's SSRC is in the incoming SSRC mapping
          table, deliver the packet to the associated RtpReceiver and
          stop.</t>

          <t>If the packet's payload type is in the payload type
          table, update the the incoming SSRC mapping table to include
          an entry that maps the packet's SSRC to the
          RtpReceiver for that payload type. In addition, deliver the packet
          to the associated RtpReceiver and stop.</t>

          <t>Otherwise, drop the packet.</t>
        </list>
      </t>

      <t>For each RTCP packet received (including each RTCP packet that is part
      of a compound RTCP packet), the following type-specific handling
      MUST be performed to route the packet:</t>

      <t>
        <list>
          <t>If the packet is of type SR, and the sender SSRC for the
          packet is found in the incoming SSRC table, deliver a copy of the
          packet to the RtpReceiver associated with that SSRC. In addition,
          for each report block in the report whose SSRC is found in the
          outgoing SSRC table, deliver a copy of the RTCP packet to the
          RtpSender associated with that SSRC.</t>

          <t>If the packet is of type RR, for each report block in the
          packet whose SSRC is found in the outgoing SSRC table, deliver a copy
          of the RTCP packet to the RtpSender associated with that SSRC.</t>

          <t>If the packet is of type SDES, and the sender SSRC for
          the packet is found in the incoming SSRC table, deliver the
          packet to the RtpReceiver associated with that SSRC. In addition, for
          each chunk in the packet that contains a MID that is in the table
          mapping MID to RtpReceiver, update the incoming SSRC mapping
          table to include an entry that maps the SSRC for that chunk to
          the RtpReceiver associated with that MID. (This case can occur
          when RTCP for a source is received before any RTP packets.)</t>

          <t>If the packet is of type BYE, for each SSRC indicated in the
          packet that is found in the incoming SSRC table, deliver a copy of the
          packet to the RtpReceiver associated with that SSRC.</t>

          <t>If the packet is of type RTPFB or PSFB, as defined in
          <xref target="RFC4585" />, and the media source SSRC for the packet
          is found in the outgoing SSRC table, deliver the packet
          to the RtpSender associated with that SSRC.</t>

        </list>
      </t>

     <t>After packets are routed to the RtpReceiver, further
      processing of the RTP packets is done at the RtpReceiver level.
      This includes using <xref target="I-D.ietf-mmusic-rid" /> to distinguish
      between multiple Encoded Streams, as well as determine
      which Source RTP stream should be repaired by a given Redundancy
      RTP stream. If the RTP packet's PT does not match any codec in use
      by the RtpReceiver, the packet will be dropped.</t>
    </section>

    <section title="Examples" anchor="sec.examples">

      <t>Note that this example section shows several SDP fragments. To
      format in 72 columns, some of the lines in SDP have been split
      into multiple lines, where leading whitespace indicates that a
      line is a continuation of the previous line. In addition, some
      blank lines have been added to improve readability but are not
      valid in SDP.</t>

      <t>More examples of SDP for WebRTC call flows can be found in
      <xref target="I-D.nandakumar-rtcweb-sdp"></xref>.</t>
      <section title="Simple Example" anchor="sec.simple-examples">

        <t>This section shows a very simple example that sets up a
        minimal audio / video call between two browsers and does not
        use trickle ICE. The example in the following section provides
        a more realistic example of what would happen in a normal
        browser to browser connection.</t>

        <t>The flow shows Alice's browser initiating the session to
        Bob's browser. The messages from Alice's JS to Bob's JS are
        assumed to flow over some signaling protocol via a web server.
        The JS on both Alice's side and Bob's side waits for all
        candidates before sending the offer or answer, so the offers
        and answers are complete. Trickle ICE is not used. Both Alice
        and Bob are using the default policy of balanced.</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
//                  set up local media state
AliceJS->AliceUA:   create new PeerConnection
AliceJS->AliceUA:   addTrack with two tracks: audio and video
AliceJS->AliceUA:   createOffer to get offer
AliceJS->AliceUA:   setLocalDescription with offer
AliceUA->AliceJS:   multiple onicecandidate events with candidates

//                  wait for ICE gathering to complete
AliceUA->AliceJS:   onicecandidate event with null candidate
AliceJS->AliceUA:   get |offer-A1| from pendingLocalDescription

//                  |offer-A1| is sent over signaling protocol to Bob
AliceJS->WebServer: signaling with |offer-A1|
WebServer->BobJS:   signaling with |offer-A1|

//                  |offer-A1| arrives at Bob
BobJS->BobUA:       create a PeerConnection
BobJS->BobUA:       setRemoteDescription with |offer-A1|
BobUA->BobJS:       onaddstream event with remoteStream

//                  Bob accepts call
BobJS->BobUA:       addTrack with local tracks
BobJS->BobUA:       createAnswer
BobJS->BobUA:       setLocalDescription with answer
BobUA->BobJS:       multiple onicecandidate events with candidates

//                  wait for ICE gathering to complete
BobUA->BobJS:       onicecandidate event with null candidate
BobJS->BobUA:       get |answer-A1| from currentLocalDescription

//                  |answer-A1| is sent over signaling protocol to Alice
BobJS->WebServer:   signaling with |answer-A1|
WebServer->AliceJS: signaling with |answer-A1|

//                  |answer-A1| arrives at Alice
AliceJS->AliceUA:   setRemoteDescription with |answer-A1|
AliceUA->AliceJS:   onaddstream event with remoteStream

//                  media flows
BobUA->AliceUA:     media sent from Bob to Alice
AliceUA->BobUA:     media sent from Alice to Bob
]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |offer-A1| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
v=0
o=- 4962303333179871722 1 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE a1 v1
a=ice-options:trickle
m=audio 56500 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 192.0.2.1
a=mid:a1
a=rtcp:56501 IN IP4 192.0.2.1
a=msid:47017fee-b6c1-4162-929c-a25110252400
       f83006c5-a0ff-4e0a-9ed9-d3e6747be7d9
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=ice-ufrag:ETEn1v9DoTMB9J4r
a=ice-pwd:OtSK0WpNtpUjkY4+86js7ZQl
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=rtcp-mux
a=rtcp-rsize
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=candidate:3348148302 1 udp 2113937151 192.0.2.1 56500
            typ host
a=candidate:3348148302 2 udp 2113937151 192.0.2.1 56501
            typ host
a=end-of-candidates

m=video 56502 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 192.0.2.1
a=rtcp:56503 IN IP4 192.0.2.1
a=mid:v1
a=msid:61317484-2ed4-49d7-9eb7-1414322a7aae
       f30bdb4a-5db8-49b5-bcdc-e0c9a23172e0
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=ice-ufrag:BGKkWnG5GmiUpdIV
a=ice-pwd:mqyWsAjvtKwTGnvhPztQ9mIf
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=rtcp-mux
a=rtcp-rsize
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=candidate:3348148302 1 udp 2113937151 192.0.2.1 56502
            typ host
a=candidate:3348148302 2 udp 2113937151 192.0.2.1 56503
            typ host
a=end-of-candidates
          ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |answer-A1| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
v=0
o=- 6729291447651054566 1 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE a1 v1
m=audio 20000 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 192.0.2.2
a=mid:a1
a=rtcp:20000 IN IP4 192.0.2.2
a=msid:PI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1
       PI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1a0
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=ice-ufrag:6sFvz2gdLkEwjZEr
a=ice-pwd:cOTZKZNVlO9RSGsEGM63JXT2
a=fingerprint:sha-256 6B:8B:F0:65:5F:78:E2:51:3B:AC:6F:F3:3F:46:1B:35
            :DC:B8:5F:64:1A:24:C2:43:F0:A1:58:D0:A1:2C:19:08
a=setup:active
a=rtcp-mux
a=rtcp-rsize
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=candidate:2299743422 1 udp 2113937151 192.0.2.2 20000
            typ host
a=end-of-candidates

m=video 20000 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 192.0.2.2
a=rtcp 20001 IN IP4 192.0.2.2
a=mid:v1
a=msid:PI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1
       PI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1v0
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=fingerprint:sha-256 6B:8B:F0:65:5F:78:E2:51:3B:AC:6F:F3:3F:46:1B:35
                     :DC:B8:5F:64:1A:24:C2:43:F0:A1:58:D0:A1:2C:19:08
a=setup:active
a=rtcp-mux
a=rtcp-rsize
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
          ]]>
</artwork>
          </figure>
        </t>
      </section>
      <section title="Normal Examples" anchor="sec.normal-examples">

        <t>This section shows a typical example of a session between
        two browsers setting up an audio channel and a data channel.
        Trickle ICE is used in full trickle mode with a bundle policy
        of max-bundle, an RTCP mux policy of require, and a single TURN
        server. Later, two video flows, one for the presenter and one
        for screen sharing, are added to the session. This example
        shows Alice's browser initiating the session to Bob's browser.
        The messages from Alice's JS to Bob's JS are assumed to flow
        over some signaling protocol via a web server.</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
//                  set up local media state
AliceJS->AliceUA:   create new PeerConnection
AliceJS->AliceUA:   addTrack with an audio track
AliceJS->AliceUA:   createDataChannel to get data channel
AliceJS->AliceUA:   createOffer to get |offer-B1|
AliceJS->AliceUA:   setLocalDescription with |offer-B1|

//                  |offer-B1| is sent over signaling protocol to Bob
AliceJS->WebServer: signaling with |offer-B1|
WebServer->BobJS:   signaling with |offer-B1|

//                  |offer-B1| arrives at Bob
BobJS->BobUA:       create a PeerConnection
BobJS->BobUA:       setRemoteDescription with |offer-B1|
BobUA->BobJS:       onaddstream with audio track from Alice

//                  candidates are sent to Bob
AliceUA->AliceJS:   onicecandidate event with |candidate-B1| (host)
AliceJS->WebServer: signaling with |candidate-B1|
AliceUA->AliceJS:   onicecandidate event with |candidate-B2| (srflx)
AliceJS->WebServer: signaling with |candidate-B2|

WebServer->BobJS:   signaling with |candidate-B1|
BobJS->BobUA:       addIceCandidate with |candidate-B1|
WebServer->BobJS:   signaling with |candidate-B2|
BobJS->BobUA:       addIceCandidate with |candidate-B2|

//                  Bob accepts call
BobJS->BobUA:       addTrack with local audio
BobJS->BobUA:       createDataChannel to get data channel
BobJS->BobUA:       createAnswer to get |answer-B1|
BobJS->BobUA:       setLocalDescription with |answer-B1|

//                  |answer-B1| is sent to Alice
BobJS->WebServer:   signaling with |answer-B1|
WebServer->AliceJS: signaling with |answer-B1|
AliceJS->AliceUA:   setRemoteDescription with |answer-B1|
AliceUA->AliceJS:   onaddstream event with audio track from Bob

//                  candidates are sent to Alice
BobUA->BobJS:       onicecandidate event with |candidate-B3| (host)
BobJS->WebServer:   signaling with |candidate-B3|
BobUA->BobJS:       onicecandidate event with |candidate-B4| (srflx)
BobJS->WebServer:   signaling with |candidate-B4|

WebServer->AliceJS: signaling with |candidate-B3|
AliceJS->AliceUA:   addIceCandidate with |candidate-B3|
WebServer->AliceJS: signaling with |candidate-B4|
AliceJS->AliceUA:   addIceCandidate with |candidate-B4|

//                  data channel opens
BobUA->BobJS:       ondatachannel event
AliceUA->AliceJS:   ondatachannel event
BobUA->BobJS:       onopen
AliceUA->AliceJS:   onopen

//                  media is flowing between browsers
BobUA->AliceUA:     audio+data sent from Bob to Alice
AliceUA->BobUA:     audio+data sent from Alice to Bob

//                  some time later Bob adds two video streams
//                  note, no candidates exchanged, because of bundle
BobJS->BobUA:       addTrack with first video stream
BobJS->BobUA:       addTrack with second video stream
BobJS->BobUA:       createOffer to get |offer-B2|
BobJS->BobUA:       setLocalDescription with |offer-B2|

//                  |offer-B2| is sent to Alice
BobJS->WebServer:   signaling with |offer-B2|
WebServer->AliceJS: signaling with |offer-B2|
AliceJS->AliceUA:   setRemoteDescription with |offer-B2|
AliceUA->AliceJS:   onaddstream event with first video stream
AliceUA->AliceJS:   onaddstream event with second video stream
AliceJS->AliceUA:   createAnswer to get |answer-B2|
AliceJS->AliceUA:   setLocalDescription with |answer-B2|

//                  |answer-B2| is sent over signaling protocol to Bob
AliceJS->WebServer: signaling with |answer-B2|
WebServer->BobJS:   signaling with |answer-B2|
BobJS->BobUA:       setRemoteDescription with |answer-B2|

//                  media is flowing between browsers
BobUA->AliceUA:     audio+video+data sent from Bob to Alice
AliceUA->BobUA:     audio+video+data sent from Alice to Bob
]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |offer-B1| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
v=0
o=- 4962303333179871723 1 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE a1 d1
a=ice-options:trickle
m=audio 9 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=mid:a1
a=msid:57017fee-b6c1-4162-929c-a25110252400
       e83006c5-a0ff-4e0a-9ed9-d3e6747be7d9
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=ice-ufrag:ATEn1v9DoTMB9J4r
a=ice-pwd:AtSK0WpNtpUjkY4+86js7ZQl
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=rtcp-mux
a=rtcp-rsize
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid

m=application 0 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=bundle-only
a=mid:d1
a=fmtp:webrtc-datachannel max-message-size=65536
a=sctp-port 5000
a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
                     :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
         ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |candidate-B1| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
candidate:109270923 1 udp 2122194687 192.168.1.2 51556 typ host
         ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |candidate-B2| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
candidate:4036177503 1 udp 1685987071 11.22.33.44 52546 typ srflx
          raddr 192.168.1.2 rport 51556
         ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |answer-B1| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
v=0
o=- 7729291447651054566 1 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE a1 d1
a=ice-options:trickle
m=audio 9 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=mid:a1
a=msid:QI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1
       QI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1a0
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=ice-ufrag:7sFvz2gdLkEwjZEr
a=ice-pwd:dOTZKZNVlO9RSGsEGM63JXT2
a=fingerprint:sha-256 6B:8B:F0:65:5F:78:E2:51:3B:AC:6F:F3:3F:46:1B:35
                     :DC:B8:5F:64:1A:24:C2:43:F0:A1:58:D0:A1:2C:19:08
a=setup:active
a=rtcp-mux
a=rtcp-rsize
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid

m=application 9 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 0.0.0.0
a=mid:d1
a=fmtp:webrtc-datachannel max-message-size=65536
a=sctp-port 5000
a=fingerprint:sha-256 6B:8B:F0:65:5F:78:E2:51:3B:AC:6F:F3:3F:46:1B:35
                     :DC:B8:5F:64:1A:24:C2:43:F0:A1:58:D0:A1:2C:19:08
a=setup:active
         ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |candidate-B3| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
candidate:109270924 1 udp 2122194687 192.168.2.3 61665 typ host
     ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |candidate-B4| looks like:</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
candidate:4036177504 1 udp 1685987071 55.66.77.88 64532 typ srflx
          raddr 192.168.2.3 rport 61665
     ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |offer-B2| looks like: (note the increment of
        the version number in the o= line, and the c= and a=rtcp lines,
        which indicate the local candidate that was selected)</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
v=0
o=- 7729291447651054566 2 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE a1 d1 v1 v2
a=ice-options:trickle
m=audio 64532 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 55.66.77.88
a=rtcp:64532 IN IP4 55.66.77.88
a=mid:a1
a=msid:QI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1
       QI39StLS8W7ZbQl1sJsWUXkr3Zf12fJUvzQ1a0
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=ice-ufrag:7sFvz2gdLkEwjZEr
a=ice-pwd:dOTZKZNVlO9RSGsEGM63JXT2
a=fingerprint:sha-256 6B:8B:F0:65:5F:78:E2:51:3B:AC:6F:F3:3F:46:1B:35
                     :DC:B8:5F:64:1A:24:C2:43:F0:A1:58:D0:A1:2C:19:08
a=setup:actpass
a=rtcp-mux
a=rtcp-rsize
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=candidate:109270924 1 udp 2122194687 192.168.2.3 61665 typ host
a=candidate:4036177504 1 udp 1685987071 55.66.77.88 64532 typ srflx
            raddr 192.168.2.3 rport 61665
a=candidate:3671762467 1 udp 41819903 66.77.88.99 50416 typ relay
            raddr 55.66.77.88 rport 64532
a=end-of-candidates

m=application 64532 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 55.66.77.88
a=mid:d1
a=fmtp:webrtc-datachannel max-message-size=65536
a=sctp-port 5000
a=ice-ufrag:7sFvz2gdLkEwjZEr
a=ice-pwd:dOTZKZNVlO9RSGsEGM63JXT2
a=fingerprint:sha-256 6B:8B:F0:65:5F:78:E2:51:3B:AC:6F:F3:3F:46:1B:35
                     :DC:B8:5F:64:1A:24:C2:43:F0:A1:58:D0:A1:2C:19:08
a=setup:actpass
a=candidate:109270924 1 udp 2122194687 192.168.2.3 61665 typ host
a=candidate:4036177504 1 udp 1685987071 55.66.77.88 64532 typ srflx
            raddr 192.168.2.3 rport 61665
a=candidate:3671762467 1 udp 41819903 66.77.88.99 50416 typ relay
            raddr 55.66.77.88 rport 64532
a=end-of-candidates

m=video 0 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 55.66.77.88
a=bundle-only
a=rtcp:64532 IN IP4 55.66.77.88
a=mid:v1
a=msid:61317484-2ed4-49d7-9eb7-1414322a7aae
       f30bdb4a-5db8-49b5-bcdc-e0c9a23172e0
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=rtcp-mux
a=rtcp-rsize
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli

m=video 0 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 55.66.77.88
a=bundle-only
a=rtcp:64532 IN IP4 55.66.77.88
a=mid:v1
a=msid:71317484-2ed4-49d7-9eb7-1414322a7aae
       f30bdb4a-5db8-49b5-bcdc-e0c9a23172e0
a=sendrecv
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:actpass
a=rtcp-mux
a=rtcp-rsize
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
         ]]>
</artwork>
          </figure>
        </t>

        <t>The SDP for |answer-B2| looks like: (note the use of
        setup:passive to maintain the existing DTLS roles, and the use
        of a=recvonly to indicate that the video streams are
        one-way)</t>

        <t>
          <figure>
            <artwork>
              <![CDATA[
v=0
o=- 4962303333179871723 2 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE a1 d1 v1 v2
a=ice-options:trickle
m=audio 52546 UDP/TLS/RTP/SAVPF 96 0 8 97 98
c=IN IP4 11.22.33.44
a=rtcp:52546 IN IP4 11.22.33.44
a=mid:a1
a=msid:57017fee-b6c1-4162-929c-a25110252400
       e83006c5-a0ff-4e0a-9ed9-d3e6747be7d9
a=sendrecv
a=rtpmap:96 opus/48000/2
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=rtpmap:98 telephone-event/48000
a=maxptime:120
a=ice-ufrag:ATEn1v9DoTMB9J4r
a=ice-pwd:AtSK0WpNtpUjkY4+86js7ZQl
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:passive
a=rtcp-mux
a=rtcp-rsize
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=candidate:109270923 1 udp 2122194687 192.168.1.2 51556 typ host
a=candidate:4036177503 1 udp 1685987071 11.22.33.44 52546 typ srflx
            raddr 192.168.1.2 rport 51556
a=candidate:3671762466 1 udp 41819903 22.33.44.55 61405 typ relay
            raddr 11.22.33.44 rport 52546
a=end-of-candidates

m=application 52546 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 11.22.33.44
a=mid:d1
a=fmtp:webrtc-datachannel max-message-size=65536
a=sctp-port 5000
a=fingerprint:sha-256 19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
                     :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:passive

m=video 52546 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 11.22.33.44
a=rtcp:52546 IN IP4 11.22.33.44
a=mid:v1
a=recvonly
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:passive
a=rtcp-mux
a=rtcp-rsize
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli

m=video 52546 UDP/TLS/RTP/SAVPF 100 101
c=IN IP4 11.22.33.44
a=rtcp:52546 IN IP4 11.22.33.44
a=mid:v2
a=recvonly
a=rtpmap:100 VP8/90000
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=fingerprint:sha-256
              19:E2:1C:3B:4B:9F:81:E6:B8:5C:F4:A5:A8:D8:73:04
             :BB:05:2F:70:9F:04:A9:0E:05:E9:26:33:E8:70:88:A2
a=setup:passive
a=rtcp-mux
a=rtcp-rsize
a=extmap:2 urn:ietf:params:rtp-hdrext:sdes:mid
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
         ]]>
</artwork>
          </figure>
        </t>
      </section>
    </section>
    <section title="Security Considerations"
    anchor="sec.security-considerations">

      <t>The IETF has published separate documents
      <xref target="I-D.ietf-rtcweb-security-arch" />
      <xref target="I-D.ietf-rtcweb-security" /> describing the security
      architecture for WebRTC as a whole. The remainder of this section
      describes security considerations for this document.</t>

      <t>While formally the JSEP interface is an API, it is better to
      think of it is an Internet protocol, with the JS being
      untrustworthy from the perspective of the browser. Thus, the
      threat model of
      <xref target="RFC3552" /> applies. In particular, JS can call the
      API in any order and with any inputs, including malicious ones.
      This is particularly relevant when we consider the SDP which is
      passed to setLocalDescription(). While correct API usage requires
      that the application pass in SDP which was derived from
      createOffer() or createAnswer(), there is no guarantee that
      applications do so. The browser MUST be prepared for the JS to
      pass in bogus data instead.</t>

      <t>Conversely, the application programmer MUST recognize that the
      JS does not have complete control of browser behavior. One case
      that bears particular mention is that editing ICE candidates out
      of the SDP or suppressing trickled candidates does not have the
      expected behavior: implementations will still perform checks from
      those candidates even if they are not sent to the other side.
      Thus, for instance, it is not possible to prevent the remote peer
      from learning your public IP address by removing server reflexive
      candidates. Applications which wish to conceal their public IP
      address should instead configure the ICE agent to use only relay
      candidates.</t>
    </section>
    <section title="IANA Considerations"
    anchor="sec.iana-considerations">

      <t>This document requires no actions from IANA.</t>
    </section>
    <section title="Acknowledgements" anchor="sec.acknowledgements">

      <t>Significant text incorporated in the draft as well and review
      was provided by Peter Thatcher, Taylor Brandstetter, Harald
      Alvestrand and Suhas Nandakumar.
      <!-- ACK 1 -->Dan Burnett, Neil Stratford, Anant Narayanan,
      Andrew Hutton, Richard Ejzak,
      <!-- ACK 2 -->
      <!-- ACK 3 -->
      <!-- ACK 4 -->Adam Bergkvist and Matthew Kaufman all provided
      valuable feedback on this proposal.
      <!-- ACK 5 -->
      <!-- ACK 5a -->
      <!-- ACK 5b -->
      <!-- ACK 5c -->
      <!-- ACK 6 -->
      <!-- ACK 7 --></t>
    </section>
  </middle>
  <back>
    <references title="Normative References">
      <!-- NORM 1 -->
      <reference anchor="RFC5245">
        <front>
          <title>Interactive Connectivity Establishment (ICE): A
          Protocol for Network Address Translator (NAT) Traversal for
          Offer/Answer Protocols</title>
          <author fullname="J. Rosenberg" initials="J."
          surname="Rosenberg">
            <organization></organization>
          </author>
          <date month="April" year="2010" />
        </front>
        <seriesInfo name="RFC" value="5245" />
        <format octets="285120"
        target="http://www.rfc-editor.org/rfc/rfc5245.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC5888">
        <front>
          <title>The Session Description Protocol (SDP) Grouping
          Framework</title>
          <author fullname="G. Camarillo" initials="G."
          surname="Camarillo">
            <organization></organization>
          </author>
          <author fullname="H. Schulzrinne" initials="H."
          surname="Schulzrinne">
            <organization></organization>
          </author>
          <date month="June" year="2010" />
        </front>
        <seriesInfo name="RFC" value="5888" />
        <format octets="43924"
        target="http://www.rfc-editor.org/rfc/rfc5888.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC5761">
        <front>
          <title>Multiplexing RTP Data and Control Packets on a Single
          Port</title>
          <author fullname="C. Perkins" initials="C."
          surname="Perkins">
            <organization></organization>
          </author>
          <author fullname="M. Westerlund" initials="M."
          surname="Westerlund">
            <organization></organization>
          </author>
          <date month="April" year="2010" />
        </front>
        <seriesInfo name="RFC" value="5761" />
        <format octets="31778"
        target="http://www.rfc-editor.org/rfc/rfc5761.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC4585">
        <front>
          <title>Extended RTP Profile for Real-time Transport Control
          Protocol (RTCP)-Based Feedback (RTP/AVPF)</title>
          <author fullname="J. Ott" initials="J." surname="Ott">
            <organization></organization>
          </author>
          <author fullname="S. Wenger" initials="S." surname="Wenger">
            <organization></organization>
          </author>
          <author fullname="N. Sato" initials="N." surname="Sato">
            <organization></organization>
          </author>
          <author fullname="C. Burmeister" initials="C."
          surname="Burmeister">
            <organization></organization>
          </author>
          <author fullname="J. Rey" initials="J." surname="Rey">
            <organization></organization>
          </author>
          <date month="July" year="2006" />
        </front>
        <seriesInfo name="RFC" value="4585" />
        <format octets="117762"
        target="http://www.rfc-editor.org/rfc/rfc4585.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC3261">
        <front>
          <title>SIP: Session Initiation Protocol</title>
          <author fullname="J. Rosenberg" initials="J."
          surname="Rosenberg">
            <organization></organization>
          </author>
          <author fullname="H. Schulzrinne" initials="H."
          surname="Schulzrinne">
            <organization></organization>
          </author>
          <author fullname="G. Camarillo" initials="G."
          surname="Camarillo">
            <organization></organization>
          </author>
          <author fullname="A. Johnston" initials="A."
          surname="Johnston">
            <organization></organization>
          </author>
          <author fullname="J. Peterson" initials="J."
          surname="Peterson">
            <organization></organization>
          </author>
          <author fullname="R. Sparks" initials="R." surname="Sparks">
            <organization></organization>
          </author>
          <author fullname="M. Handley" initials="M."
          surname="Handley">
            <organization></organization>
          </author>
          <author fullname="E. Schooler" initials="E."
          surname="Schooler">
            <organization></organization>
          </author>
          <date month="June" year="2002" />
        </front>
        <seriesInfo name="RFC" value="3261" />
        <format octets="647976"
        target="http://www.rfc-editor.org/rfc/rfc3261.txt"
        type="TXT" />
      </reference>
      <!-- NORM 2 -->
      <reference anchor='I-D.ietf-rtcweb-video'>
        <front>
          <title>WebRTC Video Processing and Codec Requirements</title>
          <author initials='A' surname='Roach' fullname='Adam Roach'>
            <organization />
          </author>
          <date month='July' day='1' year='2014' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-rtcweb-video-00' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-video-00.txt' />
      </reference>
      <reference anchor="RFC3890"
      target="http://www.rfc-editor.org/info/rfc3890">
        <front>
          <title>A Transport Independent Bandwidth Modifier for the
          Session Description Protocol (SDP)</title>
          <author initials="M." surname="Westerlund"
          fullname="M. Westerlund">
            <organization />
          </author>
          <date year="2004" month="September" />
        </front>
        <seriesInfo name="RFC" value="3890" />
        <seriesInfo name="DOI" value="10.17487/RFC3890" />
      </reference>
      <!-- NORM 2a -->
      <reference anchor="I-D.ietf-rtcweb-audio">
        <front>
          <title>WebRTC Audio Codec and Processing Requirements</title>
          <author fullname="Jean-Marc Valin" initials="J"
          surname="Valin">
            <organization></organization>
          </author>
          <author fullname="Cary Bran" initials="C" surname="Bran">
            <organization></organization>
          </author>
          <date day="2" month="August" year="2013" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-rtcweb-audio-02" />
        <format target="http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-audio-02.txt"
        type="TXT" />
      </reference>
      <!-- NORM 3 -->
      <reference anchor="I-D.ietf-mmusic-sctp-sdp">
        <front>
          <title>Stream Control Transmission Protocol (SCTP)-Based
          Media Transport in the Session Description Protocol
          (SDP)</title>
          <author fullname="Salvatore Loreto" initials="S"
          surname="Loreto">
            <organization></organization>
          </author>
          <author fullname="Gonzalo Camarillo" initials="G"
          surname="Camarillo">
            <organization></organization>
          </author>
          <date day="30" month="June" year="2013" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-mmusic-sctp-sdp-04" />
        <format target="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-sctp-sdp-04.txt"
        type="TXT" />
      </reference>
      <!-- NORM 4 -->
      <reference anchor="RFC4572">
        <front>
          <title>Connection-Oriented Media Transport over the Transport
          Layer Security (TLS) Protocol in the Session Description
          Protocol (SDP)</title>
          <author fullname="J. Lennox" initials="J." surname="Lennox">
            <organization></organization>
          </author>
          <date month="July" year="2006" />
        </front>
        <seriesInfo name="RFC" value="4572" />
        <format octets="38658"
        target="http://www.rfc-editor.org/rfc/rfc4572.txt"
        type="TXT" />
      </reference>
      <!-- NORM 5 -->
      <reference anchor="RFC4145">
        <front>
          <title>TCP-Based Media Transport in the Session Description
          Protocol (SDP)</title>
          <author fullname="D. Yon" initials="D." surname="Yon">
            <organization></organization>
          </author>
          <author fullname="G. Camarillo" initials="G."
          surname="Camarillo">
            <organization></organization>
          </author>
          <date month="September" year="2005" />
        </front>
        <seriesInfo name="RFC" value="4145" />
        <format octets="30225"
        target="http://www.rfc-editor.org/rfc/rfc4145.txt"
        type="TXT" />
      </reference>
      <!-- NORM 6 -->
      <reference anchor="I-D.nandakumar-mmusic-proto-iana-registration">

        <front>
          <title abbrev="SDP Proto Registrations">IANA registration of
          SDP 'proto' attribute for transporting RTP Media over TCP
          under various RTP profiles.</title>
          <author fullname="Suhas Nandakumar" initials="S."
          surname="Nandakumar">
            <organization>Cisco Systems Inc</organization>
            <address>
              <postal>
                <street>707 Tasman Drive</street>
                <city>San Jose</city>
                <region>CA</region>
                <code>95134</code>
                <country>USA</country>
              </postal>
              <email>snandaku@cisco.com</email>
            </address>
          </author>
          <date day="18" month="September" year="2014" />
          <area>RAI</area>
          <workgroup>MMUSIC</workgroup>
        </front>
      </reference>
      <!-- NORM 7 -->
      <reference anchor='I-D.ietf-mmusic-sdp-mux-attributes'>
        <front>
          <title>A Framework for SDP Attributes when
          Multiplexing</title>
          <author initials='S' surname='Nandakumar'
          fullname='Suhas Nandakumar'>
            <organization />
          </author>
          <date month='February' day='14' year='2014' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-mmusic-sdp-mux-attributes-01' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-mmusic-sdp-mux-attributes-01.txt' />
      </reference>
      <!-- NORM 8 -->
      <!-- NORM 9 -->
      <!-- NORM 10 -->
      <reference anchor="RFC5285">
        <front>
          <title>A General Mechanism for RTP Header Extensions</title>
          <author fullname="D. Singer" initials="D." surname="Singer">
            <organization></organization>
          </author>
          <author fullname="H. Desineni" initials="H."
          surname="Desineni">
            <organization></organization>
          </author>
          <date month="July" year="2008" />
        </front>
        <seriesInfo name="RFC" value="5285" />
        <format octets="36844"
        target="http://www.rfc-editor.org/rfc/rfc5285.txt"
        type="TXT" />
      </reference>
      <!-- NORM 11 -->
      <reference anchor="RFC6904">
        <front>
          <title>Encryption of Header Extensions in the Secure
          Real-time Transport Protocol (SRTP)</title>
          <author fullname="J. Lennox" initials="J." surname="Lennox">
            <organization></organization>
          </author>
          <date month="April" year="2013" />
        </front>
        <seriesInfo name="RFC" value="6904" />
        <format octets="33486"
        target="http://www.rfc-editor.org/rfc/rfc6904.txt"
        type="TXT" />
      </reference>
      <!-- NORM 12 -->
      <reference anchor="I-D.ietf-rtcweb-rtp-usage">
        <front>
          <title>Web Real-Time Communication (WebRTC): Media Transport
          and Use of RTP</title>
          <author fullname="Colin Perkins" initials="C"
          surname="Perkins">
            <organization></organization>
          </author>
          <author fullname="Magnus Westerlund" initials="M"
          surname="Westerlund">
            <organization></organization>
          </author>
          <author fullname="Joerg Ott" initials="J" surname="Ott">
            <organization></organization>
          </author>
          <date day="5" month="September" year="2013" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-rtcweb-rtp-usage-09" />
        <format target="http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-rtp-usage-09.txt"
        type="TXT" />
      </reference>
      <!-- NORM 13 -->
      <reference anchor="I-D.ietf-mmusic-sdp-bundle-negotiation">
        <front>
          <title>Multiplexing Negotiation Using Session Description
          Protocol (SDP) Port Numbers</title>
          <author fullname="Christer Holmberg" initials="C"
          surname="Holmberg">
            <organization></organization>
          </author>
          <author fullname="Harald Alvestrand" initials="H"
          surname="Alvestrand">
            <organization></organization>
          </author>
          <author fullname="Cullen Jennings" initials="C"
          surname="Jennings">
            <organization></organization>
          </author>
          <date day="14" month="June" year="2013" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-mmusic-sdp-bundle-negotiation-04" />
        <format target="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-sdp-bundle-negotiation-04.txt"
        type="TXT" />
      </reference>
      <!-- NORM 14 -->
      <reference anchor="I-D.ietf-mmusic-msid">
        <front>
          <title>Cross Session Stream Identification in the Session
          Description Protocol</title>
          <author fullname="Harald Alvestrand" initials="H"
          surname="Alvestrand">
            <organization></organization>
          </author>
          <date day="13" month="August" year="2013" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-mmusic-msid-01" />
        <format target="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-msid-01.txt"
        type="TXT" />
      </reference>
      <!-- NORM 15 -->
      <!-- NORM 16 -->
      <reference anchor='I-D.ietf-rtcweb-security'>
        <front>
          <title>Security Considerations for WebRTC</title>
          <author initials='E' surname='Rescorla'
          fullname='Eric Rescorla'>
            <organization />
          </author>
          <date month='January' day='21' year='2014' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-rtcweb-security-06' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-security-06.txt' />
      </reference>
      <!-- NORM 17 -->
      <reference anchor='I-D.ietf-rtcweb-security-arch'>
        <front>
          <title>WebRTC Security Architecture</title>
          <author initials='E' surname='Rescorla'
          fullname='Eric Rescorla'>
            <organization />
          </author>
          <date month='February' day='14' year='2014' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-rtcweb-security-arch-09' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-security-arch-09.txt' />
      </reference>
      <!-- NORM 18 -->
      <reference anchor='RFC3552'>
        <front>
          <title>Guidelines for Writing RFC Text on Security
          Considerations</title>
          <author initials='E.' surname='Rescorla'
          fullname='E. Rescorla'>
            <organization />
          </author>
          <author initials='B.' surname='Korver' fullname='B. Korver'>
            <organization />
          </author>
          <date year='2003' month='July' />
        </front>
        <seriesInfo name='BCP' value='72' />
        <seriesInfo name='RFC' value='3552' />
        <format type='TXT' octets='110393'
        target='http://www.rfc-editor.org/rfc/rfc3552.txt' />
      </reference>
      <!-- NORM 19 -->
      <reference anchor="RFC2119">
        <front>
          <title abbrev="RFC Key Words">Key words for use in RFCs to
          Indicate Requirement Levels</title>
          <author fullname="Scott Bradner" initials="S."
          surname="Bradner">
            <organization>Harvard University</organization>
            <address>
              <postal>
                <street>1350 Mass. Ave.</street>
                <street>Cambridge</street>
                <street>MA 02138</street>
              </postal>
              <phone>- +1 617 495 3864</phone>
              <email>sob@harvard.edu</email>
            </address>
          </author>
          <date month="March" year="1997" />
          <area>General</area>
          <keyword>keyword</keyword>
        </front>
        <seriesInfo name="BCP" value="14" />
        <seriesInfo name="RFC" value="2119" />
        <format octets="4723"
        target="http://www.rfc-editor.org/rfc/rfc2119.txt"
        type="TXT" />
        <format octets="17491"
        target="http://xml.resource.org/public/rfc/html/rfc2119.html"
        type="HTML" />
        <format octets="5777"
        target="http://xml.resource.org/public/rfc/xml/rfc2119.xml"
        type="XML" />
      </reference>
      <reference anchor="RFC3264">
        <front>
          <title>An Offer/Answer Model with Session Description
          Protocol (SDP)</title>
          <author fullname="J. Rosenberg" initials="J."
          surname="Rosenberg">
            <organization></organization>
          </author>
          <author fullname="H. Schulzrinne" initials="H."
          surname="Schulzrinne">
            <organization></organization>
          </author>
          <date month="June" year="2002" />
        </front>
        <seriesInfo name="RFC" value="3264" />
        <format octets="60854"
        target="http://www.rfc-editor.org/rfc/rfc3264.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC4566">
        <front>
          <title>SDP: Session Description Protocol</title>
          <author fullname="M. Handley" initials="M."
          surname="Handley">
            <organization></organization>
          </author>
          <author fullname="V. Jacobson" initials="V."
          surname="Jacobson">
            <organization></organization>
          </author>
          <author fullname="C. Perkins" initials="C."
          surname="Perkins">
            <organization></organization>
          </author>
          <date month="July" year="2006" />
        </front>
        <seriesInfo name="RFC" value="4566" />
        <format octets="108820"
        target="http://www.rfc-editor.org/rfc/rfc4566.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC3605">
        <front>
          <title>Real Time Control Protocol (RTCP) attribute in Session
          Description Protocol (SDP)</title>
          <author initials="C." surname="Huitema"
          fullname="C. Huitema">
            <organization />
          </author>
          <date year="2003" month="October" />
        </front>
        <seriesInfo name="RFC" value="3605" />
        <format type="TXT" octets="17270"
        target="http://www.rfc-editor.org/rfc/rfc3605.txt" />
      </reference>
      <reference anchor="I-D.ietf-rtcweb-fec">
        <front>
          <title>WebRTC Forward Error Correction Requirements</title>
          <author initials="J" surname="Uberti"
          fullname="Justin Uberti">
            <organization />
          </author>
          <date month="February" day="6" year="2015" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-rtcweb-fec-00" />
        <format type="TXT"
        target="http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-fec-00.txt" />
      </reference>
      <reference anchor='RFC6347'>
        <front>
          <title>Datagram Transport Layer Security Version 1.2</title>
          <author initials='E.' surname='Rescorla'
          fullname='E. Rescorla'>
            <organization />
          </author>
          <author initials='N.' surname='Modadugu'
          fullname='N. Modadugu'>
            <organization />
          </author>
          <date year='2012' month='January' />
        </front>
        <seriesInfo name='RFC' value='6347' />
        <format type='TXT' octets='73546'
        target='http://www.rfc-editor.org/rfc/rfc6347.txt' />
      </reference>
      <reference anchor="I-D.ietf-ice-trickle">
        <front>
          <title abbrev='Trickle ICE'>Trickle ICE: Incremental
          Provisioning of Candidates for the Interactive Connectivity
          Establishment (ICE) Protocol</title>
          <author initials='E.' surname='Ivov' fullname='Emil Ivov'>
            <organization abbrev='Jitsi'>Jitsi</organization>
            <address>
              <postal>
                <street></street>
                <city>Strasbourg</city>
                <code>67000</code>
                <country>France</country>
              </postal>
              <phone>+33 6 72 81 15 55</phone>
              <email>emcho@jitsi.org</email>
            </address>
          </author>
          <author fullname="Eric Rescorla" initials="E.K."
          surname="Rescorla">
            <organization>RTFM, Inc.</organization>
            <address>
              <postal>
                <street>2064 Edgewood Drive</street>
                <city>Palo Alto</city>
                <region>CA</region>
                <code>94303</code>
                <country>USA</country>
              </postal>
              <phone>+1 650 678 2350</phone>
              <email>ekr@rtfm.com</email>
            </address>
          </author>
          <author fullname="Justin Uberti" initials="J."
          surname="Uberti">
            <organization>Google</organization>
            <address>
              <postal>
                <street>747 6th St S</street>
                <city>Kirkland</city>
                <region>WA</region>
                <code>98033</code>
                <country>USA</country>
              </postal>
              <phone>+1 857 288 8888</phone>
              <email>justin@uberti.name</email>
            </address>
          </author>
          <author initials="P." surname="Saint-Andre"
          fullname="Peter Saint-Andre">
            <organization>&amp;yet</organization>
            <address>
              <email>peter@andyet.com</email>
              <uri>https://andyet.com/</uri>
            </address>
          </author>
          <date />
        </front>
      </reference>
      <reference anchor="RFC6236">
        <front>
          <title>Negotiation of Generic Image Attributes in the Session
          Description Protocol (SDP)</title>
          <author initials="I." surname="Johansson"
          fullname="I. Johansson">
            <organization />
          </author>
          <author initials="K." surname="Jung" fullname="K. Jung">
            <organization />
          </author>
          <date year="2011" month="May" />
        </front>
        <seriesInfo name="RFC" value="6236" />
        <format type="TXT" octets="49356"
        target="http://www.rfc-editor.org/rfc/rfc6236.txt" />
      </reference>
      <reference anchor="I-D.ietf-mmusic-sdp-simulcast">
        <front>
          <title>Using Simulcast in SDP and RTP Sessions</title>
          <author initials="B" surname="Burman" fullname="Bo Burman">
            <organization />
          </author>
          <author initials="M" surname="Westerlund"
          fullname="Magnus Westerlund">
            <organization />
          </author>
          <author initials="S" surname="Nandakumar"
          fullname="Suhas Nandakumar">
            <organization />
          </author>
          <author initials="M" surname="Zanaty" fullname="Mo Zanaty">
            <organization />
          </author>
          <date month="February" day="3" year="2016" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-mmusic-sdp-simulcast-04" />
        <format type="TXT"
        target="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-sdp-simulcast-04.txt" />
      </reference>
      <reference anchor="I-D.ietf-mmusic-rid">
        <front>
          <title>RTP Payload Format Constraints</title>
          <author initials="P" surname="Thatcher"
          fullname="Peter Thatcher">
            <organization />
          </author>
          <author initials="M" surname="Zanaty" fullname="Mo Zanaty">
            <organization />
          </author>
          <author initials="S" surname="Nandakumar"
          fullname="Suhas Nandakumar">
            <organization />
          </author>
          <author initials="B" surname="Burman" fullname="Bo Burman">
            <organization />
          </author>
          <author initials="A" surname="Roach" fullname="Adam Roach">
            <organization />
          </author>
          <author initials="B" surname="Campen"
          fullname="Byron Campen">
            <organization />
          </author>
          <date month="February" day="8" year="2016" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-mmusic-rid-04" />
        <format type="TXT"
        target="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-rid-04.txt" />
      </reference>
      <reference anchor="I-D.ietf-avtext-rid">
        <front>
          <title>RTP Stream Identifier (RID) Source Description
          (SDES)</title>
          <author initials="A" surname="Roach" fullname="Adam Roach">
            <organization />
          </author>
          <author initials="S" surname="Nandakumar"
          fullname="Suhas Nandakumar">
            <organization />
          </author>
          <author initials="P" surname="Thatcher"
          fullname="Peter Thatcher">
            <organization />
          </author>
          <date month="February" day="18" year="2016" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-ietf-avtext-rid-00" />
        <format type="TXT"
        target="http://www.ietf.org/internet-drafts/draft-ietf-avtext-rid-00.txt" />
      </reference>
      <reference anchor='I-D.ietf-mmusic-mux-exclusive'>
        <front>
          <title>Indicating Exclusive Support of RTP/RTCP Multiplexing
          using SDP</title>
          <author initials='C' surname='Holmberg'
          fullname='Christer Holmberg'>
            <organization />
          </author>
          <date month='June' day='22' year='2016' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-mmusic-mux-exclusive-08' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-mmusic-mux-exclusive-08.txt' />
      </reference>
      <reference anchor='I-D.ietf-mmusic-4572-update'>
        <front>
          <title>Updates to RFC 4572</title>
          <author initials='C' surname='Holmberg'
          fullname='Christer Holmberg'>
            <organization />
          </author>
          <date month='June' day='10' year='2016' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-mmusic-4572-update-05' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-mmusic-4572-update-05.txt' />
      </reference>
      <reference anchor="I-D.ietf-mmusic-dtls-sdp">
        <front>
          <title>Using the SDP Offer/Answer Mechanism for DTLS</title>

          <author initials="C" surname="Holmberg" fullname="Christer Holmberg">
            <organization/>
          </author>

          <author initials="R" surname="Shpount" fullname="Roman Shpount">
            <organization/>
          </author>

          <date month="July" day="18" year="2016"/>

          <abstract><t>This draft defines the SDP offer/answer procedures for negotiating and establishing a DTLS association.  The draft also defines the criteria for when a new DTLS association must be established.  The draft updates RFC 5763 and RFC 7345, by replacing common SDP offer/ answer procedures with a reference to this specification.  This draft defines a new SDP media-level attribute, 'dtls-id'.</t></abstract>

        </front>

        <seriesInfo name="Internet-Draft" value="draft-ietf-mmusic-dtls-sdp-14"/>
        <format type="TXT" target="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-dtls-sdp-14.txt"/>
      </reference>
    </references>
    <references title="Informative References">
      <!-- INFORM 1 -->
      <reference anchor="RFC3556">
        <front>
          <title>Session Description Protocol (SDP) Bandwidth Modifiers
          for RTP Control Protocol (RTCP) Bandwidth</title>
          <author fullname="S. Casner" initials="S." surname="Casner">
            <organization></organization>
          </author>
          <date month="July" year="2003" />
        </front>
        <seriesInfo name="RFC" value="3556" />
        <format octets="15310"
        target="http://www.rfc-editor.org/rfc/rfc3556.txt"
        type="TXT" />
      </reference>
      <reference anchor="RFC5576">
        <front>
          <title>Source-Specific Media Attributes in the Session
          Description Protocol (SDP)</title>
          <author fullname="J. Lennox" initials="J." surname="Lennox">
            <organization></organization>
          </author>
          <author fullname="J. Ott" initials="J." surname="Ott">
            <organization></organization>
          </author>
          <author fullname="T. Schierl" initials="T."
          surname="Schierl">
            <organization></organization>
          </author>
          <date month="June" year="2009" />
        </front>
        <seriesInfo name="RFC" value="5576" />
        <format octets="40454"
        target="http://www.rfc-editor.org/rfc/rfc5576.txt"
        type="TXT" />
      </reference>
      <!--
          <reference anchor="RFC5956">
        <front>
          <title>Forward Error Correction Grouping Semantics in the
          Session Description Protocol</title>
          <author initials="A." surname="Begen" fullname="A. Begen">
            <organization />
          </author>
          <date year="2010" month="September" />
        </front>
        <seriesInfo name="RFC" value="5956" />
        <format type="TXT" octets="29530"
        target="http://www.rfc-editor.org/rfc/rfc5956.txt" />
      </reference>
      -->
      <reference anchor="RFC5506">
        <front>
          <title>Support for Reduced-Size Real-Time Transport Control
          Protocol (RTCP): Opportunities and Consequences</title>
          <author fullname="I. Johansson" initials="I."
          surname="Johansson">
            <organization></organization>
          </author>
          <author fullname="M. Westerlund" initials="M."
          surname="Westerlund">
            <organization></organization>
          </author>
          <date month="April" year="2009" />
        </front>
        <seriesInfo name="RFC" value="5506" />
        <format octets="41011"
        target="http://www.rfc-editor.org/rfc/rfc5506.txt"
        type="TXT" />
      </reference>
      <!-- INFORM 2 -->
      <reference anchor='RFC6464'
      target='http://www.rfc-editor.org/info/rfc6464'>
        <front>
          <title>A Real-time Transport Protocol (RTP) Header Extension
          for Client-to-Mixer Audio Level Indication</title>
          <author initials='J.' surname='Lennox' fullname='J. Lennox'
          role='editor'>
            <organization />
          </author>
          <author initials='E.' surname='Ivov' fullname='E. Ivov'>
            <organization />
          </author>
          <author initials='E.' surname='Marocco'
          fullname='E. Marocco'>
            <organization />
          </author>
          <date year='2011' month='December' />
        </front>
        <seriesInfo name='RFC' value='6464' />
        <seriesInfo name='DOI' value='10.17487/RFC6464' />
      </reference>
      <!-- INFORM 3 -->
      <!-- INFORM 4 -->
      <reference anchor="RFC3960">
        <front>
          <title>Early Media and Ringing Tone Generation in the Session
          Initiation Protocol (SIP)</title>
          <author fullname="G. Camarillo" initials="G."
          surname="Camarillo">
            <organization></organization>
          </author>
          <author fullname="H. Schulzrinne" initials="H."
          surname="Schulzrinne">
            <organization></organization>
          </author>
          <date month="December" year="2004" />
        </front>
        <seriesInfo name="RFC" value="3960" />
        <format octets="31692"
        target="http://www.rfc-editor.org/rfc/rfc3960.txt"
        type="TXT" />
      </reference>
      <!-- INFORM 5 -->
      <!-- INFORM 6 -->
      <reference anchor="RFC4588">
        <front>
          <title>RTP Retransmission Payload Format</title>
          <author fullname="J. Rey" initials="J." surname="Rey">
            <organization></organization>
          </author>
          <author fullname="D. Leon" initials="D." surname="Leon">
            <organization></organization>
          </author>
          <author fullname="A. Miyazaki" initials="A."
          surname="Miyazaki">
            <organization></organization>
          </author>
          <author fullname="V. Varsa" initials="V." surname="Varsa">
            <organization></organization>
          </author>
          <author fullname="R. Hakenberg" initials="R."
          surname="Hakenberg">
            <organization></organization>
          </author>
          <date month="July" year="2006" />
        </front>
        <seriesInfo name="RFC" value="4588" />
        <format octets="76630"
        target="http://www.rfc-editor.org/rfc/rfc4588.txt"
        type="TXT" />
      </reference>
      <!-- INFORM 7 -->
      <reference anchor="RFC3389">
        <front>
          <title>Real-time Transport Protocol (RTP) Payload for Comfort
          Noise (CN)</title>
          <author fullname="R. Zopf" initials="R." surname="Zopf">
            <organization></organization>
          </author>
          <date month="September" year="2002" />
        </front>
        <seriesInfo name="RFC" value="3389" />
        <format octets="17018"
        target="http://www.rfc-editor.org/rfc/rfc3389.txt"
        type="TXT" />
      </reference>
      <!-- INFORM 8 -->
      <!-- INFORM 9 -->
      <!-- INFORM 10 -->
      <!-- INFORM 11 -->
      <!-- INFORM 12 -->
      <!-- INFORM 13 -->
      <!-- INFORM 14 -->
      <!-- INFORM 15 -->
      <!-- INFORM 16 -->
      <reference anchor="I-D.nandakumar-rtcweb-sdp">
        <front>
          <title>SDP for the WebRTC</title>
          <author fullname="Suhas Nandakumar" initials="S"
          surname="Nandakumar">
            <organization></organization>
          </author>
          <author fullname="Cullen Jennings" initials="C"
          surname="Jennings">
            <organization></organization>
          </author>
          <date day="13" month="July" year="2013" />
        </front>
        <seriesInfo name="Internet-Draft"
        value="draft-nandakumar-rtcweb-sdp-02" />
        <format target="http://www.ietf.org/internet-drafts/draft-nandakumar-rtcweb-sdp-02.txt"
        type="TXT" />
        <format target="http://www.ietf.org/internet-drafts/draft-nandakumar-rtcweb-sdp-02.pdf"
        type="PDF" />
      </reference>
      <!-- INFORM 17 -->
      <reference anchor="RFC5763">
        <front>
          <title>Framework for Establishing a Secure Real-time
          Transport Protocol (SRTP) Security Context Using Datagram
          Transport Layer Security (DTLS)</title>
          <author fullname="J. Fischl" initials="J." surname="Fischl">
            <organization></organization>
          </author>
          <author fullname="H. Tschofenig" initials="H."
          surname="Tschofenig">
            <organization></organization>
          </author>
          <author fullname="E. Rescorla" initials="E."
          surname="Rescorla">
            <organization></organization>
          </author>
          <date month="May" year="2010" />
        </front>
        <seriesInfo name="RFC" value="5763" />
        <format octets="81546"
        target="http://www.rfc-editor.org/rfc/rfc5763.txt"
        type="TXT" />
      </reference>
      <reference anchor='RFC5764'>
        <front>
          <title>Datagram Transport Layer Security (DTLS) Extension to
          Establish Keys for the Secure Real-time Transport Protocol
          (SRTP)</title>
          <author initials='D.' surname='McGrew' fullname='D. McGrew'>
            <organization />
          </author>
          <author initials='E.' surname='Rescorla'
          fullname='E. Rescorla'>
            <organization />
          </author>
          <date year='2010' month='May' />
        </front>
        <seriesInfo name='RFC' value='5764' />
        <format type='TXT' octets='60590'
        target='http://www.rfc-editor.org/rfc/rfc5764.txt' />
      </reference>
      <reference anchor="RFC4568">
        <front>
          <title>Session Description Protocol (SDP) Security
          Descriptions for Media Streams</title>
          <author fullname="F. Andreasen" initials="F."
          surname="Andreasen">
            <organization></organization>
          </author>
          <author fullname="M. Baugher" initials="M."
          surname="Baugher">
            <organization></organization>
          </author>
          <author fullname="D. Wing" initials="D." surname="Wing">
            <organization></organization>
          </author>
          <date month="July" year="2006" />
        </front>
        <seriesInfo name="RFC" value="4568" />
        <format octets="107881"
        target="http://www.rfc-editor.org/rfc/rfc4568.txt"
        type="TXT" />
      </reference>
      <reference anchor="W3C.WD-webrtc-20140617"
      target="http://www.w3.org/TR/2011/WD-webrtc-20140617">
        <front>
          <title>WebRTC 1.0: Real-time Communication Between
          Browsers</title>
          <author fullname="Adam Bergkvist" initials="A."
          surname="Bergkvist">
            <organization></organization>
          </author>
          <author fullname="Daniel C. Burnett" initials="D."
          surname="Burnett">
            <organization></organization>
          </author>
          <author fullname="Anant Narayanan" initials="A."
          surname="Narayanan">
            <organization></organization>
          </author>
          <author fullname="Cullen Jennings" initials="C."
          surname="Jennings">
            <organization></organization>
          </author>
          <date day="17" month="June" year="2014" />
        </front>
        <seriesInfo name="World Wide Web Consortium WD"
        value="WD-webrtc-20140617" />
        <format target="http://www.w3.org/TR/2011/WD-webrtc-20140617"
        type="HTML" />
      </reference>
      <reference anchor='I-D.ietf-rtcweb-ip-handling'>
        <front>
          <title>WebRTC IP Address Handling Recommendations</title>
          <author initials='J' surname='Uberti'
          fullname='Justin Uberti'>
            <organization />
          </author>
          <author initials='G' surname='Shieh'
          fullname='Guo-wei Shieh'>
            <organization />
          </author>
          <date month='March' day='20' year='2016' />
        </front>
        <seriesInfo name='Internet-Draft'
        value='draft-ietf-rtcweb-ip-handling-01' />
        <format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-rtcweb-ip-handling-01.txt' />
      </reference>
      <reference  anchor='RFC4733' target='http://www.rfc-editor.org/info/rfc4733'>
        <front>
          <title>RTP Payload for DTMF Digits, Telephony Tones, and Telephony Signals</title>
          <author initials='H.' surname='Schulzrinne' fullname='H. Schulzrinne'><organization /></author>
          <author initials='T.' surname='Taylor' fullname='T. Taylor'><organization /></author>
          <date year='2006' month='December' />
        </front>
        <seriesInfo name='RFC' value='4733'/>
        <seriesInfo name='DOI' value='10.17487/RFC4733'/>
      </reference>
    </references>
    <section title="Appendix A" anchor="sec.appendix-a">

      <t>For the syntax validation performed in
      <xref target="sec.parsing-a-desc" />, the following list of ABNF
      definitions is used:</t>
      <texttable anchor="sdp-abnf" title="SDP ABNF References">
        <ttcol align='left'>Attribute</ttcol>
        <ttcol align='left'>Reference</ttcol>
        <c>ptime</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>maxptime</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>rtpmap</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>recvonly</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>sendrecv</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>sendonly</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>inactive</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>framerate</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>fmtp</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>quality</c>
        <c>
        <xref target="RFC4566" /> Section 9</c>
        <c>rtcp</c>
        <c>
        <xref target="RFC3605" /> Section 2.1</c>
        <c>setup</c>
        <c>
        <xref target="RFC4145" /> Sections 3, 4, and 5</c>
        <c>connection</c>
        <c>
        <xref target="RFC4145" /> Sections 3, 4, and 5</c>
        <c>fingerprint</c>
        <c>
        <xref target="RFC4572" /> Section 5</c>
        <c>rtcp-fb</c>
        <c>
        <xref target="RFC4585" /> Section 4.2</c>
        <c>candidate</c>
        <c>
        <xref target="RFC5245" /> Section 15.1</c>
        <c>remote-candidates</c>
        <c>
        <xref target="RFC5245" /> Section 15.2</c>
        <c>ice-lite</c>
        <c>
        <xref target="RFC5245" /> Section 15.3</c>
        <c>ice-ufrag</c>
        <c>
        <xref target="RFC5245" /> Section 15.4</c>
        <c>ice-pwd</c>
        <c>
        <xref target="RFC5245" /> Section 15.4</c>
        <c>ice-options</c>
        <c>
        <xref target="RFC5245" /> Section 15.5</c>
        <c>extmap</c>
        <c>
        <xref target="RFC5285" /> Section 7</c>
        <c>mid</c>
        <c>
        <xref target="RFC5888" /> Section 4 and 5</c>
        <c>group</c>
        <c>
        <xref target="RFC5888" /> Section 4 and 5</c>
        <c>imageattr</c>
        <c>
        <xref target="RFC6236" /> Section 3.1</c>
        <c>extmap (encrypt option)</c>
        <c>
        <xref target="RFC6904" /> Section 4</c>
        <c>msid</c>
        <c>
        <xref target="I-D.ietf-mmusic-msid" /> Section 2</c>
        <c>rid</c>
        <c>
        <xref target="I-D.ietf-mmusic-rid" /> Section 10 </c>
        <c>simulcast</c>
        <c>
        <xref target="I-D.ietf-mmusic-sdp-simulcast" />Section 6.1</c>
        <c>dtls-id</c>
        <c>
        <xref target="I-D.ietf-mmusic-dtls-sdp" />Section 4</c>
      </texttable>
    </section>
    <section title="Change log" anchor="sec.change-log">

      <t>Note: This section will be removed by RFC Editor before
      publication.</t>

      <t>Changes in draft-17:</t>

      <t>
        <list style="symbols">
          <t>Split createOffer and createAnswer sections to clearly indicate
            attributes which always appear and which only appear when
            not bundled into another m= section.</t>

          <t>Add descriptions of RtpTransceiver methods.</t>

          <t>Describe how to process RTCP feedback attributes.</t>

          <t>Clarify transceiver directions and their interaction with 3264.</t>

          <t>Describe setCodecPreferences.</t>

          <t>Update RTP demux algorithm. Include RTCP.</t>

          <t>Update requirements for when a=rtcp is included, limiting
          to cases where it is needed for backward compatibility.</t>

          <t>Clarify SAR handling.</t>

          <t>Updated addTrack matching algorithm.</t>

          <t>Remove a=ssrc requirements.</t>

          <t>Handle a=setup in reoffers.</t>

          <t>Discuss how RTX/FEC should be handled.</t>

          <t>Discuss how telephone-event should be handled.</t>

          <t>Discuss how CN/DTX should be handled.</t>

          <t>Add missing references to ABNF table.</t>

        </list>
      </t>
      <t>Changes in draft-16:</t>

      <t>
        <list style="symbols">

          <t>Update addIceCandidate to indicate ICE generation and
          allow per-m= section end-of-candidates.</t>

          <t>Update fingerprint handling to use
          draft-ietf-mmusic-4572-update.</t>

          <t>Update text around SDP processing of RTP header extensions
          and payload formats.</t>

          <t>Add sections on simulcast, addTransceiver, and
          createDataChannel.</t>

          <t>Clarify text to ensure that the session ID is a positive
          63 bit integer.</t>

          <t>Clarify SDP processing for direction indication.</t>

          <t>Describe SDP processing for rtcp-mux-only.</t>

          <t>Specify how SDP session version in o= line.</t>

          <t>Require that when doing an re-offer, the capabilities of
          the new session are mostly required to be a subset of the
          previously negotiated session.</t>

          <t>Clarified ICE restart interaction with bundle-only.</t>

          <t>Remove support for changing SDP before calling
          setLocalDescription.</t>

          <t>Specify algorithm for demuxing RTP based on MID, PT, and
          SSRC.</t>

          <t>Clarify rules for rejecting m= lines when bundle policy is
          balanced or max-bundle.</t>
        </list>
      </t>

      <t>Changes in draft-15:</t>

      <t>
        <list style="symbols">

          <t>Clarify text around codecs offered in subsequent
          transactions to refer to what's been negotiated.</t>

          <t>Rewrite LS handling text to indicate edge cases and that
          we're living with them.</t>

          <t>Require that answerer reject m= lines when there are no
          codecs in common.</t>

          <t>Enforce max-bundle on offer processing.</t>

          <t>Fix TIAS formula to handle bits vs. kilobits.</t>

          <t>Describe addTrack algorithm.</t>

          <t>Clean up references.</t>
        </list>
      </t>

      <t>Changes in draft-14:</t>

      <t>
        <list style="symbols">

          <t>Added discussion of RtpTransceivers + RtpSenders +
          RtpReceivers, and how they interact with
          createOffer/createAnswer.</t>

          <t>Removed obsolete OfferToReceiveX options.</t>

          <t>Explained how addIceCandidate can be used for
          end-of-candidates.</t>
        </list>
      </t>

      <t>Changes in draft-13:</t>

      <t>
        <list style="symbols">

          <t>Clarified which SDP lines can be ignored.</t>

          <t>Clarified how to handle various received attributes.</t>

          <t>Revised how attributes should be generated for bundled m=
          lines.</t>

          <t>Remove unused references.</t>

          <t>Remove text advocating use of unilateral PTs.</t>

          <t>Trigger an ICE restart even if the ICE candidate policy is
          being made more strict.</t>

          <t>Remove the 'public' ICE candidate policy.</t>

          <t>Move open issues/TODOs into GitHub issues.</t>

          <t>Split local/remote description accessors into
          current/pending.</t>

          <t>Clarify a=imageattr handling.</t>

          <t>Add more detail on VoiceActivityDetection handling.</t>

          <t>Reference draft-shieh-rtcweb-ip-handling.</t>

          <t>Make it clear when an ICE restart should occur.</t>

          <t>Resolve reference TODOs.</t>

          <t>Remove MSID semantics.</t>

          <t>ice-options are now at session level.</t>

          <t>Default RTCP mux policy is now 'require'.</t>
        </list>
      </t>

      <t>Changes in draft-12:</t>

      <t>
        <list style="symbols">

          <t>Filled in sections on applying local and remote
          descriptions.</t>

          <t>Discussed downscaling and upscaling to fulfill imageattr
          requirements.</t>

          <t>Updated what SDP can be modified by the application.</t>

          <t>Updated to latest datachannel SDP.</t>

          <t>Allowed multiple fingerprint lines.</t>

          <t>Switched back to IPv4 for dummy candidates.</t>

          <t>Added additional clarity on ICE default candidates.</t>
        </list>
      </t>

      <t>Changes in draft-11:</t>

      <t>
        <list style="symbols">

          <t>Clarified handling of RTP CNAMEs.</t>

          <t>Updated what SDP lines should be processed or ignored.</t>

          <t>Specified how a=imageattr should be used.</t>
        </list>
      </t>

      <t>Changes in draft-10:</t>

      <t>
        <list style="symbols">

          <t>TODO</t>
        </list>
      </t>

      <t>Changes in draft-09:</t>

      <t>
        <list style="symbols">

          <t>Don't return null for {local,remote}Description after
          close().</t>

          <t>Changed TCP/TLS to UDP/DTLS in RTP profile names.</t>

          <t>Separate out bundle and mux policy.</t>

          <t>Added specific references to FEC mechanisms.</t>

          <t>Added canTrickle mechanism.</t>

          <t>Added section on subsequent answers and, answer
          options.</t>

          <t>Added text defining set{Local,Remote}Description
          behavior.</t>
        </list>
      </t>

      <t>Changes in draft-08:
      <list style="symbols">

        <t>Added new example section and removed old examples in
        appendix.</t>

        <t>Fixed &lt;proto&gt; field handling.</t>

        <t>Added text describing a=rtcp attribute.</t>

        <t>Reworked handling of OfferToReceiveAudio and
        OfferToReceiveVideo per discussion at IETF 90.</t>

        <t>Reworked trickle ICE handling and its impact on m= and c=
        lines per discussion at interim.</t>

        <t>Added max-bundle-and-rtcp-mux policy.</t>

        <t>Added description of maxptime handling.</t>

        <t>Updated ICE candidate pool default to 0.</t>

        <t>Resolved open issues around AppID/receiver-ID.</t>

        <t>Reworked and expanded how changes to the ICE configuration
        are handled.</t>

        <t>Some reference updates.</t>

        <t>Editorial clarification.</t>
      </list></t>

      <t>Changes in draft-07:
      <list style="symbols">

        <t>Expanded discussion of VAD and Opus DTX.</t>

        <t>Added a security considerations section.</t>

        <t>Rewrote the section on modifying SDP to require
        implementations to clearly indicate whether any given
        modification is allowed.</t>

        <t>Clarified impact of IceRestart on CreateOffer in local-offer
        state.</t>

        <t>Guidance on whether attributes should be defined at the
        media level or the session level.</t>

        <t>Renamed "default" bundle policy to "balanced".</t>

        <t>Removed default ICE candidate pool size and clarify how it
        works.</t>

        <t>Defined a canonical order for assignment of MSTs to m=
        lines.</t>

        <t>Removed discussion of rehydration.</t>

        <t>Added Eric Rescorla as a draft editor.</t>

        <t>Cleaned up references.</t>

        <t>Editorial cleanup</t>
      </list></t>

      <t>Changes in draft-06:
      <list style="symbols">

        <t>Reworked handling of m= line recycling.</t>

        <t>Added handling of BUNDLE and bundle-only.</t>

        <t>Clarified handling of rollback.</t>

        <t>Added text describing the ICE Candidate Pool and its
        behavior.</t>

        <t>Allowed OfferToReceiveX to create multiple recvonly m=
        sections.</t>
      </list></t>

      <t>Changes in draft-05:
      <list style="symbols">

        <t>Fixed several issues identified in the createOffer/Answer
        sections during document review.</t>

        <t>Updated references.</t>
      </list></t>

      <t>Changes in draft-04:
      <list style="symbols">

        <t>Filled in sections on createOffer and createAnswer.</t>

        <t>Added SDP examples.</t>

        <t>Fixed references.</t>
      </list></t>

      <t>Changes in draft-03:
      <list style="symbols">

        <t>Added text describing relationship to W3C specification</t>
      </list></t>

      <t>Changes in draft-02:
      <list style="symbols">
        <!-- A -->

        <t>Converted from nroff</t>
        <!-- B -->

        <t>Removed comparisons to old approaches abandoned by the
        working group</t>
        <!-- C -->

        <t>Removed stuff that has moved to W3C specification</t>
        <!-- D -->

        <t>Align SDP handling with W3C draft</t>
        <!-- E -->

        <t>Clarified section on forking.</t>
        <!-- F -->
        <!-- G -->
        <!-- H -->
        <!-- I -->
        <!-- J -->
        <!-- K -->
        <!-- L -->
      </list></t>

      <t>Changes in draft-01:
      <list style="symbols">

        <t>Added diagrams for architecture and state machine.</t>

        <t>Added sections on forking and rehydration.</t>

        <t>Clarified meaning of "pranswer" and "answer".</t>

        <t>Reworked how ICE restarts and media directions are
        controlled.</t>

        <t>Added list of parameters that can be changed in a
        description.</t>

        <t>Updated suggested API and examples to match latest
        thinking.</t>

        <t>Suggested API and examples have been moved to an
        appendix.</t>
      </list></t>

      <t>Changes in draft -00:
      <list style="symbols">

        <t>Migrated from draft-uberti-rtcweb-jsep-02.</t>
      </list></t>
    </section>
  </back>
</rfc>
