Use VoiceChannel/VideoChannel directly from RtpSender/RtpReceiver.

This eliminates the need for the extra layer of indirection provided by
mediastreamprovider.h. It will thus make it easier to implement new
functionality in RtpSender/RtpReceiver.

It also brings us one step closer to the end goal of combining "senders"
and "send streams". Currently the sender still needs to go through the
BaseChannel and MediaChannel, using an SSRC as a key.

R=pthatcher@webrtc.org

Review URL: https://codereview.webrtc.org/2046173002 .

Cr-Commit-Position: refs/heads/master@{#13285}
diff --git a/webrtc/api/BUILD.gn b/webrtc/api/BUILD.gn
index 1dd79bc..fa46e4a 100644
--- a/webrtc/api/BUILD.gn
+++ b/webrtc/api/BUILD.gn
@@ -52,7 +52,6 @@
     "mediastreaminterface.h",
     "mediastreamobserver.cc",
     "mediastreamobserver.h",
-    "mediastreamprovider.h",
     "mediastreamproxy.h",
     "mediastreamtrack.h",
     "mediastreamtrackproxy.h",
diff --git a/webrtc/api/api.gyp b/webrtc/api/api.gyp
index 077a558..3ab0bf9 100644
--- a/webrtc/api/api.gyp
+++ b/webrtc/api/api.gyp
@@ -128,7 +128,6 @@
         'mediastreaminterface.h',
         'mediastreamobserver.cc',
         'mediastreamobserver.h',
-        'mediastreamprovider.h',
         'mediastreamproxy.h',
         'mediastreamtrack.h',
         'mediastreamtrackproxy.h',
diff --git a/webrtc/api/datachannel.cc b/webrtc/api/datachannel.cc
index 3435fa5..5bffa03 100644
--- a/webrtc/api/datachannel.cc
+++ b/webrtc/api/datachannel.cc
@@ -13,7 +13,6 @@
 #include <memory>
 #include <string>
 
-#include "webrtc/api/mediastreamprovider.h"
 #include "webrtc/api/sctputils.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/refcount.h"
diff --git a/webrtc/api/mediastreamprovider.h b/webrtc/api/mediastreamprovider.h
deleted file mode 100644
index 784a954..0000000
--- a/webrtc/api/mediastreamprovider.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  Copyright 2012 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef WEBRTC_API_MEDIASTREAMPROVIDER_H_
-#define WEBRTC_API_MEDIASTREAMPROVIDER_H_
-
-#include <memory>
-
-#include "webrtc/api/rtpsenderinterface.h"
-#include "webrtc/base/basictypes.h"
-#include "webrtc/media/base/videosinkinterface.h"
-#include "webrtc/media/base/videosourceinterface.h"
-
-namespace cricket {
-
-class AudioSource;
-class VideoFrame;
-struct AudioOptions;
-struct VideoOptions;
-
-}  // namespace cricket
-
-namespace webrtc {
-
-class AudioSinkInterface;
-
-// TODO(deadbeef): Change the key from an ssrc to a "sender_id" or
-// "receiver_id" string, which will be the MSID in the short term and MID in
-// the long term.
-
-// TODO(deadbeef): These interfaces are effectively just a way for the
-// RtpSenders/Receivers to get to the BaseChannels. These interfaces should be
-// refactored away eventually, as the classes converge.
-
-// This interface is called by AudioRtpSender/Receivers to change the settings
-// of an audio track connected to certain PeerConnection.
-class AudioProviderInterface {
- public:
-  // Enable/disable the audio playout of a remote audio track with |ssrc|.
-  virtual void SetAudioPlayout(uint32_t ssrc, bool enable) = 0;
-  // Enable/disable sending audio on the local audio track with |ssrc|.
-  // When |enable| is true |options| should be applied to the audio track.
-  virtual void SetAudioSend(uint32_t ssrc,
-                            bool enable,
-                            const cricket::AudioOptions& options,
-                            cricket::AudioSource* source) = 0;
-
-  // Sets the audio playout volume of a remote audio track with |ssrc|.
-  // |volume| is in the range of [0, 10].
-  virtual void SetAudioPlayoutVolume(uint32_t ssrc, double volume) = 0;
-
-  // Allows for setting a direct audio sink for an incoming audio source.
-  // Only one audio sink is supported per ssrc and ownership of the sink is
-  // passed to the provider.
-  virtual void SetRawAudioSink(
-      uint32_t ssrc,
-      std::unique_ptr<webrtc::AudioSinkInterface> sink) = 0;
-
-  virtual RtpParameters GetAudioRtpSendParameters(uint32_t ssrc) const = 0;
-  virtual bool SetAudioRtpSendParameters(uint32_t ssrc,
-                                         const RtpParameters& parameters) = 0;
-
-  virtual RtpParameters GetAudioRtpReceiveParameters(uint32_t ssrc) const = 0;
-  virtual bool SetAudioRtpReceiveParameters(
-      uint32_t ssrc,
-      const RtpParameters& parameters) = 0;
-
-  // Called when the first audio packet is received.
-  sigslot::signal0<> SignalFirstAudioPacketReceived;
-
- protected:
-  virtual ~AudioProviderInterface() {}
-};
-
-// This interface is called by VideoRtpSender/Receivers to change the settings
-// of a video track connected to a certain PeerConnection.
-class VideoProviderInterface {
- public:
-  // Enable/disable the video playout of a remote video track with |ssrc|.
-  virtual void SetVideoPlayout(
-      uint32_t ssrc,
-      bool enable,
-      rtc::VideoSinkInterface<cricket::VideoFrame>* sink) = 0;
-  // Enable/disable sending video on the local video track with |ssrc|.
-  // TODO(deadbeef): Make |options| a reference parameter.
-  // TODO(deadbeef): Eventually, |enable| and |options| will be contained
-  // in |source|. When that happens, remove those parameters and rename
-  // this to SetVideoSource.
-  virtual void SetVideoSend(
-      uint32_t ssrc,
-      bool enable,
-      const cricket::VideoOptions* options,
-      rtc::VideoSourceInterface<cricket::VideoFrame>* source) = 0;
-
-  virtual RtpParameters GetVideoRtpSendParameters(uint32_t ssrc) const = 0;
-  virtual bool SetVideoRtpSendParameters(uint32_t ssrc,
-                                         const RtpParameters& parameters) = 0;
-
-  virtual RtpParameters GetVideoRtpReceiveParameters(uint32_t ssrc) const = 0;
-  virtual bool SetVideoRtpReceiveParameters(
-      uint32_t ssrc,
-      const RtpParameters& parameters) = 0;
-
-  // Called when the first video packet is received.
-  sigslot::signal0<> SignalFirstVideoPacketReceived;
-
- protected:
-  virtual ~VideoProviderInterface() {}
-};
-
-}  // namespace webrtc
-
-#endif  // WEBRTC_API_MEDIASTREAMPROVIDER_H_
diff --git a/webrtc/api/peerconnection.cc b/webrtc/api/peerconnection.cc
index b9cb83e..ac08d6c 100644
--- a/webrtc/api/peerconnection.cc
+++ b/webrtc/api/peerconnection.cc
@@ -396,6 +396,34 @@
   return cricket::CF_NONE;
 }
 
+// Helper method to set a voice/video channel on all applicable senders
+// and receivers when one is created/destroyed by WebRtcSession.
+//
+// Used by On(Voice|Video)Channel(Created|Destroyed)
+template <class SENDER,
+          class RECEIVER,
+          class CHANNEL,
+          class SENDERS,
+          class RECEIVERS>
+void SetChannelOnSendersAndReceivers(CHANNEL* channel,
+                                     SENDERS& senders,
+                                     RECEIVERS& receivers,
+                                     cricket::MediaType media_type) {
+  for (auto& sender : senders) {
+    if (sender->media_type() == media_type) {
+      static_cast<SENDER*>(sender->internal())->SetChannel(channel);
+    }
+  }
+  for (auto& receiver : receivers) {
+    if (receiver->media_type() == media_type) {
+      if (!channel) {
+        receiver->internal()->Stop();
+      }
+      static_cast<RECEIVER*>(receiver->internal())->SetChannel(channel);
+    }
+  }
+}
+
 }  // namespace
 
 namespace webrtc {
@@ -608,8 +636,12 @@
   // All the callbacks will be posted to the application from PeerConnection.
   session_->RegisterIceObserver(this);
   session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
+  session_->SignalVoiceChannelCreated.connect(
+      this, &PeerConnection::OnVoiceChannelCreated);
   session_->SignalVoiceChannelDestroyed.connect(
       this, &PeerConnection::OnVoiceChannelDestroyed);
+  session_->SignalVideoChannelCreated.connect(
+      this, &PeerConnection::OnVideoChannelCreated);
   session_->SignalVideoChannelDestroyed.connect(
       this, &PeerConnection::OnVideoChannelDestroyed);
   session_->SignalDataChannelCreated.connect(
@@ -713,7 +745,7 @@
     new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
         signaling_thread(),
         new AudioRtpSender(static_cast<AudioTrackInterface*>(track),
-                           session_.get(), stats_.get()));
+                           session_->voice_channel(), stats_.get()));
     if (!streams.empty()) {
       new_sender->internal()->set_stream_id(streams[0]->label());
     }
@@ -726,7 +758,7 @@
     new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
         signaling_thread(),
         new VideoRtpSender(static_cast<VideoTrackInterface*>(track),
-                           session_.get()));
+                           session_->video_channel()));
     if (!streams.empty()) {
       new_sender->internal()->set_stream_id(streams[0]->label());
     }
@@ -791,10 +823,11 @@
   rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
   if (kind == MediaStreamTrackInterface::kAudioKind) {
     new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
-        signaling_thread(), new AudioRtpSender(session_.get(), stats_.get()));
+        signaling_thread(),
+        new AudioRtpSender(session_->voice_channel(), stats_.get()));
   } else if (kind == MediaStreamTrackInterface::kVideoKind) {
     new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
-        signaling_thread(), new VideoRtpSender(session_.get()));
+        signaling_thread(), new VideoRtpSender(session_->video_channel()));
   } else {
     LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
     return new_sender;
@@ -1322,8 +1355,8 @@
                                          uint32_t ssrc) {
   receivers_.push_back(
       RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
-          signaling_thread(),
-          new AudioRtpReceiver(stream, track_id, ssrc, session_.get())));
+          signaling_thread(), new AudioRtpReceiver(stream, track_id, ssrc,
+                                                   session_->voice_channel())));
 }
 
 void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream,
@@ -1333,7 +1366,7 @@
       RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
           signaling_thread(),
           new VideoRtpReceiver(stream, track_id, factory_->worker_thread(),
-                               ssrc, session_.get())));
+                               ssrc, session_->video_channel())));
 }
 
 // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
@@ -1349,19 +1382,6 @@
   }
 }
 
-void PeerConnection::StopReceivers(cricket::MediaType media_type) {
-  TrackInfos* current_tracks = GetRemoteTracks(media_type);
-  for (const auto& track_info : *current_tracks) {
-    auto it = FindReceiverForTrack(track_info.track_id);
-    if (it == receivers_.end()) {
-      LOG(LS_WARNING) << "RtpReceiver for track with id " << track_info.track_id
-                      << " doesn't exist.";
-    } else {
-      (*it)->internal()->Stop();
-    }
-  }
-}
-
 void PeerConnection::OnIceConnectionChange(
     PeerConnectionInterface::IceConnectionState new_state) {
   RTC_DCHECK(signaling_thread()->IsCurrent());
@@ -1427,8 +1447,9 @@
   // Normal case; we've never seen this track before.
   rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender =
       RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
-          signaling_thread(), new AudioRtpSender(track, stream->label(),
-                                                 session_.get(), stats_.get()));
+          signaling_thread(),
+          new AudioRtpSender(track, stream->label(), session_->voice_channel(),
+                             stats_.get()));
   senders_.push_back(new_sender);
   // If the sender has already been configured in SDP, we call SetSsrc,
   // which will connect the sender to the underlying transport. This can
@@ -1470,8 +1491,8 @@
   // Normal case; we've never seen this track before.
   rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender =
       RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
-          signaling_thread(),
-          new VideoRtpSender(track, stream->label(), session_.get()));
+          signaling_thread(), new VideoRtpSender(track, stream->label(),
+                                                 session_->video_channel()));
   senders_.push_back(new_sender);
   const TrackInfo* track_info =
       FindTrackInfo(local_video_tracks_, stream->label(), track->id());
@@ -2013,12 +2034,28 @@
   }
 }
 
