Adds the support of RTCOfferOptions for PeerConnectionInterface::CreateOffer.
Constraints are still supported for CreateOffer, but converted to RTCOfferOptions internally.

BUG=3282
R=pthatcher@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/20029004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6822 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/mediastreamsignaling.cc b/talk/app/webrtc/mediastreamsignaling.cc
index 2d30cc2..7cdd5ed 100644
--- a/talk/app/webrtc/mediastreamsignaling.cc
+++ b/talk/app/webrtc/mediastreamsignaling.cc
@@ -127,6 +127,12 @@
   return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV;
 }
 
+static bool IsValidOfferToReceiveMedia(int value) {
+  typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
+  return (value >= Options::kUndefined) &&
+      (value <= Options::kMaxOfferToReceiveMedia);
+}
+
 // Factory class for creating remote MediaStreams and MediaStreamTracks.
 class RemoteMediaStreamFactory {
  public:
@@ -363,14 +369,32 @@
 }
 
 bool MediaStreamSignaling::GetOptionsForOffer(
-    const MediaConstraintsInterface* constraints,
-    cricket::MediaSessionOptions* options) {
-  UpdateSessionOptions();
-  if (!ParseConstraints(constraints, &options_, false)) {
+    const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
+    cricket::MediaSessionOptions* session_options) {
+  typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
+  if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) ||
+      !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) {
     return false;
   }
+
+  UpdateSessionOptions();
+
+  // |options.has_audio| and |options.has_video| can only change from false to
+  // true, but never change from true to false. This is to make sure
+  // CreateOffer / CreateAnswer doesn't remove a media content
+  // description that has been created.
+  if (rtc_options.offer_to_receive_audio > 0) {
+    options_.has_audio = true;
+  }
+  if (rtc_options.offer_to_receive_video > 0) {
+    options_.has_video = true;
+  }
+  options_.vad_enabled = rtc_options.voice_activity_detection;
+  options_.transport_options.ice_restart = rtc_options.ice_restart;
+  options_.bundle_enabled = rtc_options.use_rtp_mux;
+
   options_.bundle_enabled = EvaluateNeedForBundle(options_);
-  *options = options_;
+  *session_options = options_;
   return true;
 }
 
diff --git a/talk/app/webrtc/mediastreamsignaling.h b/talk/app/webrtc/mediastreamsignaling.h
index ac8a02a..214c6a1 100644
--- a/talk/app/webrtc/mediastreamsignaling.h
+++ b/talk/app/webrtc/mediastreamsignaling.h
@@ -200,11 +200,11 @@
                                      const rtc::Buffer& payload);
   void RemoveSctpDataChannel(int sid);
 
-  // Returns a MediaSessionOptions struct with options decided by |constraints|,
+  // Returns a MediaSessionOptions struct with options decided by |options|,
   // the local MediaStreams and DataChannels.
   virtual bool GetOptionsForOffer(
-      const MediaConstraintsInterface* constraints,
-      cricket::MediaSessionOptions* options);
+      const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
+      cricket::MediaSessionOptions* session_options);
 
   // Returns a MediaSessionOptions struct with options decided by
   // |constraints|, the local MediaStreams and DataChannels.
diff --git a/talk/app/webrtc/mediastreamsignaling_unittest.cc b/talk/app/webrtc/mediastreamsignaling_unittest.cc
index 259f4c0..3c89d49 100644
--- a/talk/app/webrtc/mediastreamsignaling_unittest.cc
+++ b/talk/app/webrtc/mediastreamsignaling_unittest.cc
@@ -62,11 +62,14 @@
 using webrtc::MediaConstraintsInterface;
 using webrtc::MediaStreamInterface;
 using webrtc::MediaStreamTrackInterface;
+using webrtc::PeerConnectionInterface;
 using webrtc::SdpParseError;
 using webrtc::SessionDescriptionInterface;
 using webrtc::StreamCollection;
 using webrtc::StreamCollectionInterface;
 
+typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
+
 // Reference SDP with a MediaStream with label "stream1" and audio track with
 // id "audio_1" and a video track with id "video_1;
 static const char kSdpStringWithStream1[] =
@@ -588,115 +591,137 @@
   rtc::scoped_ptr<FakeDataChannelProvider> data_channel_provider_;
 };
 
+TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidAudioOption) {
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
+
+  cricket::MediaSessionOptions options;
+  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
+
+  rtc_options.offer_to_receive_audio =
+      RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
+  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
+}
+
+
+TEST_F(MediaStreamSignalingTest, GetOptionsForOfferWithInvalidVideoOption) {
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.offer_to_receive_video =
+      RTCOfferAnswerOptions::kUndefined - 1;
+
+  cricket::MediaSessionOptions options;
+  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
+
+  rtc_options.offer_to_receive_video =
+      RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
+  EXPECT_FALSE(signaling_->GetOptionsForOffer(rtc_options, &options));
+}
+
 // Test that a MediaSessionOptions is created for an offer if
-// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set but no
+// OfferToReceiveAudio and OfferToReceiveVideo options are set but no
 // MediaStreams are sent.
 TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
-  FakeConstraints constraints;
-  constraints.SetMandatoryReceiveAudio(true);
-  constraints.SetMandatoryReceiveVideo(true);
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.offer_to_receive_audio = 1;
+  rtc_options.offer_to_receive_video = 1;
+
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   EXPECT_TRUE(options.has_audio);
   EXPECT_TRUE(options.has_video);
   EXPECT_TRUE(options.bundle_enabled);
 }
 
 // Test that a correct MediaSessionOptions is created for an offer if
-// kOfferToReceiveAudio constraints is set but no MediaStreams are sent.
+// OfferToReceiveAudio is set but no MediaStreams are sent.
 TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithAudio) {
-  FakeConstraints constraints;
-  constraints.SetMandatoryReceiveAudio(true);
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.offer_to_receive_audio = 1;
+
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   EXPECT_TRUE(options.has_audio);
   EXPECT_FALSE(options.has_video);
   EXPECT_TRUE(options.bundle_enabled);
 }
 
 // Test that a correct MediaSessionOptions is created for an offer if
-// no constraints or MediaStreams are sent.
+// the default OfferOptons is used or MediaStreams are sent.
 TEST_F(MediaStreamSignalingTest, GetDefaultMediaSessionOptionsForOffer) {
+  RTCOfferAnswerOptions rtc_options;
+
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL, &options));
-  EXPECT_TRUE(options.has_audio);
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
+  EXPECT_FALSE(options.has_audio);
   EXPECT_FALSE(options.has_video);
-  EXPECT_TRUE(options.bundle_enabled);
+  EXPECT_FALSE(options.bundle_enabled);
+  EXPECT_TRUE(options.vad_enabled);
+  EXPECT_FALSE(options.transport_options.ice_restart);
 }
 
 // Test that a correct MediaSessionOptions is created for an offer if
-// kOfferToReceiveVideo constraints is set but no MediaStreams are sent.
+// OfferToReceiveVideo is set but no MediaStreams are sent.
 TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsForOfferWithVideo) {
-  FakeConstraints constraints;
-  constraints.SetMandatoryReceiveAudio(false);
-  constraints.SetMandatoryReceiveVideo(true);
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.offer_to_receive_audio = 0;
+  rtc_options.offer_to_receive_video = 1;
+
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   EXPECT_FALSE(options.has_audio);
   EXPECT_TRUE(options.has_video);
   EXPECT_TRUE(options.bundle_enabled);
 }
 
 // Test that a correct MediaSessionOptions is created for an offer if
-// kUseRtpMux constraints is set to false.
+// UseRtpMux is set to false.
 TEST_F(MediaStreamSignalingTest,
        GetMediaSessionOptionsForOfferWithBundleDisabled) {
-  FakeConstraints constraints;
-  constraints.SetMandatoryReceiveAudio(true);
-  constraints.SetMandatoryReceiveVideo(true);
-  constraints.SetMandatoryUseRtpMux(false);
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.offer_to_receive_audio = 1;
+  rtc_options.offer_to_receive_video = 1;
+  rtc_options.use_rtp_mux = false;
+
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   EXPECT_TRUE(options.has_audio);
   EXPECT_TRUE(options.has_video);
   EXPECT_FALSE(options.bundle_enabled);
 }
 
 // Test that a correct MediaSessionOptions is created to restart ice if
-// kIceRestart constraints is set. It also tests that subsequent
-// MediaSessionOptions don't have |transport_options.ice_restart| set.
+// IceRestart is set. It also tests that subsequent MediaSessionOptions don't
+// have |transport_options.ice_restart| set.
 TEST_F(MediaStreamSignalingTest,
        GetMediaSessionOptionsForOfferWithIceRestart) {
-  FakeConstraints constraints;
-  constraints.SetMandatoryIceRestart(true);
+  RTCOfferAnswerOptions rtc_options;
+  rtc_options.ice_restart = true;
+
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&constraints, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   EXPECT_TRUE(options.transport_options.ice_restart);
 
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL, &options));
+  rtc_options = RTCOfferAnswerOptions();
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   EXPECT_FALSE(options.transport_options.ice_restart);
 }
 
