| Index: webrtc/pc/webrtcsession_unittest.cc
 | 
| diff --git a/webrtc/pc/webrtcsession_unittest.cc b/webrtc/pc/webrtcsession_unittest.cc
 | 
| index bb1c877a5c6a9c85fee5f9eea884a272b2c5f708..f6d334e3e42dcfd8d8b977c52b9cf1933fbe40de 100644
 | 
| --- a/webrtc/pc/webrtcsession_unittest.cc
 | 
| +++ b/webrtc/pc/webrtcsession_unittest.cc
 | 
| @@ -142,9 +142,6 @@
 | 
|  static const char kStream2[] = "stream2";
 | 
|  static const char kVideoTrack2[] = "video2";
 | 
|  static const char kAudioTrack2[] = "audio2";
 | 
| -
 | 
| -static constexpr bool kStopped = true;
 | 
| -static constexpr bool kActive = false;
 | 
|  
 | 
|  enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE };
 | 
|  
 | 
| @@ -401,6 +398,7 @@
 | 
|      allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
 | 
|                            cricket::PORTALLOCATOR_DISABLE_RELAY);
 | 
|      EXPECT_TRUE(channel_manager_->Init());
 | 
| +    desc_factory_->set_add_legacy_streams(false);
 | 
|      allocator_->set_step_delay(cricket::kMinimumStepDelay);
 | 
|    }
 | 
|  
 | 
| @@ -509,261 +507,109 @@
 | 
|      InitWithCryptoOptions(crypto_options);
 | 
|    }
 | 
|  
 | 
| -  // The following convenience functions can be applied for both local side and
 | 
| -  // remote side. The flags can be overwritten for different use cases.
 | 
|    void SendAudioVideoStream1() {
 | 
|      send_stream_1_ = true;
 | 
|      send_stream_2_ = false;
 | 
| -    local_send_audio_ = true;
 | 
| -    local_send_video_ = true;
 | 
| -    remote_send_audio_ = true;
 | 
| -    remote_send_video_ = true;
 | 
| +    send_audio_ = true;
 | 
| +    send_video_ = true;
 | 
|    }
 | 
|  
 | 
|    void SendAudioVideoStream2() {
 | 
|      send_stream_1_ = false;
 | 
|      send_stream_2_ = true;
 | 
| -    local_send_audio_ = true;
 | 
| -    local_send_video_ = true;
 | 
| -    remote_send_audio_ = true;
 | 
| -    remote_send_video_ = true;
 | 
| +    send_audio_ = true;
 | 
| +    send_video_ = true;
 | 
|    }
 | 
|  
 | 
|    void SendAudioVideoStream1And2() {
 | 
|      send_stream_1_ = true;
 | 
|      send_stream_2_ = true;
 | 
| -    local_send_audio_ = true;
 | 
| -    local_send_video_ = true;
 | 
| -    remote_send_audio_ = true;
 | 
| -    remote_send_video_ = true;
 | 
| +    send_audio_ = true;
 | 
| +    send_video_ = true;
 | 
|    }
 | 
|  
 | 
|    void SendNothing() {
 | 
|      send_stream_1_ = false;
 | 
|      send_stream_2_ = false;
 | 
| -    local_send_audio_ = false;
 | 
| -    local_send_video_ = false;
 | 
| -    remote_send_audio_ = false;
 | 
| -    remote_send_video_ = false;
 | 
| +    send_audio_ = false;
 | 
| +    send_video_ = false;
 | 
|    }
 | 
|  
 | 
|    void SendAudioOnlyStream2() {
 | 
|      send_stream_1_ = false;
 | 
|      send_stream_2_ = true;
 | 
| -    local_send_audio_ = true;
 | 
| -    local_send_video_ = false;
 | 
| -    remote_send_audio_ = true;
 | 
| -    remote_send_video_ = false;
 | 
| +    send_audio_ = true;
 | 
| +    send_video_ = false;
 | 
|    }
 | 
|  
 | 
|    void SendVideoOnlyStream2() {
 | 
|      send_stream_1_ = false;
 | 
|      send_stream_2_ = true;
 | 
| -    local_send_audio_ = false;
 | 
| -    local_send_video_ = true;
 | 
| -    remote_send_audio_ = false;
 | 
| -    remote_send_video_ = true;
 | 
| -  }
 | 
| -
 | 
| -  // Helper function used to add a specific media section to the
 | 
| -  // |session_options|.
 | 
| -  void AddMediaSection(cricket::MediaType type,
 | 
| -                       const std::string& mid,
 | 
| -                       cricket::MediaContentDirection direction,
 | 
| -                       bool stopped,
 | 
| -                       cricket::MediaSessionOptions* opts) {
 | 
| -    opts->media_description_options.push_back(cricket::MediaDescriptionOptions(
 | 
| -        type, mid,
 | 
| -        cricket::RtpTransceiverDirection::FromMediaContentDirection(direction),
 | 
| -        stopped));
 | 
| -  }
 | 
| -
 | 
| -  // Add the media sections to the options from |offered_media_sections_| when
 | 
| -  // creating an answer or a new offer.
 | 
| -  // This duplicates a lot of logic from PeerConnection but this can be fixed
 | 
| -  // when PeerConnection and WebRtcSession are merged.
 | 