+void PeerConnection::OnVoiceChannelCreated() {
+  SetChannelOnSendersAndReceivers<AudioRtpSender, AudioRtpReceiver>(
+      session_->voice_channel(), senders_, receivers_,
+      cricket::MEDIA_TYPE_AUDIO);
+}
+
 void PeerConnection::OnVoiceChannelDestroyed() {
-  StopReceivers(cricket::MEDIA_TYPE_AUDIO);
+  SetChannelOnSendersAndReceivers<AudioRtpSender, AudioRtpReceiver,
+                                  cricket::VoiceChannel>(
+      nullptr, senders_, receivers_, cricket::MEDIA_TYPE_AUDIO);
+}
+
+void PeerConnection::OnVideoChannelCreated() {
+  SetChannelOnSendersAndReceivers<VideoRtpSender, VideoRtpReceiver>(
+      session_->video_channel(), senders_, receivers_,
+      cricket::MEDIA_TYPE_VIDEO);
 }
 
 void PeerConnection::OnVideoChannelDestroyed() {
-  StopReceivers(cricket::MEDIA_TYPE_VIDEO);
+  SetChannelOnSendersAndReceivers<VideoRtpSender, VideoRtpReceiver,
+                                  cricket::VideoChannel>(
+      nullptr, senders_, receivers_, cricket::MEDIA_TYPE_VIDEO);
 }
 
 void PeerConnection::OnDataChannelCreated() {
diff --git a/webrtc/api/peerconnection.h b/webrtc/api/peerconnection.h
index aba595c..fc754b9 100644
--- a/webrtc/api/peerconnection.h
+++ b/webrtc/api/peerconnection.h
@@ -174,7 +174,6 @@
   void CreateVideoReceiver(MediaStreamInterface* stream,
                            const std::string& track_id,
                            uint32_t ssrc);
-  void StopReceivers(cricket::MediaType media_type);
   void DestroyReceiver(const std::string& track_id);
   void DestroyAudioSender(MediaStreamInterface* stream,
                           AudioTrackInterface* audio_track,
@@ -325,7 +324,9 @@
   void OnSctpDataChannelClosed(DataChannel* channel);
 
   // Notifications from WebRtcSession relating to BaseChannels.
+  void OnVoiceChannelCreated();
   void OnVoiceChannelDestroyed();
+  void OnVideoChannelCreated();
   void OnVideoChannelDestroyed();
   void OnDataChannelCreated();
   void OnDataChannelDestroyed();
diff --git a/webrtc/api/remoteaudiosource.cc b/webrtc/api/remoteaudiosource.cc
index 14eb82b..47213fa 100644
--- a/webrtc/api/remoteaudiosource.cc
+++ b/webrtc/api/remoteaudiosource.cc
@@ -15,7 +15,6 @@
 #include <memory>
 #include <utility>
 
-#include "webrtc/api/mediastreamprovider.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/constructormagic.h"
 #include "webrtc/base/logging.h"
@@ -42,7 +41,7 @@
 class RemoteAudioSource::Sink : public AudioSinkInterface {
  public:
   explicit Sink(RemoteAudioSource* source) : source_(source) {}
-  ~Sink() override { source_->OnAudioProviderGone(); }
+  ~Sink() override { source_->OnAudioChannelGone(); }
 
  private:
   void OnData(const AudioSinkInterface::Data& audio) override {
@@ -56,10 +55,10 @@
 
 rtc::scoped_refptr<RemoteAudioSource> RemoteAudioSource::Create(
     uint32_t ssrc,
-    AudioProviderInterface* provider) {
+    cricket::VoiceChannel* channel) {
   rtc::scoped_refptr<RemoteAudioSource> ret(
       new rtc::RefCountedObject<RemoteAudioSource>());
-  ret->Initialize(ssrc, provider);
+  ret->Initialize(ssrc, channel);
   return ret;
 }
 
@@ -76,12 +75,12 @@
 }
 
 void RemoteAudioSource::Initialize(uint32_t ssrc,
-                                   AudioProviderInterface* provider) {
+                                   cricket::VoiceChannel* channel) {
   RTC_DCHECK(main_thread_->IsCurrent());
-  // To make sure we always get notified when the provider goes out of scope,
+  // To make sure we always get notified when the channel goes out of scope,
   // we register for callbacks here and not on demand in AddSink.
-  if (provider) {  // May be null in tests.
-    provider->SetRawAudioSink(
+  if (channel) {  // May be null in tests.
+    channel->SetRawAudioSink(
         ssrc, std::unique_ptr<AudioSinkInterface>(new Sink(this)));
   }
 }
@@ -145,8 +144,8 @@
   }
 }
 
-void RemoteAudioSource::OnAudioProviderGone() {
-  // Called when the data provider is deleted.  It may be the worker thread
+void RemoteAudioSource::OnAudioChannelGone() {
+  // Called when the audio channel is deleted.  It may be the worker thread
   // in libjingle or may be a different worker thread.
   main_thread_->Post(RTC_FROM_HERE, new MessageHandler(this));
 }
diff --git a/webrtc/api/remoteaudiosource.h b/webrtc/api/remoteaudiosource.h
index abb55f6..4cc68f8 100644
--- a/webrtc/api/remoteaudiosource.h
+++ b/webrtc/api/remoteaudiosource.h
@@ -14,10 +14,10 @@
 #include <list>
 #include <string>
 
-#include "webrtc/api/mediastreaminterface.h"
 #include "webrtc/api/notifier.h"
 #include "webrtc/audio_sink.h"
 #include "webrtc/base/criticalsection.h"
+#include "webrtc/pc/channel.h"
 
 namespace rtc {
 struct Message;
@@ -26,15 +26,13 @@
 
 namespace webrtc {
 
-class AudioProviderInterface;
-
 // This class implements the audio source used by the remote audio track.
 class RemoteAudioSource : public Notifier<AudioSourceInterface> {
  public:
   // Creates an instance of RemoteAudioSource.
   static rtc::scoped_refptr<RemoteAudioSource> Create(
       uint32_t ssrc,
-      AudioProviderInterface* provider);
+      cricket::VoiceChannel* channel);
 
   // MediaSourceInterface implementation.
   MediaSourceInterface::SourceState state() const override;
@@ -49,7 +47,7 @@
 
   // Post construction initialize where we can do things like save a reference
   // to ourselves (need to be fully constructed).
-  void Initialize(uint32_t ssrc, AudioProviderInterface* provider);
+  void Initialize(uint32_t ssrc, cricket::VoiceChannel* channel);
 
  private:
   typedef std::list<AudioObserver*> AudioObserverList;
@@ -61,7 +59,7 @@
 
   class Sink;
   void OnData(const AudioSinkInterface::Data& audio);
-  void OnAudioProviderGone();
+  void OnAudioChannelGone();
 
   class MessageHandler;
   void OnMessage(rtc::Message* msg);
diff --git a/webrtc/api/rtpreceiver.cc b/webrtc/api/rtpreceiver.cc
index 882bc2b..8fde438 100644
--- a/webrtc/api/rtpreceiver.cc
+++ b/webrtc/api/rtpreceiver.cc
@@ -21,22 +21,24 @@
 AudioRtpReceiver::AudioRtpReceiver(MediaStreamInterface* stream,
                                    const std::string& track_id,
                                    uint32_t ssrc,
-                                   AudioProviderInterface* provider)
+                                   cricket::VoiceChannel* channel)
     : id_(track_id),
       ssrc_(ssrc),
-      provider_(provider),
+      channel_(channel),
       track_(AudioTrackProxy::Create(
           rtc::Thread::Current(),
           AudioTrack::Create(track_id,
-                             RemoteAudioSource::Create(ssrc, provider)))),
+                             RemoteAudioSource::Create(ssrc, channel)))),
       cached_track_enabled_(track_->enabled()) {
   RTC_DCHECK(track_->GetSource()->remote());
   track_->RegisterObserver(this);
   track_->GetSource()->RegisterAudioObserver(this);
   Reconfigure();
   stream->AddTrack(track_);
-  provider_->SignalFirstAudioPacketReceived.connect(
-      this, &AudioRtpReceiver::OnFirstAudioPacketReceived);
+  if (channel_) {
+    channel_->SignalFirstPacketReceived.connect(
+        this, &AudioRtpReceiver::OnFirstPacketReceived);
+  }
 }
 
 AudioRtpReceiver::~AudioRtpReceiver() {
@@ -53,48 +55,78 @@
 }
 
 void AudioRtpReceiver::OnSetVolume(double volume) {
+  RTC_DCHECK(volume >= 0 && volume <= 10);
+  cached_volume_ = volume;
+  if (!channel_) {
+    LOG(LS_ERROR) << "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
+    return;
+  }
   // When the track is disabled, the volume of the source, which is the
   // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
   // setting the volume to the source when the track is disabled.
-  if (provider_ && track_->enabled())
-    provider_->SetAudioPlayoutVolume(ssrc_, volume);
+  if (!stopped_ && track_->enabled()) {
+    RTC_DCHECK(channel_->SetOutputVolume(ssrc_, cached_volume_));
+  }
 }
 
 RtpParameters AudioRtpReceiver::GetParameters() const {
-  return provider_->GetAudioRtpReceiveParameters(ssrc_);
+  if (!channel_ || stopped_) {
+    return RtpParameters();
+  }
+  return channel_->GetRtpReceiveParameters(ssrc_);
 }
 
 bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) {
   TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters");
-  return provider_->SetAudioRtpReceiveParameters(ssrc_, parameters);
+  if (!channel_ || stopped_) {
+    return false;
+  }
+  return channel_->SetRtpReceiveParameters(ssrc_, parameters);
 }
 
 void AudioRtpReceiver::Stop() {
   // TODO(deadbeef): Need to do more here to fully stop receiving packets.
-  if (!provider_) {
+  if (stopped_) {
     return;
   }
-  provider_->SetAudioPlayout(ssrc_, false);
-  provider_ = nullptr;
+  if (channel_) {
+    // Allow that SetOutputVolume fail. This is the normal case when the
+    // underlying media channel has already been deleted.
+    channel_->SetOutputVolume(ssrc_, 0);
+  }
+  stopped_ = true;
 }
 
 void AudioRtpReceiver::Reconfigure() {
-  if (!provider_) {
+  RTC_DCHECK(!stopped_);
+  if (!channel_) {
+    LOG(LS_ERROR) << "AudioRtpReceiver::Reconfigure: No audio channel exists.";
     return;
   }
-  provider_->SetAudioPlayout(ssrc_, track_->enabled());
+  RTC_DCHECK(
+      channel_->SetOutputVolume(ssrc_, track_->enabled() ? cached_volume_ : 0));
 }
 
 void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
   observer_ = observer;
-  // If received the first packet before setting the observer, call the
-  // observer.
+  // Deliver any notifications the observer may have missed by being set late.
   if (received_first_packet_) {
     observer_->OnFirstPacketReceived(media_type());
   }
 }
 
-void AudioRtpReceiver::OnFirstAudioPacketReceived() {
+void AudioRtpReceiver::SetChannel(cricket::VoiceChannel* channel) {
+  if (channel_) {
+    channel_->SignalFirstPacketReceived.disconnect(this);
+  }
+  channel_ = channel;
+  if (channel_) {
+    channel_->SignalFirstPacketReceived.connect(
+        this, &AudioRtpReceiver::OnFirstPacketReceived);
+  }
+}
+
+void AudioRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) {
   if (observer_) {
     observer_->OnFirstPacketReceived(media_type());
   }
@@ -105,10 +137,10 @@
                                    const std::string& track_id,
                                    rtc::Thread* worker_thread,
                                    uint32_t ssrc,
-                                   VideoProviderInterface* provider)
+                                   cricket::VideoChannel* channel)
     : id_(track_id),
       ssrc_(ssrc),
-      provider_(provider),
+      channel_(channel),
       source_(new RefCountedObject<VideoTrackSource>(&broadcaster_,
                                                      true /* remote */)),
       track_(VideoTrackProxy::Create(
@@ -120,48 +152,77 @@
                                             worker_thread,
                                             source_)))) {
   source_->SetState(MediaSourceInterface::kLive);
-  provider_->SetVideoPlayout(ssrc_, true, &broadcaster_);
+  if (!channel_) {
+    LOG(LS_ERROR)
+        << "VideoRtpReceiver::VideoRtpReceiver: No video channel exists.";
+  } else {
+    RTC_DCHECK(channel_->SetSink(ssrc_, &broadcaster_));
+  }
   stream->AddTrack(track_);
-  provider_->SignalFirstVideoPacketReceived.connect(
-      this, &VideoRtpReceiver::OnFirstVideoPacketReceived);
+  if (channel_) {
+    channel_->SignalFirstPacketReceived.connect(
+        this, &VideoRtpReceiver::OnFirstPacketReceived);
+  }
 }
 
 VideoRtpReceiver::~VideoRtpReceiver() {
   // Since cricket::VideoRenderer is not reference counted,
-  // we need to remove it from the provider before we are deleted.
+  // we need to remove it from the channel before we are deleted.
   Stop();
 }
 
 RtpParameters VideoRtpReceiver::GetParameters() const {
-  return provider_->GetVideoRtpReceiveParameters(ssrc_);
+  if (!channel_ || stopped_) {
+    return RtpParameters();
+  }
+  return channel_->GetRtpReceiveParameters(ssrc_);
 }
 
 bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
   TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