-// Test that GetMediaSessionOptionsForOffer and GetOptionsForAnswer work as
-// expected if unknown constraints are used.
-TEST_F(MediaStreamSignalingTest, GetMediaSessionOptionsWithBadConstraints) {
-  FakeConstraints mandatory;
-  mandatory.AddMandatory("bad_key", "bad_value");
-  cricket::MediaSessionOptions options;
-  EXPECT_FALSE(signaling_->GetOptionsForOffer(&mandatory, &options));
-  EXPECT_FALSE(signaling_->GetOptionsForAnswer(&mandatory, &options));
-
-  FakeConstraints optional;
-  optional.AddOptional("bad_key", "bad_value");
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&optional, &options));
-  EXPECT_TRUE(signaling_->GetOptionsForAnswer(&optional, &options));
-}
-
 // Test that a correct MediaSessionOptions are created for an offer if
 // a MediaStream is sent and later updated with a new track.
 // MediaConstraints are not used.
 TEST_F(MediaStreamSignalingTest, AddTrackToLocalMediaStream) {
+  RTCOfferAnswerOptions rtc_options;
   rtc::scoped_refptr<StreamCollection> local_streams(
       CreateStreamCollection(1));
   MediaStreamInterface* local_stream = local_streams->at(0);
   EXPECT_TRUE(signaling_->AddLocalStream(local_stream));
   cricket::MediaSessionOptions options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   VerifyMediaOptions(local_streams, options);
 
   cricket::MediaSessionOptions updated_options;
   local_stream->AddTrack(AudioTrack::Create(kAudioTracks[1], NULL));
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL, &options));
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(rtc_options, &options));
   VerifyMediaOptions(local_streams, options);
 }
 
@@ -714,21 +739,20 @@
   EXPECT_TRUE(answer_options.has_audio);
   EXPECT_TRUE(answer_options.has_video);
 
-  FakeConstraints offer_c;
-  offer_c.SetMandatoryReceiveAudio(false);
-  offer_c.SetMandatoryReceiveVideo(false);
+  RTCOfferAnswerOptions rtc_offer_optoins;
 
   cricket::MediaSessionOptions offer_options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&offer_c, &offer_options));
+  EXPECT_TRUE(
+      signaling_->GetOptionsForOffer(rtc_offer_optoins, &offer_options));
   EXPECT_FALSE(offer_options.has_audio);
   EXPECT_FALSE(offer_options.has_video);
 
-  FakeConstraints updated_offer_c;
-  updated_offer_c.SetMandatoryReceiveAudio(true);
-  updated_offer_c.SetMandatoryReceiveVideo(true);
+  RTCOfferAnswerOptions updated_rtc_offer_optoins;
+  updated_rtc_offer_optoins.offer_to_receive_audio = 1;
+  updated_rtc_offer_optoins.offer_to_receive_video = 1;
 
   cricket::MediaSessionOptions updated_offer_options;
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(&updated_offer_c,
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(updated_rtc_offer_optoins,
                                              &updated_offer_options));
   EXPECT_TRUE(updated_offer_options.has_audio);
   EXPECT_TRUE(updated_offer_options.has_video);
@@ -748,7 +772,8 @@
   EXPECT_TRUE(updated_answer_options.has_audio);
   EXPECT_TRUE(updated_answer_options.has_video);
 
-  EXPECT_TRUE(signaling_->GetOptionsForOffer(NULL,
+  RTCOfferAnswerOptions default_rtc_options;
+  EXPECT_TRUE(signaling_->GetOptionsForOffer(default_rtc_options,
                                              &updated_offer_options));
   EXPECT_TRUE(updated_offer_options.has_audio);
   EXPECT_TRUE(updated_offer_options.has_video);
diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc
index 089da82..7c02793 100644
--- a/talk/app/webrtc/peerconnection.cc
+++ b/talk/app/webrtc/peerconnection.cc
@@ -508,7 +508,62 @@
     LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
     return;
   }
-  session_->CreateOffer(observer, constraints);
+  RTCOfferAnswerOptions options;
+  // Defaults to receiving audio and not receiving video.
+  options.offer_to_receive_audio =
+      RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+  options.offer_to_receive_video = 0;
+
+  bool value;
+  size_t mandatory_constraints = 0;
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kOfferToReceiveAudio,
+                     &value,
+                     &mandatory_constraints)) {
+    options.offer_to_receive_audio =
+        value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
+  }
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kOfferToReceiveVideo,
+                     &value,
+                     &mandatory_constraints)) {
+    options.offer_to_receive_video =
+        value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
+  }
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kVoiceActivityDetection,
+                     &value,
+                     &mandatory_constraints)) {
+    options.voice_activity_detection = value;
+  }
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kIceRestart,
+                     &value,
+                     &mandatory_constraints)) {
+    options.ice_restart = value;
+  }
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kUseRtpMux,
+                     &value,
+                     &mandatory_constraints)) {
+    options.use_rtp_mux = value;
+  }
+
+  CreateOffer(observer, options);
+}
+
+void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
+                                 const RTCOfferAnswerOptions& options) {
+  if (!VERIFY(observer != NULL)) {
+    LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
+    return;
+  }
+  session_->CreateOffer(observer, options);
 }
 
 void PeerConnection::CreateAnswer(
diff --git a/talk/app/webrtc/peerconnection.h b/talk/app/webrtc/peerconnection.h
index bb4e4eb..b1d4462 100644
--- a/talk/app/webrtc/peerconnection.h
+++ b/talk/app/webrtc/peerconnection.h
@@ -92,6 +92,8 @@
   // JSEP01
   virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
                            const MediaConstraintsInterface* constraints);