| -  void AddExistingMediaSectionsAndSendersToOptions(
 | 
| -      cricket::MediaSessionOptions* session_options,
 | 
| -      bool send_audio,
 | 
| -      bool recv_audio,
 | 
| -      bool send_video,
 | 
| -      bool recv_video) {
 | 
| -    int num_sim_layer = 1;
 | 
| -    for (auto media_description_options : offered_media_sections_) {
 | 
| -      if (media_description_options.type == cricket::MEDIA_TYPE_AUDIO) {
 | 
| -        bool stopped = !send_audio && !recv_audio;
 | 
| -        auto media_desc_options = cricket::MediaDescriptionOptions(
 | 
| -            cricket::MEDIA_TYPE_AUDIO, media_description_options.mid,
 | 
| -            cricket::RtpTransceiverDirection(send_audio, recv_audio), stopped);
 | 
| -        if (send_stream_1_ && send_audio) {
 | 
| -          media_desc_options.AddAudioSender(kAudioTrack1, kStream1);
 | 
| -        }
 | 
| -        if (send_stream_2_ && send_audio) {
 | 
| -          media_desc_options.AddAudioSender(kAudioTrack2, kStream2);
 | 
| -        }
 | 
| -        session_options->media_description_options.push_back(
 | 
| -            media_desc_options);
 | 
| -      } else if (media_description_options.type == cricket::MEDIA_TYPE_VIDEO) {
 | 
| -        bool stopped = !send_video && !recv_video;
 | 
| -        auto media_desc_options = cricket::MediaDescriptionOptions(
 | 
| -            cricket::MEDIA_TYPE_VIDEO, media_description_options.mid,
 | 
| -            cricket::RtpTransceiverDirection(send_video, recv_video), stopped);
 | 
| -        if (send_stream_1_ && send_video) {
 | 
| -          media_desc_options.AddVideoSender(kVideoTrack1, kStream1,
 | 
| -                                            num_sim_layer);
 | 
| -        }
 | 
| -        if (send_stream_2_ && send_video) {
 | 
| -          media_desc_options.AddVideoSender(kVideoTrack2, kStream2,
 | 
| -                                            num_sim_layer);
 | 
| -        }
 | 
| -        session_options->media_description_options.push_back(
 | 
| -            media_desc_options);
 | 
| -      } else if (media_description_options.type == cricket::MEDIA_TYPE_DATA) {
 | 
| -        session_options->media_description_options.push_back(
 | 
| -            cricket::MediaDescriptionOptions(
 | 
| -                cricket::MEDIA_TYPE_DATA, media_description_options.mid,
 | 
| -                // Direction for data sections is meaningless, but legacy
 | 
| -                // endpoints might expect sendrecv.
 | 
| -                cricket::RtpTransceiverDirection(true, true), false));
 | 
| -      } else {
 | 
| -        RTC_NOTREACHED();
 | 
| -      }
 | 
| +    send_audio_ = false;
 | 
| +    send_video_ = true;
 | 
| +  }
 | 
| +
 | 
| +  void AddStreamsToOptions(cricket::MediaSessionOptions* session_options) {
 | 
| +    if (send_stream_1_ && send_audio_) {
 | 
| +      session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1,
 | 
| +                                     kStream1);
 | 
|      }
 | 
| -  }
 | 
| -
 | 
| -  // Add the existing media sections first and then add new media sections if
 | 
| -  // needed.
 | 
| -  void AddMediaSectionsAndSendersToOptions(
 | 
| -      cricket::MediaSessionOptions* session_options,
 | 
| -      bool send_audio,
 | 
| -      bool recv_audio,
 | 
| -      bool send_video,
 | 
| -      bool recv_video) {
 | 
| -    AddExistingMediaSectionsAndSendersToOptions(
 | 
| -        session_options, send_audio, recv_audio, send_video, recv_video);
 | 
| -
 | 
| -    if (!session_options->has_audio() && (send_audio || recv_audio)) {
 | 
| -      cricket::MediaDescriptionOptions media_desc_options =
 | 
| -          cricket::MediaDescriptionOptions(
 | 
| -              cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
 | 
| -              cricket::RtpTransceiverDirection(send_audio, recv_audio),
 | 
| -              kActive);
 | 
| -      if (send_stream_1_ && send_audio) {
 | 
| -        media_desc_options.AddAudioSender(kAudioTrack1, kStream1);
 | 
| -      }
 | 
| -      if (send_stream_2_ && send_audio) {
 | 
| -        media_desc_options.AddAudioSender(kAudioTrack2, kStream2);
 | 
| -      }
 | 
| -      session_options->media_description_options.push_back(media_desc_options);
 | 
| -      offered_media_sections_.push_back(media_desc_options);
 | 
| +    if (send_stream_1_ && send_video_) {
 | 
| +      session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1,
 | 
| +                                     kStream1);
 | 
|      }
 | 
| -
 | 
| -    if (!session_options->has_video() && (send_video || recv_video)) {
 | 
| -      cricket::MediaDescriptionOptions media_desc_options =
 | 
| -          cricket::MediaDescriptionOptions(
 | 
| -              cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
 | 
| -              cricket::RtpTransceiverDirection(send_video, recv_video),
 | 
| -              kActive);
 | 
| -      int num_sim_layer = 1;
 | 
| -      if (send_stream_1_ && send_video) {
 | 
| -        media_desc_options.AddVideoSender(kVideoTrack1, kStream1,
 | 
| -                                          num_sim_layer);
 | 
| -      }
 | 
| -      if (send_stream_2_ && send_video) {
 | 
| -        media_desc_options.AddVideoSender(kVideoTrack2, kStream2,
 | 
| -                                          num_sim_layer);
 | 
| -      }
 | 
| -      session_options->media_description_options.push_back(media_desc_options);
 | 
| -      offered_media_sections_.push_back(media_desc_options);
 | 
| +    if (send_stream_2_ && send_audio_) {
 | 
| +      session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2,
 | 
| +                                     kStream2);
 | 
|      }
 | 
| -
 | 
| -    if (!session_options->has_data() &&
 | 
| -        (data_channel_ ||
 | 
| -         session_options->data_channel_type != cricket::DCT_NONE)) {
 | 
| -      cricket::MediaDescriptionOptions media_desc_options =
 | 
| -          cricket::MediaDescriptionOptions(
 | 
| -              cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
 | 
| -              cricket::RtpTransceiverDirection(true, true), kActive);
 | 
| -      if (session_options->data_channel_type == cricket::DCT_RTP) {
 | 
| -        media_desc_options.AddRtpDataChannel(data_channel_->label(),
 | 
| -                                             data_channel_->label());
 | 
| -      }
 | 
| -      session_options->media_description_options.push_back(media_desc_options);
 | 
| -      offered_media_sections_.push_back(media_desc_options);
 | 
| +    if (send_stream_2_ && send_video_) {
 | 
| +      session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2,
 | 
| +                                     kStream2);
 | 
| +    }
 | 
| +    if (data_channel_ && session_->data_channel_type() == cricket::DCT_RTP) {
 | 
| +      session_options->AddSendStream(cricket::MEDIA_TYPE_DATA,
 | 
| +                                     data_channel_->label(),
 | 
| +                                     data_channel_->label());
 | 
|      }
 | 
|    }
 | 
|  
 | 
|    void GetOptionsForOffer(
 | 
|        const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
 | 
|        cricket::MediaSessionOptions* session_options) {
 | 
| -    ExtractSharedMediaSessionOptions(rtc_options, session_options);
 | 
| -
 | 
| -    // |recv_X| is true by default if |offer_to_receive_X| is undefined.
 | 
| -    bool recv_audio = rtc_options.offer_to_receive_audio != 0;
 | 
| -    bool recv_video = rtc_options.offer_to_receive_video != 0;
 | 
| -
 | 
| -    AddMediaSectionsAndSendersToOptions(session_options, local_send_audio_,
 | 
| -                                        recv_audio, local_send_video_,
 | 
| -                                        recv_video);
 | 
| +    ASSERT_TRUE(ExtractMediaSessionOptions(rtc_options, true, session_options));
 | 
| +
 | 
| +    AddStreamsToOptions(session_options);
 | 
| +    if (rtc_options.offer_to_receive_audio ==
 | 
| +        RTCOfferAnswerOptions::kUndefined) {
 | 
| +      session_options->recv_audio =
 | 
| +          session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO);
 | 
| +    }
 | 