-  return provider_->SetVideoRtpReceiveParameters(ssrc_, parameters);
+  if (!channel_ || stopped_) {
+    return false;
+  }
+  return channel_->SetRtpReceiveParameters(ssrc_, parameters);
 }
 
 void VideoRtpReceiver::Stop() {
   // TODO(deadbeef): Need to do more here to fully stop receiving packets.
-  if (!provider_) {
+  if (stopped_) {
     return;
   }
   source_->SetState(MediaSourceInterface::kEnded);
   source_->OnSourceDestroyed();
-  provider_->SetVideoPlayout(ssrc_, false, nullptr);
-  provider_ = nullptr;
+  if (!channel_) {
+    LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
+  } else {
+    // Allow that SetSink fail. This is the normal case when the underlying
+    // media channel has already been deleted.
+    channel_->SetSink(ssrc_, nullptr);
+  }
+  stopped_ = true;
 }
 
 void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
   observer_ = observer;
-  // If received the first packet before setting the observer, call the
-  // observer.
+  // Deliver any notifications the observer may have missed by being set late.
   if (received_first_packet_) {
     observer_->OnFirstPacketReceived(media_type());
   }
 }
 
-void VideoRtpReceiver::OnFirstVideoPacketReceived() {
+void VideoRtpReceiver::SetChannel(cricket::VideoChannel* channel) {
+  if (channel_) {
+    channel_->SignalFirstPacketReceived.disconnect(this);
+  }
+  channel_ = channel;
+  if (channel_) {
+    channel_->SignalFirstPacketReceived.connect(
+        this, &VideoRtpReceiver::OnFirstPacketReceived);
+  }
+}
+
+void VideoRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) {
   if (observer_) {
     observer_->OnFirstPacketReceived(media_type());
   }
diff --git a/webrtc/api/rtpreceiver.h b/webrtc/api/rtpreceiver.h
index 3b1fd92..4b3bd4d 100644
--- a/webrtc/api/rtpreceiver.h
+++ b/webrtc/api/rtpreceiver.h
@@ -10,20 +10,21 @@
 
 // This file contains classes that implement RtpReceiverInterface.
 // An RtpReceiver associates a MediaStreamTrackInterface with an underlying
-// transport (provided by AudioProviderInterface/VideoProviderInterface)
+// transport (provided by cricket::VoiceChannel/cricket::VideoChannel)
 
 #ifndef WEBRTC_API_RTPRECEIVER_H_
 #define WEBRTC_API_RTPRECEIVER_H_
 
 #include <string>
 
-#include "webrtc/api/mediastreamprovider.h"
+#include "webrtc/api/mediastreaminterface.h"
 #include "webrtc/api/rtpreceiverinterface.h"
 #include "webrtc/api/remoteaudiosource.h"
 #include "webrtc/api/videotracksource.h"
 #include "webrtc/base/basictypes.h"
 #include "webrtc/base/sigslot.h"
 #include "webrtc/media/base/videobroadcaster.h"
+#include "webrtc/pc/channel.h"
 
 namespace webrtc {
 
@@ -41,7 +42,7 @@
   AudioRtpReceiver(MediaStreamInterface* stream,
                    const std::string& track_id,
                    uint32_t ssrc,
-                   AudioProviderInterface* provider);
+                   cricket::VoiceChannel* channel);
 
   virtual ~AudioRtpReceiver();
 
@@ -60,6 +61,10 @@
     return track_.get();
   }
 
+  cricket::MediaType media_type() const override {
+    return cricket::MEDIA_TYPE_AUDIO;
+  }
+
   std::string id() const override { return id_; }
 
   RtpParameters GetParameters() const override;
@@ -70,17 +75,21 @@
 
   void SetObserver(RtpReceiverObserverInterface* observer) override;
 
-  cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_AUDIO; }
+  // Does not take ownership.
+  // Should call SetChannel(nullptr) before |channel| is destroyed.
+  void SetChannel(cricket::VoiceChannel* channel);
 
  private:
   void Reconfigure();
-  void OnFirstAudioPacketReceived();
+  void OnFirstPacketReceived(cricket::BaseChannel* channel);
 
   const std::string id_;
   const uint32_t ssrc_;
-  AudioProviderInterface* provider_;  // Set to null in Stop().
+  cricket::VoiceChannel* channel_;
   const rtc::scoped_refptr<AudioTrackInterface> track_;
   bool cached_track_enabled_;
+  double cached_volume_ = 1;
+  bool stopped_ = false;
   RtpReceiverObserverInterface* observer_ = nullptr;
   bool received_first_packet_ = false;
 };
@@ -92,7 +101,7 @@
                    const std::string& track_id,
                    rtc::Thread* worker_thread,
                    uint32_t ssrc,
-                   VideoProviderInterface* provider);
+                   cricket::VideoChannel* channel);
 
   virtual ~VideoRtpReceiver();
 
@@ -105,6 +114,10 @@
     return track_.get();
   }
 
+  cricket::MediaType media_type() const override {
+    return cricket::MEDIA_TYPE_VIDEO;
+  }
+
   std::string id() const override { return id_; }
 
   RtpParameters GetParameters() const override;
@@ -115,14 +128,16 @@
 
   void SetObserver(RtpReceiverObserverInterface* observer) override;
 
-  cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_VIDEO; }
+  // Does not take ownership.
+  // Should call SetChannel(nullptr) before |channel| is destroyed.
+  void SetChannel(cricket::VideoChannel* channel);
 
  private:
-  void OnFirstVideoPacketReceived();
+  void OnFirstPacketReceived(cricket::BaseChannel* channel);
 
   std::string id_;
   uint32_t ssrc_;
-  VideoProviderInterface* provider_;
+  cricket::VideoChannel* channel_;
   // |broadcaster_| is needed since the decoder can only handle one sink.
   // It might be better if the decoder can handle multiple sinks and consider
   // the VideoSinkWants.
@@ -131,6 +146,7 @@
   // the VideoRtpReceiver is stopped.
   rtc::scoped_refptr<VideoTrackSource> source_;
   rtc::scoped_refptr<VideoTrackInterface> track_;
+  bool stopped_ = false;
   RtpReceiverObserverInterface* observer_ = nullptr;
   bool received_first_packet_ = false;
 };
diff --git a/webrtc/api/rtpreceiverinterface.h b/webrtc/api/rtpreceiverinterface.h
index 4943023..53a3739 100644
--- a/webrtc/api/rtpreceiverinterface.h
+++ b/webrtc/api/rtpreceiverinterface.h
@@ -18,6 +18,7 @@
 
 #include "webrtc/api/mediastreaminterface.h"
 #include "webrtc/api/proxy.h"
+#include "webrtc/api/rtpparameters.h"
 #include "webrtc/base/refcount.h"
 #include "webrtc/base/scoped_ref_ptr.h"
 #include "webrtc/pc/mediasession.h"
@@ -26,6 +27,12 @@
 
 class RtpReceiverObserverInterface {
  public:
+  // Note: Currently if there are multiple RtpReceivers of the same media type,
+  // they will all call OnFirstPacketReceived at once.
+  //
+  // In the future, it's likely that an RtpReceiver will only call
+  // OnFirstPacketReceived when a packet is received specifically for its
+  // SSRC/mid.
   virtual void OnFirstPacketReceived(cricket::MediaType media_type) = 0;
 
  protected:
@@ -36,6 +43,9 @@
  public:
   virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
 
+  // Audio or video receiver?
+  virtual cricket::MediaType media_type() const = 0;
+
   // Not to be confused with "mid", this is a field we can temporarily use
   // to uniquely identify a receiver until we implement Unified Plan SDP.
   virtual std::string id() const = 0;
@@ -46,10 +56,10 @@
   virtual RtpParameters GetParameters() const = 0;
   virtual bool SetParameters(const RtpParameters& parameters) = 0;
 
+  // Does not take ownership of observer.
+  // Must call SetObserver(nullptr) before the observer is destroyed.
   virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0;
 
-  virtual cricket::MediaType media_type() = 0;
-
  protected:
   virtual ~RtpReceiverInterface() {}
 };
@@ -57,11 +67,11 @@
 // Define proxy for RtpReceiverInterface.
 BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
 PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
+PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
 PROXY_CONSTMETHOD0(std::string, id)
 PROXY_CONSTMETHOD0(RtpParameters, GetParameters);
 PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
 PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*);
-PROXY_METHOD0(cricket::MediaType, media_type);
 END_SIGNALING_PROXY()
 
 }  // namespace webrtc
diff --git a/webrtc/api/rtpsender.cc b/webrtc/api/rtpsender.cc
index f66e66b..fc4c232 100644
--- a/webrtc/api/rtpsender.cc
+++ b/webrtc/api/rtpsender.cc
@@ -45,40 +45,38 @@
 
 AudioRtpSender::AudioRtpSender(AudioTrackInterface* track,
                                const std::string& stream_id,
-                               AudioProviderInterface* provider,
+                               cricket::VoiceChannel* channel,
                                StatsCollector* stats)
     : id_(track->id()),
       stream_id_(stream_id),
-      provider_(provider),
+      channel_(channel),
       stats_(stats),
       track_(track),
       cached_track_enabled_(track->enabled()),
       sink_adapter_(new LocalAudioSinkAdapter()) {
-  RTC_DCHECK(provider != nullptr);
   track_->RegisterObserver(this);
   track_->AddSink(sink_adapter_.get());
 }
 
 AudioRtpSender::AudioRtpSender(AudioTrackInterface* track,
-                               AudioProviderInterface* provider,
+                               cricket::VoiceChannel* channel,
                                StatsCollector* stats)
     : id_(track->id()),
       stream_id_(rtc::CreateRandomUuid()),
-      provider_(provider),
+      channel_(channel),
       stats_(stats),
       track_(track),
       cached_track_enabled_(track->enabled()),
       sink_adapter_(new LocalAudioSinkAdapter()) {
-  RTC_DCHECK(provider != nullptr);
   track_->RegisterObserver(this);
   track_->AddSink(sink_adapter_.get());
 }
 
-AudioRtpSender::AudioRtpSender(AudioProviderInterface* provider,
+AudioRtpSender::AudioRtpSender(cricket::VoiceChannel* channel,
                                StatsCollector* stats)
     : id_(rtc::CreateRandomUuid()),
       stream_id_(rtc::CreateRandomUuid()),
-      provider_(provider),
+      channel_(channel),
       stats_(stats),
       sink_adapter_(new LocalAudioSinkAdapter()) {}
 
@@ -132,26 +130,31 @@
     track_->AddSink(sink_adapter_.get());
   }
 
-  // Update audio provider.
+  // Update audio channel.
   if (can_send_track()) {
     SetAudioSend();
     if (stats_) {
       stats_->AddLocalAudioTrack(track_.get(), ssrc_);
     }
   } else if (prev_can_send_track) {
-    cricket::AudioOptions options;
-    provider_->SetAudioSend(ssrc_, false, options, nullptr);
+    ClearAudioSend();
   }
   return true;
 }
 
 RtpParameters AudioRtpSender::GetParameters() const {
-  return provider_->GetAudioRtpSendParameters(ssrc_);
+  if (!channel_ || stopped_) {
+    return RtpParameters();
+  }
+  return channel_->GetRtpSendParameters(ssrc_);
 }
 
 bool AudioRtpSender::SetParameters(const RtpParameters& parameters) {
   TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
-  return provider_->SetAudioRtpSendParameters(ssrc_, parameters);
+  if (!channel_ || stopped_) {
+    return false;
+  }
+  return channel_->SetRtpSendParameters(ssrc_, parameters);
 }
 
 void AudioRtpSender::SetSsrc(uint32_t ssrc) {
@@ -161,8 +164,7 @@
   }
   // If we are already sending with a particular SSRC, stop sending.
   if (can_send_track()) {
-    cricket::AudioOptions options;
-    provider_->SetAudioSend(ssrc_, false, options, nullptr);
+    ClearAudioSend();
     if (stats_) {
       stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
     }
@@ -187,8 +189,7 @@
     track_->UnregisterObserver(this);
   }
   if (can_send_track()) {
-    cricket::AudioOptions options;
-    provider_->SetAudioSend(ssrc_, false, options, nullptr);
+    ClearAudioSend();
     if (stats_) {
       stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
     }
@@ -198,6 +199,10 @@
 
 void AudioRtpSender::SetAudioSend() {
   RTC_DCHECK(!stopped_ && can_send_track());
+  if (!channel_) {
+    LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
+    return;
+  }
   cricket::AudioOptions options;
 #if !defined(WEBRTC_CHROMIUM_BUILD)
   // TODO(tommi): Remove this hack when we move CreateAudioSource out of
@@ -212,37 +217,50 @@
 #endif
 
   cricket::AudioSource* source = sink_adapter_.get();
-  ASSERT(source != nullptr);
-  provider_->SetAudioSend(ssrc_, track_->enabled(), options, source);
+  RTC_DCHECK(source != nullptr);
+  if (!channel_->SetAudioSend(ssrc_, track_->enabled(), &options, source)) {
+    LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
+  }
+}
+
+void AudioRtpSender::ClearAudioSend() {
+  RTC_DCHECK(ssrc_ != 0);
+  RTC_DCHECK(!stopped_);
+  if (!channel_) {
+    LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
+    return;
+  }
+  cricket::AudioOptions options;
+  if (!channel_->SetAudioSend(ssrc_, false, &options, nullptr)) {
+    LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
+  }
 }
 
 VideoRtpSender::VideoRtpSender(VideoTrackInterface* track,
                                const std::string& stream_id,
-                               VideoProviderInterface* provider)
+                               cricket::VideoChannel* channel)
     : id_(track->id()),
       stream_id_(stream_id),
