 Chromium Code Reviews
 Chromium Code Reviews Issue 2991693002:
  Adding support for Unified Plan offer/answer negotiation.  (Closed)
    
  
    Issue 2991693002:
  Adding support for Unified Plan offer/answer negotiation.  (Closed) 
  | Index: webrtc/pc/webrtcsession_unittest.cc | 
| diff --git a/webrtc/pc/webrtcsession_unittest.cc b/webrtc/pc/webrtcsession_unittest.cc | 
| index f6d334e3e42dcfd8d8b977c52b9cf1933fbe40de..77685fcc609c4ec59799b4e6f1cad61eb6a1d170 100644 | 
| --- a/webrtc/pc/webrtcsession_unittest.cc | 
| +++ b/webrtc/pc/webrtcsession_unittest.cc | 
| @@ -398,7 +398,6 @@ class WebRtcSessionTest | 
| 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); | 
| } | 
| @@ -512,6 +511,8 @@ class WebRtcSessionTest | 
| send_stream_2_ = false; | 
| send_audio_ = true; | 
| send_video_ = true; | 
| + recv_audio_ = true; | 
| + recv_video_ = true; | 
| 
Taylor Brandstetter
2017/07/28 19:00:26
It's not obvious why "SendAudioVideoStream1" would
 
Zhi Huang
2017/08/02 04:38:37
I realized that we don't need to set recv_X actual
 | 
| } | 
| void SendAudioVideoStream2() { | 
| @@ -519,6 +520,8 @@ class WebRtcSessionTest | 
| send_stream_2_ = true; | 
| send_audio_ = true; | 
| send_video_ = true; | 
| + recv_audio_ = true; | 
| + recv_video_ = true; | 
| } | 
| void SendAudioVideoStream1And2() { | 
| @@ -526,6 +529,8 @@ class WebRtcSessionTest | 
| send_stream_2_ = true; | 
| send_audio_ = true; | 
| send_video_ = true; | 
| + recv_audio_ = true; | 
| + recv_video_ = true; | 
| } | 
| void SendNothing() { | 
| @@ -540,6 +545,8 @@ class WebRtcSessionTest | 
| send_stream_2_ = true; | 
| send_audio_ = true; | 
| send_video_ = false; | 
| + recv_audio_ = true; | 
| + recv_video_ = true; | 
| } | 
| void SendVideoOnlyStream2() { | 
| @@ -547,69 +554,195 @@ class WebRtcSessionTest | 
| send_stream_2_ = true; | 
| send_audio_ = false; | 
| send_video_ = true; | 
| + recv_audio_ = true; | 
| + recv_video_ = true; | 
| } | 
| - void AddStreamsToOptions(cricket::MediaSessionOptions* session_options) { | 
| - if (send_stream_1_ && send_audio_) { | 
| - session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1, | 
| - kStream1); | 
| - } | 
| - if (send_stream_1_ && send_video_) { | 
| - session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1, | 
| - kStream1); | 
| + // Helper function used to add a specific media section to the | 
| + // |session_options|. | 
| + void AddMediaSection(cricket::MediaType type, | 
| + const std::string& mid, | 
| + bool send, | 
| + bool recv, | 
| + bool stopped, | 
| 
Taylor Brandstetter
2017/07/28 19:00:26
Similar comment for this as for AddMediaSection in
 
Zhi Huang
2017/08/02 04:38:37
Done.
 | 
| + cricket::MediaSessionOptions& session_options) { | 
| + session_options.media_description_options.push_back( | 
| + cricket::MediaDescriptionOptions( | 
| + type, mid, cricket::RtpTransceiverDirection(send, recv), stopped)); | 
| + } | 
| + | 
| + // Add the media sections to the options from |offered_media_sections_| when | 
| + // creating an answer or a new offer. | 
| 
Taylor Brandstetter
2017/07/28 19:00:27
Can you add a comment mentioning that this duplica
 