| +    if (rtc_options.offer_to_receive_video ==
 | 
| +        RTCOfferAnswerOptions::kUndefined) {
 | 
| +      session_options->recv_video =
 | 
| +          session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO);
 | 
| +    }
 | 
|      session_options->bundle_enabled =
 | 
|          session_options->bundle_enabled &&
 | 
|          (session_options->has_audio() || session_options->has_video() ||
 | 
|           session_options->has_data());
 | 
|  
 | 
| +    if (session_->data_channel_type() == cricket::DCT_SCTP && data_channel_) {
 | 
| +      session_options->data_channel_type = cricket::DCT_SCTP;
 | 
| +    } else if (session_->data_channel_type() == cricket::DCT_QUIC) {
 | 
| +      session_options->data_channel_type = cricket::DCT_QUIC;
 | 
| +    }
 | 
| +
 | 
|      session_options->crypto_options = crypto_options_;
 | 
|    }
 | 
|  
 | 
|    void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) {
 | 
| -    AddExistingMediaSectionsAndSendersToOptions(
 | 
| -        session_options, local_send_audio_, local_recv_audio_,
 | 
| -        local_send_video_, local_recv_video_);
 | 
| -
 | 
| +    // ParseConstraintsForAnswer is used to set some defaults.
 | 
| +    ASSERT_TRUE(webrtc::ParseConstraintsForAnswer(nullptr, session_options));
 | 
| +
 | 
| +    AddStreamsToOptions(session_options);
 | 
|      session_options->bundle_enabled =
 | 
|          session_options->bundle_enabled &&
 | 
| -        (session_options->has_audio() || session_options->has_video() ||
 | 
| -         session_options->has_data());
 | 
| -
 | 
| -    if (session_->data_channel_type() != cricket::DCT_RTP) {
 | 
| -      session_options->data_channel_type = session_->data_channel_type();
 | 
| -    }
 | 
| -
 | 
| -    session_options->crypto_options = crypto_options_;
 | 
| -  }
 | 
| -
 | 
| -  void GetOptionsForRemoteAnswer(
 | 
| -      cricket::MediaSessionOptions* session_options) {
 | 
| -    bool recv_audio = local_send_audio_ || remote_recv_audio_;
 | 
| -    bool recv_video = local_send_video_ || remote_recv_video_;
 | 
| -    bool send_audio = false;
 | 
| -    bool send_video = false;
 | 
| -
 | 
| -    AddExistingMediaSectionsAndSendersToOptions(
 | 
| -        session_options, send_audio, recv_audio, send_video, recv_video);
 | 
| -
 | 
| -    session_options->bundle_enabled =
 | 
| -        session_options->bundle_enabled &&
 | 
| -        (session_options->has_audio() || session_options->has_video() ||
 | 
| -         session_options->has_data());
 | 
| -
 | 
| -    if (session_->data_channel_type() != cricket::DCT_RTP) {
 | 
| -      session_options->data_channel_type = session_->data_channel_type();
 | 
| -    }
 | 
| -
 | 
| -    session_options->crypto_options = crypto_options_;
 | 
| -  }
 | 
| -
 | 
| -  void GetOptionsForAudioOnlyRemoteOffer(
 | 
| -      cricket::MediaSessionOptions* session_options) {
 | 
| -    remote_recv_audio_ = true;
 | 
| -    remote_recv_video_ = false;
 | 
| -    GetOptionsForRemoteOffer(session_options);
 | 
| -  }
 | 
| -
 | 
| -  void GetOptionsForRemoteOffer(cricket::MediaSessionOptions* session_options) {
 | 
| -    AddMediaSectionsAndSendersToOptions(session_options, remote_send_audio_,
 | 
| -                                        remote_recv_audio_, remote_send_video_,
 | 
| -                                        remote_recv_video_);
 | 
| -    session_options->bundle_enabled =
 | 
|          (session_options->has_audio() || session_options->has_video() ||
 | 
|           session_options->has_data());
 | 
|  
 | 
| @@ -789,6 +635,7 @@
 | 
|      PeerConnectionInterface::RTCOfferAnswerOptions options;
 | 
|      options.offer_to_receive_audio =
 | 
|          RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
 | 
| +
 | 
|      return CreateOffer(options);
 | 
|    }
 | 
|  
 | 
| @@ -811,6 +658,9 @@
 | 
|          = new WebRtcSessionCreateSDPObserverForTest();
 | 
|      cricket::MediaSessionOptions session_options = options;
 | 
|      GetOptionsForAnswer(&session_options);
 | 
| +    // Overwrite recv_audio and recv_video with passed-in values.
 | 
| +    session_options.recv_video = options.recv_video;
 | 
| +    session_options.recv_audio = options.recv_audio;
 | 
|      session_->CreateAnswer(observer, session_options);
 | 
|      EXPECT_TRUE_WAIT(
 | 
|          observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
 | 
| @@ -820,7 +670,8 @@
 | 
|  
 | 
|    SessionDescriptionInterface* CreateAnswer() {
 | 
|      cricket::MediaSessionOptions options;
 | 
| -    options.bundle_enabled = true;
 | 
| +    options.recv_video = true;
 | 
| +    options.recv_audio = true;
 | 
|      return CreateAnswer(options);
 | 
|    }
 | 
|  
 | 
| @@ -938,7 +789,7 @@
 | 
|    void VerifyAnswerFromNonCryptoOffer() {
 | 
|      // Create an SDP without Crypto.
 | 
|      cricket::MediaSessionOptions options;
 | 
| -    GetOptionsForRemoteOffer(&options);
 | 
| +    options.recv_video = true;
 | 
|      JsepSessionDescription* offer(
 | 
|          CreateRemoteOffer(options, cricket::SEC_DISABLED));
 | 
|      ASSERT_TRUE(offer != NULL);
 | 
| @@ -952,7 +803,7 @@
 | 
|  
 | 
|    void VerifyAnswerFromCryptoOffer() {
 | 
|      cricket::MediaSessionOptions options;
 | 
| -    GetOptionsForRemoteOffer(&options);
 | 
| +    options.recv_video = true;
 | 
|      options.bundle_enabled = true;
 | 
|      std::unique_ptr<JsepSessionDescription> offer(
 | 
|          CreateRemoteOffer(options, cricket::SEC_REQUIRED));
 | 
| @@ -1075,7 +926,7 @@
 | 
|      SetLocalDescriptionWithoutError(answer);
 | 
|    }
 | 
|    void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
 | 
| -    ASSERT_TRUE(session_->SetLocalDescription(desc, nullptr));
 | 
| +    EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
 | 
|      session_->MaybeStartGathering();
 | 
|    }
 | 
|    void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
 | 
| @@ -1104,7 +955,7 @@
 | 
|                                     expected_error, desc);
 | 
