| Index: webrtc/pc/webrtcsessiondescriptionfactory.cc
 | 
| diff --git a/webrtc/pc/webrtcsessiondescriptionfactory.cc b/webrtc/pc/webrtcsessiondescriptionfactory.cc
 | 
| index 8eccd65767dcd92190780e2de469d46e9d880759..beb8d1e5a1bb86b7b04722f9baa329d433e206f7 100644
 | 
| --- a/webrtc/pc/webrtcsessiondescriptionfactory.cc
 | 
| +++ b/webrtc/pc/webrtcsessiondescriptionfactory.cc
 | 
| @@ -30,24 +30,30 @@ static const char kFailedDueToSessionShutdown[] =
 | 
|  
 | 
|  static const uint64_t kInitSessionVersion = 2;
 | 
|  
 | 
| -static bool CompareStream(const MediaSessionOptions::Stream& stream1,
 | 
| -                          const MediaSessionOptions::Stream& stream2) {
 | 
| -  return stream1.id < stream2.id;
 | 
| +static bool CompareSenderOptions(const cricket::SenderOptions& sender1,
 | 
| +                                 const cricket::SenderOptions& sender2) {
 | 
| +  return sender1.track_id < sender2.track_id;
 | 
|  }
 | 
|  
 | 
| -static bool SameId(const MediaSessionOptions::Stream& stream1,
 | 
| -                   const MediaSessionOptions::Stream& stream2) {
 | 
| -  return stream1.id == stream2.id;
 | 
| +static bool SameId(const cricket::SenderOptions& sender1,
 | 
| +                   const cricket::SenderOptions& sender2) {
 | 
| +  return sender1.track_id == sender2.track_id;
 | 
|  }
 | 
|  
 | 
| -// Checks if each Stream within the |streams| has unique id.
 | 
| -static bool ValidStreams(const MediaSessionOptions::Streams& streams) {
 | 
| -  MediaSessionOptions::Streams sorted_streams = streams;
 | 
| -  std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream);
 | 
| -  MediaSessionOptions::Streams::iterator it =
 | 
| -      std::adjacent_find(sorted_streams.begin(), sorted_streams.end(),
 | 
| -                         SameId);
 | 
| -  return it == sorted_streams.end();
 | 
| +// Check that each sender has a unique ID.
 | 
| +static bool ValidMediaSessionOptions(
 | 
| +    const cricket::MediaSessionOptions& session_options) {
 | 
| +  std::vector<cricket::SenderOptions> sorted_senders;
 | 
| +  for (const cricket::MediaDescriptionOptions& media_description_options :
 | 
| +       session_options.media_description_options) {
 | 
| +    sorted_senders.insert(sorted_senders.end(),
 | 
| +                          media_description_options.sender_options.begin(),
 | 
| +                          media_description_options.sender_options.end());
 | 
| +  }
 | 
| +  std::sort(sorted_senders.begin(), sorted_senders.end(), CompareSenderOptions);
 | 
| +  std::vector<cricket::SenderOptions>::iterator it =
 | 
| +      std::adjacent_find(sorted_senders.begin(), sorted_senders.end(), SameId);
 | 
| +  return it == sorted_senders.end();
 | 
|  }
 | 
|  
 | 
|  enum {
 | 
| @@ -128,7 +134,6 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
 | 
|        session_id_(session_id),
 | 
|        certificate_request_state_(CERTIFICATE_NOT_NEEDED) {
 | 
|    RTC_DCHECK(signaling_thread_);
 | 
| -  session_desc_factory_.set_add_legacy_streams(false);
 | 
|    bool dtls_enabled = cert_generator_ || certificate;
 | 
|    // SRTP-SDES is disabled if DTLS is on.
 | 
|    SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED);
 | 
| @@ -237,8 +242,8 @@ void WebRtcSessionDescriptionFactory::CreateOffer(
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  if (!ValidStreams(session_options.streams)) {
 | 
| -    error += " called with invalid media streams.";
 | 
| +  if (!ValidMediaSessionOptions(session_options)) {
 | 
| +    error += " called with invalid session options";
 | 
|      LOG(LS_ERROR) << error;
 | 
|      PostCreateSessionDescriptionFailed(observer, error);
 | 
|      return;
 | 
| @@ -279,8 +284,8 @@ void WebRtcSessionDescriptionFactory::CreateAnswer(
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  if (!ValidStreams(session_options.streams)) {
 | 
| -    error += " called with invalid media streams.";
 | 
| +  if (!ValidMediaSessionOptions(session_options)) {
 | 
| +    error += " called with invalid session options.";
 | 
|      LOG(LS_ERROR) << error;
 | 
|      PostCreateSessionDescriptionFailed(observer, error);
 | 
|      return;
 | 
| @@ -340,13 +345,12 @@ void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) {
 | 
|  void WebRtcSessionDescriptionFactory::InternalCreateOffer(
 | 
|      CreateSessionDescriptionRequest request) {
 | 
|    if (session_->local_description()) {
 | 
| -    for (const cricket::TransportInfo& transport :
 | 
| -         session_->local_description()->description()->transport_infos()) {
 | 
| -      // If the needs-ice-restart flag is set as described by JSEP, we should
 | 
| -      // generate an offer with a new ufrag/password to trigger an ICE restart.
 | 
| -      if (session_->NeedsIceRestart(transport.content_name)) {
 | 
| -        request.options.transport_options[transport.content_name].ice_restart =
 | 
| -            true;
 | 
| +    // If the needs-ice-restart flag is set as described by JSEP, we should
 | 
| +    // generate an offer with a new ufrag/password to trigger an ICE restart.
 | 
| +    for (cricket::MediaDescriptionOptions& options :
 | 
| +         request.options.media_description_options) {
 | 
| +      if (session_->NeedsIceRestart(options.mid)) {
 | 
| +        options.transport_options.ice_restart = true;
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| @@ -375,13 +379,11 @@ void WebRtcSessionDescriptionFactory::InternalCreateOffer(
 | 
|      return;
 | 
|    }
 | 
|    if (session_->local_description()) {
 | 
| -    for (const cricket::ContentInfo& content :
 | 
| -         session_->local_description()->description()->contents()) {
 | 
| -      // Include all local ICE candidates in the SessionDescription unless
 | 
| -      // an ICE restart was requested.
 | 
| -      if (!request.options.transport_options[content.name].ice_restart) {
 | 
| +    for (const cricket::MediaDescriptionOptions& options :
 | 
| +         request.options.media_description_options) {
 | 
| +      if (!options.transport_options.ice_restart) {
 | 
|          CopyCandidatesFromSessionDescription(session_->local_description(),
 | 
| -                                             content.name, offer);
 | 
| +                                             options.mid, offer);
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| @@ -391,18 +393,18 @@ void WebRtcSessionDescriptionFactory::InternalCreateOffer(
 | 
|  void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
 | 
|      CreateSessionDescriptionRequest request) {
 | 
|    if (session_->remote_description()) {
 | 
| -    for (const cricket::ContentInfo& content :
 | 
| -         session_->remote_description()->description()->contents()) {
 | 
| +    for (cricket::MediaDescriptionOptions& options :
 | 
| +         request.options.media_description_options) {
 | 
|        // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1
 | 
|        // an answer should also contain new ICE ufrag and password if an offer
 | 
|        // has been received with new ufrag and password.
 | 
| -      request.options.transport_options[content.name].ice_restart =
 | 
| -          session_->IceRestartPending(content.name);
 | 
| +      options.transport_options.ice_restart =
 | 
| +          session_->IceRestartPending(options.mid);
 | 
|        // We should pass the current SSL role to the transport description
 | 
|        // factory, if there is already an existing ongoing session.
 | 
|        rtc::SSLRole ssl_role;
 | 
| -      if (session_->GetSslRole(content.name, &ssl_role)) {
 | 
| -        request.options.transport_options[content.name].prefer_passive_role =
 | 
| +      if (session_->GetSslRole(options.mid, &ssl_role)) {
 | 
| +        options.transport_options.prefer_passive_role =
 | 
|              (rtc::SSL_SERVER == ssl_role);
 | 
|        }
 | 
|      }
 | 
| @@ -433,13 +435,13 @@ void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
 | 
|      return;
 | 
|    }
 | 
|    if (session_->local_description()) {
 | 
| -    for (const cricket::ContentInfo& content :
 | 
| -         session_->local_description()->description()->contents()) {
 | 
| -      // Include all local ICE candidates in the SessionDescription unless
 | 
| -      // the remote peer has requested an ICE restart.
 | 
| -      if (!request.options.transport_options[content.name].ice_restart) {
 | 
| +    // Include all local ICE candidates in the SessionDescription unless
 | 
| +    // the remote peer has requested an ICE restart.
 | 
| +    for (const cricket::MediaDescriptionOptions& options :
 | 
| +         request.options.media_description_options) {
 | 
| +      if (!options.transport_options.ice_restart) {
 | 
|          CopyCandidatesFromSessionDescription(session_->local_description(),
 | 
| -                                             content.name, answer);
 | 
| +                                             options.mid, answer);
 | 
|        }
 | 
|      }
 | 
|    }
 | 
| 
 |