Zhi Huang
2017/08/02 04:38:37
Done.
 | 
| + 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); | 
| + audio_section_added_ = true; | 
| + } 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); | 
| + video_section_added_ = true; | 
| + } 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)); | 
| + data_section_added_ = true; | 
| + } else { | 
| + RTC_NOTREACHED(); | 
| + } | 
| } | 
| - if (send_stream_2_ && send_audio_) { | 
| - session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2, | 
| - kStream2); | 
| + } | 
| + | 
| + // Add the existing media sections first and then add new media sections if | 
| + // needed. | 
| + void AddMediaSectionsAndSendersToOptions( | 
| + cricket::MediaSessionOptions* session_options, | 
| + bool recv_audio, | 
| + bool recv_video) { | 
| + audio_section_added_ = false; | 
| + video_section_added_ = false; | 
| + data_section_added_ = false; | 
| 
Taylor Brandstetter
2017/07/28 19:00:26
nit: Using member variables here seems error-prone
 
Zhi Huang
2017/08/02 04:38:36
Done.
 | 
| + AddExistingMediaSectionsAndSendersToOptions( | 
| + session_options, send_audio_, recv_audio, send_video_, recv_video); | 
| + | 
| + if (!audio_section_added_ && (send_audio_ || recv_audio)) { | 
| + cricket::MediaDescriptionOptions media_desc_options = | 
| + cricket::MediaDescriptionOptions( | 
| + cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, | 
| + cricket::RtpTransceiverDirection(send_audio_, recv_audio), true); | 
| + 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_2_ && send_video_) { | 
| - session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2, | 
| - kStream2); | 
| + | 
| + if (!video_section_added_ && (send_video_ || recv_video)) { | 
| + cricket::MediaDescriptionOptions media_desc_options = | 
| + cricket::MediaDescriptionOptions( | 
| + cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, | 
| + cricket::RtpTransceiverDirection(send_video_, recv_video), true); | 
| + 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 (data_channel_ && session_->data_channel_type() == cricket::DCT_RTP) { | 
| - session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, | 
| - data_channel_->label(), | 
| - data_channel_->label()); | 
| + | 
| + if (!data_section_added_ && | 
| + (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), false); | 
| + 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); | 
| } | 
| } | 
| void GetOptionsForOffer( | 
| const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 
| cricket::MediaSessionOptions* session_options) { | 
| - ASSERT_TRUE(ExtractMediaSessionOptions(rtc_options, true, session_options)); | 
| + ExtractSharedMediaSessionOptions(rtc_options, session_options); | 
| + | 
| + // |recv_X| is true by default if |offer_to_receive_X| is undefined. | 
| + bool recv_audio = | 
| 
Taylor Brandstetter
2017/07/28 19:00:26
Couldn't this just be:
bool recv_audio = rtc_opti
 
Zhi Huang
2017/08/02 04:38:37
Done.
 | 
| + rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined | 
| + ? true | 
| + : (rtc_options.offer_to_receive_audio > 0); | 
| + bool recv_video = | 
| + rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined | 
| + ? true | 
| + : (rtc_options.offer_to_receive_video > 0); | 
| + AddMediaSectionsAndSendersToOptions(session_options, recv_audio, | 
| + recv_video); | 
| + session_options->bundle_enabled = | 
| + session_options->bundle_enabled && | 
| + (session_options->has_audio() || session_options->has_video() || | 
| + session_options->has_data()); | 
| + | 
| + session_options->crypto_options = crypto_options_; | 
| + } | 
| + | 
| + void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) { | 
| + // |recv_X| is true if callee wants to receive or the caller wants to send. | 
| + bool recv_audio = recv_audio_ || send_audio_; | 
| + bool recv_video = recv_video_ || send_video_; | 
| + bool send_audio = false; | 
| + bool send_video = false; | 
| + | 
| + AddExistingMediaSectionsAndSendersToOptions( | 
| + session_options, send_audio, recv_audio, send_video, recv_video); | 
| - 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; | 
| + if (session_->data_channel_type() != cricket::DCT_RTP) { | 
| + session_options->data_channel_type = session_->data_channel_type(); | 
| } | 
| session_options->crypto_options = crypto_options_; | 
| } | 
| - void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) { | 
| - // ParseConstraintsForAnswer is used to set some defaults. | 
| - ASSERT_TRUE(webrtc::ParseConstraintsForAnswer(nullptr, session_options)); | 
| + void GetOptionsForAudioOnlyRemoteOffer( | 
| + cricket::MediaSessionOptions* session_options) { | 
| + recv_audio_ = true; | 
| + recv_video_ = false; | 
| + GetOptionsForRemoteOffer(session_options); | 
| + } | 
| - AddStreamsToOptions(session_options); | 
| + void GetOptionsForRemoteOffer(cricket::MediaSessionOptions* session_options) { | 
| + AddMediaSectionsAndSendersToOptions(session_options, recv_audio_, | 
| + recv_video_); | 
| session_options->bundle_enabled = | 
| - session_options->bundle_enabled && | 
| (session_options->has_audio() || session_options->has_video() || | 
| session_options->has_data()); | 
| @@ -635,7 +768,6 @@ class WebRtcSessionTest | 
| PeerConnectionInterface::RTCOfferAnswerOptions options; | 
| options.offer_to_receive_audio = | 
| RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; | 
| - | 
| return CreateOffer(options); | 
| } | 
| @@ -658,9 +790,6 @@ class WebRtcSessionTest | 
| = 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, | 
| @@ -670,8 +799,7 @@ class WebRtcSessionTest | 
| SessionDescriptionInterface* CreateAnswer() { | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| - options.recv_audio = true; | 
| + options.bundle_enabled = true; | 
| 
Taylor Brandstetter
2017/07/28 19:00:26
It seems odd to set bundle_enabled to true here, b
 
Zhi Huang
2017/08/02 04:38:37
The helper methods here are different. For answer,
 
Taylor Brandstetter
2017/08/03 00:24:48
Acknowledged; sorry for glossing over that.
 | 
| return CreateAnswer(options); | 
| } | 
| @@ -789,7 +917,7 @@ class WebRtcSessionTest | 
| void VerifyAnswerFromNonCryptoOffer() { | 
| // Create an SDP without Crypto. | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| JsepSessionDescription* offer( | 
| CreateRemoteOffer(options, cricket::SEC_DISABLED)); | 
| ASSERT_TRUE(offer != NULL); | 
| @@ -803,7 +931,7 @@ class WebRtcSessionTest | 
| void VerifyAnswerFromCryptoOffer() { | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| options.bundle_enabled = true; | 
| std::unique_ptr<JsepSessionDescription> offer( | 
| CreateRemoteOffer(options, cricket::SEC_REQUIRED)); | 
| @@ -992,21 +1120,26 @@ class WebRtcSessionTest | 
| SessionDescriptionInterface** nocrypto_answer) { | 
| // Create a SDP without Crypto. | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| options.bundle_enabled = true; | 
| *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED); | 
| ASSERT_TRUE(*offer != NULL); | 
| VerifyCryptoParams((*offer)->description()); | 
| - *nocrypto_answer = CreateRemoteAnswer(*offer, options, | 
| - cricket::SEC_DISABLED); | 
| + cricket::MediaSessionOptions answer_options; | 
| + GetOptionsForAnswer(&answer_options); | 
| + *nocrypto_answer = | 
| + CreateRemoteAnswer(*offer, answer_options, cricket::SEC_DISABLED); | 
| EXPECT_TRUE(*nocrypto_answer != NULL); | 
| } | 
| void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer, | 
| SessionDescriptionInterface** nodtls_answer) { | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, | 
| + false /*send*/, true /*recv*/, false, options); | 
| + AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, | 
| + false /*send*/, true /*recv*/, false, options); | 
| options.bundle_enabled = true; | 
| std::unique_ptr<SessionDescriptionInterface> temp_offer( | 
| @@ -1068,8 +1201,7 @@ class WebRtcSessionTest | 
| const char* sctp_stream_name, int new_port, | 
| cricket::MediaSessionOptions options) { | 
| options.data_channel_type = cricket::DCT_SCTP; | 
| - options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel", | 
| - sctp_stream_name); | 
| + GetOptionsForRemoteOffer(&options); | 
| return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options)); | 
| } | 
| @@ -1097,7 +1229,7 @@ class WebRtcSessionTest | 
| // before this function to decide which streams to create. | 
| JsepSessionDescription* CreateRemoteOffer() { | 
| cricket::MediaSessionOptions options; | 
| - GetOptionsForAnswer(&options); | 
| + GetOptionsForRemoteOffer(&options); | 
| return CreateRemoteOffer(options, session_->remote_description()); | 
| } | 
| @@ -1132,6 +1264,7 @@ class WebRtcSessionTest | 
| const SessionDescriptionInterface* offer) { | 
| cricket::MediaSessionOptions options; | 
| GetOptionsForAnswer(&options); | 
| + options.bundle_enabled = true; | 
| return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); | 
| } | 
| @@ -1455,6 +1588,7 @@ class WebRtcSessionTest | 
| 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); | 
| @@ -1462,16 +1596,19 @@ class WebRtcSessionTest | 
| } | 
| PeerConnectionInterface::RTCOfferAnswerOptions options; | 
| - cricket::MediaSessionOptions session_options; | 
| + cricket::MediaSessionOptions offer_session_options; | 
| + cricket::MediaSessionOptions answer_session_options; | 
| + GetOptionsForOffer(options, &offer_session_options); | 
| + GetOptionsForAnswer(&answer_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, session_options); | 
| + session_->CreateOffer(observers[i], options, offer_session_options); | 
| } else { | 
| - session_->CreateAnswer(observers[i], session_options); | 
| + session_->CreateAnswer(observers[i], answer_session_options); | 
| } | 
| } | 
| @@ -1531,6 +1668,12 @@ class WebRtcSessionTest | 
| bool send_stream_2_ = false; | 
| bool send_audio_ = false; | 
| bool send_video_ = false; | 
| + bool recv_audio_ = true; | 
| + bool recv_video_ = true; | 
| + bool audio_section_added_ = false; | 
| + bool video_section_added_ = false; | 
| + bool data_section_added_ = false; | 
| + std::vector<cricket::MediaDescriptionOptions> offered_media_sections_; | 
| rtc::scoped_refptr<DataChannel> data_channel_; | 
| // Last values received from data channel creation signal. | 
| std::string last_data_channel_label_; | 
| @@ -1770,7 +1913,7 @@ TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) { | 
| TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) { | 
| Init(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| JsepSessionDescription* offer = CreateRemoteOffer( | 
| options, cricket::SEC_DISABLED); | 
| ASSERT_TRUE(offer != NULL); | 
| @@ -1816,7 +1959,7 @@ TEST_P(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) { | 
| InitWithDtls(GetParam()); | 
| SetFactoryDtlsSrtp(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| JsepSessionDescription* offer = | 
| CreateRemoteOffer(options, cricket::SEC_DISABLED); | 
| ASSERT_TRUE(offer != NULL); | 
| @@ -1855,7 +1998,7 @@ TEST_P(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) { | 
| SetLocalDescriptionWithoutError(offer); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForAnswer(&options); | 
| JsepSessionDescription* answer = | 
| CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); | 
| ASSERT_TRUE(answer != NULL); | 
| @@ -1871,7 +2014,7 @@ TEST_P(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) { | 
| TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) { | 
| InitWithDtls(GetParam()); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| options.bundle_enabled = true; | 
| JsepSessionDescription* offer = CreateRemoteOffer( | 
| options, cricket::SEC_REQUIRED); | 
| @@ -1909,12 +2052,16 @@ TEST_P(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) { | 
| TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) { | 
| InitWithDtls(GetParam()); | 
| SessionDescriptionInterface* offer = CreateOffer(); | 
| - cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + cricket::MediaSessionOptions offer_options; | 
| + GetOptionsForRemoteOffer(&offer_options); | 
| + | 
| std::unique_ptr<SessionDescriptionInterface> temp_offer( | 
| - CreateRemoteOffer(options, cricket::SEC_ENABLED)); | 
| - JsepSessionDescription* answer = | 
| - CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED); | 
| + CreateRemoteOffer(offer_options, cricket::SEC_ENABLED)); | 
| + | 
| + cricket::MediaSessionOptions answer_options; | 
| + GetOptionsForAnswer(&answer_options); | 
| + JsepSessionDescription* answer = CreateRemoteAnswer( | 
| + temp_offer.get(), answer_options, cricket::SEC_ENABLED); | 
| // SetRemoteDescription and SetLocalDescription will take the ownership of | 
| // the offer and answer. | 
| @@ -1941,7 +2088,7 @@ TEST_P(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) { | 
| SetLocalDescriptionWithoutError(offer); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForAnswer(&options); | 
| JsepSessionDescription* answer = | 
| CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); | 
| ASSERT_TRUE(answer != NULL); | 
| @@ -1959,7 +2106,7 @@ TEST_P(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) { | 
| InitWithDtls(GetParam()); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| JsepSessionDescription* offer = | 
| CreateRemoteOffer(options, cricket::SEC_DISABLED); | 
| ASSERT_TRUE(offer != NULL); | 
| @@ -1992,7 +2139,7 @@ TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) { | 
| SetLocalDescriptionWithoutError(offer); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForAnswer(&options); | 
| // First, negotiate different SSL roles. | 
| SessionDescriptionInterface* answer = | 
| @@ -2014,7 +2161,9 @@ TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) { | 
| session_->remote_description()); | 
| SetRemoteDescriptionWithoutError(offer); | 
| - answer = CreateAnswer(); | 
| + cricket::MediaSessionOptions answer_options; | 
| + answer_options.bundle_enabled = true; | 
| + answer = CreateAnswer(answer_options); | 
| audio_transport_info = answer->description()->GetTransportInfoByName("audio"); | 
| EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE, | 
| audio_transport_info->description.connection_role); | 
| @@ -2031,7 +2180,7 @@ TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) { | 
| kSessionVersion, | 
| session_->remote_description()); | 
| SetRemoteDescriptionWithoutError(offer); | 
| - answer = CreateAnswer(); | 
| + answer = CreateAnswer(answer_options); | 
| audio_transport_info = answer->description()->GetTransportInfoByName("audio"); | 
| EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE, | 
| audio_transport_info->description.connection_role); | 
| @@ -2392,6 +2541,7 @@ TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) { | 
| 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()); | 
| @@ -2417,42 +2567,27 @@ TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) { | 
| // 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); | 
| - SessionDescriptionInterface* answer = CreateAnswer(); | 
| + cricket::MediaSessionOptions answer_options; | 
| + answer_options.bundle_enabled = false; | 
| + SessionDescriptionInterface* answer = CreateAnswer(answer_options); | 
| 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_content_name " + | 
| - std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP)); | 
| + "audio " + 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_content_name " + | 
| - std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP)); | 
| + "video " + 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); | 
| } | 
| @@ -2466,9 +2601,17 @@ TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) { | 
| ASSERT_TRUE(offer != NULL); | 
| const cricket::ContentInfo* content = | 
| cricket::GetFirstAudioContent(offer->description()); | 
| - EXPECT_TRUE(content != NULL); | 
| + ASSERT_TRUE(content != NULL); | 
| + EXPECT_EQ( | 
| + cricket::MD_RECVONLY, | 
| + static_cast<const cricket::AudioContentDescription*>(content->description) | 
| + ->direction()); | 
| content = cricket::GetFirstVideoContent(offer->description()); | 
| - EXPECT_TRUE(content == NULL); | 
| + ASSERT_TRUE(content != NULL); | 
| + EXPECT_EQ( | 
| + cricket::MD_RECVONLY, | 
| + static_cast<const cricket::VideoContentDescription*>(content->description) | 
| + ->direction()); | 
| } | 
| // Test that an offer contains the correct media content descriptions based on | 
| @@ -2481,17 +2624,34 @@ TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) { | 
| const cricket::ContentInfo* content = | 
| cricket::GetFirstAudioContent(offer->description()); | 
| - EXPECT_TRUE(content != NULL); | 
| + ASSERT_TRUE(content != NULL); | 
| + EXPECT_EQ( | 
| + cricket::MD_SENDRECV, | 
| + static_cast<const cricket::AudioContentDescription*>(content->description) | 
| + ->direction()); | 
| content = cricket::GetFirstVideoContent(offer->description()); | 
| - EXPECT_TRUE(content == NULL); | 
| + ASSERT_TRUE(content != NULL); | 
| + EXPECT_EQ( | 
| + cricket::MD_RECVONLY, | 
| + static_cast<const cricket::VideoContentDescription*>(content->description) | 
| + ->direction()); | 
| // Test Audio / Video offer. | 
| SendAudioVideoStream1(); | 
| offer.reset(CreateOffer()); | 
| content = cricket::GetFirstAudioContent(offer->description()); | 
| - EXPECT_TRUE(content != NULL); | 
| + ASSERT_TRUE(content != NULL); | 
| + EXPECT_EQ( | 
| + cricket::MD_SENDRECV, | 
| + static_cast<const cricket::AudioContentDescription*>(content->description) | 
| + ->direction()); | 
| + | 
| content = cricket::GetFirstVideoContent(offer->description()); | 
| - EXPECT_TRUE(content != NULL); | 
| + ASSERT_TRUE(content != NULL); | 
| + EXPECT_EQ( | 
| + cricket::MD_SENDRECV, | 
| + static_cast<const cricket::VideoContentDescription*>(content->description) | 
| + ->direction()); | 
| } | 
| // Test that an offer contains no media content descriptions if | 
| @@ -2519,6 +2679,7 @@ TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) { | 
| PeerConnectionInterface::RTCOfferAnswerOptions options; | 
| options.offer_to_receive_audio = | 
| RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; | 
| + options.offer_to_receive_video = 0; | 
| std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options)); | 
| @@ -2553,6 +2714,8 @@ TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) { | 
| // 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()); | 
| @@ -2596,6 +2759,7 @@ TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) { | 
| 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); | 
| @@ -2640,8 +2804,8 @@ TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) { | 
| SetRemoteDescriptionWithoutError(offer.release()); | 
| cricket::MediaSessionOptions session_options; | 
| - session_options.recv_audio = false; | 
| - session_options.recv_video = false; | 
| + recv_audio_ = false; | 
| + recv_video_ = false; | 
| std::unique_ptr<SessionDescriptionInterface> answer( | 
| CreateAnswer(session_options)); | 
| @@ -2664,9 +2828,6 @@ TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) { | 
| 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)); | 
| @@ -2726,6 +2887,10 @@ TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) { | 
| SessionDescriptionInterface* offer = CreateOffer(); | 
| cricket::MediaSessionOptions options; | 
| + AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, false /*send*/, | 
| + true /*recv*/, false, options); | 
| + AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, false /*send*/, | 
| + false /*recv*/, true, options); | 
| SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options); | 
| // SetLocalDescription and SetRemoteDescriptions takes ownership of offer | 
| @@ -2782,10 +2947,13 @@ TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) { | 
| SessionDescriptionInterface* offer = CreateOffer(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_audio = false; | 
| - options.recv_video = true; | 
| - SessionDescriptionInterface* answer = CreateRemoteAnswer( | 
| - offer, options, cricket::SEC_ENABLED); | 
| + AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, false /*send*/, | 
| + false /*recv*/, true, options); | 
| + AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, false /*send*/, | 
| + true /*recv*/, false, options); | 
| + | 
| + SessionDescriptionInterface* answer = | 
| + CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED); | 
| // SetLocalDescription and SetRemoteDescriptions takes ownership of offer | 
| // and answer. | 
| @@ -3025,13 +3193,16 @@ TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) { | 
| InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced); | 
| SendAudioVideoStream1(); | 
| - PeerConnectionInterface::RTCOfferAnswerOptions options; | 
| - options.use_rtp_mux = true; | 
| + cricket::MediaSessionOptions offer_options; | 
| + GetOptionsForRemoteOffer(&offer_options); | 
| + offer_options.bundle_enabled = true; | 
| - SessionDescriptionInterface* offer = CreateRemoteOffer(); | 
| + SessionDescriptionInterface* offer = CreateRemoteOffer(offer_options); | 
| SetRemoteDescriptionWithoutError(offer); | 
| - SessionDescriptionInterface* answer = CreateAnswer(); | 
| + cricket::MediaSessionOptions answer_options; | 
| + answer_options.bundle_enabled = true; | 
| + SessionDescriptionInterface* answer = CreateAnswer(answer_options); | 
| SetLocalDescriptionWithoutError(answer); | 
| EXPECT_EQ(session_->voice_rtp_transport_channel(), | 
| @@ -3196,10 +3367,10 @@ TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) { | 
| EXPECT_EQ(session_->voice_rtp_transport_channel(), | 
| session_->video_rtp_transport_channel()); | 
| - SendAudioVideoStream2(); | 
| + SendVideoOnlyStream2(); | 
| cricket::MediaSessionOptions recv_options; | 
| - recv_options.recv_audio = false; | 
| - recv_options.recv_video = true; | 
| + recv_audio_ = false; | 
| + GetOptionsForAnswer(&recv_options); | 
| SessionDescriptionInterface* answer = | 
| CreateRemoteAnswer(session_->local_description(), recv_options); | 
| SetRemoteDescriptionWithoutError(answer); | 
| @@ -3286,10 +3457,10 @@ TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) { | 
| InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat); | 
| SendAudioVideoStream1(); | 
| - PeerConnectionInterface::RTCOfferAnswerOptions options; | 
| - options.use_rtp_mux = true; | 
| + PeerConnectionInterface::RTCOfferAnswerOptions rtc_options; | 
| + rtc_options.use_rtp_mux = true; | 
| - SessionDescriptionInterface* offer = CreateOffer(options); | 
| + SessionDescriptionInterface* offer = CreateOffer(rtc_options); | 
| SetLocalDescriptionWithoutError(offer); | 
| EXPECT_NE(session_->voice_rtp_transport_channel(), | 
| @@ -3645,7 +3816,7 @@ TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) { | 
| TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) { | 
| Init(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options)); | 
| SetRemoteDescriptionWithoutError(offer.release()); | 
| @@ -3656,7 +3827,8 @@ TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) { | 
| // Receive an offer with new ufrag and password. | 
| for (const cricket::ContentInfo& content : | 
| session_->local_description()->description()->contents()) { | 
| - options.transport_options[content.name].ice_restart = true; | 
| + auto it = options.FindMediaDescription(content.name); | 
| 
Taylor Brandstetter
2017/07/28 19:00:26
"ASSERT_NE(options.media_description_options.end()
 
Zhi Huang
2017/08/02 04:38:36
We can change this to index based iteration.
 | 
| + it->transport_options.ice_restart = true; | 
| } | 
| std::unique_ptr<JsepSessionDescription> updated_offer1( | 
| CreateRemoteOffer(options, session_->remote_description())); | 
| @@ -3685,8 +3857,7 @@ TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) { | 
| TEST_F(WebRtcSessionTest, TestOfferChangingOnlyUfragOrPassword) { | 
| Init(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_audio = true; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| // Create an offer with audio and video. | 
| std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options)); | 
| SetIceUfragPwd(offer.get(), "original_ufrag", "original_password12345"); | 
| @@ -3726,7 +3897,7 @@ TEST_F(WebRtcSessionTest, TestOfferChangingOnlyUfragOrPassword) { | 
| TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) { | 
| Init(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options)); | 
| SetRemoteDescriptionWithoutError(offer.release()); | 
| @@ -3753,8 +3924,7 @@ TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) { | 
| TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewAndOldUfragAndPassword) { | 
| Init(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| - options.recv_audio = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| options.bundle_enabled = false; | 
| std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options)); | 
| @@ -3886,9 +4056,9 @@ TEST_P(WebRtcSessionTest, SctpContentAndTransportName) { | 
| // 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()); | 
| @@ -3912,6 +4082,7 @@ TEST_P(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) { | 
| // 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); | 
| @@ -4055,7 +4226,7 @@ TEST_P(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) { | 
| SetFactoryDtlsSrtp(); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| std::unique_ptr<JsepSessionDescription> offer( | 
| CreateRemoteOffer(options, cricket::SEC_DISABLED)); | 
| ASSERT_TRUE(offer.get() != NULL); | 
| @@ -4129,6 +4300,7 @@ TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) { | 
| 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. | 
| @@ -4172,7 +4344,7 @@ TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) { | 
| SetRemoteDescriptionWithoutError(answer); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); | 
| cricket::Candidate candidate1; | 
| @@ -4201,7 +4373,7 @@ TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) { | 
| SetRemoteDescriptionWithoutError(answer); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_video = true; | 
| + GetOptionsForRemoteOffer(&options); | 
| offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); | 
| SetRemoteDescriptionWithoutError(offer); | 
| @@ -4226,8 +4398,7 @@ TEST_P(WebRtcSessionTest, TestNegotiateQuic) { | 
| ASSERT_TRUE(offer->description()); | 
| SetLocalDescriptionWithoutError(offer); | 
| cricket::MediaSessionOptions options; | 
| - options.recv_audio = true; | 
| - options.recv_video = true; | 
| + GetOptionsForAnswer(&options); | 
| SessionDescriptionInterface* answer = | 
| CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); | 
| ASSERT_TRUE(answer); | 
| @@ -4240,7 +4411,8 @@ TEST_P(WebRtcSessionTest, TestNegotiateQuic) { | 
| // by local side. | 
| TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) { | 
| Init(); | 
| - SendAudioVideoStream1(); | 
| + // Send video only to match the |kSdpWithRtx|. | 
| + SendVideoOnlyStream2(); | 
| std::string offer_sdp(kSdpWithRtx); | 
| SessionDescriptionInterface* offer = | 
| @@ -4251,6 +4423,11 @@ TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) { | 
| 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")); | 
| @@ -4316,8 +4493,7 @@ TEST_F(WebRtcSessionTest, CreateOffersAndShutdown) { | 
| options.offer_to_receive_audio = | 
| RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; | 
| cricket::MediaSessionOptions session_options; | 
| - session_options.recv_audio = true; | 
| - | 
| + GetOptionsForOffer(options, &session_options); | 
| for (auto& o : observers) { | 
| o = new WebRtcSessionCreateSDPObserverForTest(); | 
| session_->CreateOffer(o, options, session_options); |