-      provider_(provider),
+      channel_(channel),
       track_(track),
       cached_track_enabled_(track->enabled()) {
-  RTC_DCHECK(provider != nullptr);
   track_->RegisterObserver(this);
 }
 
 VideoRtpSender::VideoRtpSender(VideoTrackInterface* track,
-                               VideoProviderInterface* provider)
+                               cricket::VideoChannel* channel)
     : id_(track->id()),
       stream_id_(rtc::CreateRandomUuid()),
-      provider_(provider),
+      channel_(channel),
       track_(track),
       cached_track_enabled_(track->enabled()) {
-  RTC_DCHECK(provider != nullptr);
   track_->RegisterObserver(this);
 }
 
-VideoRtpSender::VideoRtpSender(VideoProviderInterface* provider)
+VideoRtpSender::VideoRtpSender(cricket::VideoChannel* channel)
     : id_(rtc::CreateRandomUuid()),
       stream_id_(rtc::CreateRandomUuid()),
-      provider_(provider) {}
+      channel_(channel) {}
 
 VideoRtpSender::~VideoRtpSender() {
   Stop();
@@ -288,7 +306,7 @@
     track_->RegisterObserver(this);
   }
 
-  // Update video provider.
+  // Update video channel.
   if (can_send_track()) {
     SetVideoSend();
   } else if (prev_can_send_track) {
@@ -298,12 +316,18 @@
 }
 
 RtpParameters VideoRtpSender::GetParameters() const {
-  return provider_->GetVideoRtpSendParameters(ssrc_);
+  if (!channel_ || stopped_) {
+    return RtpParameters();
+  }
+  return channel_->GetRtpSendParameters(ssrc_);
 }
 
 bool VideoRtpSender::SetParameters(const RtpParameters& parameters) {
   TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
-  return provider_->SetVideoRtpSendParameters(ssrc_, parameters);
+  if (!channel_ || stopped_) {
+    return false;
+  }
+  return channel_->SetRtpSendParameters(ssrc_, parameters);
 }
 
 void VideoRtpSender::SetSsrc(uint32_t ssrc) {
@@ -338,19 +362,31 @@
 
 void VideoRtpSender::SetVideoSend() {
   RTC_DCHECK(!stopped_ && can_send_track());
+  if (!channel_) {
+    LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
+    return;
+  }
   cricket::VideoOptions options;
   VideoTrackSourceInterface* source = track_->GetSource();
   if (source) {
     options.is_screencast = rtc::Optional<bool>(source->is_screencast());
     options.video_noise_reduction = source->needs_denoising();
   }
-  provider_->SetVideoSend(ssrc_, track_->enabled(), &options, track_);
+  RTC_DCHECK(
+      channel_->SetVideoSend(ssrc_, track_->enabled(), &options, track_));
 }
 
 void VideoRtpSender::ClearVideoSend() {
   RTC_DCHECK(ssrc_ != 0);
-  RTC_DCHECK(provider_ != nullptr);
-  provider_->SetVideoSend(ssrc_, false, nullptr, nullptr);
+  RTC_DCHECK(!stopped_);
+  if (!channel_) {
+    LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
+    return;
+  }
+  // Allow SetVideoSend to fail since |enable| is false and |source| is null.
+  // This the normal case when the underlying media channel has already been
+  // deleted.
+  channel_->SetVideoSend(ssrc_, false, nullptr, nullptr);
 }
 
 }  // namespace webrtc
diff --git a/webrtc/api/rtpsender.h b/webrtc/api/rtpsender.h
index a0bcc94..067ae5e 100644
--- a/webrtc/api/rtpsender.h
+++ b/webrtc/api/rtpsender.h
@@ -18,12 +18,13 @@
 #include <memory>
 #include <string>
 
-#include "webrtc/api/mediastreamprovider.h"
+#include "webrtc/api/mediastreaminterface.h"
 #include "webrtc/api/rtpsenderinterface.h"
 #include "webrtc/api/statscollector.h"
 #include "webrtc/base/basictypes.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/media/base/audiosource.h"
+#include "webrtc/pc/channel.h"
 
 namespace webrtc {
 
@@ -72,18 +73,21 @@
  public:
   // StatsCollector provided so that Add/RemoveLocalAudioTrack can be called
   // at the appropriate times.
+  // |channel| can be null if one does not exist yet.
   AudioRtpSender(AudioTrackInterface* track,
                  const std::string& stream_id,
-                 AudioProviderInterface* provider,
+                 cricket::VoiceChannel* channel,
                  StatsCollector* stats);
 
   // Randomly generates stream_id.
+  // |channel| can be null if one does not exist yet.
   AudioRtpSender(AudioTrackInterface* track,
-                 AudioProviderInterface* provider,
+                 cricket::VoiceChannel* channel,
                  StatsCollector* stats);
 
   // Randomly generates id and stream_id.
-  AudioRtpSender(AudioProviderInterface* provider, StatsCollector* stats);
+  // |channel| can be null if one does not exist yet.
+  AudioRtpSender(cricket::VoiceChannel* channel, StatsCollector* stats);
 
   virtual ~AudioRtpSender();
 
@@ -122,6 +126,10 @@
 
   void Stop() override;
 
+  // Does not take ownership.
+  // Should call SetChannel(nullptr) before |channel| is destroyed.
+  void SetChannel(cricket::VoiceChannel* channel) { channel_ = channel; }
+
  private:
   // TODO(nisse): Since SSRC == 0 is technically valid, figure out
   // some other way to test if we have a valid SSRC.
@@ -129,10 +137,12 @@
   // Helper function to construct options for
   // AudioProviderInterface::SetAudioSend.
   void SetAudioSend();
+  // Helper function to call SetAudioSend with "stop sending" parameters.
+  void ClearAudioSend();
 
   std::string id_;
   std::string stream_id_;
-  AudioProviderInterface* provider_;
+  cricket::VoiceChannel* channel_ = nullptr;
   StatsCollector* stats_;
   rtc::scoped_refptr<AudioTrackInterface> track_;
   uint32_t ssrc_ = 0;
@@ -147,15 +157,18 @@
 class VideoRtpSender : public ObserverInterface,
                        public rtc::RefCountedObject<RtpSenderInternal> {
  public:
+  // |channel| can be null if one does not exist yet.
   VideoRtpSender(VideoTrackInterface* track,
                  const std::string& stream_id,
-                 VideoProviderInterface* provider);
+                 cricket::VideoChannel* channel);
 
   // Randomly generates stream_id.
-  VideoRtpSender(VideoTrackInterface* track, VideoProviderInterface* provider);
+  // |channel| can be null if one does not exist yet.
+  VideoRtpSender(VideoTrackInterface* track, cricket::VideoChannel* channel);
 
   // Randomly generates id and stream_id.
-  explicit VideoRtpSender(VideoProviderInterface* provider);
+  // |channel| can be null if one does not exist yet.
+  explicit VideoRtpSender(cricket::VideoChannel* channel);
 
   virtual ~VideoRtpSender();
 
@@ -194,6 +207,10 @@
 
   void Stop() override;
 
+  // Does not take ownership.
+  // Should call SetChannel(nullptr) before |channel| is destroyed.
+  void SetChannel(cricket::VideoChannel* channel) { channel_ = channel; }
+
  private:
   bool can_send_track() const { return track_ && ssrc_; }
   // Helper function to construct options for
@@ -204,7 +221,7 @@
 
   std::string id_;
   std::string stream_id_;
-  VideoProviderInterface* provider_;
+  cricket::VideoChannel* channel_ = nullptr;
   rtc::scoped_refptr<VideoTrackInterface> track_;
   uint32_t ssrc_ = 0;
   bool cached_track_enabled_ = false;
diff --git a/webrtc/api/rtpsenderreceiver_unittest.cc b/webrtc/api/rtpsenderreceiver_unittest.cc
index a08e1b4..8c91e14 100644
--- a/webrtc/api/rtpsenderreceiver_unittest.cc
+++ b/webrtc/api/rtpsenderreceiver_unittest.cc
@@ -15,6 +15,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/api/audiotrack.h"
+#include "webrtc/api/fakemediacontroller.h"
+#include "webrtc/api/localaudiosource.h"
 #include "webrtc/api/mediastream.h"
 #include "webrtc/api/remoteaudiosource.h"
 #include "webrtc/api/rtpreceiver.h"
@@ -25,6 +27,10 @@
 #include "webrtc/api/videotrack.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/media/base/mediachannel.h"
+#include "webrtc/media/base/fakemediaengine.h"
+#include "webrtc/media/engine/fakewebrtccall.h"
+#include "webrtc/p2p/base/faketransportcontroller.h"
+#include "webrtc/pc/channelmanager.h"
 
 using ::testing::_;
 using ::testing::Exactly;
@@ -41,70 +47,57 @@
 
 namespace webrtc {
 
-// Helper class to test RtpSender/RtpReceiver.
-class MockAudioProvider : public AudioProviderInterface {
- public:
-  // TODO(nisse): Valid overrides commented out, because the gmock
-  // methods don't use any override declarations, and we want to avoid
-  // warnings from -Winconsistent-missing-override. See
-  // http://crbug.com/428099.
-  ~MockAudioProvider() /* override */ {}
-
-  MOCK_METHOD2(SetAudioPlayout,
-               void(uint32_t ssrc,
-                    bool enable));
-  MOCK_METHOD4(SetAudioSend,
-               void(uint32_t ssrc,
-                    bool enable,
-                    const cricket::AudioOptions& options,
-                    cricket::AudioSource* source));
-  MOCK_METHOD2(SetAudioPlayoutVolume, void(uint32_t ssrc, double volume));
-  MOCK_CONST_METHOD1(GetAudioRtpSendParameters, RtpParameters(uint32_t ssrc));
-  MOCK_METHOD2(SetAudioRtpSendParameters,
-               bool(uint32_t ssrc, const RtpParameters&));
-  MOCK_CONST_METHOD1(GetAudioRtpReceiveParameters,
-                     RtpParameters(uint32_t ssrc));
-  MOCK_METHOD2(SetAudioRtpReceiveParameters,
-               bool(uint32_t ssrc, const RtpParameters&));
-
-  void SetRawAudioSink(
-      uint32_t, std::unique_ptr<AudioSinkInterface> sink) /* override */ {
-    sink_ = std::move(sink);
-  }
-
- private:
-  std::unique_ptr<AudioSinkInterface> sink_;
-};
-
-// Helper class to test RtpSender/RtpReceiver.
-class MockVideoProvider : public VideoProviderInterface {
- public:
-  virtual ~MockVideoProvider() {}
-  MOCK_METHOD3(SetVideoPlayout,
-               void(uint32_t ssrc,
-                    bool enable,
-                    rtc::VideoSinkInterface<cricket::VideoFrame>* sink));
-  MOCK_METHOD4(SetVideoSend,
-               void(uint32_t ssrc,
-                    bool enable,
-                    const cricket::VideoOptions* options,
-                    rtc::VideoSourceInterface<cricket::VideoFrame>* source));
-
-  MOCK_CONST_METHOD1(GetVideoRtpSendParameters, RtpParameters(uint32_t ssrc));
-  MOCK_METHOD2(SetVideoRtpSendParameters,
-               bool(uint32_t ssrc, const RtpParameters&));
-  MOCK_CONST_METHOD1(GetVideoRtpReceiveParameters,
-                     RtpParameters(uint32_t ssrc));
-  MOCK_METHOD2(SetVideoRtpReceiveParameters,
-               bool(uint32_t ssrc, const RtpParameters&));
-};
-
 class RtpSenderReceiverTest : public testing::Test {
  public:
-  virtual void SetUp() {
-    stream_ = MediaStream::Create(kStreamLabel1);
+  RtpSenderReceiverTest()
+      :  // Create fake media engine/etc. so we can create channels to use to
+        // test RtpSenders/RtpReceivers.
+        media_engine_(new cricket::FakeMediaEngine()),
+        channel_manager_(media_engine_,
+                         rtc::Thread::Current(),
+                         rtc::Thread::Current()),
+        fake_call_(webrtc::Call::Config()),
+        fake_media_controller_(&channel_manager_, &fake_call_),
+        stream_(MediaStream::Create(kStreamLabel1)) {
+    // Create channels to be used by the RtpSenders and RtpReceivers.
+    channel_manager_.Init();
+    voice_channel_ = channel_manager_.CreateVoiceChannel(
+        &fake_media_controller_, &fake_transport_controller_, cricket::CN_AUDIO,
+        nullptr, false, cricket::AudioOptions());
+    video_channel_ = channel_manager_.CreateVideoChannel(
+        &fake_media_controller_, &fake_transport_controller_, cricket::CN_VIDEO,
+        nullptr, false, cricket::VideoOptions());
+    voice_media_channel_ = media_engine_->GetVoiceChannel(0);
+    video_media_channel_ = media_engine_->GetVideoChannel(0);
+    RTC_CHECK(voice_channel_);
+    RTC_CHECK(video_channel_);
+    RTC_CHECK(voice_media_channel_);
+    RTC_CHECK(video_media_channel_);
+
+    // Create streams for predefined SSRCs. Streams need to exist in order
+    // for the senders and receievers to apply parameters to them.
+    // Normally these would be created by SetLocalDescription and
+    // SetRemoteDescription.
+    voice_media_channel_->AddSendStream(
+        cricket::StreamParams::CreateLegacy(kAudioSsrc));
+    voice_media_channel_->AddRecvStream(
+        cricket::StreamParams::CreateLegacy(kAudioSsrc));
+    voice_media_channel_->AddSendStream(
+        cricket::StreamParams::CreateLegacy(kAudioSsrc2));
+    voice_media_channel_->AddRecvStream(
+        cricket::StreamParams::CreateLegacy(kAudioSsrc2));
+    video_media_channel_->AddSendStream(
+        cricket::StreamParams::CreateLegacy(kVideoSsrc));
+    video_media_channel_->AddRecvStream(
+        cricket::StreamParams::CreateLegacy(kVideoSsrc));
+    video_media_channel_->AddSendStream(
+        cricket::StreamParams::CreateLegacy(kVideoSsrc2));
+    video_media_channel_->AddRecvStream(
+        cricket::StreamParams::CreateLegacy(kVideoSsrc2));
   }
 
+  void TearDown() override { channel_manager_.Terminate(); }
+
   void AddVideoTrack() {
     rtc::scoped_refptr<VideoTrackSourceInterface> source(
         FakeVideoTrackSource::Create());
@@ -112,68 +105,128 @@
     EXPECT_TRUE(stream_->AddTrack(video_track_));
   }
 
-  void CreateAudioRtpSender() {
-    audio_track_ = AudioTrack::Create(kAudioTrackId, NULL);
+  void CreateAudioRtpSender() { CreateAudioRtpSender(nullptr); }
+
+  void CreateAudioRtpSender(rtc::scoped_refptr<LocalAudioSource> source) {
+    audio_track_ = AudioTrack::Create(kAudioTrackId, source);
     EXPECT_TRUE(stream_->AddTrack(audio_track_));
-    EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
     audio_rtp_sender_ =
         new AudioRtpSender(stream_->GetAudioTracks()[0], stream_->label(),
-                           &audio_provider_, nullptr);
+                           voice_channel_, nullptr);
     audio_rtp_sender_->SetSsrc(kAudioSsrc);
+    VerifyVoiceChannelInput();
   }
 
   void CreateVideoRtpSender() {
     AddVideoTrack();
-    EXPECT_CALL(video_provider_,
-                SetVideoSend(kVideoSsrc, true, _, video_track_.get()));
     video_rtp_sender_ = new VideoRtpSender(stream_->GetVideoTracks()[0],
-                                           stream_->label(), &video_provider_);
+                                           stream_->label(), video_channel_);
     video_rtp_sender_->SetSsrc(kVideoSsrc);
+    VerifyVideoChannelInput();
   }
 
   void DestroyAudioRtpSender() {
-    EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, _))
-        .Times(1);
     audio_rtp_sender_ = nullptr;
+    VerifyVoiceChannelNoInput();
   }
 
   void DestroyVideoRtpSender() {
-    EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, false, _, nullptr))
-        .Times(1);
     video_rtp_sender_ = nullptr;
