Add x-mt line to the offer.

We already support decoding of the x-mt line. This change adds the
a=x-mt line to the SDP offer. This is not a backward compatible change
for media transport (because of the changes in pre-shared key handling)

1) if media transport is enabled, and SDES is enabled, generate the
media transport offer.
2) if media transport generated the offer, add that offer to the x-mt
line.
3) in order to create media transport, require an x-mt line (backward incompatible).

The way it works is that
1) PeerConnection, on the offerer, asks jsep transport for the
configuration of the media transport.
2) Tentative media transport is created in JsepTransportController when
that happens.
3) SessionDescription will include configuration from this tentative
media transport.
4) When the LocalDescription is set on the offerer, the tentative media
transport is promoted to the real media transport.

Caveats:
- now we really only support MaxBundle. In the previous implementations,
two media transports were briefly created in some tests, and the second
one was destroyed shortly after instantiation.
- we, for now, enforce SDES. In the future, whether SDES is used will be
refactored out of the peer connection.

In the future (on the callee) we should ignore 'is_media_transport' setting. If
Offer contains x-mt, media transport should be used (if the factory is
present). However, we need to decide how to negotiate media transport
for data channels vs data transport for media (x-mt line at this point
doesn't differentiate the two, so we still need to use app setting).

This change also removes the negotation of pre-shared key from the
a=crypto line. Instead, media transport will have its own, 256bit key.
Such key should be transported in the x-mt line. This makes the code
much simpler, and simplifies the dependency / a=crypto lines parsing.

Also, adds a proper test for the connection re-offer (on both sides: callee and caller).
Before, it was possible that media transport could get recreated, based on the offer.
The tests we had didn't test this scenario, and the loopback media factory didn't allow for such test.
This change adds counts to that loopback media factory, and asserts that only 1 media transport is created, even
when there is a re-offer.

Bug: webrtc:9719
Change-Id: Ibd8739af90e914da40ab412454bba8e1529f5a01
Reviewed-on: https://webrtc-review.googlesource.com/c/125040
Reviewed-by: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Peter Slatala <psla@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26933}
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h
index c98ff25..537b2b1 100644
--- a/pc/jsep_transport_controller.h
+++ b/pc/jsep_transport_controller.h
@@ -188,6 +188,13 @@
   void SetMediaTransportSettings(bool use_media_transport_for_media,
                                  bool use_media_transport_for_data_channels);
 
+  // If media transport is present enabled and supported,
+  // when this method is called, it creates a media transport and generates its
+  // offer. The new offer is then returned, and the created media transport will
+  // subsequently be used.
+  absl::optional<cricket::SessionDescription::MediaTransportSetting>
+  GenerateOrGetLastMediaTransportOffer();
+
   // All of these signals are fired on the signaling thread.
 
   // If any transport failed => failed,
@@ -288,14 +295,15 @@
       const cricket::ContentInfo& content_info,
       const cricket::SessionDescription& description);
 
-  // Creates media transport if config wants to use it, and pre-shared key is
-  // provided in content info. It modifies the config to disable media transport
-  // if pre-shared key is not provided.
+  // Creates media transport if config wants to use it, and a=x-mt line is
+  // present for the current media transport. Returned MediaTransportInterface
+  // is not connected, and must be connected to ICE. You must call
+  // |GenerateOrGetLastMediaTransportOffer| on the caller before calling
+  // MaybeCreateMediaTransport.
   std::unique_ptr<webrtc::MediaTransportInterface> MaybeCreateMediaTransport(
       const cricket::ContentInfo& content_info,
       const cricket::SessionDescription& description,
-      bool local,
-      cricket::IceTransportInternal* ice_transport);
+      bool local);
   void MaybeDestroyJsepTransport(const std::string& mid);
   void DestroyAllJsepTransports_n();
 
@@ -377,6 +385,35 @@
   // (the factory needs to be provided in the config, and config must allow for
   // media transport).
   bool is_media_transport_factory_enabled_ = true;
+
+  // Early on in the call we don't know if media transport is going to be used,
+  // but we need to get the server-supported parameters to add to an SDP.
+  // This server media transport will be promoted to the used media transport
+  // after the local description is set, and the ownership will be transferred
+  // to the actual JsepTransport.
+  // This "offer" media transport is not created if it's done on the party that
+  // provides answer. This offer media transport is only created once at the
+  // beginning of the connection, and never again.
+  std::unique_ptr<MediaTransportInterface> offer_media_transport_ = nullptr;
+
+  // Contains the offer of the |offer_media_transport_|, in case if it needs to
+  // be repeated.
+  absl::optional<cricket::SessionDescription::MediaTransportSetting>
+      media_transport_offer_settings_;
+
+  // When the new offer is regenerated (due to upgrade), we don't want to
+  // re-create media transport. New streams might be created; but media
+  // transport stays the same. This flag prevents re-creation of the transport
+  // on the offerer.
+  // The first media transport is created in jsep transport controller as the
+  // |offer_media_transport_|, and then the ownership is moved to the
+  // appropriate JsepTransport, at which point |offer_media_transport_| is
+  // zeroed out. On the callee (answerer), the first media transport is not even
+  // assigned to |offer_media_transport_|. Both offerer and answerer can
+  // recreate the Offer (e.g. after adding streams in Plan B), and so we want to
+  // prevent recreation of the media transport when that happens.
+  bool media_transport_created_once_ = false;
+
   const cricket::SessionDescription* local_desc_ = nullptr;
   const cricket::SessionDescription* remote_desc_ = nullptr;
   absl::optional<bool> initial_offerer_;