+  virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
+                           const RTCOfferAnswerOptions& options);
   virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
                             const MediaConstraintsInterface* constraints);
   virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
diff --git a/talk/app/webrtc/peerconnectioninterface.h b/talk/app/webrtc/peerconnectioninterface.h
index 5c43d3b..59785e8 100644
--- a/talk/app/webrtc/peerconnectioninterface.h
+++ b/talk/app/webrtc/peerconnectioninterface.h
@@ -192,6 +192,38 @@
     explicit RTCConfiguration(IceTransportsType type) : type(type) {}
   };
 
+  struct RTCOfferAnswerOptions {
+    static const int kUndefined = -1;
+    static const int kMaxOfferToReceiveMedia = 1;
+
+    // The default value for constraint offerToReceiveX:true.
+    static const int kOfferToReceiveMediaTrue = 1;
+
+    int offer_to_receive_video;
+    int offer_to_receive_audio;
+    bool voice_activity_detection;
+    bool ice_restart;
+    bool use_rtp_mux;
+
+    RTCOfferAnswerOptions()
+        : offer_to_receive_video(kUndefined),
+          offer_to_receive_audio(kUndefined),
+          voice_activity_detection(true),
+          ice_restart(false),
+          use_rtp_mux(true) {}
+
+    RTCOfferAnswerOptions(int offer_to_receive_video,
+                          int offer_to_receive_audio,
+                          bool voice_activity_detection,
+                          bool ice_restart,
+                          bool use_rtp_mux)
+        : offer_to_receive_video(offer_to_receive_video),
+          offer_to_receive_audio(offer_to_receive_audio),
+          voice_activity_detection(voice_activity_detection),
+          ice_restart(ice_restart),
+          use_rtp_mux(use_rtp_mux) {}
+  };
+
   // Used by GetStats to decide which stats to include in the stats reports.
   // |kStatsOutputLevelStandard| includes the standard stats for Javascript API;
   // |kStatsOutputLevelDebug| includes both the standard stats and additional
@@ -239,7 +271,13 @@
   // Create a new offer.
   // The CreateSessionDescriptionObserver callback will be called when done.
   virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
-                           const MediaConstraintsInterface* constraints) = 0;
+                           const MediaConstraintsInterface* constraints) {}
+
+  // TODO(jiayl): remove the default impl and the old interface when chromium
+  // code is updated.
+  virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
+                           const RTCOfferAnswerOptions& options) {}
+
   // Create an answer to an offer.
   // The CreateSessionDescriptionObserver callback will be called when done.
   virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index 17b05de8..3add7e1 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -693,9 +693,10 @@
   return false;
 }
 
-void WebRtcSession::CreateOffer(CreateSessionDescriptionObserver* observer,
-                                const MediaConstraintsInterface* constraints) {
-  webrtc_session_desc_factory_->CreateOffer(observer, constraints);
+void WebRtcSession::CreateOffer(
+    CreateSessionDescriptionObserver* observer,
+    const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
+  webrtc_session_desc_factory_->CreateOffer(observer, options);
 }
 
 void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer,
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index efab75c..f5de979 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -144,8 +144,9 @@
   // TODO - It may be necessary to supply error code as well.
   sigslot::signal0<> SignalError;
 
-  void CreateOffer(CreateSessionDescriptionObserver* observer,
-                   const MediaConstraintsInterface* constraints);
+  void CreateOffer(
+      CreateSessionDescriptionObserver* observer,
+      const PeerConnectionInterface::RTCOfferAnswerOptions& options);
   void CreateAnswer(CreateSessionDescriptionObserver* observer,
                     const MediaConstraintsInterface* constraints);
   // The ownership of |desc| will be transferred after this call.
diff --git a/talk/app/webrtc/webrtcsession_unittest.cc b/talk/app/webrtc/webrtcsession_unittest.cc
index 51f0c03..b5e1dda 100644
--- a/talk/app/webrtc/webrtcsession_unittest.cc
+++ b/talk/app/webrtc/webrtcsession_unittest.cc
@@ -99,6 +99,8 @@
 using webrtc::kSessionError;
 using webrtc::kSessionErrorDesc;
 
+typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
+
 static const int kClientAddrPort = 0;
 static const char kClientAddrHost1[] = "11.11.11.11";
 static const char kClientAddrHost2[] = "22.22.22.22";
@@ -378,18 +380,26 @@
   // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
   // to decide which streams to create.
   void InitiateCall() {
-    SessionDescriptionInterface* offer = CreateOffer(NULL);
+    SessionDescriptionInterface* offer = CreateOffer();
     SetLocalDescriptionWithoutError(offer);
     EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
         observer_.ice_gathering_state_,
         kIceCandidatesTimeout);
   }
 