+    VerifyVideoChannelNoInput();
   }
 
   void CreateAudioRtpReceiver() {
     audio_track_ = AudioTrack::Create(
         kAudioTrackId, RemoteAudioSource::Create(kAudioSsrc, NULL));
     EXPECT_TRUE(stream_->AddTrack(audio_track_));
-    EXPECT_CALL(audio_provider_, SetAudioPlayout(kAudioSsrc, true));
     audio_rtp_receiver_ = new AudioRtpReceiver(stream_, kAudioTrackId,
-                                               kAudioSsrc, &audio_provider_);
+                                               kAudioSsrc, voice_channel_);
     audio_track_ = audio_rtp_receiver_->audio_track();
+    VerifyVoiceChannelOutput();
   }
 
   void CreateVideoRtpReceiver() {
-    EXPECT_CALL(video_provider_, SetVideoPlayout(kVideoSsrc, true, _));
     video_rtp_receiver_ =
         new VideoRtpReceiver(stream_, kVideoTrackId, rtc::Thread::Current(),
-                             kVideoSsrc, &video_provider_);
+                             kVideoSsrc, video_channel_);
     video_track_ = video_rtp_receiver_->video_track();
+    VerifyVideoChannelOutput();
   }
 
   void DestroyAudioRtpReceiver() {
-    EXPECT_CALL(audio_provider_, SetAudioPlayout(kAudioSsrc, false));
     audio_rtp_receiver_ = nullptr;
+    VerifyVoiceChannelNoOutput();
   }
 
   void DestroyVideoRtpReceiver() {
-    EXPECT_CALL(video_provider_, SetVideoPlayout(kVideoSsrc, false, NULL));
     video_rtp_receiver_ = nullptr;
+    VerifyVideoChannelNoOutput();
+  }
+
+  void VerifyVoiceChannelInput() { VerifyVoiceChannelInput(kAudioSsrc); }
+
+  void VerifyVoiceChannelInput(uint32_t ssrc) {
+    // Verify that the media channel has an audio source, and the stream isn't
+    // muted.
+    EXPECT_TRUE(voice_media_channel_->HasSource(ssrc));
+    EXPECT_FALSE(voice_media_channel_->IsStreamMuted(ssrc));
+  }
+
+  void VerifyVideoChannelInput() { VerifyVideoChannelInput(kVideoSsrc); }
+
+  void VerifyVideoChannelInput(uint32_t ssrc) {
+    // Verify that the media channel has a video source,
+    EXPECT_TRUE(video_media_channel_->HasSource(ssrc));
+  }
+
+  void VerifyVoiceChannelNoInput() { VerifyVoiceChannelNoInput(kAudioSsrc); }
+
+  void VerifyVoiceChannelNoInput(uint32_t ssrc) {
+    // Verify that the media channel's source is reset.
+    EXPECT_FALSE(voice_media_channel_->HasSource(ssrc));
+  }
+
+  void VerifyVideoChannelNoInput() { VerifyVideoChannelNoInput(kVideoSsrc); }
+
+  void VerifyVideoChannelNoInput(uint32_t ssrc) {
+    // Verify that the media channel's source is reset.
+    EXPECT_FALSE(video_media_channel_->HasSource(ssrc));
+  }
+
+  void VerifyVoiceChannelOutput() {
+    // Verify that the volume is initialized to 1.
+    double volume;
+    EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+    EXPECT_EQ(1, volume);
+  }
+
+  void VerifyVideoChannelOutput() {
+    // Verify that the media channel has a sink.
+    EXPECT_TRUE(video_media_channel_->HasSink(kVideoSsrc));
+  }
+
+  void VerifyVoiceChannelNoOutput() {
+    // Verify that the volume is reset to 0.
+    double volume;
+    EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+    EXPECT_EQ(0, volume);
+  }
+
+  void VerifyVideoChannelNoOutput() {
+    // Verify that the media channel's sink is reset.
+    EXPECT_FALSE(video_media_channel_->HasSink(kVideoSsrc));
   }
 
  protected:
-  MockAudioProvider audio_provider_;
-  MockVideoProvider video_provider_;
+  cricket::FakeMediaEngine* media_engine_;
+  cricket::FakeTransportController fake_transport_controller_;
+  cricket::ChannelManager channel_manager_;
+  cricket::FakeCall fake_call_;
+  cricket::FakeMediaController fake_media_controller_;
+  cricket::VoiceChannel* voice_channel_;
+  cricket::VideoChannel* video_channel_;
+  cricket::FakeVoiceMediaChannel* voice_media_channel_;
+  cricket::FakeVideoMediaChannel* video_media_channel_;
   rtc::scoped_refptr<AudioRtpSender> audio_rtp_sender_;
   rtc::scoped_refptr<VideoRtpSender> video_rtp_sender_;
   rtc::scoped_refptr<AudioRtpReceiver> audio_rtp_receiver_;
@@ -183,72 +236,96 @@
   rtc::scoped_refptr<AudioTrackInterface> audio_track_;
 };
 
-// Test that |audio_provider_| is notified when an audio track is associated
+// Test that |voice_channel_| is updated when an audio track is associated
 // and disassociated with an AudioRtpSender.
 TEST_F(RtpSenderReceiverTest, AddAndDestroyAudioRtpSender) {
   CreateAudioRtpSender();
   DestroyAudioRtpSender();
 }
 
-// Test that |video_provider_| is notified when a video track is associated and
+// Test that |video_channel_| is updated when a video track is associated and
 // disassociated with a VideoRtpSender.
 TEST_F(RtpSenderReceiverTest, AddAndDestroyVideoRtpSender) {
   CreateVideoRtpSender();
   DestroyVideoRtpSender();
 }
 
-// Test that |audio_provider_| is notified when a remote audio and track is
+// Test that |voice_channel_| is updated when a remote audio track is
 // associated and disassociated with an AudioRtpReceiver.
 TEST_F(RtpSenderReceiverTest, AddAndDestroyAudioRtpReceiver) {
   CreateAudioRtpReceiver();
   DestroyAudioRtpReceiver();
 }
 
-// Test that |video_provider_| is notified when a remote
-// video track is associated and disassociated with a VideoRtpReceiver.
+// Test that |video_channel_| is updated when a remote video track is
+// associated and disassociated with a VideoRtpReceiver.
 TEST_F(RtpSenderReceiverTest, AddAndDestroyVideoRtpReceiver) {
   CreateVideoRtpReceiver();
   DestroyVideoRtpReceiver();
 }
 
-TEST_F(RtpSenderReceiverTest, LocalAudioTrackDisable) {
-  CreateAudioRtpSender();
+// Test that the AudioRtpSender applies options from the local audio source.
+TEST_F(RtpSenderReceiverTest, LocalAudioSourceOptionsApplied) {
+  cricket::AudioOptions options;
+  options.echo_cancellation = rtc::Optional<bool>(true);
+  auto source = LocalAudioSource::Create(
+      PeerConnectionFactoryInterface::Options(), &options);
+  CreateAudioRtpSender(source.get());
 
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, _));
-  audio_track_->set_enabled(false);
-
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
-  audio_track_->set_enabled(true);
+  EXPECT_EQ(rtc::Optional<bool>(true),
+            voice_media_channel_->options().echo_cancellation);
 
   DestroyAudioRtpSender();
 }
 
+// Test that the stream is muted when the track is disabled, and unmuted when
+// the track is enabled.
+TEST_F(RtpSenderReceiverTest, LocalAudioTrackDisable) {
+  CreateAudioRtpSender();
+
+  audio_track_->set_enabled(false);
+  EXPECT_TRUE(voice_media_channel_->IsStreamMuted(kAudioSsrc));
+
+  audio_track_->set_enabled(true);
+  EXPECT_FALSE(voice_media_channel_->IsStreamMuted(kAudioSsrc));
+
+  DestroyAudioRtpSender();
+}
+
+// Test that the volume is set to 0 when the track is disabled, and back to
+// 1 when the track is enabled.
 TEST_F(RtpSenderReceiverTest, RemoteAudioTrackDisable) {
   CreateAudioRtpReceiver();
 
-  EXPECT_CALL(audio_provider_, SetAudioPlayout(kAudioSsrc, false));
-  audio_track_->set_enabled(false);
+  double volume;
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(1, volume);
 
-  EXPECT_CALL(audio_provider_, SetAudioPlayout(kAudioSsrc, true));
+  audio_track_->set_enabled(false);
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(0, volume);
+
   audio_track_->set_enabled(true);
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(1, volume);
 
   DestroyAudioRtpReceiver();
 }
 