|    }
 | 
|    void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
 | 
| -    ASSERT_TRUE(session_->SetRemoteDescription(desc, nullptr));
 | 
| +    EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
 | 
|    }
 | 
|    void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
 | 
|                                         WebRtcSession::State expected_state) {
 | 
| @@ -1141,26 +992,21 @@
 | 
|        SessionDescriptionInterface** nocrypto_answer) {
 | 
|      // Create a SDP without Crypto.
 | 
|      cricket::MediaSessionOptions options;
 | 
| -    GetOptionsForRemoteOffer(&options);
 | 
| +    options.recv_video = true;
 | 
|      options.bundle_enabled = true;
 | 
|      *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
 | 
|      ASSERT_TRUE(*offer != NULL);
 | 
|      VerifyCryptoParams((*offer)->description());
 | 
|  
 | 
| -    cricket::MediaSessionOptions answer_options;
 | 
| -    GetOptionsForRemoteAnswer(&answer_options);
 | 
| -    *nocrypto_answer =
 | 
| -        CreateRemoteAnswer(*offer, answer_options, cricket::SEC_DISABLED);
 | 
| +    *nocrypto_answer = CreateRemoteAnswer(*offer, options,
 | 
| +                                          cricket::SEC_DISABLED);
 | 
|      EXPECT_TRUE(*nocrypto_answer != NULL);
 | 
|    }
 | 
|  
 | 
|    void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
 | 
|        SessionDescriptionInterface** nodtls_answer) {
 | 
|      cricket::MediaSessionOptions options;
 | 
| -    AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
 | 
| -                    cricket::MD_RECVONLY, kActive, &options);
 | 
| -    AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
 | 
| -                    cricket::MD_RECVONLY, kActive, &options);
 | 
| +    options.recv_video = true;
 | 
|      options.bundle_enabled = true;
 | 
|  
 | 
|      std::unique_ptr<SessionDescriptionInterface> temp_offer(
 | 
| @@ -1222,7 +1068,8 @@
 | 
|        const char* sctp_stream_name, int new_port,
 | 
|        cricket::MediaSessionOptions options) {
 | 
|      options.data_channel_type = cricket::DCT_SCTP;
 | 
| -    GetOptionsForRemoteOffer(&options);
 | 
| +    options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel",
 | 
| +                          sctp_stream_name);
 | 
|      return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
 | 
|    }
 | 
|  
 | 
| @@ -1250,7 +1097,7 @@
 | 
|    // before this function to decide which streams to create.
 | 
|    JsepSessionDescription* CreateRemoteOffer() {
 | 
|      cricket::MediaSessionOptions options;
 | 
| -    GetOptionsForRemoteOffer(&options);
 | 
| +    GetOptionsForAnswer(&options);
 | 
|      return CreateRemoteOffer(options, session_->remote_description());
 | 
|    }
 | 
|  
 | 
| @@ -1285,7 +1132,6 @@
 | 
|        const SessionDescriptionInterface* offer) {
 | 
|      cricket::MediaSessionOptions options;
 | 
|      GetOptionsForAnswer(&options);
 | 
| -    options.bundle_enabled = true;
 | 
|      return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
 | 
|    }
 | 
|  
 | 
| @@ -1609,7 +1455,6 @@
 | 
|      SetFactoryDtlsSrtp();
 | 
|      if (type == CreateSessionDescriptionRequest::kAnswer) {
 | 
|        cricket::MediaSessionOptions options;
 | 
| -      GetOptionsForRemoteOffer(&options);
 | 
|        std::unique_ptr<JsepSessionDescription> offer(
 | 
|            CreateRemoteOffer(options, cricket::SEC_DISABLED));
 | 
|        ASSERT_TRUE(offer.get() != NULL);
 | 
| @@ -1617,19 +1462,16 @@
 | 
|      }
 | 
|  
 | 
|      PeerConnectionInterface::RTCOfferAnswerOptions options;
 | 
| -    cricket::MediaSessionOptions offer_session_options;
 | 
| -    cricket::MediaSessionOptions answer_session_options;
 | 
| -    GetOptionsForOffer(options, &offer_session_options);
 | 
| -    GetOptionsForAnswer(&answer_session_options);
 | 
| +    cricket::MediaSessionOptions session_options;
 | 
|      const int kNumber = 3;
 | 
|      rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
 | 
|          observers[kNumber];
 | 
|      for (int i = 0; i < kNumber; ++i) {
 | 
|        observers[i] = new WebRtcSessionCreateSDPObserverForTest();
 | 
|        if (type == CreateSessionDescriptionRequest::kOffer) {
 | 
| -        session_->CreateOffer(observers[i], options, offer_session_options);
 | 
| +        session_->CreateOffer(observers[i], options, session_options);
 | 
|        } else {
 | 
| -        session_->CreateAnswer(observers[i], answer_session_options);
 | 
| +        session_->CreateAnswer(observers[i], session_options);
 | 
|        }
 | 
|      }
 | 
|  
 | 
| @@ -1687,15 +1529,8 @@
 | 
|    // The following flags affect options created for CreateOffer/CreateAnswer.
 | 
|    bool send_stream_1_ = false;
 | 
|    bool send_stream_2_ = false;
 | 
| -  bool local_send_audio_ = false;
 | 
| -  bool local_send_video_ = false;
 | 
| -  bool local_recv_audio_ = true;
 | 
| -  bool local_recv_video_ = true;
 | 
| -  bool remote_send_audio_ = false;
 | 
| -  bool remote_send_video_ = false;
 | 
| -  bool remote_recv_audio_ = true;
 | 
| -  bool remote_recv_video_ = true;
 | 
| -  std::vector<cricket::MediaDescriptionOptions> offered_media_sections_;
 | 
| +  bool send_audio_ = false;
 | 
| +  bool send_video_ = false;
 | 
|    rtc::scoped_refptr<DataChannel> data_channel_;
 | 
|    // Last values received from data channel creation signal.
 | 
|    std::string last_data_channel_label_;
 | 
| @@ -1935,7 +1770,7 @@
 | 
|  TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
 | 
|    Init();
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    JsepSessionDescription* offer = CreateRemoteOffer(
 | 
|        options, cricket::SEC_DISABLED);
 | 
|    ASSERT_TRUE(offer != NULL);
 | 
| @@ -1981,7 +1816,7 @@
 | 
|    InitWithDtls(GetParam());
 | 
|    SetFactoryDtlsSrtp();
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    JsepSessionDescription* offer =
 | 
|        CreateRemoteOffer(options, cricket::SEC_DISABLED);
 | 
|    ASSERT_TRUE(offer != NULL);
 | 
| @@ -2020,7 +1855,7 @@
 | 
|    SetLocalDescriptionWithoutError(offer);
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForAnswer(&options);
 | 
| +  options.recv_video = true;
 | 