+  SessionDescriptionInterface* CreateOffer() {
+    PeerConnectionInterface::RTCOfferAnswerOptions options;
+    options.offer_to_receive_audio =
+        RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+
+    return CreateOffer(options);
+  }
+
   SessionDescriptionInterface* CreateOffer(
-      const webrtc::MediaConstraintsInterface* constraints) {
+      const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
     rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
         observer = new WebRtcSessionCreateSDPObserverForTest();
-    session_->CreateOffer(observer, constraints);
+    session_->CreateOffer(observer, options);
     EXPECT_TRUE_WAIT(
         observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
         2000);
@@ -833,9 +843,11 @@
     AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
     Init(NULL);
     mediastream_signaling_.SendAudioVideoStream1();
-    FakeConstraints constraints;
-    constraints.SetMandatoryUseRtpMux(bundle);
-    SessionDescriptionInterface* offer = CreateOffer(&constraints);
+
+    PeerConnectionInterface::RTCOfferAnswerOptions options;
+    options.use_rtp_mux = bundle;
+
+    SessionDescriptionInterface* offer = CreateOffer(options);
     // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
     // and answer.
     SetLocalDescriptionWithoutError(offer);
@@ -905,7 +917,7 @@
     AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
     Init(NULL);
     mediastream_signaling_.SendAudioVideoStream1();
-    SessionDescriptionInterface* offer = CreateOffer(NULL);
+    SessionDescriptionInterface* offer = CreateOffer();
 
     EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
               observer_.ice_gathering_state_);
@@ -1005,7 +1017,7 @@
     webrtc::InternalDataChannelInit dci;
     dci.reliable = false;
     session_->CreateDataChannel("datachannel", &dci);
-    SessionDescriptionInterface* offer = CreateOffer(NULL);
+    SessionDescriptionInterface* offer = CreateOffer();
     SetLocalDescriptionWithoutError(offer);
   }
 
@@ -1021,13 +1033,14 @@
       SetRemoteDescriptionWithoutError(offer.release());
     }
 
+    PeerConnectionInterface::RTCOfferAnswerOptions 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], NULL);
+        session_->CreateOffer(observers[i], options);
       } else {
         session_->CreateAnswer(observers[i], NULL);
       }
@@ -1140,7 +1153,7 @@
 TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   const std::string session_id_orig = offer->session_id();
   const std::string session_version_orig = offer->session_version();
   SetLocalDescriptionWithoutError(offer);
@@ -1166,7 +1179,7 @@
 
   // Create new offer without send streams.
   mediastream_signaling_.SendNothing();
-  offer = CreateOffer(NULL);
+  offer = CreateOffer();
 
   // Verify the session id is the same and the session version is
   // increased.
@@ -1195,7 +1208,7 @@
 TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream2();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   VerifyCryptoParams(offer->description());
   SetRemoteDescriptionWithoutError(offer);
 
@@ -1222,7 +1235,7 @@
   EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
 
   mediastream_signaling_.SendAudioVideoStream1And2();
-  offer = CreateOffer(NULL);
+  offer = CreateOffer();
   SetRemoteDescriptionWithoutError(offer);
 
   // Answer by turning off all send streams.
@@ -1252,12 +1265,12 @@
   Init(NULL);
   media_engine_->set_fail_create_channel(true);
 
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   ASSERT_TRUE(offer != NULL);
   // SetRemoteDescription and SetLocalDescription will take the ownership of
   // the offer.
   SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
-  offer = CreateOffer(NULL);
+  offer = CreateOffer();
   ASSERT_TRUE(offer != NULL);
   SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
 }
@@ -1374,7 +1387,7 @@
   SetFactoryDtlsSrtp();
 
   // Verify that we get a crypto fingerprint in the answer.
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   ASSERT_TRUE(offer != NULL);
   VerifyFingerprintStatus(offer->description(), true);
   // Check that we don't have an a=crypto line in the offer.
@@ -1440,7 +1453,7 @@
 TEST_F(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
   MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
   InitWithDtls();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   cricket::MediaSessionOptions options;
   options.has_video = true;
   JsepSessionDescription* answer =
@@ -1461,7 +1474,7 @@
   InitWithDtls();
 
   // Verify that we get a crypto fingerprint in the answer.
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   ASSERT_TRUE(offer != NULL);
   VerifyFingerprintStatus(offer->description(), false);
   // Check that we don't have an a=crypto line in the offer.
@@ -1514,11 +1527,11 @@
   Init(NULL);
   mediastream_signaling_.SendNothing();
   // SetLocalDescription take ownership of offer.
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
 
   // SetLocalDescription take ownership of offer.
-  SessionDescriptionInterface* offer2 = CreateOffer(NULL);
+  SessionDescriptionInterface* offer2 = CreateOffer();
   SetLocalDescriptionWithoutError(offer2);
 }
 