+// Currently no action is taken when a remote video track is disabled or
+// enabled, so there's nothing to test here, other than what is normally
+// verified in DestroyVideoRtpSender.
 TEST_F(RtpSenderReceiverTest, LocalVideoTrackDisable) {
   CreateVideoRtpSender();
 
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc, false, _, video_track_.get()));
   video_track_->set_enabled(false);
-
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc, true, _, video_track_.get()));
   video_track_->set_enabled(true);
 
   DestroyVideoRtpSender();
 }
 
+// Test that the state of the video track created by the VideoRtpReceiver is
+// updated when the receiver is destroyed.
 TEST_F(RtpSenderReceiverTest, RemoteVideoTrackState) {
   CreateVideoRtpReceiver();
 
@@ -263,282 +340,268 @@
             video_track_->GetSource()->state());
 }
 
+// Currently no action is taken when a remote video track is disabled or
+// enabled, so there's nothing to test here, other than what is normally
+// verified in DestroyVideoRtpReceiver.
 TEST_F(RtpSenderReceiverTest, RemoteVideoTrackDisable) {
   CreateVideoRtpReceiver();
 
   video_track_->set_enabled(false);
-
   video_track_->set_enabled(true);
 
   DestroyVideoRtpReceiver();
 }
 
+// Test that the AudioRtpReceiver applies volume changes from the track source
+// to the media channel.
 TEST_F(RtpSenderReceiverTest, RemoteAudioTrackSetVolume) {
   CreateAudioRtpReceiver();
 
-  double volume = 0.5;
-  EXPECT_CALL(audio_provider_, SetAudioPlayoutVolume(kAudioSsrc, volume));
-  audio_track_->GetSource()->SetVolume(volume);
+  double volume;
+  audio_track_->GetSource()->SetVolume(0.5);
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(0.5, volume);
 
   // Disable the audio track, this should prevent setting the volume.
-  EXPECT_CALL(audio_provider_, SetAudioPlayout(kAudioSsrc, false));
   audio_track_->set_enabled(false);
-  audio_track_->GetSource()->SetVolume(1.0);
+  audio_track_->GetSource()->SetVolume(0.8);
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(0, volume);
 
-  EXPECT_CALL(audio_provider_, SetAudioPlayout(kAudioSsrc, true));
+  // When the track is enabled, the previously set volume should take effect.
   audio_track_->set_enabled(true);
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(0.8, volume);
 
-  double new_volume = 0.8;
-  EXPECT_CALL(audio_provider_, SetAudioPlayoutVolume(kAudioSsrc, new_volume));
-  audio_track_->GetSource()->SetVolume(new_volume);
+  // Try changing volume one more time.
+  audio_track_->GetSource()->SetVolume(0.9);
+  EXPECT_TRUE(voice_media_channel_->GetOutputVolume(kAudioSsrc, &volume));
+  EXPECT_EQ(0.9, volume);
 
   DestroyAudioRtpReceiver();
 }
 
-// Test that provider methods aren't called without both a track and an SSRC.
+// Test that the media channel isn't enabled for sending if the audio sender
+// doesn't have both a track and SSRC.
 TEST_F(RtpSenderReceiverTest, AudioSenderWithoutTrackAndSsrc) {
-  rtc::scoped_refptr<AudioRtpSender> sender =
-      new AudioRtpSender(&audio_provider_, nullptr);
+  audio_rtp_sender_ = new AudioRtpSender(voice_channel_, nullptr);
   rtc::scoped_refptr<AudioTrackInterface> track =
       AudioTrack::Create(kAudioTrackId, nullptr);
-  EXPECT_TRUE(sender->SetTrack(track));
-  EXPECT_TRUE(sender->SetTrack(nullptr));
-  sender->SetSsrc(kAudioSsrc);
-  sender->SetSsrc(0);
-  // Just let it get destroyed and make sure it doesn't call any methods on the
-  // provider interface.
+
+  // Track but no SSRC.
+  EXPECT_TRUE(audio_rtp_sender_->SetTrack(track));
+  VerifyVoiceChannelNoInput();
+
+  // SSRC but no track.
+  EXPECT_TRUE(audio_rtp_sender_->SetTrack(nullptr));
+  audio_rtp_sender_->SetSsrc(kAudioSsrc);
+  VerifyVoiceChannelNoInput();
 }
 
-// Test that provider methods aren't called without both a track and an SSRC.
+// Test that the media channel isn't enabled for sending if the video sender
+// doesn't have both a track and SSRC.
 TEST_F(RtpSenderReceiverTest, VideoSenderWithoutTrackAndSsrc) {
-  rtc::scoped_refptr<VideoRtpSender> sender =
-      new VideoRtpSender(&video_provider_);
-  EXPECT_TRUE(sender->SetTrack(video_track_));
-  EXPECT_TRUE(sender->SetTrack(nullptr));
-  sender->SetSsrc(kVideoSsrc);
-  sender->SetSsrc(0);
-  // Just let it get destroyed and make sure it doesn't call any methods on the
-  // provider interface.
+  video_rtp_sender_ = new VideoRtpSender(video_channel_);
+
+  // Track but no SSRC.
+  EXPECT_TRUE(video_rtp_sender_->SetTrack(video_track_));
+  VerifyVideoChannelNoInput();
+
+  // SSRC but no track.
+  EXPECT_TRUE(video_rtp_sender_->SetTrack(nullptr));
+  video_rtp_sender_->SetSsrc(kVideoSsrc);
+  VerifyVideoChannelNoInput();
 }
 
-// Test that an audio sender calls the expected methods on the provider once
-// it has a track and SSRC, when the SSRC is set first.
+// Test that the media channel is enabled for sending when the audio sender
+// has a track and SSRC, when the SSRC is set first.
 TEST_F(RtpSenderReceiverTest, AudioSenderEarlyWarmupSsrcThenTrack) {
-  rtc::scoped_refptr<AudioRtpSender> sender =
-      new AudioRtpSender(&audio_provider_, nullptr);
+  audio_rtp_sender_ = new AudioRtpSender(voice_channel_, nullptr);
   rtc::scoped_refptr<AudioTrackInterface> track =
       AudioTrack::Create(kAudioTrackId, nullptr);
-  sender->SetSsrc(kAudioSsrc);
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
-  sender->SetTrack(track);
+  audio_rtp_sender_->SetSsrc(kAudioSsrc);
+  audio_rtp_sender_->SetTrack(track);
+  VerifyVoiceChannelInput();
 
-  // Calls expected from destructor.
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, _)).Times(1);
+  DestroyAudioRtpSender();
 }
 
-// Test that an audio sender calls the expected methods on the provider once
-// it has a track and SSRC, when the SSRC is set last.
+// Test that the media channel is enabled for sending when the audio sender
+// has a track and SSRC, when the SSRC is set last.
 TEST_F(RtpSenderReceiverTest, AudioSenderEarlyWarmupTrackThenSsrc) {
-  rtc::scoped_refptr<AudioRtpSender> sender =
-      new AudioRtpSender(&audio_provider_, nullptr);
+  audio_rtp_sender_ = new AudioRtpSender(voice_channel_, nullptr);
   rtc::scoped_refptr<AudioTrackInterface> track =
       AudioTrack::Create(kAudioTrackId, nullptr);
-  sender->SetTrack(track);
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
-  sender->SetSsrc(kAudioSsrc);
+  audio_rtp_sender_->SetTrack(track);
+  audio_rtp_sender_->SetSsrc(kAudioSsrc);
+  VerifyVoiceChannelInput();
 
-  // Calls expected from destructor.
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, _)).Times(1);
+  DestroyAudioRtpSender();
 }
 
-// Test that a video sender calls the expected methods on the provider once
-// it has a track and SSRC, when the SSRC is set first.
+// Test that the media channel is enabled for sending when the video sender
+// has a track and SSRC, when the SSRC is set first.
 TEST_F(RtpSenderReceiverTest, VideoSenderEarlyWarmupSsrcThenTrack) {
   AddVideoTrack();
-  rtc::scoped_refptr<VideoRtpSender> sender =
-      new VideoRtpSender(&video_provider_);
-  sender->SetSsrc(kVideoSsrc);
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc, true, _, video_track_.get()));
-  sender->SetTrack(video_track_);
+  video_rtp_sender_ = new VideoRtpSender(video_channel_);
+  video_rtp_sender_->SetSsrc(kVideoSsrc);
+  video_rtp_sender_->SetTrack(video_track_);
+  VerifyVideoChannelInput();
 
-  // Calls expected from destructor.
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, false, _, nullptr))
-      .Times(1);
+  DestroyVideoRtpSender();
 }
 
-// Test that a video sender calls the expected methods on the provider once
-// it has a track and SSRC, when the SSRC is set last.
+// Test that the media channel is enabled for sending when the video sender
+// has a track and SSRC, when the SSRC is set last.
 TEST_F(RtpSenderReceiverTest, VideoSenderEarlyWarmupTrackThenSsrc) {
   AddVideoTrack();
-  rtc::scoped_refptr<VideoRtpSender> sender =
-      new VideoRtpSender(&video_provider_);
-  sender->SetTrack(video_track_);
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc, true, _, video_track_.get()));
-  sender->SetSsrc(kVideoSsrc);
+  video_rtp_sender_ = new VideoRtpSender(video_channel_);
+  video_rtp_sender_->SetTrack(video_track_);
+  video_rtp_sender_->SetSsrc(kVideoSsrc);
+  VerifyVideoChannelInput();
 
-  // Calls expected from destructor.
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, false, _, nullptr))
-      .Times(1);
+  DestroyVideoRtpSender();
 }
 
-// Test that the sender is disconnected from the provider when its SSRC is
-// set to 0.
+// Test that the media channel stops sending when the audio sender's SSRC is set
+// to 0.
 TEST_F(RtpSenderReceiverTest, AudioSenderSsrcSetToZero) {
-  rtc::scoped_refptr<AudioTrackInterface> track =
-      AudioTrack::Create(kAudioTrackId, nullptr);
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
-  rtc::scoped_refptr<AudioRtpSender> sender =
-      new AudioRtpSender(track, kStreamLabel1, &audio_provider_, nullptr);
-  sender->SetSsrc(kAudioSsrc);
+  CreateAudioRtpSender();
 
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, _)).Times(1);
-  sender->SetSsrc(0);
-
-  // Make sure it's SetSsrc that called methods on the provider, and not the
-  // destructor.
-  EXPECT_CALL(audio_provider_, SetAudioSend(_, _, _, _)).Times(0);
+  audio_rtp_sender_->SetSsrc(0);
+  VerifyVoiceChannelNoInput();
 }
 
-// Test that the sender is disconnected from the provider when its SSRC is
-// set to 0.
+// Test that the media channel stops sending when the video sender's SSRC is set
+// to 0.
 TEST_F(RtpSenderReceiverTest, VideoSenderSsrcSetToZero) {
-  AddVideoTrack();
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc, true, _, video_track_.get()));
-  rtc::scoped_refptr<VideoRtpSender> sender =
-      new VideoRtpSender(video_track_, kStreamLabel1, &video_provider_);
-  sender->SetSsrc(kVideoSsrc);
+  CreateAudioRtpSender();
 
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, false, _, nullptr))
-      .Times(1);
-  sender->SetSsrc(0);
-
-  // Make sure it's SetSsrc that called methods on the provider, and not the
-  // destructor.
-  EXPECT_CALL(video_provider_, SetVideoSend(_, _, _, _)).Times(0);
+  audio_rtp_sender_->SetSsrc(0);
+  VerifyVideoChannelNoInput();
 }
 
+// Test that the media channel stops sending when the audio sender's track is
+// set to null.
 TEST_F(RtpSenderReceiverTest, AudioSenderTrackSetToNull) {
-  rtc::scoped_refptr<AudioTrackInterface> track =
-      AudioTrack::Create(kAudioTrackId, nullptr);
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
-  rtc::scoped_refptr<AudioRtpSender> sender =
-      new AudioRtpSender(track, kStreamLabel1, &audio_provider_, nullptr);
-  sender->SetSsrc(kAudioSsrc);
+  CreateAudioRtpSender();
 
-  // Expect that SetAudioSend will be called before the reference to the track
-  // is released.
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, nullptr))
-      .Times(1)
-      .WillOnce(InvokeWithoutArgs([&track] {
-        EXPECT_LT(2, track->AddRef());
-        track->Release();
-      }));
-  EXPECT_TRUE(sender->SetTrack(nullptr));
-
-  // Make sure it's SetTrack that called methods on the provider, and not the
-  // destructor.
-  EXPECT_CALL(audio_provider_, SetAudioSend(_, _, _, _)).Times(0);
+  EXPECT_TRUE(audio_rtp_sender_->SetTrack(nullptr));
+  VerifyVoiceChannelNoInput();
 }
 