|    JsepSessionDescription* answer =
 | 
|        CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
 | 
|    ASSERT_TRUE(answer != NULL);
 | 
| @@ -2036,7 +1871,7 @@
 | 
|  TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
 | 
|    InitWithDtls(GetParam());
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    options.bundle_enabled = true;
 | 
|    JsepSessionDescription* offer = CreateRemoteOffer(
 | 
|        options, cricket::SEC_REQUIRED);
 | 
| @@ -2074,16 +1909,12 @@
 | 
|  TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
 | 
|    InitWithDtls(GetParam());
 | 
|    SessionDescriptionInterface* offer = CreateOffer();
 | 
| -  cricket::MediaSessionOptions offer_options;
 | 
| -  GetOptionsForRemoteOffer(&offer_options);
 | 
| -
 | 
| +  cricket::MediaSessionOptions options;
 | 
| +  options.recv_video = true;
 | 
|    std::unique_ptr<SessionDescriptionInterface> temp_offer(
 | 
| -      CreateRemoteOffer(offer_options, cricket::SEC_ENABLED));
 | 
| -
 | 
| -  cricket::MediaSessionOptions answer_options;
 | 
| -  GetOptionsForAnswer(&answer_options);
 | 
| -  JsepSessionDescription* answer = CreateRemoteAnswer(
 | 
| -      temp_offer.get(), answer_options, cricket::SEC_ENABLED);
 | 
| +      CreateRemoteOffer(options, cricket::SEC_ENABLED));
 | 
| +  JsepSessionDescription* answer =
 | 
| +      CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
 | 
|  
 | 
|    // SetRemoteDescription and SetLocalDescription will take the ownership of
 | 
|    // the offer and answer.
 | 
| @@ -2110,7 +1941,7 @@
 | 
|    SetLocalDescriptionWithoutError(offer);
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForAnswer(&options);
 | 
| +  options.recv_video = true;
 | 
|    JsepSessionDescription* answer =
 | 
|        CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
 | 
|    ASSERT_TRUE(answer != NULL);
 | 
| @@ -2128,7 +1959,7 @@
 | 
|    InitWithDtls(GetParam());
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    JsepSessionDescription* offer =
 | 
|        CreateRemoteOffer(options, cricket::SEC_DISABLED);
 | 
|    ASSERT_TRUE(offer != NULL);
 | 
| @@ -2161,7 +1992,7 @@
 | 
|    SetLocalDescriptionWithoutError(offer);
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForAnswer(&options);
 | 
| +  options.recv_video = true;
 | 
|  
 | 
|    // First, negotiate different SSL roles.
 | 
|    SessionDescriptionInterface* answer =
 | 
| @@ -2183,9 +2014,7 @@
 | 
|                                         session_->remote_description());
 | 
|    SetRemoteDescriptionWithoutError(offer);
 | 
|  
 | 
| -  cricket::MediaSessionOptions answer_options;
 | 
| -  answer_options.bundle_enabled = true;
 | 
| -  answer = CreateAnswer(answer_options);
 | 
| +  answer = CreateAnswer();
 | 
|    audio_transport_info = answer->description()->GetTransportInfoByName("audio");
 | 
|    EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
 | 
|              audio_transport_info->description.connection_role);
 | 
| @@ -2202,7 +2031,7 @@
 | 
|                                         kSessionVersion,
 | 
|                                         session_->remote_description());
 | 
|    SetRemoteDescriptionWithoutError(offer);
 | 
| -  answer = CreateAnswer(answer_options);
 | 
| +  answer = CreateAnswer();
 | 
|    audio_transport_info = answer->description()->GetTransportInfoByName("audio");
 | 
|    EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
 | 
|              audio_transport_info->description.connection_role);
 | 
| @@ -2563,7 +2392,6 @@
 | 
|  
 | 
|    std::unique_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
 | 
|  
 | 
| -  ASSERT_TRUE(local_offer);
 | 
|    ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
 | 
|    EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
 | 
|  
 | 
| @@ -2589,27 +2417,42 @@
 | 
|    // present in SDP.
 | 
|    std::string sdp;
 | 
|    EXPECT_TRUE(offer->ToString(&sdp));
 | 
| +  const std::string kAudioMid = "a=mid:audio";
 | 
| +  const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
 | 
| +  const std::string kVideoMid = "a=mid:video";
 | 
| +  const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
 | 
| +
 | 
| +  // Replacing |audio| with |audio_content_name|.
 | 
| +  rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
 | 
| +                             kAudioMidReplaceStr.c_str(),
 | 
| +                             kAudioMidReplaceStr.length(),
 | 
| +                             &sdp);
 | 
| +  // Replacing |video| with |video_content_name|.
 | 
| +  rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
 | 
| +                             kVideoMidReplaceStr.c_str(),
 | 
| +                             kVideoMidReplaceStr.length(),
 | 
| +                             &sdp);
 | 
|  
 | 
|    SessionDescriptionInterface* modified_offer =
 | 
|        CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
 | 
|  
 | 
|    SetRemoteDescriptionWithoutError(modified_offer);
 | 
|  
 | 
| -  cricket::MediaSessionOptions answer_options;
 | 
| -  answer_options.bundle_enabled = false;
 | 
| -  SessionDescriptionInterface* answer = CreateAnswer(answer_options);
 | 
| +  SessionDescriptionInterface* answer = CreateAnswer();
 | 
|    SetLocalDescriptionWithoutError(answer);
 | 
|  
 | 
|    rtc::PacketTransportInternal* voice_transport_channel =
 | 
|        session_->voice_rtp_transport_channel();
 | 
|    EXPECT_TRUE(voice_transport_channel != NULL);
 | 
|    EXPECT_EQ(voice_transport_channel->debug_name(),
 | 
| -            "audio " + std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
 | 
| +            "audio_content_name " +
 | 
| +                std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
 | 
|    rtc::PacketTransportInternal* video_transport_channel =
 | 
|        session_->video_rtp_transport_channel();
 | 
|    ASSERT_TRUE(video_transport_channel != NULL);
 | 
|    EXPECT_EQ(video_transport_channel->debug_name(),
 | 
| -            "video " + std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
 | 
| +            "video_content_name " +
 | 
| +                std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
 | 
|    EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
 | 
|    EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
 | 
|  }
 | 
| @@ -2623,17 +2466,9 @@
 | 
|    ASSERT_TRUE(offer != NULL);
 | 
|    const cricket::ContentInfo* content =
 | 
|        cricket::GetFirstAudioContent(offer->description());
 | 
| -  ASSERT_TRUE(content != NULL);
 | 
| -  EXPECT_EQ(
 | 
| -      cricket::MD_RECVONLY,
 | 
| -      static_cast<const cricket::AudioContentDescription*>(content->description)
 | 
| -          ->direction());
 | 
| +  EXPECT_TRUE(content != NULL);
 | 
|    content = cricket::GetFirstVideoContent(offer->description());
 | 
| -  ASSERT_TRUE(content != NULL);
 | 
| -  EXPECT_EQ(
 | 
| -      cricket::MD_RECVONLY,
 | 
| -      static_cast<const cricket::VideoContentDescription*>(content->description)
 | 
| -          ->direction());
 | 
| +  EXPECT_TRUE(content == NULL);
 | 
|  }
 | 