@@ -1526,19 +1539,19 @@
   Init(NULL);
   mediastream_signaling_.SendNothing();
   // SetLocalDescription take ownership of offer.
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetRemoteDescriptionWithoutError(offer);
 
-  SessionDescriptionInterface* offer2 = CreateOffer(NULL);
+  SessionDescriptionInterface* offer2 = CreateOffer();
   SetRemoteDescriptionWithoutError(offer2);
 }
 
 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
   Init(NULL);
   mediastream_signaling_.SendNothing();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
-  offer = CreateOffer(NULL);
+  offer = CreateOffer();
   SetRemoteDescriptionOfferExpectError(
       "Called in wrong state: STATE_SENTINITIATE", offer);
 }
@@ -1546,9 +1559,9 @@
 TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
   Init(NULL);
   mediastream_signaling_.SendNothing();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetRemoteDescriptionWithoutError(offer);
-  offer = CreateOffer(NULL);
+  offer = CreateOffer();
   SetLocalDescriptionOfferExpectError(
       "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
 }
@@ -1579,7 +1592,7 @@
 TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
   Init(NULL);
   mediastream_signaling_.SendNothing();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
 
   JsepSessionDescription* pranswer =
@@ -1606,8 +1619,8 @@
 TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
   Init(NULL);
   mediastream_signaling_.SendNothing();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   SessionDescriptionInterface* answer =
       CreateRemoteAnswer(offer.get());
   SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
@@ -1617,8 +1630,8 @@
 TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
   Init(NULL);
   mediastream_signaling_.SendNothing();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-        CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   SessionDescriptionInterface* answer =
       CreateRemoteAnswer(offer.get());
   SetRemoteDescriptionAnswerExpectError(
@@ -1636,7 +1649,7 @@
   // Fail since we have not set a offer description.
   EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
 
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
   // Candidate should be allowed to add before remote description.
   EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
@@ -1770,7 +1783,7 @@
   JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
                                  candidate1);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
 
   EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
   SetRemoteDescriptionWithoutError(offer);
@@ -1805,8 +1818,8 @@
   EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
                    kIceCandidatesTimeout);
 
-  rtc::scoped_ptr<SessionDescriptionInterface> local_offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
+
   ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
   EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
   ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
@@ -1827,8 +1840,7 @@
 TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
 
   // CreateOffer creates session description with the content names "audio" and
   // "video". Goal is to modify these content names and verify transport channel
@@ -1871,8 +1883,8 @@
 // the send streams when no constraints have been set.
 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
   Init(NULL);
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   ASSERT_TRUE(offer != NULL);
   const cricket::ContentInfo* content =
       cricket::GetFirstAudioContent(offer->description());
@@ -1887,8 +1899,8 @@
   Init(NULL);
   // Test Audio only offer.
   mediastream_signaling_.UseOptionsAudioOnly();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-        CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   const cricket::ContentInfo* content =
       cricket::GetFirstAudioContent(offer->description());
   EXPECT_TRUE(content != NULL);
@@ -1897,7 +1909,7 @@
 
   // Test Audio / Video offer.
   mediastream_signaling_.SendAudioVideoStream1();
-  offer.reset(CreateOffer(NULL));
+  offer.reset(CreateOffer());
   content = cricket::GetFirstAudioContent(offer->description());
   EXPECT_TRUE(content != NULL);
   content = cricket::GetFirstVideoContent(offer->description());
@@ -1908,12 +1920,13 @@
 // kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
 TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
   Init(NULL);
-  webrtc::FakeConstraints constraints_no_receive;
-  constraints_no_receive.SetMandatoryReceiveAudio(false);
-  constraints_no_receive.SetMandatoryReceiveVideo(false);
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.offer_to_receive_audio = 0;
+  options.offer_to_receive_video = 0;
 
   rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(&constraints_no_receive));
+      CreateOffer(options));
+
   ASSERT_TRUE(offer != NULL);
   const cricket::ContentInfo* content =
       cricket::GetFirstAudioContent(offer->description());
@@ -1926,10 +1939,12 @@
 // kOfferToReceiveAudio constraints are set to true.
 TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
   Init(NULL);
-  webrtc::FakeConstraints constraints_audio_only;
-  constraints_audio_only.SetMandatoryReceiveAudio(true);
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.offer_to_receive_audio =
+      RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+
   rtc::scoped_ptr<SessionDescriptionInterface> offer(
-        CreateOffer(&constraints_audio_only));
+        CreateOffer(options));
 
   const cricket::ContentInfo* content =
       cricket::GetFirstAudioContent(offer->description());
@@ -1943,11 +1958,15 @@
 TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
   Init(NULL);
   // Test Audio / Video offer.