+// Test that the media channel stops sending when the video sender's track is
+// set to null.
 TEST_F(RtpSenderReceiverTest, VideoSenderTrackSetToNull) {
-  rtc::scoped_refptr<VideoTrackSourceInterface> source(
-      FakeVideoTrackSource::Create());
-  rtc::scoped_refptr<VideoTrackInterface> track =
-      VideoTrack::Create(kVideoTrackId, source);
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, true, _, track.get()));
-  rtc::scoped_refptr<VideoRtpSender> sender =
-      new VideoRtpSender(track, kStreamLabel1, &video_provider_);
-  sender->SetSsrc(kVideoSsrc);
+  CreateVideoRtpSender();
 
-  // Expect that SetVideoSend will be called before the reference to the track
-  // is released.
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, false, _, nullptr))
-      .Times(1)
-      .WillOnce(InvokeWithoutArgs([&track] {
-        EXPECT_LT(2, track->AddRef());
-        track->Release();
-      }));
-  EXPECT_TRUE(sender->SetTrack(nullptr));
-
-  // Make sure it's SetTrack that called methods on the provider, and not the
-  // destructor.
-  EXPECT_CALL(video_provider_, SetVideoSend(_, _, _, _)).Times(0);
+  video_rtp_sender_->SetSsrc(0);
+  VerifyVideoChannelNoInput();
 }
 
+// Test that when the audio sender's SSRC is changed, the media channel stops
+// sending with the old SSRC and starts sending with the new one.
 TEST_F(RtpSenderReceiverTest, AudioSenderSsrcChanged) {
-  AddVideoTrack();
-  rtc::scoped_refptr<AudioTrackInterface> track =
-      AudioTrack::Create(kAudioTrackId, nullptr);
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, true, _, _));
-  rtc::scoped_refptr<AudioRtpSender> sender =
-      new AudioRtpSender(track, kStreamLabel1, &audio_provider_, nullptr);
-  sender->SetSsrc(kAudioSsrc);
+  CreateAudioRtpSender();
 
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc, false, _, _)).Times(1);
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc2, true, _, _)).Times(1);
-  sender->SetSsrc(kAudioSsrc2);
+  audio_rtp_sender_->SetSsrc(kAudioSsrc2);
+  VerifyVoiceChannelNoInput(kAudioSsrc);
+  VerifyVoiceChannelInput(kAudioSsrc2);
 
-  // Calls expected from destructor.
-  EXPECT_CALL(audio_provider_, SetAudioSend(kAudioSsrc2, false, _, _)).Times(1);
+  audio_rtp_sender_ = nullptr;
+  VerifyVoiceChannelNoInput(kAudioSsrc2);
 }
 
+// Test that when the audio sender's SSRC is changed, the media channel stops
+// sending with the old SSRC and starts sending with the new one.
 TEST_F(RtpSenderReceiverTest, VideoSenderSsrcChanged) {
-  AddVideoTrack();
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc, true, _, video_track_.get()));
-  rtc::scoped_refptr<VideoRtpSender> sender =
-      new VideoRtpSender(video_track_, kStreamLabel1, &video_provider_);
-  sender->SetSsrc(kVideoSsrc);
+  CreateVideoRtpSender();
 
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc, false, _, nullptr))
-      .Times(1);
-  EXPECT_CALL(video_provider_,
-              SetVideoSend(kVideoSsrc2, true, _, video_track_.get()))
-      .Times(1);
-  sender->SetSsrc(kVideoSsrc2);
+  video_rtp_sender_->SetSsrc(kVideoSsrc2);
+  VerifyVideoChannelNoInput(kVideoSsrc);
+  VerifyVideoChannelInput(kVideoSsrc2);
 
-  // Calls expected from destructor.
-  EXPECT_CALL(video_provider_, SetVideoSend(kVideoSsrc2, false, _, nullptr))
-      .Times(1);
+  video_rtp_sender_ = nullptr;
+  VerifyVideoChannelNoInput(kVideoSsrc2);
 }
 
 TEST_F(RtpSenderReceiverTest, AudioSenderCanSetParameters) {
   CreateAudioRtpSender();
 
-  EXPECT_CALL(audio_provider_, GetAudioRtpSendParameters(kAudioSsrc))
-      .WillOnce(Return(RtpParameters()));
-  EXPECT_CALL(audio_provider_, SetAudioRtpSendParameters(kAudioSsrc, _))
-      .WillOnce(Return(true));
   RtpParameters params = audio_rtp_sender_->GetParameters();
+  EXPECT_EQ(1u, params.encodings.size());
   EXPECT_TRUE(audio_rtp_sender_->SetParameters(params));
 
   DestroyAudioRtpSender();
 }
 
+TEST_F(RtpSenderReceiverTest, SetAudioMaxSendBitrate) {
+  CreateAudioRtpSender();
+
+  EXPECT_EQ(-1, voice_media_channel_->max_bps());
+  webrtc::RtpParameters params = audio_rtp_sender_->GetParameters();
+  EXPECT_EQ(1, params.encodings.size());
+  EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
+  params.encodings[0].max_bitrate_bps = 1000;
+  EXPECT_TRUE(audio_rtp_sender_->SetParameters(params));
+
+  // Read back the parameters and verify they have been changed.
+  params = audio_rtp_sender_->GetParameters();
+  EXPECT_EQ(1, params.encodings.size());
+  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
+
+  // Verify that the audio channel received the new parameters.
+  params = voice_media_channel_->GetRtpSendParameters(kAudioSsrc);
+  EXPECT_EQ(1, params.encodings.size());
+  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
+
+  // Verify that the global bitrate limit has not been changed.
+  EXPECT_EQ(-1, voice_media_channel_->max_bps());
+
+  DestroyAudioRtpSender();
+}
+
 TEST_F(RtpSenderReceiverTest, VideoSenderCanSetParameters) {
   CreateVideoRtpSender();
 
-  EXPECT_CALL(video_provider_, GetVideoRtpSendParameters(kVideoSsrc))
-      .WillOnce(Return(RtpParameters()));
-  EXPECT_CALL(video_provider_, SetVideoRtpSendParameters(kVideoSsrc, _))
-      .WillOnce(Return(true));
   RtpParameters params = video_rtp_sender_->GetParameters();
+  EXPECT_EQ(1u, params.encodings.size());
   EXPECT_TRUE(video_rtp_sender_->SetParameters(params));
 
   DestroyVideoRtpSender();
 }
 
