Add an alt-protocol to SDP to indicate which m= sections use a plugin transport.

The plugin transport parameters (a=x-opaque: lines) relate to how to create and
set up a plugin transport.  When SDP bundle is used, the x-opaque line needs to
be copied into the bundled m= section.  This means x-opaque can appear on a
section even if the offerer does not intend to use the transport for the media
described by that section.  Consequently, the answerer cannot currently tell
whether the caller is offering an alternate transport for media, data, or both.

This change adds an a=x-alt-protocol: line to SDP.  The value following this
line matches the <protocol> part of the x-opaque:<protocol>:<params> line.
However, alt-protocol is not bundled--it only ever applies to the m= section
that contains the line.  This allows the offerer to express which m= sections
should actually use an alternate transport, even in the case of bundle.

Note that this is still limited by the available configuration options:
datagram transport can be used for media (audio + video) and/or data.  It is
still not possible to use it for audio but not video, or vice versa.

PeerConnection places an alt-protocol line in each media (audio/video) m=
section if it is configured to use a datagram transport for media.  It places
an alt-protocol line in each data m= section if it is configured to use a
datagram transport for data channels.  PeerConnection leaves alt-protocol in
media (audio/video) m= sections of the answer if it is configured to use a
datagram transport for media, and in data m= sections of the answer if it is
configured to use a datagram transport for data channels.

JsepTransport now negotiates use of the datagram transport independently for
media and data channels.  It only uses it for media if the m= sections for
bundled audio/video have an alt-protocol line matching the x-opaque protocol,
and only uses it for data channels if a bundled m= section for data has an
alt-protocol line matching the x-opaque protocol.

Bug: webrtc:9719
Change-Id: I773e4fc10c57d815afcd76a2a74da38dd0c52b3b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/154763
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Seth Hampson <shampson@webrtc.org>
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29351}
diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc
index ad8fb7e..7a42dca 100644
--- a/pc/webrtc_sdp.cc
+++ b/pc/webrtc_sdp.cc
@@ -239,6 +239,9 @@
 // This is a non-standardized setting for plugin transports.
 static const char kOpaqueTransportParametersLine[] = "x-opaque";
 
+// This is a non-standardized setting for plugin transports.
+static const char kAltProtocolLine[] = "x-alt-protocol";
+
 // RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload
 // types.
 const int kWildcardPayloadType = -1;
@@ -549,6 +552,14 @@
   AddLine(os.str(), message);
 }
 
+static void AddAltProtocolLine(const std::string& protocol,
+                               std::string* message) {
+  rtc::StringBuilder os;
+  InitAttrLine(kAltProtocolLine, &os);
+  os << kSdpDelimiterColon << protocol;
+  AddLine(os.str(), message);
+}
+
 // Writes a SDP attribute line based on |attribute| and |value| to |message|.
 static void AddAttributeLine(const std::string& attribute,
                              int value,
@@ -1540,6 +1551,10 @@
     }
   }
 
+  if (media_desc->alt_protocol()) {
+    AddAltProtocolLine(*media_desc->alt_protocol(), message);
+  }
+
   // RFC 3388
   // mid-attribute      = "a=mid:" identification-tag
   // identification-tag = token
@@ -2149,6 +2164,12 @@
   return true;
 }
 
+bool ParseAltProtocolLine(const std::string& line,
+                          std::string* protocol,
+                          SdpParseError* error) {
+  return GetValue(line, kAltProtocolLine, protocol, error);
+}
+
 bool ParseSessionDescription(const std::string& message,
                              size_t* pos,
                              std::string* session_id,
@@ -3180,6 +3201,12 @@
               &transport->opaque_parameters->parameters, error)) {
         return false;
       }
+    } else if (HasAttribute(line, kAltProtocolLine)) {
+      std::string alt_protocol;
+      if (!ParseAltProtocolLine(line, &alt_protocol, error)) {
+        return false;
+      }
+      media_desc->set_alt_protocol(alt_protocol);
     } else if (HasAttribute(line, kAttributeFmtp)) {
       if (!ParseFmtpAttributes(line, media_type, media_desc, error)) {
         return false;