-  webrtc::FakeConstraints constraints_audio_video;
-  constraints_audio_video.SetMandatoryReceiveAudio(true);
-  constraints_audio_video.SetMandatoryReceiveVideo(true);
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.offer_to_receive_audio =
+      RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+  options.offer_to_receive_video =
+      RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+
   rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(&constraints_audio_video));
+      CreateOffer(options));
+
   const cricket::ContentInfo* content =
       cricket::GetFirstAudioContent(offer->description());
 
@@ -1963,7 +1982,7 @@
 // an offer.
 TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
   Init(NULL);
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
   SetRemoteDescriptionWithoutError(answer);
@@ -2090,10 +2109,14 @@
 TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
   AddCNCodecs();
   Init(NULL);
-  webrtc::FakeConstraints constraints;
-  constraints.SetOptionalVAD(false);
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.offer_to_receive_audio =
+      RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+  options.voice_activity_detection = false;
+
   rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(&constraints));
+      CreateOffer(options));
+
   const cricket::ContentInfo* content =
       cricket::GetFirstAudioContent(offer->description());
   EXPECT_TRUE(content != NULL);
@@ -2125,7 +2148,7 @@
   EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
 
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
 
   cricket::MediaSessionOptions options;
   options.has_video = false;
@@ -2182,7 +2205,7 @@
   EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
   EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
 
   cricket::MediaSessionOptions options;
   options.has_audio = false;
@@ -2233,8 +2256,7 @@
 TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
   VerifyCryptoParams(offer->description());
   SetRemoteDescriptionWithoutError(offer.release());
   scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
@@ -2245,8 +2267,7 @@
   options_.disable_encryption = true;
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  scoped_ptr<SessionDescriptionInterface> offer(
-        CreateOffer(NULL));
+  scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
   VerifyNoCryptoParams(offer->description(), false);
 }
 
@@ -2265,7 +2286,8 @@
 TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   std::string sdp;
   RemoveIceUfragPwdLines(offer.get(), &sdp);
   SessionDescriptionInterface* modified_offer =
@@ -2291,7 +2313,8 @@
   Init(NULL);
   tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   std::string sdp;
   // Modifying ice ufrag and pwd in local offer with strings smaller than the
   // recommended values of 4 and 22 bytes respectively.
@@ -2340,8 +2363,8 @@
   Init(NULL);
   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
       allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   cricket::SessionDescription* offer_copy =
       offer->description()->Copy();
   offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
@@ -2358,9 +2381,12 @@
   mediastream_signaling_.SendAudioVideoStream1();
   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
       allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
-  FakeConstraints constraints;
-  constraints.SetMandatoryUseRtpMux(true);
-  SessionDescriptionInterface* offer = CreateOffer(&constraints);
+
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.use_rtp_mux = true;
+
+  SessionDescriptionInterface* offer = CreateOffer(options);
+
   SetLocalDescriptionWithoutError(offer);
   mediastream_signaling_.SendAudioVideoStream2();
   rtc::scoped_ptr<SessionDescriptionInterface> answer(
@@ -2396,9 +2422,11 @@
   mediastream_signaling_.SendAudioVideoStream1();
   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
       allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
-  FakeConstraints constraints;
-  constraints.SetMandatoryUseRtpMux(true);
-  SessionDescriptionInterface* offer = CreateOffer(&constraints);
+
+  PeerConnectionInterface::RTCOfferAnswerOptions options;
+  options.use_rtp_mux = true;
+
+  SessionDescriptionInterface* offer = CreateOffer(options);
   std::string offer_str;
   offer->ToString(&offer_str);
   // Disable rtcp-mux
@@ -2568,7 +2596,7 @@
 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
   Init(NULL);
   EXPECT_FALSE(session_->initiator());
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
   SetLocalDescriptionWithoutError(offer);
   EXPECT_TRUE(session_->initiator());
@@ -2594,7 +2622,7 @@
 TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   rtc::scoped_ptr<SessionDescriptionInterface> answer(
       CreateRemoteAnswer(offer));
   SetLocalDescriptionWithoutError(offer);
@@ -2616,7 +2644,7 @@
 TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
   SetLocalDescriptionWithoutError(offer);
 
@@ -2630,7 +2658,7 @@
 TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetRemoteDescriptionWithoutError(offer);
   rtc::scoped_ptr<SessionDescriptionInterface> answer(
       CreateAnswer(NULL));
@@ -2652,7 +2680,7 @@
 TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetRemoteDescriptionWithoutError(offer);
   SessionDescriptionInterface* answer = CreateAnswer(NULL);
   SetLocalDescriptionWithoutError(answer);
@@ -2665,8 +2693,8 @@
 TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   std::string offer_str;
   offer->ToString(&offer_str);
   // Disable google-ice
@@ -2697,7 +2725,7 @@
 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
   rtc::scoped_ptr<SessionDescriptionInterface> answer(
       CreateRemoteAnswer(session_->local_description()));
@@ -2798,8 +2826,7 @@
 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
 
   // Making sure SetLocalDescription correctly sets crypto value in
   // SessionDescription object after de-serialization of sdp string. The value
@@ -2818,8 +2845,7 @@
   options_.disable_encryption = true;
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(
-      CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
 
   // Making sure SetLocalDescription correctly sets crypto value in
   // SessionDescription object after de-serialization of sdp string. The value
@@ -2900,7 +2926,7 @@
 TEST_F(WebRtcSessionTest, TestSessionContentError) {
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   const std::string session_id_orig = offer->session_id();
   const std::string session_version_orig = offer->session_version();
   SetLocalDescriptionWithoutError(offer);
@@ -2985,7 +3011,7 @@
 
   InitWithDtls();
 
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
   EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
   EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
 }
@@ -3099,7 +3125,8 @@
 
   EXPECT_TRUE(session_->waiting_for_identity());
   mediastream_signaling_.SendAudioVideoStream1();
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
+
   EXPECT_TRUE(offer != NULL);
   VerifyNoCryptoParams(offer->description(), true);
   VerifyFingerprintStatus(offer->description(), true);
@@ -3132,7 +3159,8 @@
   InitWithDtls();
 
   EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
   EXPECT_TRUE(offer != NULL);
 }
 
@@ -3143,7 +3171,8 @@
   InitWithDtls(true);
 
   EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
-  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
+
+  rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
   EXPECT_TRUE(offer == NULL);
 }
 