+TEST_F(RtpSenderReceiverTest, SetVideoMaxSendBitrate) {
+  CreateVideoRtpSender();
+
+  EXPECT_EQ(-1, video_media_channel_->max_bps());
+  webrtc::RtpParameters params = video_rtp_sender_->GetParameters();
+  EXPECT_EQ(1, params.encodings.size());
+  EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
+  params.encodings[0].max_bitrate_bps = 1000;
+  EXPECT_TRUE(video_rtp_sender_->SetParameters(params));
+
+  // Read back the parameters and verify they have been changed.
+  params = video_rtp_sender_->GetParameters();
+  EXPECT_EQ(1, params.encodings.size());
+  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
+
+  // Verify that the video channel received the new parameters.
+  params = video_media_channel_->GetRtpSendParameters(kVideoSsrc);
+  EXPECT_EQ(1, params.encodings.size());
+  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
+
+  // Verify that the global bitrate limit has not been changed.
+  EXPECT_EQ(-1, video_media_channel_->max_bps());
+
+  DestroyVideoRtpSender();
+}
+
 TEST_F(RtpSenderReceiverTest, AudioReceiverCanSetParameters) {
   CreateAudioRtpReceiver();
 
-  EXPECT_CALL(audio_provider_, GetAudioRtpReceiveParameters(kAudioSsrc))
-      .WillOnce(Return(RtpParameters()));
-  EXPECT_CALL(audio_provider_, SetAudioRtpReceiveParameters(kAudioSsrc, _))
-      .WillOnce(Return(true));
   RtpParameters params = audio_rtp_receiver_->GetParameters();
+  EXPECT_EQ(1u, params.encodings.size());
   EXPECT_TRUE(audio_rtp_receiver_->SetParameters(params));
 
   DestroyAudioRtpReceiver();
@@ -547,11 +610,8 @@
 TEST_F(RtpSenderReceiverTest, VideoReceiverCanSetParameters) {
   CreateVideoRtpReceiver();
 
-  EXPECT_CALL(video_provider_, GetVideoRtpReceiveParameters(kVideoSsrc))
-      .WillOnce(Return(RtpParameters()));
-  EXPECT_CALL(video_provider_, SetVideoRtpReceiveParameters(kVideoSsrc, _))
-      .WillOnce(Return(true));
   RtpParameters params = video_rtp_receiver_->GetParameters();
+  EXPECT_EQ(1u, params.encodings.size());
   EXPECT_TRUE(video_rtp_receiver_->SetParameters(params));
 
   DestroyVideoRtpReceiver();
diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc
index b9a3fc8..9801d58 100644
--- a/webrtc/api/webrtcsession.cc
+++ b/webrtc/api/webrtcsession.cc
@@ -1169,161 +1169,6 @@
   return desc.str();
 }
 
-void WebRtcSession::SetAudioPlayout(uint32_t ssrc, bool enable) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!voice_channel_) {
-    LOG(LS_ERROR) << "SetAudioPlayout: No audio channel exists.";
-    return;
-  }
-  if (!voice_channel_->SetOutputVolume(ssrc, enable ? 1 : 0)) {
-    // Allow that SetOutputVolume fail if |enable| is false but assert
-    // otherwise. This in the normal case when the underlying media channel has
-    // already been deleted.
-    ASSERT(enable == false);
-  }
-}
-
-void WebRtcSession::SetAudioSend(uint32_t ssrc,
-                                 bool enable,
-                                 const cricket::AudioOptions& options,
-                                 cricket::AudioSource* source) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!voice_channel_) {
-    LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
-    return;
-  }
-  if (!voice_channel_->SetAudioSend(ssrc, enable, &options, source)) {
-    LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc;
-  }
-}
-
-void WebRtcSession::SetAudioPlayoutVolume(uint32_t ssrc, double volume) {
-  ASSERT(signaling_thread()->IsCurrent());
-  ASSERT(volume >= 0 && volume <= 10);
-  if (!voice_channel_) {
-    LOG(LS_ERROR) << "SetAudioPlayoutVolume: No audio channel exists.";
-    return;
-  }
-
-  if (!voice_channel_->SetOutputVolume(ssrc, volume)) {
-    ASSERT(false);
-  }
-}
-
-void WebRtcSession::SetRawAudioSink(uint32_t ssrc,
-                                    std::unique_ptr<AudioSinkInterface> sink) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!voice_channel_)
-    return;
-
-  voice_channel_->SetRawAudioSink(ssrc, std::move(sink));
-}
-
-RtpParameters WebRtcSession::GetAudioRtpSendParameters(uint32_t ssrc) const {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (voice_channel_) {
-    return voice_channel_->GetRtpSendParameters(ssrc);
-  }
-  return RtpParameters();
-}
-
-bool WebRtcSession::SetAudioRtpSendParameters(uint32_t ssrc,
-                                              const RtpParameters& parameters) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!voice_channel_) {
-    return false;
-  }
-  return voice_channel_->SetRtpSendParameters(ssrc, parameters);
-}
-
-RtpParameters WebRtcSession::GetAudioRtpReceiveParameters(uint32_t ssrc) const {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (voice_channel_) {
-    return voice_channel_->GetRtpReceiveParameters(ssrc);
-  }
-  return RtpParameters();
-}
-
-bool WebRtcSession::SetAudioRtpReceiveParameters(
-    uint32_t ssrc,
-    const RtpParameters& parameters) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!voice_channel_) {
-    return false;
-  }
-  return voice_channel_->SetRtpReceiveParameters(ssrc, parameters);
-}
-
-void WebRtcSession::SetVideoPlayout(
-    uint32_t ssrc,
-    bool enable,
-    rtc::VideoSinkInterface<cricket::VideoFrame>* sink) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!video_channel_) {
-    LOG(LS_WARNING) << "SetVideoPlayout: No video channel exists.";
-    return;
-  }
-  if (!video_channel_->SetSink(ssrc, enable ? sink : NULL)) {
-    // Allow that SetSink fail if |sink| is NULL but assert otherwise.
-    // This in the normal case when the underlying media channel has already
-    // been deleted.
-    ASSERT(sink == NULL);
-  }
-}
-
-void WebRtcSession::SetVideoSend(
-    uint32_t ssrc,
-    bool enable,
-    const cricket::VideoOptions* options,
-    rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!video_channel_) {
-    LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
-    return;
-  }
-  if (!video_channel_->SetVideoSend(ssrc, enable, options, source)) {
-    // Allow that MuteStream fail if |enable| is false and |source| is NULL but
-    // assert otherwise. This in the normal case when the underlying media
-    // channel has already been deleted.
-    ASSERT(enable == false && source == nullptr);
-  }
-}
-
-RtpParameters WebRtcSession::GetVideoRtpSendParameters(uint32_t ssrc) const {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (video_channel_) {
-    return video_channel_->GetRtpSendParameters(ssrc);
-  }
-  return RtpParameters();
-}
-
-bool WebRtcSession::SetVideoRtpSendParameters(uint32_t ssrc,
-                                              const RtpParameters& parameters) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!video_channel_) {
-    return false;
-  }
-  return video_channel_->SetRtpSendParameters(ssrc, parameters);
-}
-
-RtpParameters WebRtcSession::GetVideoRtpReceiveParameters(uint32_t ssrc) const {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (video_channel_) {
-    return video_channel_->GetRtpReceiveParameters(ssrc);
-  }
-  return RtpParameters();
-}
-
-bool WebRtcSession::SetVideoRtpReceiveParameters(
-    uint32_t ssrc,
-    const RtpParameters& parameters) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (!video_channel_) {
-    return false;
-  }
-  return video_channel_->SetRtpReceiveParameters(ssrc, parameters);
-}
-
 bool WebRtcSession::CanInsertDtmf(const std::string& track_id) {
   ASSERT(signaling_thread()->IsCurrent());
   if (!voice_channel_) {
@@ -1767,8 +1612,6 @@
 
   voice_channel_->SignalDtlsSetupFailure.connect(
       this, &WebRtcSession::OnDtlsSetupFailure);
-  voice_channel_->SignalFirstPacketReceived.connect(
-      this, &WebRtcSession::OnChannelFirstPacketReceived);
 
   SignalVoiceChannelCreated();
   voice_channel_->SignalSentPacket.connect(this,
@@ -1792,8 +1635,6 @@
   }
   video_channel_->SignalDtlsSetupFailure.connect(
       this, &WebRtcSession::OnDtlsSetupFailure);
-  video_channel_->SignalFirstPacketReceived.connect(
-      this, &WebRtcSession::OnChannelFirstPacketReceived);
 
   SignalVideoChannelCreated();
   video_channel_->SignalSentPacket.connect(this,
@@ -1835,21 +1676,6 @@
            rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);
 }
 
-void WebRtcSession::OnChannelFirstPacketReceived(
-    cricket::BaseChannel* channel) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  if (!received_first_audio_packet_ &&
-      channel->media_type() == cricket::MEDIA_TYPE_AUDIO) {
-    received_first_audio_packet_ = true;
-    SignalFirstAudioPacketReceived();
-  } else if (!received_first_video_packet_ &&
-             channel->media_type() == cricket::MEDIA_TYPE_VIDEO) {
-    received_first_video_packet_ = true;
-    SignalFirstVideoPacketReceived();
-  }
-}
-
 void WebRtcSession::OnDataChannelMessageReceived(
     cricket::DataChannel* channel,
     const cricket::ReceiveDataParams& params,
diff --git a/webrtc/api/webrtcsession.h b/webrtc/api/webrtcsession.h
index 76af6c7..d69abc0 100644
--- a/webrtc/api/webrtcsession.h
+++ b/webrtc/api/webrtcsession.h
@@ -19,7 +19,6 @@
 #include "webrtc/api/datachannel.h"
 #include "webrtc/api/dtmfsender.h"
 #include "webrtc/api/mediacontroller.h"
-#include "webrtc/api/mediastreamprovider.h"
 #include "webrtc/api/peerconnectioninterface.h"
 #include "webrtc/api/statstypes.h"
 #include "webrtc/base/constructormagic.h"
@@ -115,11 +114,11 @@
 // participates in the network-level negotiation.  The individual streams of
 // packets are represented by TransportChannels.  The application-level protocol
 // is represented by SessionDecription objects.
-class WebRtcSession : public AudioProviderInterface,
-                      public VideoProviderInterface,
-                      public DtmfProviderInterface,
-                      public DataChannelProviderInterface,
-                      public sigslot::has_slots<> {
+class WebRtcSession :
+
+    public DtmfProviderInterface,
+    public DataChannelProviderInterface,
+    public sigslot::has_slots<> {
  public:
   enum State {
     STATE_INIT = 0,
@@ -234,41 +233,6 @@
   virtual bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id);
   virtual bool GetRemoteTrackIdBySsrc(uint32_t ssrc, std::string* track_id);
 
-  // AudioMediaProviderInterface implementation.
-  void SetAudioPlayout(uint32_t ssrc, bool enable) override;
-  void SetAudioSend(uint32_t ssrc,
-                    bool enable,
-                    const cricket::AudioOptions& options,
-                    cricket::AudioSource* source) override;
-  void SetAudioPlayoutVolume(uint32_t ssrc, double volume) override;
-  void SetRawAudioSink(uint32_t ssrc,
-                       std::unique_ptr<AudioSinkInterface> sink) override;
-
-  RtpParameters GetAudioRtpSendParameters(uint32_t ssrc) const override;
-  bool SetAudioRtpSendParameters(uint32_t ssrc,
-                                 const RtpParameters& parameters) override;
-  RtpParameters GetAudioRtpReceiveParameters(uint32_t ssrc) const override;
-  bool SetAudioRtpReceiveParameters(uint32_t ssrc,
-                                    const RtpParameters& parameters) override;
-
-  // Implements VideoMediaProviderInterface.
-  void SetVideoPlayout(
-      uint32_t ssrc,
-      bool enable,
-      rtc::VideoSinkInterface<cricket::VideoFrame>* sink) override;
-  void SetVideoSend(
-      uint32_t ssrc,
-      bool enable,
-      const cricket::VideoOptions* options,
-      rtc::VideoSourceInterface<cricket::VideoFrame>* source) override;
-
-  RtpParameters GetVideoRtpSendParameters(uint32_t ssrc) const override;
-  bool SetVideoRtpSendParameters(uint32_t ssrc,
-                                 const RtpParameters& parameters) override;
-  RtpParameters GetVideoRtpReceiveParameters(uint32_t ssrc) const override;
-  bool SetVideoRtpReceiveParameters(uint32_t ssrc,
-                                    const RtpParameters& parameters) override;
-
   // Implements DtmfProviderInterface.
   bool CanInsertDtmf(const std::string& track_id) override;
   bool InsertDtmf(const std::string& track_id,
@@ -310,8 +274,6 @@
   void OnCertificateReady(
       const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
   void OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp);
-  // Called when the channel received the first packet.
-  void OnChannelFirstPacketReceived(cricket::BaseChannel*);
 
   // For unit test.
   bool waiting_for_certificate_for_testing() const;
diff --git a/webrtc/api/webrtcsession_unittest.cc b/webrtc/api/webrtcsession_unittest.cc
index fab5e1a..ee1d19b 100644
--- a/webrtc/api/webrtcsession_unittest.cc
+++ b/webrtc/api/webrtcsession_unittest.cc
@@ -253,11 +253,6 @@
     return rtcp_transport_channel(data_channel());
   }
 
-  using webrtc::WebRtcSession::SetAudioPlayout;
-  using webrtc::WebRtcSession::SetAudioSend;
-  using webrtc::WebRtcSession::SetVideoPlayout;
-  using webrtc::WebRtcSession::SetVideoSend;
-
  private:
   cricket::TransportChannel* rtp_transport_channel(cricket::BaseChannel* ch) {
     if (!ch) {
@@ -3392,163 +3387,6 @@
   SetLocalDescriptionWithoutError(offer);
 }
 
-TEST_F(WebRtcSessionTest, SetAudioPlayout) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  ASSERT_EQ(1u, channel->recv_streams().size());
-  uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc();
-  double volume;
-  EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
-  EXPECT_EQ(1, volume);
-  session_->SetAudioPlayout(receive_ssrc, false);
-  EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
-  EXPECT_EQ(0, volume);
-  session_->SetAudioPlayout(receive_ssrc, true);
-  EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
-  EXPECT_EQ(1, volume);
-}
-
-TEST_F(WebRtcSessionTest, SetAudioMaxSendBitrate) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
-  EXPECT_EQ(-1, channel->max_bps());
-  webrtc::RtpParameters params = session_->GetAudioRtpSendParameters(send_ssrc);
-  EXPECT_EQ(1, params.encodings.size());
-  EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
-  params.encodings[0].max_bitrate_bps = 1000;
-  EXPECT_TRUE(session_->SetAudioRtpSendParameters(send_ssrc, params));
-
-  // Read back the parameters and verify they have been changed.
-  params = session_->GetAudioRtpSendParameters(send_ssrc);
-  EXPECT_EQ(1, params.encodings.size());
-  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
-
-  // Verify that the audio channel received the new parameters.
-  params = channel->GetRtpSendParameters(send_ssrc);
-  EXPECT_EQ(1, params.encodings.size());
-  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
-
-  // Verify that the global bitrate limit has not been changed.
-  EXPECT_EQ(-1, channel->max_bps());
-}
-
-TEST_F(WebRtcSessionTest, SetAudioSend) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  ASSERT_EQ(1u, channel->send_streams().size());
-  uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
-  EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
-
-  cricket::AudioOptions options;
-  options.echo_cancellation = rtc::Optional<bool>(true);
-
-  std::unique_ptr<FakeAudioSource> source(new FakeAudioSource());
-  session_->SetAudioSend(send_ssrc, false, options, source.get());
-  EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
-  EXPECT_EQ(rtc::Optional<bool>(), channel->options().echo_cancellation);
-  EXPECT_TRUE(source->sink() != nullptr);
-
-  // This will trigger SetSink(nullptr) to the |source|.
-  session_->SetAudioSend(send_ssrc, true, options, nullptr);
-  EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
-  EXPECT_EQ(rtc::Optional<bool>(true), channel->options().echo_cancellation);
-  EXPECT_TRUE(source->sink() == nullptr);
-}
-
-TEST_F(WebRtcSessionTest, AudioSourceForLocalStream) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  ASSERT_EQ(1u, channel->send_streams().size());
-  uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
-
-  std::unique_ptr<FakeAudioSource> source(new FakeAudioSource());
-  cricket::AudioOptions options;
-  session_->SetAudioSend(send_ssrc, true, options, source.get());
-  EXPECT_TRUE(source->sink() != nullptr);
-
-  // Delete the |source| and it will trigger OnClose() to the sink, and this
-  // will invalidate the |source_| pointer in the sink and prevent getting a
-  // SetSink(nullptr) callback afterwards.
-  source.reset();
-
-  // This will trigger SetSink(nullptr) if no OnClose() callback.
-  session_->SetAudioSend(send_ssrc, true, options, nullptr);
-}
-
-TEST_F(WebRtcSessionTest, SetVideoPlayout) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  ASSERT_LT(0u, channel->sinks().size());
-  EXPECT_TRUE(channel->sinks().begin()->second == NULL);
-  ASSERT_EQ(1u, channel->recv_streams().size());
-  uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc();
-  cricket::FakeVideoRenderer renderer;
-  session_->SetVideoPlayout(receive_ssrc, true, &renderer);
-  EXPECT_TRUE(channel->sinks().begin()->second == &renderer);
-  session_->SetVideoPlayout(receive_ssrc, false, &renderer);
-  EXPECT_TRUE(channel->sinks().begin()->second == NULL);
-}
-
-TEST_F(WebRtcSessionTest, SetVideoMaxSendBitrate) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
-  EXPECT_EQ(-1, channel->max_bps());
-  webrtc::RtpParameters params = session_->GetVideoRtpSendParameters(send_ssrc);
-  EXPECT_EQ(1, params.encodings.size());
-  EXPECT_EQ(-1, params.encodings[0].max_bitrate_bps);
-  params.encodings[0].max_bitrate_bps = 1000;
-  EXPECT_TRUE(session_->SetVideoRtpSendParameters(send_ssrc, params));
-
-  // Read back the parameters and verify they have been changed.
-  params = session_->GetVideoRtpSendParameters(send_ssrc);
-  EXPECT_EQ(1, params.encodings.size());
-  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
-
-  // Verify that the video channel received the new parameters.
-  params = channel->GetRtpSendParameters(send_ssrc);
-  EXPECT_EQ(1, params.encodings.size());
-  EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
-
-  // Verify that the global bitrate limit has not been changed.
-  EXPECT_EQ(-1, channel->max_bps());
-}
-
-TEST_F(WebRtcSessionTest, SetVideoSend) {
-  Init();
-  SendAudioVideoStream1();
-  CreateAndSetRemoteOfferAndLocalAnswer();
-  cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
-  ASSERT_TRUE(channel != NULL);
-  ASSERT_EQ(1u, channel->send_streams().size());
-  uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
-  EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
-  cricket::VideoOptions* options = NULL;
-  session_->SetVideoSend(send_ssrc, false, options, nullptr);
-  EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
-  session_->SetVideoSend(send_ssrc, true, options, nullptr);
-  EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
-}
-
 TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
   TestCanInsertDtmf(false);
 }