Relanding: Adding support for Unified Plan offer/answer negotiation to the mediasession layer.

This layer takes in a simplified "options" struct and the current local description,
and generates a new offer/answer. Previously the options struct assumed there would
only be one media description per media type (audio/video), but it now supports
N number of audio/video descriptions.

The |add_legacy_stream| options is removed from the mediasession.cc/.h
in this CL.

The next step is to add the ability for PeerConnection/WebRtcSession to create
"options" to represent multiple RtpTransceivers, and apply the Unified Plan
descriptions correctly. Right now, only Plan B descriptions will be
generated in unit tests.

BUG=chromium:465349

Review-Url: https://codereview.webrtc.org/2991693002
Cr-Original-Commit-Position: refs/heads/master@{#19343}
Committed: https://chromium.googlesource.com/external/webrtc/+/a77e6bbd30276bdc5b30f2cbc1e92ca181ae76f0
Review-Url: https://codereview.webrtc.org/2991693002
Cr-Commit-Position: refs/heads/master@{#19394}
diff --git a/webrtc/pc/mediasession.h b/webrtc/pc/mediasession.h
index 596bd18..35bd444 100644
--- a/webrtc/pc/mediasession.h
+++ b/webrtc/pc/mediasession.h
@@ -102,83 +102,72 @@
 NegotiateRtpTransceiverDirection(RtpTransceiverDirection offer,
                                  RtpTransceiverDirection wants);
 
-struct MediaSessionOptions {
-  MediaSessionOptions()
-      : recv_audio(true),
-        recv_video(false),
-        data_channel_type(DCT_NONE),
-        is_muc(false),
-        vad_enabled(true),  // When disabled, removes all CN codecs from SDP.
-        rtcp_mux_enabled(true),
-        bundle_enabled(false),
-        video_bandwidth(kAutoBandwidth),
-        data_bandwidth(kDataMaxBandwidth),
-        rtcp_cname(kDefaultRtcpCname) {}
+// Options for an RtpSender contained with an media description/"m=" section.
+struct SenderOptions {
+  std::string track_id;
+  std::string stream_id;
+  int num_sim_layers;
+};
 
-  bool has_audio() const {
-    return recv_audio || HasSendMediaStream(MEDIA_TYPE_AUDIO);
-  }
-  bool has_video() const {
-    return recv_video || HasSendMediaStream(MEDIA_TYPE_VIDEO);
-  }
-  bool has_data() const { return data_channel_type != DCT_NONE; }
+// Options for an individual media description/"m=" section.
+struct MediaDescriptionOptions {
+  MediaDescriptionOptions(MediaType type,
+                          const std::string& mid,
+                          RtpTransceiverDirection direction,
+                          bool stopped)
+      : type(type), mid(mid), direction(direction), stopped(stopped) {}
 
-  // Add a stream with MediaType type and id.
-  // All streams with the same sync_label will get the same CNAME.
-  // All ids must be unique.
-  void AddSendStream(MediaType type,
-                 const std::string& id,
-                 const std::string& sync_label);
-  void AddSendVideoStream(const std::string& id,
-                      const std::string& sync_label,
+  // TODO(deadbeef): When we don't support Plan B, there will only be one
+  // sender per media description and this can be simplified.
+  void AddAudioSender(const std::string& track_id,
+                      const std::string& stream_id);
+  void AddVideoSender(const std::string& track_id,
+                      const std::string& stream_id,
                       int num_sim_layers);
-  void RemoveSendStream(MediaType type, const std::string& id);
 
+  // Internally just uses sender_options.
+  void AddRtpDataChannel(const std::string& track_id,
+                         const std::string& stream_id);
 
-  // Helper function.
-  void AddSendStreamInternal(MediaType type,
-                         const std::string& id,
-                         const std::string& sync_label,
+  MediaType type;
+  std::string mid;
+  RtpTransceiverDirection direction;
+  bool stopped;
+  TransportOptions transport_options;
+  // Note: There's no equivalent "RtpReceiverOptions" because only send
+  // stream information goes in the local descriptions.
+  std::vector<SenderOptions> sender_options;
+
+ private:
+  // Doesn't DCHECK on |type|.
+  void AddSenderInternal(const std::string& track_id,
+                         const std::string& stream_id,
                          int num_sim_layers);
+};
 
-  bool HasSendMediaStream(MediaType type) const;
+// Provides a mechanism for describing how m= sections should be generated.
+// The m= section with index X will use media_description_options[X]. There
+// must be an option for each existing section if creating an answer, or a
+// subsequent offer.
+struct MediaSessionOptions {
+  MediaSessionOptions() {}
 
-  // TODO(deadbeef): Put all the audio/video/data-specific options into a map
-  // structure (content name -> options).
-  // MediaSessionDescriptionFactory assumes there will never be more than one
-  // audio/video/data content, but this will change with unified plan.
-  bool recv_audio;
-  bool recv_video;
-  DataChannelType data_channel_type;
-  bool is_muc;
-  bool vad_enabled;
-  bool rtcp_mux_enabled;
-  bool bundle_enabled;
-  // bps. -1 == auto.
-  int video_bandwidth;
-  int data_bandwidth;
-  bool enable_ice_renomination = false;
-  // content name ("mid") => options.
-  std::map<std::string, TransportOptions> transport_options;
-  std::string rtcp_cname;
+  bool has_audio() const { return HasMediaDescription(MEDIA_TYPE_AUDIO); }
+  bool has_video() const { return HasMediaDescription(MEDIA_TYPE_VIDEO); }
+  bool has_data() const { return HasMediaDescription(MEDIA_TYPE_DATA); }
+
+  bool HasMediaDescription(MediaType type) const;
+
+  DataChannelType data_channel_type = DCT_NONE;
+  bool is_muc = false;
+  bool vad_enabled = true;  // When disabled, removes all CN codecs from SDP.
+  bool rtcp_mux_enabled = true;
+  bool bundle_enabled = false;
+  std::string rtcp_cname = kDefaultRtcpCname;
   rtc::CryptoOptions crypto_options;
-
-  struct Stream {
-    Stream(MediaType type,
-           const std::string& id,
-           const std::string& sync_label,
-           int num_sim_layers)
-        : type(type), id(id), sync_label(sync_label),
-          num_sim_layers(num_sim_layers) {
-    }
-    MediaType type;
-    std::string id;
-    std::string sync_label;
-    int num_sim_layers;
-  };
-
-  typedef std::vector<Stream> Streams;
-  Streams streams;
+  // List of media description options in the same order that the media
+  // descriptions will be generated.
+  std::vector<MediaDescriptionOptions> media_description_options;
 };
 
 // "content" (as used in XEP-0166) descriptions for voice and video.
@@ -277,7 +266,6 @@
     streams_.push_back(sp);
   }
   // Sets the CNAME of all StreamParams if it have not been set.
-  // This can be used to set the CNAME of legacy streams.
   void SetCnameIfEmpty(const std::string& cname) {
     for (cricket::StreamParamsVec::iterator it = streams_.begin();
          it != streams_.end(); ++it) {
@@ -469,11 +457,6 @@
   void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
   SecurePolicy secure() const { return secure_; }
   void set_secure(SecurePolicy s) { secure_ = s; }
-  // Decides if a StreamParams shall be added to the audio and video media
-  // content in SessionDescription when CreateOffer and CreateAnswer is called
-  // even if |options| don't include a Stream. This is needed to support legacy
-  // applications. |add_legacy_| is true per default.
-  void set_add_legacy_streams(bool add_legacy) { add_legacy_ = add_legacy; }
 
   void set_enable_encrypted_rtp_header_extensions(bool enable) {
     enable_encrypted_rtp_header_extensions_ = enable;
@@ -493,13 +476,15 @@
   const AudioCodecs& GetAudioCodecsForAnswer(
       const RtpTransceiverDirection& offer,
       const RtpTransceiverDirection& answer) const;
-  void GetCodecsToOffer(const SessionDescription* current_description,
-                        const AudioCodecs& supported_audio_codecs,
-                        const VideoCodecs& supported_video_codecs,
-                        const DataCodecs& supported_data_codecs,
-                        AudioCodecs* audio_codecs,
-                        VideoCodecs* video_codecs,
-                        DataCodecs* data_codecs) const;
+  void GetCodecsForOffer(const SessionDescription* current_description,
+                         AudioCodecs* audio_codecs,
+                         VideoCodecs* video_codecs,
+                         DataCodecs* data_codecs) const;
+  void GetCodecsForAnswer(const SessionDescription* current_description,
+                          const SessionDescription* remote_offer,
+                          AudioCodecs* audio_codecs,
+                          VideoCodecs* video_codecs,
+                          DataCodecs* data_codecs) const;
   void GetRtpHdrExtsToOffer(const SessionDescription* current_description,
                             RtpHeaderExtensions* audio_extensions,
                             RtpHeaderExtensions* video_extensions) const;
@@ -526,7 +511,9 @@
   // error.
 
   bool AddAudioContentForOffer(
-      const MediaSessionOptions& options,
+      const MediaDescriptionOptions& media_description_options,
+      const MediaSessionOptions& session_options,
+      const ContentInfo* current_content,
       const SessionDescription* current_description,
       const RtpHeaderExtensions& audio_rtp_extensions,
       const AudioCodecs& audio_codecs,
@@ -534,7 +521,9 @@
       SessionDescription* desc) const;
 
   bool AddVideoContentForOffer(
-      const MediaSessionOptions& options,
+      const MediaDescriptionOptions& media_description_options,
+      const MediaSessionOptions& session_options,
+      const ContentInfo* current_content,
       const SessionDescription* current_description,
       const RtpHeaderExtensions& video_rtp_extensions,
       const VideoCodecs& video_codecs,
@@ -542,43 +531,66 @@
       SessionDescription* desc) const;
 
   bool AddDataContentForOffer(
-      const MediaSessionOptions& options,
+      const MediaDescriptionOptions& media_description_options,
+      const MediaSessionOptions& session_options,
+      const ContentInfo* current_content,
       const SessionDescription* current_description,
-      DataCodecs* data_codecs,
+      const DataCodecs& data_codecs,
       StreamParamsVec* current_streams,
       SessionDescription* desc) const;
 
-  bool AddAudioContentForAnswer(const SessionDescription* offer,
-                                const MediaSessionOptions& options,
-                                const SessionDescription* current_description,
-                                const TransportInfo* bundle_transport,
-                                StreamParamsVec* current_streams,
-                                SessionDescription* answer) const;
+  bool AddAudioContentForAnswer(
+      const MediaDescriptionOptions& media_description_options,
+      const MediaSessionOptions& session_options,
+      const ContentInfo* offer_content,
+      const SessionDescription* offer_description,
+      const ContentInfo* current_content,
+      const SessionDescription* current_description,
+      const TransportInfo* bundle_transport,
+      const AudioCodecs& audio_codecs,
+      StreamParamsVec* current_streams,
+      SessionDescription* answer) const;
 
-  bool AddVideoContentForAnswer(const SessionDescription* offer,
-                                const MediaSessionOptions& options,
-                                const SessionDescription* current_description,
-                                const TransportInfo* bundle_transport,
-                                StreamParamsVec* current_streams,
-                                SessionDescription* answer) const;
+  bool AddVideoContentForAnswer(
+      const MediaDescriptionOptions& media_description_options,
+      const MediaSessionOptions& session_options,
+      const ContentInfo* offer_content,
+      const SessionDescription* offer_description,
+      const ContentInfo* current_content,
+      const SessionDescription* current_description,
+      const TransportInfo* bundle_transport,
+      const VideoCodecs& video_codecs,
+      StreamParamsVec* current_streams,
+      SessionDescription* answer) const;
 
-  bool AddDataContentForAnswer(const SessionDescription* offer,
-                               const MediaSessionOptions& options,
-                               const SessionDescription* current_description,
-                               const TransportInfo* bundle_transport,
-                               StreamParamsVec* current_streams,
-                               SessionDescription* answer) const;
+  bool AddDataContentForAnswer(
+      const MediaDescriptionOptions& media_description_options,
+      const MediaSessionOptions& session_options,
+      const ContentInfo* offer_content,
+      const SessionDescription* offer_description,
+      const ContentInfo* current_content,
+      const SessionDescription* current_description,
+      const TransportInfo* bundle_transport,
+      const DataCodecs& data_codecs,
+      StreamParamsVec* current_streams,
+      SessionDescription* answer) const;
+
+  void ComputeAudioCodecsIntersectionAndUnion();
 
   AudioCodecs audio_send_codecs_;
   AudioCodecs audio_recv_codecs_;
+  // Intersection of send and recv.
   AudioCodecs audio_sendrecv_codecs_;
+  // Union of send and recv.
+  AudioCodecs all_audio_codecs_;
   RtpHeaderExtensions audio_rtp_extensions_;
   VideoCodecs video_codecs_;
   RtpHeaderExtensions video_rtp_extensions_;
   DataCodecs data_codecs_;
-  SecurePolicy secure_;
-  bool add_legacy_;
   bool enable_encrypted_rtp_header_extensions_ = false;
+  // TODO(zhihuang): Rename secure_ to sdec_policy_; rename the related getter
+  // and setter.
+  SecurePolicy secure_ = SEC_DISABLED;
   std::string lang_;
   const TransportDescriptionFactory* transport_desc_factory_;
 };