@@ -3211,7 +3240,7 @@
       webrtc::MediaConstraintsInterface::kEnableDscp, true);
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
 
   SetLocalDescriptionWithoutError(offer);
 
@@ -3237,7 +3266,7 @@
       true);
   Init(NULL);
   mediastream_signaling_.SendAudioVideoStream1();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
 
   SetLocalDescriptionWithoutError(offer);
 
@@ -3258,7 +3287,7 @@
   SetFactoryDtlsSrtp();
 
   mediastream_signaling_.UseOptionsAudioOnly();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
 
   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
@@ -3288,7 +3317,7 @@
   SetFactoryDtlsSrtp();
 
   mediastream_signaling_.UseOptionsAudioOnly();
-  SessionDescriptionInterface* offer = CreateOffer(NULL);
+  SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
 
   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
index 3dce0d3..7930330 100644
--- a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
+++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
@@ -166,8 +166,9 @@
 
 void WebRtcSessionDescriptionFactory::CreateOffer(
     CreateSessionDescriptionObserver* observer,
-    const MediaConstraintsInterface* constraints) {
-  cricket::MediaSessionOptions options;
+    const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
+  cricket::MediaSessionOptions session_options;
+
   std::string error = "CreateOffer";
   if (identity_request_state_ == IDENTITY_FAILED) {
     error += kFailedDueToIdentityFailed;
@@ -176,14 +177,15 @@
     return;
   }
 
-  if (!mediastream_signaling_->GetOptionsForOffer(constraints, &options)) {
-    error += " called with invalid constraints.";
+  if (!mediastream_signaling_->GetOptionsForOffer(options,
+                                                  &session_options)) {
+    error += " called with invalid options.";
     LOG(LS_ERROR) << error;
     PostCreateSessionDescriptionFailed(observer, error);
     return;
   }
 
-  if (!ValidStreams(options.streams)) {
+  if (!ValidStreams(session_options.streams)) {
     error += " called with invalid media streams.";
     LOG(LS_ERROR) << error;
     PostCreateSessionDescriptionFailed(observer, error);
@@ -192,11 +194,11 @@
 
   if (data_channel_type_ == cricket::DCT_SCTP &&
       mediastream_signaling_->HasDataChannels()) {
-    options.data_channel_type = cricket::DCT_SCTP;
+    session_options.data_channel_type = cricket::DCT_SCTP;
   }
 
   CreateSessionDescriptionRequest request(
-      CreateSessionDescriptionRequest::kOffer, observer, options);
+      CreateSessionDescriptionRequest::kOffer, observer, session_options);
   if (identity_request_state_ == IDENTITY_WAITING) {
     create_session_description_requests_.push(request);
   } else {
diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.h b/talk/app/webrtc/webrtcsessiondescriptionfactory.h
index b09cfcd..f94d35a 100644
--- a/talk/app/webrtc/webrtcsessiondescriptionfactory.h
+++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.h
@@ -107,7 +107,7 @@
 
   void CreateOffer(
       CreateSessionDescriptionObserver* observer,
-      const MediaConstraintsInterface* constraints);
+      const PeerConnectionInterface::RTCOfferAnswerOptions& options);
   void CreateAnswer(
       CreateSessionDescriptionObserver* observer,
       const MediaConstraintsInterface* constraints);