|  
 | 
|  // Test that an offer contains the correct media content descriptions based on
 | 
| @@ -2646,34 +2481,17 @@
 | 
|  
 | 
|    const cricket::ContentInfo* content =
 | 
|        cricket::GetFirstAudioContent(offer->description());
 | 
| -  ASSERT_TRUE(content != NULL);
 | 
| -  EXPECT_EQ(
 | 
| -      cricket::MD_SENDRECV,
 | 
| -      static_cast<const cricket::AudioContentDescription*>(content->description)
 | 
| -          ->direction());
 | 
| +  EXPECT_TRUE(content != NULL);
 | 
|    content = cricket::GetFirstVideoContent(offer->description());
 | 
| -  ASSERT_TRUE(content != NULL);
 | 
| -  EXPECT_EQ(
 | 
| -      cricket::MD_RECVONLY,
 | 
| -      static_cast<const cricket::VideoContentDescription*>(content->description)
 | 
| -          ->direction());
 | 
| +  EXPECT_TRUE(content == NULL);
 | 
|  
 | 
|    // Test Audio / Video offer.
 | 
|    SendAudioVideoStream1();
 | 
|    offer.reset(CreateOffer());
 | 
|    content = cricket::GetFirstAudioContent(offer->description());
 | 
| -  ASSERT_TRUE(content != NULL);
 | 
| -  EXPECT_EQ(
 | 
| -      cricket::MD_SENDRECV,
 | 
| -      static_cast<const cricket::AudioContentDescription*>(content->description)
 | 
| -          ->direction());
 | 
| -
 | 
| +  EXPECT_TRUE(content != NULL);
 | 
|    content = cricket::GetFirstVideoContent(offer->description());
 | 
| -  ASSERT_TRUE(content != NULL);
 | 
| -  EXPECT_EQ(
 | 
| -      cricket::MD_SENDRECV,
 | 
| -      static_cast<const cricket::VideoContentDescription*>(content->description)
 | 
| -          ->direction());
 | 
| +  EXPECT_TRUE(content != NULL);
 | 
|  }
 | 
|  
 | 
|  // Test that an offer contains no media content descriptions if
 | 
| @@ -2701,7 +2519,6 @@
 | 
|    PeerConnectionInterface::RTCOfferAnswerOptions options;
 | 
|    options.offer_to_receive_audio =
 | 
|        RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
 | 
| -  options.offer_to_receive_video = 0;
 | 
|  
 | 
|    std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
 | 
|  
 | 
| @@ -2736,8 +2553,6 @@
 | 
|    // removed.
 | 
|    options.offer_to_receive_audio = 0;
 | 
|    options.offer_to_receive_video = 0;
 | 
| -  // Remove the media sections added in previous offer.
 | 
| -  offered_media_sections_.clear();
 | 
|    offer.reset(CreateOffer(options));
 | 
|  
 | 
|    content = cricket::GetFirstAudioContent(offer->description());
 | 
| @@ -2781,7 +2596,6 @@
 | 
|    Init();
 | 
|    // Create a remote offer with audio only.
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForAudioOnlyRemoteOffer(&options);
 | 
|  
 | 
|    std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
 | 
|    ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
 | 
| @@ -2826,10 +2640,8 @@
 | 
|    SetRemoteDescriptionWithoutError(offer.release());
 | 
|  
 | 
|    cricket::MediaSessionOptions session_options;
 | 
| -  remote_send_audio_ = false;
 | 
| -  remote_send_video_ = false;
 | 
| -  local_recv_audio_ = false;
 | 
| -  local_recv_video_ = false;
 | 
| +  session_options.recv_audio = false;
 | 
| +  session_options.recv_video = false;
 | 
|    std::unique_ptr<SessionDescriptionInterface> answer(
 | 
|        CreateAnswer(session_options));
 | 
|  
 | 
| @@ -2852,6 +2664,9 @@
 | 
|    SetRemoteDescriptionWithoutError(offer.release());
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| +  options.recv_audio = false;
 | 
| +  options.recv_video = false;
 | 
| +
 | 
|    // Test with a stream with tracks.
 | 
|    SendAudioVideoStream1();
 | 
|    std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer(options));
 | 
| @@ -2911,11 +2726,6 @@
 | 
|    SessionDescriptionInterface* offer = CreateOffer();
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
 | 
| -                  cricket::MD_RECVONLY, kActive, &options);
 | 
| -  AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
 | 
| -                  cricket::MD_INACTIVE, kStopped, &options);
 | 
| -  local_recv_video_ = false;
 | 
|    SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
 | 
|  
 | 
|    // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
 | 
| @@ -2926,7 +2736,7 @@
 | 
|    video_channel_ = media_engine_->GetVideoChannel(0);
 | 
|    voice_channel_ = media_engine_->GetVoiceChannel(0);
 | 
|  
 | 
| -  ASSERT_TRUE(video_channel_ == nullptr);
 | 
| +  ASSERT_TRUE(video_channel_ == NULL);
 | 
|  
 | 
|    ASSERT_EQ(0u, voice_channel_->recv_streams().size());
 | 
|    ASSERT_EQ(1u, voice_channel_->send_streams().size());
 | 
| @@ -2934,14 +2744,13 @@
 | 
|  
 | 
|    // Let the remote end update the session descriptions, with Audio and Video.
 | 
|    SendAudioVideoStream2();
 | 
| -  local_recv_video_ = true;
 | 
|    CreateAndSetRemoteOfferAndLocalAnswer();
 | 
|  
 | 
|    video_channel_ = media_engine_->GetVideoChannel(0);
 | 
|    voice_channel_ = media_engine_->GetVoiceChannel(0);
 | 
|  
 | 
| -  ASSERT_TRUE(video_channel_ != nullptr);
 | 
| -  ASSERT_TRUE(voice_channel_ != nullptr);
 | 
| +  ASSERT_TRUE(video_channel_ != NULL);
 | 
| +  ASSERT_TRUE(voice_channel_ != NULL);
 | 
|  
 | 
|    ASSERT_EQ(1u, video_channel_->recv_streams().size());
 | 
|    ASSERT_EQ(1u, video_channel_->send_streams().size());
 | 
| @@ -2953,17 +2762,10 @@
 | 
|    EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
 | 
|  
 | 
|    // Change session back to audio only.
 | 
| -  // The remote side doesn't send and recv video.
 | 
|    SendAudioOnlyStream2();
 | 
| -  remote_recv_video_ = false;
 | 
|    CreateAndSetRemoteOfferAndLocalAnswer();
 | 
|  
 | 
| -  video_channel_ = media_engine_->GetVideoChannel(0);
 | 
| -  voice_channel_ = media_engine_->GetVoiceChannel(0);
 | 
| -
 | 
| -  // The audio is expected to be rejected.
 | 
| -  EXPECT_TRUE(video_channel_ == nullptr);
 | 
| -
 | 
| +  EXPECT_EQ(0u, video_channel_->recv_streams().size());
 | 
|    ASSERT_EQ(1u, voice_channel_->recv_streams().size());
 | 
|    EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
 | 
|    ASSERT_EQ(1u, voice_channel_->send_streams().size());
 | 
| @@ -2980,13 +2782,10 @@
 | 
|    SessionDescriptionInterface* offer = CreateOffer();
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
 | 
| -                  cricket::MD_INACTIVE, kStopped, &options);
 | 
| -  AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
 | 
| -                  cricket::MD_RECVONLY, kActive, &options);
 | 
| -  local_recv_audio_ = false;
 | 
| -  SessionDescriptionInterface* answer =
 | 
| -      CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
 | 
| +  options.recv_audio = false;
 | 
| +  options.recv_video = true;
 | 
| +  SessionDescriptionInterface* answer = CreateRemoteAnswer(
 | 
| +      offer, options, cricket::SEC_ENABLED);
 | 
|  
 | 
|    // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
 | 
|    // and answer.
 | 
| @@ -3005,40 +2804,22 @@
 | 
|  
 | 
|    // Update the session descriptions, with Audio and Video.
 | 
|    SendAudioVideoStream2();
 | 
| -  local_recv_audio_ = true;
 | 
| -  SessionDescriptionInterface* offer2 = CreateRemoteOffer();
 | 
| -  SetRemoteDescriptionWithoutError(offer2);
 | 
| -  cricket::MediaSessionOptions answer_options;
 | 
| -  // Disable the bundling here. If the media is bundled on audio
 | 
| -  // transport, then we can't reject the audio because switching the bundled
 | 
| -  // transport is not currently supported.
 | 
| -  // (https://bugs.chromium.org/p/webrtc/issues/detail?id=6704)
 | 
| -  answer_options.bundle_enabled = false;
 | 
| -  SessionDescriptionInterface* answer2 = CreateAnswer(answer_options);
 | 
| -  SetLocalDescriptionWithoutError(answer2);
 | 
| +  CreateAndSetRemoteOfferAndLocalAnswer();
 | 
|  
 | 
|    voice_channel_ = media_engine_->GetVoiceChannel(0);
 | 
| -
 | 
|    ASSERT_TRUE(voice_channel_ != NULL);
 | 
| +
 | 
|    ASSERT_EQ(1u, voice_channel_->recv_streams().size());
 | 
|    ASSERT_EQ(1u, voice_channel_->send_streams().size());
 | 
|    EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
 | 
|    EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
 | 
|  
 | 
|    // Change session back to video only.
 | 
| -  // The remote side doesn't send and recv audio.
 | 
|    SendVideoOnlyStream2();
 | 
| -  remote_recv_audio_ = false;
 | 
| -  SessionDescriptionInterface* offer3 = CreateRemoteOffer();
 | 
| -  SetRemoteDescriptionWithoutError(offer3);
 | 
| -  SessionDescriptionInterface* answer3 = CreateAnswer(answer_options);
 | 
| -  SetLocalDescriptionWithoutError(answer3);
 | 
| +  CreateAndSetRemoteOfferAndLocalAnswer();
 | 
|  
 | 
|    video_channel_ = media_engine_->GetVideoChannel(0);
 | 
|    voice_channel_ = media_engine_->GetVoiceChannel(0);
 | 
| -
 | 
| -  // The video is expected to be rejected.
 | 
| -  EXPECT_TRUE(voice_channel_ == nullptr);
 | 
|  
 | 
|    ASSERT_EQ(1u, video_channel_->recv_streams().size());
 | 
|    EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
 | 
| @@ -3244,16 +3025,13 @@
 | 
|    InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
 | 
|    SendAudioVideoStream1();
 | 
|  
 | 
| -  cricket::MediaSessionOptions offer_options;
 | 
| -  GetOptionsForRemoteOffer(&offer_options);
 | 
| -  offer_options.bundle_enabled = true;
 | 
| -
 | 
| -  SessionDescriptionInterface* offer = CreateRemoteOffer(offer_options);
 | 
| +  PeerConnectionInterface::RTCOfferAnswerOptions options;
 | 
| +  options.use_rtp_mux = true;
 | 
| +
 | 
| +  SessionDescriptionInterface* offer = CreateRemoteOffer();
 | 
|    SetRemoteDescriptionWithoutError(offer);
 | 
|  
 | 
| -  cricket::MediaSessionOptions answer_options;
 | 
| -  answer_options.bundle_enabled = true;
 | 
| -  SessionDescriptionInterface* answer = CreateAnswer(answer_options);
 | 
| +  SessionDescriptionInterface* answer = CreateAnswer();
 | 
|    SetLocalDescriptionWithoutError(answer);
 | 
|  
 | 
|    EXPECT_EQ(session_->voice_rtp_transport_channel(),
 | 
| @@ -3418,11 +3196,10 @@
 | 
|    EXPECT_EQ(session_->voice_rtp_transport_channel(),
 | 
|              session_->video_rtp_transport_channel());
 | 
|  
 | 
| -  SendVideoOnlyStream2();
 | 
| -  local_send_audio_ = false;
 | 
| -  remote_recv_audio_ = false;
 | 
| +  SendAudioVideoStream2();
 | 
|    cricket::MediaSessionOptions recv_options;
 | 
| -  GetOptionsForRemoteAnswer(&recv_options);
 | 
| +  recv_options.recv_audio = false;
 | 
| +  recv_options.recv_video = true;
 | 
|    SessionDescriptionInterface* answer =
 | 
|        CreateRemoteAnswer(session_->local_description(), recv_options);
 | 
|    SetRemoteDescriptionWithoutError(answer);
 | 
| @@ -3509,10 +3286,10 @@
 | 
|    InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
 | 
|    SendAudioVideoStream1();
 | 
|  
 | 
| -  PeerConnectionInterface::RTCOfferAnswerOptions rtc_options;
 | 
| -  rtc_options.use_rtp_mux = true;
 | 
| -
 | 
| -  SessionDescriptionInterface* offer = CreateOffer(rtc_options);
 | 
| +  PeerConnectionInterface::RTCOfferAnswerOptions options;
 | 
| +  options.use_rtp_mux = true;
 | 
| +
 | 
| +  SessionDescriptionInterface* offer = CreateOffer(options);
 | 
|    SetLocalDescriptionWithoutError(offer);
 | 
|  
 | 
|    EXPECT_NE(session_->voice_rtp_transport_channel(),
 | 
| @@ -3868,7 +3645,7 @@
 | 
|  TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
 | 
|    Init();
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
 | 
|    SetRemoteDescriptionWithoutError(offer.release());
 | 
|  
 | 
| @@ -3877,10 +3654,10 @@
 | 
|    SetLocalDescriptionWithoutError(answer.release());
 | 
|  
 | 
|    // Receive an offer with new ufrag and password.
 | 
| -  for (size_t i = 0; i < options.media_description_options.size(); ++i) {
 | 
| -    options.media_description_options[i].transport_options.ice_restart = true;
 | 
| -  }
 | 
| -
 | 
| +  for (const cricket::ContentInfo& content :
 | 
| +       session_->local_description()->description()->contents()) {
 | 
| +    options.transport_options[content.name].ice_restart = true;
 | 
| +  }
 | 
|    std::unique_ptr<JsepSessionDescription> updated_offer1(
 | 
|        CreateRemoteOffer(options, session_->remote_description()));
 | 
|    SetRemoteDescriptionWithoutError(updated_offer1.release());
 | 
| @@ -3908,7 +3685,8 @@
 | 
|  TEST_F(WebRtcSessionTest, TestOfferChangingOnlyUfragOrPassword) {
 | 
|    Init();
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_audio = true;
 | 
| +  options.recv_video = true;
 | 
|    // Create an offer with audio and video.
 | 
|    std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
 | 
|    SetIceUfragPwd(offer.get(), "original_ufrag", "original_password12345");
 | 
| @@ -3948,7 +3726,7 @@
 | 
|  TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
 | 
|    Init();
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
 | 
|    SetRemoteDescriptionWithoutError(offer.release());
 | 
|  
 | 
| @@ -3975,7 +3753,8 @@
 | 
|  TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewAndOldUfragAndPassword) {
 | 
|    Init();
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
| +  options.recv_audio = true;
 | 
|    options.bundle_enabled = false;
 | 
|    std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
 | 
|  
 | 
| @@ -4107,9 +3886,9 @@
 | 
|    // Create answer that finishes BUNDLE negotiation, which means everything
 | 
|    // should be bundled on the first transport (audio).
 | 
|    cricket::MediaSessionOptions answer_options;
 | 
| +  answer_options.recv_video = true;
 | 
|    answer_options.bundle_enabled = true;
 | 
|    answer_options.data_channel_type = cricket::DCT_SCTP;
 | 
| -  GetOptionsForAnswer(&answer_options);
 | 
|    SetRemoteDescriptionWithoutError(CreateRemoteAnswer(
 | 
|        session_->local_description(), answer_options, cricket::SEC_DISABLED));
 | 
|    ASSERT_TRUE(session_->sctp_content_name());
 | 
| @@ -4133,7 +3912,6 @@
 | 
|    // Create remote offer with SCTP.
 | 
|    cricket::MediaSessionOptions options;
 | 
|    options.data_channel_type = cricket::DCT_SCTP;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
|    JsepSessionDescription* offer =
 | 
|        CreateRemoteOffer(options, cricket::SEC_DISABLED);
 | 
|    SetRemoteDescriptionWithoutError(offer);
 | 
| @@ -4277,7 +4055,7 @@
 | 
|    SetFactoryDtlsSrtp();
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    std::unique_ptr<JsepSessionDescription> offer(
 | 
|        CreateRemoteOffer(options, cricket::SEC_DISABLED));
 | 
|    ASSERT_TRUE(offer.get() != NULL);
 | 
| @@ -4351,7 +4129,6 @@
 | 
|    Init();
 | 
|    // Create a remote offer with secured transport disabled.
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
|    JsepSessionDescription* offer(CreateRemoteOffer(
 | 
|        options, cricket::SEC_DISABLED));
 | 
|    // Adds a DTLS fingerprint to the remote offer.
 | 
| @@ -4395,7 +4172,7 @@
 | 
|    SetRemoteDescriptionWithoutError(answer);
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
 | 
|  
 | 
|    cricket::Candidate candidate1;
 | 
| @@ -4424,7 +4201,7 @@
 | 
|    SetRemoteDescriptionWithoutError(answer);
 | 
|  
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForRemoteOffer(&options);
 | 
| +  options.recv_video = true;
 | 
|    offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
 | 
|    SetRemoteDescriptionWithoutError(offer);
 | 
|  
 | 
| @@ -4449,7 +4226,8 @@
 | 
|    ASSERT_TRUE(offer->description());
 | 
|    SetLocalDescriptionWithoutError(offer);
 | 
|    cricket::MediaSessionOptions options;
 | 
| -  GetOptionsForAnswer(&options);
 | 
| +  options.recv_audio = true;
 | 
| +  options.recv_video = true;
 | 
|    SessionDescriptionInterface* answer =
 | 
|        CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
 | 
|    ASSERT_TRUE(answer);
 | 
| @@ -4462,8 +4240,7 @@
 | 
|  // by local side.
 | 
|  TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) {
 | 
|    Init();
 | 
| -  // Send video only to match the |kSdpWithRtx|.
 | 
| -  SendVideoOnlyStream2();
 | 
| +  SendAudioVideoStream1();
 | 
|    std::string offer_sdp(kSdpWithRtx);
 | 
|  
 | 
|    SessionDescriptionInterface* offer =
 | 
| @@ -4474,11 +4251,6 @@
 | 
|    EXPECT_TRUE(ContainsVideoCodecWithName(offer, "rtx"));
 | 
|    SetRemoteDescriptionWithoutError(offer);
 | 
|  
 | 
| -  // |offered_media_sections_| is used when creating answer.
 | 
| -  offered_media_sections_.push_back(cricket::MediaDescriptionOptions(
 | 
| -      cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
 | 
| -      cricket::RtpTransceiverDirection(true, true), false));
 | 
| -  // Don't create media section for audio in the answer.
 | 
|    SessionDescriptionInterface* answer = CreateAnswer();
 | 
|    // Answer SDP does not contain the RTX codec.
 | 
|    EXPECT_FALSE(ContainsVideoCodecWithName(answer, "rtx"));
 | 
| @@ -4544,7 +4316,8 @@
 | 
|    options.offer_to_receive_audio =
 | 
|        RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
 | 
|    cricket::MediaSessionOptions session_options;
 | 
| -  GetOptionsForOffer(options, &session_options);
 | 
| +  session_options.recv_audio = true;
 | 
| +
 | 
|    for (auto& o : observers) {
 | 
|      o = new WebRtcSessionCreateSDPObserverForTest();
 | 
|      session_->CreateOffer(o, options, session_options);
 | 
| 
 |