Split ChannelProxy into send and receive classes.

Bug: webrtc:9801
Change-Id: I21573ccc34f6da515d11b58fa6008807395d5dd1
Reviewed-on: https://webrtc-review.googlesource.com/c/103120
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24965}
diff --git a/audio/BUILD.gn b/audio/BUILD.gn
index 7d3d6b7..e42a726 100644
--- a/audio/BUILD.gn
+++ b/audio/BUILD.gn
@@ -26,8 +26,10 @@
     "audio_transport_impl.h",
     "channel.cc",
     "channel.h",
-    "channel_proxy.cc",
-    "channel_proxy.h",
+    "channel_receive_proxy.cc",
+    "channel_receive_proxy.h",
+    "channel_send_proxy.cc",
+    "channel_send_proxy.h",
     "conversion.h",
     "null_audio_poller.cc",
     "null_audio_poller.h",
diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc
index b507afc..e6c9b96 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -16,7 +16,7 @@
 #include "api/call/audio_sink.h"
 #include "audio/audio_send_stream.h"
 #include "audio/audio_state.h"
-#include "audio/channel_proxy.h"
+#include "audio/channel_receive_proxy.h"
 #include "audio/conversion.h"
 #include "call/rtp_stream_receiver_controller_interface.h"
 #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
@@ -62,7 +62,7 @@
 
 namespace internal {
 namespace {
-std::unique_ptr<voe::ChannelProxy> CreateChannelAndProxy(
+std::unique_ptr<voe::ChannelReceiveProxy> CreateChannelAndProxy(
     webrtc::AudioState* audio_state,
     ProcessThread* module_process_thread,
     const webrtc::AudioReceiveStream::Config& config,
@@ -70,11 +70,13 @@
   RTC_DCHECK(audio_state);
   internal::AudioState* internal_audio_state =
       static_cast<internal::AudioState*>(audio_state);
-  return absl::make_unique<voe::ChannelProxy>(absl::make_unique<voe::Channel>(
-      module_process_thread, internal_audio_state->audio_device_module(),
-      nullptr /* RtcpRttStats */, event_log, config.rtp.remote_ssrc,
-      config.jitter_buffer_max_packets, config.jitter_buffer_fast_accelerate,
-      config.decoder_factory, config.codec_pair_id));
+  return absl::make_unique<voe::ChannelReceiveProxy>(
+      absl::make_unique<voe::Channel>(
+          module_process_thread, internal_audio_state->audio_device_module(),
+          nullptr /* RtcpRttStats */, event_log, config.rtp.remote_ssrc,
+          config.jitter_buffer_max_packets,
+          config.jitter_buffer_fast_accelerate, config.decoder_factory,
+          config.codec_pair_id));
 }
 }  // namespace
 
@@ -101,7 +103,7 @@
     const webrtc::AudioReceiveStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     webrtc::RtcEventLog* event_log,
-    std::unique_ptr<voe::ChannelProxy> channel_proxy)
+    std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy)
     : audio_state_(audio_state), channel_proxy_(std::move(channel_proxy)) {
   RTC_LOG(LS_INFO) << "AudioReceiveStream: " << config.rtp.remote_ssrc;
   RTC_DCHECK(receiver_controller);
diff --git a/audio/audio_receive_stream.h b/audio/audio_receive_stream.h
index 64552e3..e982b04 100644
--- a/audio/audio_receive_stream.h
+++ b/audio/audio_receive_stream.h
@@ -32,7 +32,7 @@
 class RtpStreamReceiverInterface;
 
 namespace voe {
-class ChannelProxy;
+class ChannelReceiveProxy;
 }  // namespace voe
 
 namespace internal {
@@ -54,7 +54,7 @@
                      const webrtc::AudioReceiveStream::Config& config,
                      const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
                      webrtc::RtcEventLog* event_log,
-                     std::unique_ptr<voe::ChannelProxy> channel_proxy);
+                     std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy);
   ~AudioReceiveStream() override;
 
   // webrtc::AudioReceiveStream implementation.
@@ -101,7 +101,7 @@
   rtc::ThreadChecker module_process_thread_checker_;
   webrtc::AudioReceiveStream::Config config_;
   rtc::scoped_refptr<webrtc::AudioState> audio_state_;
-  std::unique_ptr<voe::ChannelProxy> channel_proxy_;
+  std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy_;
   AudioSendStream* associated_send_stream_ = nullptr;
 
   bool playing_ RTC_GUARDED_BY(worker_thread_checker_) = false;
diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc
index eb93bd0..59963da 100644
--- a/audio/audio_receive_stream_unittest.cc
+++ b/audio/audio_receive_stream_unittest.cc
@@ -81,7 +81,7 @@
         new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
     audio_state_ = AudioState::Create(config);
 
-    channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
+    channel_proxy_ = new testing::StrictMock<MockChannelReceiveProxy>();
     EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
     EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
     EXPECT_CALL(*channel_proxy_,
@@ -112,12 +112,12 @@
         new internal::AudioReceiveStream(
             &rtp_stream_receiver_controller_, &packet_router_, stream_config_,
             audio_state_, &event_log_,
-            std::unique_ptr<voe::ChannelProxy>(channel_proxy_)));
+            std::unique_ptr<voe::ChannelReceiveProxy>(channel_proxy_)));
   }
 
   AudioReceiveStream::Config& config() { return stream_config_; }
   rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
-  MockVoEChannelProxy* channel_proxy() { return channel_proxy_; }
+  MockChannelReceiveProxy* channel_proxy() { return channel_proxy_; }
 
   void SetupMockForGetStats() {
     using testing::DoAll;
@@ -148,7 +148,7 @@
   rtc::scoped_refptr<AudioState> audio_state_;
   rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
   AudioReceiveStream::Config stream_config_;
-  testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
+  testing::StrictMock<MockChannelReceiveProxy>* channel_proxy_ = nullptr;
   RtpStreamReceiverController rtp_stream_receiver_controller_;
 };
 
@@ -364,7 +364,7 @@
                    kTransportSequenceNumberId + 1));
   new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1));
 
-  MockVoEChannelProxy& channel_proxy = *helper.channel_proxy();
+  MockChannelReceiveProxy& channel_proxy = *helper.channel_proxy();
   EXPECT_CALL(channel_proxy, SetLocalSSRC(kLocalSsrc + 1)).Times(1);
   EXPECT_CALL(channel_proxy, SetNACKStatus(true, 15 + 1)).Times(1);
   EXPECT_CALL(channel_proxy, SetReceiveCodecs(new_config.decoder_map));
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index eb9e8df..8de7a71 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -17,7 +17,7 @@
 #include "absl/memory/memory.h"
 
 #include "audio/audio_state.h"
-#include "audio/channel_proxy.h"
+#include "audio/channel_send_proxy.h"
 #include "audio/conversion.h"
 #include "call/rtp_transport_controller_send_interface.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
@@ -38,7 +38,7 @@
 constexpr size_t kPacketLossRateMinNumAckedPackets = 50;
 constexpr size_t kRecoverablePacketLossRateMinNumAckedPairs = 40;
 
-void CallEncoder(const std::unique_ptr<voe::ChannelProxy>& channel_proxy,
+void CallEncoder(const std::unique_ptr<voe::ChannelSendProxy>& channel_proxy,
                  rtc::FunctionView<void(AudioEncoder*)> lambda) {
   channel_proxy->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
     RTC_DCHECK(encoder_ptr);
@@ -46,7 +46,7 @@
   });
 }
 
-std::unique_ptr<voe::ChannelProxy> CreateChannelAndProxy(
+std::unique_ptr<voe::ChannelSendProxy> CreateChannelAndProxy(
     webrtc::AudioState* audio_state,
     rtc::TaskQueue* worker_queue,
     ProcessThread* module_process_thread,
@@ -55,9 +55,11 @@
   RTC_DCHECK(audio_state);
   internal::AudioState* internal_audio_state =
       static_cast<internal::AudioState*>(audio_state);
-  return absl::make_unique<voe::ChannelProxy>(absl::make_unique<voe::Channel>(
-      worker_queue, module_process_thread,
-      internal_audio_state->audio_device_module(), rtcp_rtt_stats, event_log));
+  return absl::make_unique<voe::ChannelSendProxy>(
+      absl::make_unique<voe::Channel>(
+          worker_queue, module_process_thread,
+          internal_audio_state->audio_device_module(), rtcp_rtt_stats,
+          event_log));
 }
 }  // namespace
 
@@ -120,7 +122,7 @@
     RtcpRttStats* rtcp_rtt_stats,
     const absl::optional<RtpState>& suspended_rtp_state,
     TimeInterval* overall_call_lifetime,
-    std::unique_ptr<voe::ChannelProxy> channel_proxy)
+    std::unique_ptr<voe::ChannelSendProxy> channel_proxy)
     : worker_queue_(worker_queue),
       config_(Config(nullptr)),
       audio_state_(audio_state),
@@ -473,7 +475,7 @@
   return rtp_rtcp_module_->GetRtpState();
 }
 
-const voe::ChannelProxy& AudioSendStream::GetChannelProxy() const {
+const voe::ChannelSendProxy& AudioSendStream::GetChannelProxy() const {
   RTC_DCHECK(channel_proxy_.get());
   return *channel_proxy_.get();
 }
diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h
index ba87202..1ea676b 100644
--- a/audio/audio_send_stream.h
+++ b/audio/audio_send_stream.h
@@ -31,7 +31,7 @@
 class RtpTransportControllerSendInterface;
 
 namespace voe {
-class ChannelProxy;
+class ChannelSendProxy;
 }  // namespace voe
 
 namespace internal {
@@ -61,7 +61,7 @@
                   RtcpRttStats* rtcp_rtt_stats,
                   const absl::optional<RtpState>& suspended_rtp_state,
                   TimeInterval* overall_call_lifetime,
-                  std::unique_ptr<voe::ChannelProxy> channel_proxy);
+                  std::unique_ptr<voe::ChannelSendProxy> channel_proxy);
   ~AudioSendStream() override;
 
   // webrtc::AudioSendStream implementation.
@@ -96,7 +96,7 @@
   void SetTransportOverhead(int transport_overhead_per_packet);
 
   RtpState GetRtpState() const;
-  const voe::ChannelProxy& GetChannelProxy() const;
+  const voe::ChannelSendProxy& GetChannelProxy() const;
 
  private:
   class TimedTransport;
@@ -133,7 +133,7 @@
   rtc::TaskQueue* worker_queue_;
   webrtc::AudioSendStream::Config config_;
   rtc::scoped_refptr<webrtc::AudioState> audio_state_;
-  std::unique_ptr<voe::ChannelProxy> channel_proxy_;
+  std::unique_ptr<voe::ChannelSendProxy> channel_proxy_;
   RtcEventLog* const event_log_;
 
   int encoder_sample_rate_hz_ = 0;
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index a767e02..0fa2393 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -169,7 +169,7 @@
             stream_config_, audio_state_, &worker_queue_, &rtp_transport_,
             &bitrate_allocator_, &event_log_, &rtcp_rtt_stats_, absl::nullopt,
             &active_lifetime_,
-            std::unique_ptr<voe::ChannelProxy>(channel_proxy_)));
+            std::unique_ptr<voe::ChannelSendProxy>(channel_proxy_)));
   }
 
   AudioSendStream::Config& config() { return stream_config_; }
@@ -177,7 +177,7 @@
     return *static_cast<MockAudioEncoderFactory*>(
         stream_config_.encoder_factory.get());
   }
-  MockVoEChannelProxy* channel_proxy() { return channel_proxy_; }
+  MockChannelSendProxy* channel_proxy() { return channel_proxy_; }
   RtpTransportControllerSendInterface* transport() { return &rtp_transport_; }
   TimeInterval* active_lifetime() { return &active_lifetime_; }
 
@@ -189,7 +189,7 @@
 
   void SetupDefaultChannelProxy(bool audio_bwe_enabled) {
     EXPECT_TRUE(channel_proxy_ == nullptr);
-    channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
+    channel_proxy_ = new testing::StrictMock<MockChannelSendProxy>();
     EXPECT_CALL(*channel_proxy_, GetRtpRtcp()).WillRepeatedly(Invoke([this]() {
       return &this->rtp_rtcp_;
     }));
@@ -297,7 +297,7 @@
  private:
   rtc::scoped_refptr<AudioState> audio_state_;
   AudioSendStream::Config stream_config_;
-  testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
+  testing::StrictMock<MockChannelSendProxy>* channel_proxy_ = nullptr;
   rtc::scoped_refptr<MockAudioProcessing> audio_processing_;
   AudioProcessingStats audio_processing_stats_;
   TimeInterval active_lifetime_;
diff --git a/audio/channel_proxy.cc b/audio/channel_proxy.cc
deleted file mode 100644
index 5e8181a..0000000
--- a/audio/channel_proxy.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- *  Copyright (c) 2015 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.
- */
-
-#include "audio/channel_proxy.h"
-
-#include <utility>
-
-#include "api/call/audio_sink.h"
-#include "call/rtp_transport_controller_send_interface.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_minmax.h"
-
-namespace webrtc {
-namespace voe {
-ChannelProxy::ChannelProxy() {}
-
-ChannelProxy::ChannelProxy(std::unique_ptr<Channel> channel)
-    : channel_(std::move(channel)) {
-  RTC_DCHECK(channel_);
-  module_process_thread_checker_.DetachFromThread();
-}
-
-ChannelProxy::~ChannelProxy() {}
-
-bool ChannelProxy::SetEncoder(int payload_type,
-                              std::unique_ptr<AudioEncoder> encoder) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->SetEncoder(payload_type, std::move(encoder));
-}
-
-void ChannelProxy::ModifyEncoder(
-    rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->ModifyEncoder(modifier);
-}
-
-void ChannelProxy::SetRTCPStatus(bool enable) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetRTCPStatus(enable);
-}
-
-void ChannelProxy::SetLocalSSRC(uint32_t ssrc) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  int error = channel_->SetLocalSSRC(ssrc);
-  RTC_DCHECK_EQ(0, error);
-}
-
-void ChannelProxy::SetMid(const std::string& mid, int extension_id) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetMid(mid, extension_id);
-}
-
-void ChannelProxy::SetRTCP_CNAME(const std::string& c_name) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  // Note: VoERTP_RTCP::SetRTCP_CNAME() accepts a char[256] array.
-  std::string c_name_limited = c_name.substr(0, 255);
-  int error = channel_->SetRTCP_CNAME(c_name_limited.c_str());
-  RTC_DCHECK_EQ(0, error);
-}
-
-void ChannelProxy::SetNACKStatus(bool enable, int max_packets) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetNACKStatus(enable, max_packets);
-}
-
-void ChannelProxy::SetSendAudioLevelIndicationStatus(bool enable, int id) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  int error = channel_->SetSendAudioLevelIndicationStatus(enable, id);
-  RTC_DCHECK_EQ(0, error);
-}
-
-void ChannelProxy::EnableSendTransportSequenceNumber(int id) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->EnableSendTransportSequenceNumber(id);
-}
-
-void ChannelProxy::RegisterSenderCongestionControlObjects(
-    RtpTransportControllerSendInterface* transport,
-    RtcpBandwidthObserver* bandwidth_observer) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->RegisterSenderCongestionControlObjects(transport,
-                                                   bandwidth_observer);
-}
-
-void ChannelProxy::RegisterReceiverCongestionControlObjects(
-    PacketRouter* packet_router) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->RegisterReceiverCongestionControlObjects(packet_router);
-}
-
-void ChannelProxy::ResetSenderCongestionControlObjects() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->ResetSenderCongestionControlObjects();
-}
-
-void ChannelProxy::ResetReceiverCongestionControlObjects() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->ResetReceiverCongestionControlObjects();
-}
-
-CallStatistics ChannelProxy::GetRTCPStatistics() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  CallStatistics stats = {0};
-  int error = channel_->GetRTPStatistics(stats);
-  RTC_DCHECK_EQ(0, error);
-  return stats;
-}
-
-std::vector<ReportBlock> ChannelProxy::GetRemoteRTCPReportBlocks() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  std::vector<webrtc::ReportBlock> blocks;
-  int error = channel_->GetRemoteRTCPReportBlocks(&blocks);
-  RTC_DCHECK_EQ(0, error);
-  return blocks;
-}
-
-NetworkStatistics ChannelProxy::GetNetworkStatistics() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  NetworkStatistics stats = {0};
-  int error = channel_->GetNetworkStatistics(stats);
-  RTC_DCHECK_EQ(0, error);
-  return stats;
-}
-
-AudioDecodingCallStats ChannelProxy::GetDecodingCallStatistics() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  AudioDecodingCallStats stats;
-  channel_->GetDecodingCallStatistics(&stats);
-  return stats;
-}
-
-ANAStats ChannelProxy::GetANAStatistics() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->GetANAStatistics();
-}
-
-int ChannelProxy::GetSpeechOutputLevelFullRange() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->GetSpeechOutputLevelFullRange();
-}
-
-double ChannelProxy::GetTotalOutputEnergy() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->GetTotalOutputEnergy();
-}
-
-double ChannelProxy::GetTotalOutputDuration() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->GetTotalOutputDuration();
-}
-
-uint32_t ChannelProxy::GetDelayEstimate() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
-             module_process_thread_checker_.CalledOnValidThread());
-  return channel_->GetDelayEstimate();
-}
-
-bool ChannelProxy::SetSendTelephoneEventPayloadType(int payload_type,
-                                                    int payload_frequency) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->SetSendTelephoneEventPayloadType(payload_type,
-                                                    payload_frequency) == 0;
-}
-
-bool ChannelProxy::SendTelephoneEventOutband(int event, int duration_ms) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->SendTelephoneEventOutband(event, duration_ms) == 0;
-}
-
-void ChannelProxy::SetBitrate(int bitrate_bps, int64_t probing_interval_ms) {
-  // This method can be called on the worker thread, module process thread
-  // or on a TaskQueue via VideoSendStreamImpl::OnEncoderConfigurationChanged.
-  // TODO(solenberg): Figure out a good way to check this or enforce calling
-  // rules.
-  // RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
-  //            module_process_thread_checker_.CalledOnValidThread());
-  channel_->SetBitRate(bitrate_bps, probing_interval_ms);
-}
-
-void ChannelProxy::SetReceiveCodecs(
-    const std::map<int, SdpAudioFormat>& codecs) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetReceiveCodecs(codecs);
-}
-
-void ChannelProxy::SetSink(AudioSinkInterface* sink) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetSink(sink);
-}
-
-void ChannelProxy::SetInputMute(bool muted) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetInputMute(muted);
-}
-
-void ChannelProxy::RegisterTransport(Transport* transport) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->RegisterTransport(transport);
-}
-
-void ChannelProxy::OnRtpPacket(const RtpPacketReceived& packet) {
-  // May be called on either worker thread or network thread.
-  channel_->OnRtpPacket(packet);
-}
-
-bool ChannelProxy::ReceivedRTCPPacket(const uint8_t* packet, size_t length) {
-  // May be called on either worker thread or network thread.
-  return channel_->ReceivedRTCPPacket(packet, length) == 0;
-}
-
-void ChannelProxy::SetChannelOutputVolumeScaling(float scaling) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetChannelOutputVolumeScaling(scaling);
-}
-
-AudioMixer::Source::AudioFrameInfo ChannelProxy::GetAudioFrameWithInfo(
-    int sample_rate_hz,
-    AudioFrame* audio_frame) {
-  RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
-  return channel_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
-}
-
-int ChannelProxy::PreferredSampleRate() const {
-  RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
-  return channel_->PreferredSampleRate();
-}
-
-void ChannelProxy::ProcessAndEncodeAudio(
-    std::unique_ptr<AudioFrame> audio_frame) {
-  RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
-  return channel_->ProcessAndEncodeAudio(std::move(audio_frame));
-}
-
-void ChannelProxy::SetTransportOverhead(int transport_overhead_per_packet) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetTransportOverhead(transport_overhead_per_packet);
-}
-
-void ChannelProxy::AssociateSendChannel(
-    const ChannelProxy& send_channel_proxy) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetAssociatedSendChannel(send_channel_proxy.channel_.get());
-}
-
-void ChannelProxy::DisassociateSendChannel() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetAssociatedSendChannel(nullptr);
-}
-
-RtpRtcp* ChannelProxy::GetRtpRtcp() const {
-  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
-  return channel_->GetRtpRtcp();
-}
-
-absl::optional<Syncable::Info> ChannelProxy::GetSyncInfo() const {
-  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
-  return channel_->GetSyncInfo();
-}
-
-uint32_t ChannelProxy::GetPlayoutTimestamp() const {
-  RTC_DCHECK_RUNS_SERIALIZED(&video_capture_thread_race_checker_);
-  unsigned int timestamp = 0;
-  int error = channel_->GetPlayoutTimestamp(timestamp);
-  RTC_DCHECK(!error || timestamp == 0);
-  return timestamp;
-}
-
-void ChannelProxy::SetMinimumPlayoutDelay(int delay_ms) {
-  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
-  // Limit to range accepted by both VoE and ACM, so we're at least getting as
-  // close as possible, instead of failing.
-  delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
-  int error = channel_->SetMinimumPlayoutDelay(delay_ms);
-  if (0 != error) {
-    RTC_LOG(LS_WARNING) << "Error setting minimum playout delay.";
-  }
-}
-
-bool ChannelProxy::GetRecCodec(CodecInst* codec_inst) const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->GetRecCodec(*codec_inst) == 0;
-}
-
-void ChannelProxy::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->OnTwccBasedUplinkPacketLossRate(packet_loss_rate);
-}
-
-void ChannelProxy::OnRecoverableUplinkPacketLossRate(
-    float recoverable_packet_loss_rate) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->OnRecoverableUplinkPacketLossRate(recoverable_packet_loss_rate);
-}
-
-std::vector<RtpSource> ChannelProxy::GetSources() const {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return channel_->GetSources();
-}
-
-void ChannelProxy::StartSend() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  int error = channel_->StartSend();
-  RTC_DCHECK_EQ(0, error);
-}
-
-void ChannelProxy::StopSend() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->StopSend();
-}
-
-void ChannelProxy::StartPlayout() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  int error = channel_->StartPlayout();
-  RTC_DCHECK_EQ(0, error);
-}
-
-void ChannelProxy::StopPlayout() {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  int error = channel_->StopPlayout();
-  RTC_DCHECK_EQ(0, error);
-}
-}  // namespace voe
-}  // namespace webrtc
diff --git a/audio/channel_receive_proxy.cc b/audio/channel_receive_proxy.cc
new file mode 100644
index 0000000..c57bae0
--- /dev/null
+++ b/audio/channel_receive_proxy.cc
@@ -0,0 +1,201 @@
+/*
+ *  Copyright (c) 2015 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.
+ */
+
+#include "audio/channel_receive_proxy.h"
+
+#include <utility>
+
+#include "api/call/audio_sink.h"
+#include "audio/channel_send_proxy.h"
+#include "call/rtp_transport_controller_send_interface.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_minmax.h"
+
+namespace webrtc {
+namespace voe {
+ChannelReceiveProxy::ChannelReceiveProxy() {}
+
+ChannelReceiveProxy::ChannelReceiveProxy(std::unique_ptr<Channel> channel)
+    : channel_(std::move(channel)) {
+  RTC_DCHECK(channel_);
+  module_process_thread_checker_.DetachFromThread();
+}
+
+ChannelReceiveProxy::~ChannelReceiveProxy() {}
+
+void ChannelReceiveProxy::SetLocalSSRC(uint32_t ssrc) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  int error = channel_->SetLocalSSRC(ssrc);
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelReceiveProxy::SetNACKStatus(bool enable, int max_packets) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetNACKStatus(enable, max_packets);
+}
+
+CallStatistics ChannelReceiveProxy::GetRTCPStatistics() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  CallStatistics stats = {0};
+  int error = channel_->GetRTPStatistics(stats);
+  RTC_DCHECK_EQ(0, error);
+  return stats;
+}
+
+void ChannelReceiveProxy::RegisterTransport(Transport* transport) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->RegisterTransport(transport);
+}
+
+bool ChannelReceiveProxy::ReceivedRTCPPacket(const uint8_t* packet,
+                                             size_t length) {
+  // May be called on either worker thread or network thread.
+  return channel_->ReceivedRTCPPacket(packet, length) == 0;
+}
+
+void ChannelReceiveProxy::RegisterReceiverCongestionControlObjects(
+    PacketRouter* packet_router) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->RegisterReceiverCongestionControlObjects(packet_router);
+}
+
+void ChannelReceiveProxy::ResetReceiverCongestionControlObjects() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->ResetReceiverCongestionControlObjects();
+}
+
+NetworkStatistics ChannelReceiveProxy::GetNetworkStatistics() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  NetworkStatistics stats = {0};
+  int error = channel_->GetNetworkStatistics(stats);
+  RTC_DCHECK_EQ(0, error);
+  return stats;
+}
+
+AudioDecodingCallStats ChannelReceiveProxy::GetDecodingCallStatistics() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  AudioDecodingCallStats stats;
+  channel_->GetDecodingCallStatistics(&stats);
+  return stats;
+}
+
+int ChannelReceiveProxy::GetSpeechOutputLevelFullRange() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->GetSpeechOutputLevelFullRange();
+}
+
+double ChannelReceiveProxy::GetTotalOutputEnergy() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->GetTotalOutputEnergy();
+}
+
+double ChannelReceiveProxy::GetTotalOutputDuration() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->GetTotalOutputDuration();
+}
+
+uint32_t ChannelReceiveProxy::GetDelayEstimate() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
+             module_process_thread_checker_.CalledOnValidThread());
+  return channel_->GetDelayEstimate();
+}
+
+void ChannelReceiveProxy::SetReceiveCodecs(
+    const std::map<int, SdpAudioFormat>& codecs) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetReceiveCodecs(codecs);
+}
+
+void ChannelReceiveProxy::SetSink(AudioSinkInterface* sink) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetSink(sink);
+}
+
+void ChannelReceiveProxy::OnRtpPacket(const RtpPacketReceived& packet) {
+  // May be called on either worker thread or network thread.
+  channel_->OnRtpPacket(packet);
+}
+
+void ChannelReceiveProxy::SetChannelOutputVolumeScaling(float scaling) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetChannelOutputVolumeScaling(scaling);
+}
+
+AudioMixer::Source::AudioFrameInfo ChannelReceiveProxy::GetAudioFrameWithInfo(
+    int sample_rate_hz,
+    AudioFrame* audio_frame) {
+  RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
+  return channel_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
+}
+
+int ChannelReceiveProxy::PreferredSampleRate() const {
+  RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
+  return channel_->PreferredSampleRate();
+}
+
+void ChannelReceiveProxy::AssociateSendChannel(
+    const ChannelSendProxy& send_channel_proxy) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetAssociatedSendChannel(send_channel_proxy.GetChannel());
+}
+
+void ChannelReceiveProxy::DisassociateSendChannel() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetAssociatedSendChannel(nullptr);
+}
+
+absl::optional<Syncable::Info> ChannelReceiveProxy::GetSyncInfo() const {
+  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
+  return channel_->GetSyncInfo();
+}
+
+uint32_t ChannelReceiveProxy::GetPlayoutTimestamp() const {
+  RTC_DCHECK_RUNS_SERIALIZED(&video_capture_thread_race_checker_);
+  unsigned int timestamp = 0;
+  int error = channel_->GetPlayoutTimestamp(timestamp);
+  RTC_DCHECK(!error || timestamp == 0);
+  return timestamp;
+}
+
+void ChannelReceiveProxy::SetMinimumPlayoutDelay(int delay_ms) {
+  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
+  // Limit to range accepted by both VoE and ACM, so we're at least getting as
+  // close as possible, instead of failing.
+  delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
+  int error = channel_->SetMinimumPlayoutDelay(delay_ms);
+  if (0 != error) {
+    RTC_LOG(LS_WARNING) << "Error setting minimum playout delay.";
+  }
+}
+
+bool ChannelReceiveProxy::GetRecCodec(CodecInst* codec_inst) const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->GetRecCodec(*codec_inst) == 0;
+}
+
+std::vector<RtpSource> ChannelReceiveProxy::GetSources() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->GetSources();
+}
+
+void ChannelReceiveProxy::StartPlayout() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  int error = channel_->StartPlayout();
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelReceiveProxy::StopPlayout() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  int error = channel_->StopPlayout();
+  RTC_DCHECK_EQ(0, error);
+}
+}  // namespace voe
+}  // namespace webrtc
diff --git a/audio/channel_proxy.h b/audio/channel_receive_proxy.h
similarity index 62%
copy from audio/channel_proxy.h
copy to audio/channel_receive_proxy.h
index f82c1fd..9426968 100644
--- a/audio/channel_proxy.h
+++ b/audio/channel_receive_proxy.h
@@ -8,16 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef AUDIO_CHANNEL_PROXY_H_
-#define AUDIO_CHANNEL_PROXY_H_
+#ifndef AUDIO_CHANNEL_RECEIVE_PROXY_H_
+#define AUDIO_CHANNEL_RECEIVE_PROXY_H_
 
 #include <map>
 #include <memory>
-#include <string>
 #include <vector>
 
 #include "api/audio/audio_mixer.h"
-#include "api/audio_codecs/audio_encoder.h"
 #include "api/rtpreceiverinterface.h"
 #include "audio/channel.h"
 #include "call/rtp_packet_sink_interface.h"
@@ -29,95 +27,63 @@
 
 class AudioSinkInterface;
 class PacketRouter;
-class RtcEventLog;
-class RtcpBandwidthObserver;
-class RtcpRttStats;
-class RtpPacketSender;
 class RtpPacketReceived;
-class RtpRtcp;
-class RtpTransportControllerSendInterface;
 class Transport;
-class TransportFeedbackObserver;
 
 namespace voe {
 
+class ChannelSendProxy;
+
 // This class provides the "view" of a voe::Channel that we need to implement
-// webrtc::AudioSendStream and webrtc::AudioReceiveStream. It serves two
-// purposes:
+// webrtc::AudioReceiveStream. It serves two purposes:
 //  1. Allow mocking just the interfaces used, instead of the entire
 //     voe::Channel class.
 //  2. Provide a refined interface for the stream classes, including assumptions
 //     on return values and input adaptation.
-class ChannelProxy : public RtpPacketSinkInterface {
+class ChannelReceiveProxy : public RtpPacketSinkInterface {
  public:
-  ChannelProxy();
-  explicit ChannelProxy(std::unique_ptr<Channel> channel);
-  virtual ~ChannelProxy();
+  ChannelReceiveProxy();
+  explicit ChannelReceiveProxy(std::unique_ptr<Channel> channel);
+  virtual ~ChannelReceiveProxy();
 
-  virtual bool SetEncoder(int payload_type,
-                          std::unique_ptr<AudioEncoder> encoder);
-  virtual void ModifyEncoder(
-      rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier);
-
-  virtual void SetRTCPStatus(bool enable);
+  // Shared with ChannelSendProxy
   virtual void SetLocalSSRC(uint32_t ssrc);
-  virtual void SetMid(const std::string& mid, int extension_id);
-  virtual void SetRTCP_CNAME(const std::string& c_name);
   virtual void SetNACKStatus(bool enable, int max_packets);
-  virtual void SetSendAudioLevelIndicationStatus(bool enable, int id);
-  virtual void EnableSendTransportSequenceNumber(int id);
-  virtual void RegisterSenderCongestionControlObjects(
-      RtpTransportControllerSendInterface* transport,
-      RtcpBandwidthObserver* bandwidth_observer);
+  virtual CallStatistics GetRTCPStatistics() const;
+  virtual void RegisterTransport(Transport* transport);
+  virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
+
   virtual void RegisterReceiverCongestionControlObjects(
       PacketRouter* packet_router);
-  virtual void ResetSenderCongestionControlObjects();
   virtual void ResetReceiverCongestionControlObjects();
-  virtual CallStatistics GetRTCPStatistics() const;
-  virtual std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const;
   virtual NetworkStatistics GetNetworkStatistics() const;
   virtual AudioDecodingCallStats GetDecodingCallStatistics() const;
-  virtual ANAStats GetANAStatistics() const;
   virtual int GetSpeechOutputLevelFullRange() const;
   // See description of "totalAudioEnergy" in the WebRTC stats spec:
   // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
   virtual double GetTotalOutputEnergy() const;
   virtual double GetTotalOutputDuration() const;
   virtual uint32_t GetDelayEstimate() const;
-  virtual bool SetSendTelephoneEventPayloadType(int payload_type,
-                                                int payload_frequency);
-  virtual bool SendTelephoneEventOutband(int event, int duration_ms);
-  virtual void SetBitrate(int bitrate_bps, int64_t probing_interval_ms);
   virtual void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
   virtual void SetSink(AudioSinkInterface* sink);
-  virtual void SetInputMute(bool muted);
-  virtual void RegisterTransport(Transport* transport);
 
   // Implements RtpPacketSinkInterface
   void OnRtpPacket(const RtpPacketReceived& packet) override;
-  virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
+
   virtual void SetChannelOutputVolumeScaling(float scaling);
   virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
       int sample_rate_hz,
       AudioFrame* audio_frame);
   virtual int PreferredSampleRate() const;
-  virtual void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame);
-  virtual void SetTransportOverhead(int transport_overhead_per_packet);
-  virtual void AssociateSendChannel(const ChannelProxy& send_channel_proxy);
+  virtual void AssociateSendChannel(const ChannelSendProxy& send_channel_proxy);
   virtual void DisassociateSendChannel();
-  virtual RtpRtcp* GetRtpRtcp() const;
 
   // Produces the transport-related timestamps; current_delay_ms is left unset.
   absl::optional<Syncable::Info> GetSyncInfo() const;
   virtual uint32_t GetPlayoutTimestamp() const;
   virtual void SetMinimumPlayoutDelay(int delay_ms);
   virtual bool GetRecCodec(CodecInst* codec_inst) const;
-  virtual void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate);
-  virtual void OnRecoverableUplinkPacketLossRate(
-      float recoverable_packet_loss_rate);
   virtual std::vector<webrtc::RtpSource> GetSources() const;
-  virtual void StartSend();
-  virtual void StopSend();
   virtual void StartPlayout();
   virtual void StopPlayout();
 
@@ -136,9 +102,9 @@
   rtc::RaceChecker video_capture_thread_race_checker_;
   std::unique_ptr<Channel> channel_;
 
-  RTC_DISALLOW_COPY_AND_ASSIGN(ChannelProxy);
+  RTC_DISALLOW_COPY_AND_ASSIGN(ChannelReceiveProxy);
 };
 }  // namespace voe
 }  // namespace webrtc
 
-#endif  // AUDIO_CHANNEL_PROXY_H_
+#endif  // AUDIO_CHANNEL_RECEIVE_PROXY_H_
diff --git a/audio/channel_send_proxy.cc b/audio/channel_send_proxy.cc
new file mode 100644
index 0000000..43aac58
--- /dev/null
+++ b/audio/channel_send_proxy.cc
@@ -0,0 +1,201 @@
+/*
+ *  Copyright (c) 2015 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.
+ */
+
+#include "audio/channel_send_proxy.h"
+
+#include <utility>
+
+#include "api/call/audio_sink.h"
+#include "call/rtp_transport_controller_send_interface.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_minmax.h"
+
+namespace webrtc {
+namespace voe {
+ChannelSendProxy::ChannelSendProxy() {}
+
+ChannelSendProxy::ChannelSendProxy(std::unique_ptr<Channel> channel)
+    : channel_(std::move(channel)) {
+  RTC_DCHECK(channel_);
+  module_process_thread_checker_.DetachFromThread();
+}
+
+ChannelSendProxy::~ChannelSendProxy() {}
+
+void ChannelSendProxy::SetLocalSSRC(uint32_t ssrc) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  int error = channel_->SetLocalSSRC(ssrc);
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelSendProxy::SetNACKStatus(bool enable, int max_packets) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetNACKStatus(enable, max_packets);
+}
+
+CallStatistics ChannelSendProxy::GetRTCPStatistics() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  CallStatistics stats = {0};
+  int error = channel_->GetRTPStatistics(stats);
+  RTC_DCHECK_EQ(0, error);
+  return stats;
+}
+
+void ChannelSendProxy::RegisterTransport(Transport* transport) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->RegisterTransport(transport);
+}
+
+bool ChannelSendProxy::ReceivedRTCPPacket(const uint8_t* packet,
+                                          size_t length) {
+  // May be called on either worker thread or network thread.
+  return channel_->ReceivedRTCPPacket(packet, length) == 0;
+}
+
+bool ChannelSendProxy::SetEncoder(int payload_type,
+                                  std::unique_ptr<AudioEncoder> encoder) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->SetEncoder(payload_type, std::move(encoder));
+}
+
+void ChannelSendProxy::ModifyEncoder(
+    rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->ModifyEncoder(modifier);
+}
+
+void ChannelSendProxy::SetRTCPStatus(bool enable) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetRTCPStatus(enable);
+}
+
+void ChannelSendProxy::SetMid(const std::string& mid, int extension_id) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetMid(mid, extension_id);
+}
+
+void ChannelSendProxy::SetRTCP_CNAME(const std::string& c_name) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  // Note: VoERTP_RTCP::SetRTCP_CNAME() accepts a char[256] array.
+  std::string c_name_limited = c_name.substr(0, 255);
+  int error = channel_->SetRTCP_CNAME(c_name_limited.c_str());
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelSendProxy::SetSendAudioLevelIndicationStatus(bool enable, int id) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  int error = channel_->SetSendAudioLevelIndicationStatus(enable, id);
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelSendProxy::EnableSendTransportSequenceNumber(int id) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->EnableSendTransportSequenceNumber(id);
+}
+
+void ChannelSendProxy::RegisterSenderCongestionControlObjects(
+    RtpTransportControllerSendInterface* transport,
+    RtcpBandwidthObserver* bandwidth_observer) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->RegisterSenderCongestionControlObjects(transport,
+                                                   bandwidth_observer);
+}
+
+void ChannelSendProxy::ResetSenderCongestionControlObjects() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->ResetSenderCongestionControlObjects();
+}
+
+std::vector<ReportBlock> ChannelSendProxy::GetRemoteRTCPReportBlocks() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  std::vector<webrtc::ReportBlock> blocks;
+  int error = channel_->GetRemoteRTCPReportBlocks(&blocks);
+  RTC_DCHECK_EQ(0, error);
+  return blocks;
+}
+
+ANAStats ChannelSendProxy::GetANAStatistics() const {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->GetANAStatistics();
+}
+
+bool ChannelSendProxy::SetSendTelephoneEventPayloadType(int payload_type,
+                                                        int payload_frequency) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->SetSendTelephoneEventPayloadType(payload_type,
+                                                    payload_frequency) == 0;
+}
+
+bool ChannelSendProxy::SendTelephoneEventOutband(int event, int duration_ms) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  return channel_->SendTelephoneEventOutband(event, duration_ms) == 0;
+}
+
+void ChannelSendProxy::SetBitrate(int bitrate_bps,
+                                  int64_t probing_interval_ms) {
+  // This method can be called on the worker thread, module process thread
+  // or on a TaskQueue via VideoSendStreamImpl::OnEncoderConfigurationChanged.
+  // TODO(solenberg): Figure out a good way to check this or enforce calling
+  // rules.
+  // RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
+  //            module_process_thread_checker_.CalledOnValidThread());
+  channel_->SetBitRate(bitrate_bps, probing_interval_ms);
+}
+
+void ChannelSendProxy::SetInputMute(bool muted) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetInputMute(muted);
+}
+
+void ChannelSendProxy::ProcessAndEncodeAudio(
+    std::unique_ptr<AudioFrame> audio_frame) {
+  RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
+  return channel_->ProcessAndEncodeAudio(std::move(audio_frame));
+}
+
+void ChannelSendProxy::SetTransportOverhead(int transport_overhead_per_packet) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->SetTransportOverhead(transport_overhead_per_packet);
+}
+
+RtpRtcp* ChannelSendProxy::GetRtpRtcp() const {
+  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
+  return channel_->GetRtpRtcp();
+}
+
+void ChannelSendProxy::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->OnTwccBasedUplinkPacketLossRate(packet_loss_rate);
+}
+
+void ChannelSendProxy::OnRecoverableUplinkPacketLossRate(
+    float recoverable_packet_loss_rate) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->OnRecoverableUplinkPacketLossRate(recoverable_packet_loss_rate);
+}
+
+void ChannelSendProxy::StartSend() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  int error = channel_->StartSend();
+  RTC_DCHECK_EQ(0, error);
+}
+
+void ChannelSendProxy::StopSend() {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  channel_->StopSend();
+}
+
+Channel* ChannelSendProxy::GetChannel() const {
+  return channel_.get();
+}
+
+}  // namespace voe
+}  // namespace webrtc
diff --git a/audio/channel_proxy.h b/audio/channel_send_proxy.h
similarity index 62%
rename from audio/channel_proxy.h
rename to audio/channel_send_proxy.h
index f82c1fd..88ce610 100644
--- a/audio/channel_proxy.h
+++ b/audio/channel_send_proxy.h
@@ -8,51 +8,46 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef AUDIO_CHANNEL_PROXY_H_
-#define AUDIO_CHANNEL_PROXY_H_
+#ifndef AUDIO_CHANNEL_SEND_PROXY_H_
+#define AUDIO_CHANNEL_SEND_PROXY_H_
 
-#include <map>
 #include <memory>
 #include <string>
 #include <vector>
 
-#include "api/audio/audio_mixer.h"
 #include "api/audio_codecs/audio_encoder.h"
-#include "api/rtpreceiverinterface.h"
 #include "audio/channel.h"
-#include "call/rtp_packet_sink_interface.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/race_checker.h"
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
 
-class AudioSinkInterface;
-class PacketRouter;
-class RtcEventLog;
 class RtcpBandwidthObserver;
-class RtcpRttStats;
-class RtpPacketSender;
-class RtpPacketReceived;
 class RtpRtcp;
 class RtpTransportControllerSendInterface;
 class Transport;
-class TransportFeedbackObserver;
 
 namespace voe {
 
 // This class provides the "view" of a voe::Channel that we need to implement
-// webrtc::AudioSendStream and webrtc::AudioReceiveStream. It serves two
-// purposes:
+// webrtc::AudioSendStream. It serves two purposes:
 //  1. Allow mocking just the interfaces used, instead of the entire
 //     voe::Channel class.
 //  2. Provide a refined interface for the stream classes, including assumptions
 //     on return values and input adaptation.
-class ChannelProxy : public RtpPacketSinkInterface {
+class ChannelSendProxy {
  public:
-  ChannelProxy();
-  explicit ChannelProxy(std::unique_ptr<Channel> channel);
-  virtual ~ChannelProxy();
+  ChannelSendProxy();
+  explicit ChannelSendProxy(std::unique_ptr<Channel> channel);
+  virtual ~ChannelSendProxy();
+
+  // Shared with ChannelReceiveProxy
+  virtual void SetLocalSSRC(uint32_t ssrc);
+  virtual void SetNACKStatus(bool enable, int max_packets);
+  virtual CallStatistics GetRTCPStatistics() const;
+  virtual void RegisterTransport(Transport* transport);
+  virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
 
   virtual bool SetEncoder(int payload_type,
                           std::unique_ptr<AudioEncoder> encoder);
@@ -60,66 +55,34 @@
       rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier);
 
   virtual void SetRTCPStatus(bool enable);
-  virtual void SetLocalSSRC(uint32_t ssrc);
   virtual void SetMid(const std::string& mid, int extension_id);
   virtual void SetRTCP_CNAME(const std::string& c_name);
-  virtual void SetNACKStatus(bool enable, int max_packets);
   virtual void SetSendAudioLevelIndicationStatus(bool enable, int id);
   virtual void EnableSendTransportSequenceNumber(int id);
   virtual void RegisterSenderCongestionControlObjects(
       RtpTransportControllerSendInterface* transport,
       RtcpBandwidthObserver* bandwidth_observer);
-  virtual void RegisterReceiverCongestionControlObjects(
-      PacketRouter* packet_router);
   virtual void ResetSenderCongestionControlObjects();
-  virtual void ResetReceiverCongestionControlObjects();
-  virtual CallStatistics GetRTCPStatistics() const;
   virtual std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const;
-  virtual NetworkStatistics GetNetworkStatistics() const;
-  virtual AudioDecodingCallStats GetDecodingCallStatistics() const;
   virtual ANAStats GetANAStatistics() const;
-  virtual int GetSpeechOutputLevelFullRange() const;
-  // See description of "totalAudioEnergy" in the WebRTC stats spec:
-  // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
-  virtual double GetTotalOutputEnergy() const;
-  virtual double GetTotalOutputDuration() const;
-  virtual uint32_t GetDelayEstimate() const;
   virtual bool SetSendTelephoneEventPayloadType(int payload_type,
                                                 int payload_frequency);
   virtual bool SendTelephoneEventOutband(int event, int duration_ms);
   virtual void SetBitrate(int bitrate_bps, int64_t probing_interval_ms);
-  virtual void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
-  virtual void SetSink(AudioSinkInterface* sink);
   virtual void SetInputMute(bool muted);
-  virtual void RegisterTransport(Transport* transport);
 
-  // Implements RtpPacketSinkInterface
-  void OnRtpPacket(const RtpPacketReceived& packet) override;
-  virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
-  virtual void SetChannelOutputVolumeScaling(float scaling);
-  virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
-      int sample_rate_hz,
-      AudioFrame* audio_frame);
-  virtual int PreferredSampleRate() const;
   virtual void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame);
   virtual void SetTransportOverhead(int transport_overhead_per_packet);
-  virtual void AssociateSendChannel(const ChannelProxy& send_channel_proxy);
-  virtual void DisassociateSendChannel();
   virtual RtpRtcp* GetRtpRtcp() const;
 
-  // Produces the transport-related timestamps; current_delay_ms is left unset.
-  absl::optional<Syncable::Info> GetSyncInfo() const;
-  virtual uint32_t GetPlayoutTimestamp() const;
-  virtual void SetMinimumPlayoutDelay(int delay_ms);
-  virtual bool GetRecCodec(CodecInst* codec_inst) const;
   virtual void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate);
   virtual void OnRecoverableUplinkPacketLossRate(
       float recoverable_packet_loss_rate);
-  virtual std::vector<webrtc::RtpSource> GetSources() const;
   virtual void StartSend();
   virtual void StopSend();
-  virtual void StartPlayout();
-  virtual void StopPlayout();
+
+  // Needed by ChannelReceiveProxy::AssociateSendChannel.
+  virtual Channel* GetChannel() const;
 
  private:
   // Thread checkers document and lock usage of some methods on voe::Channel to
@@ -136,9 +99,9 @@
   rtc::RaceChecker video_capture_thread_race_checker_;
   std::unique_ptr<Channel> channel_;
 
-  RTC_DISALLOW_COPY_AND_ASSIGN(ChannelProxy);
+  RTC_DISALLOW_COPY_AND_ASSIGN(ChannelSendProxy);
 };
 }  // namespace voe
 }  // namespace webrtc
 
-#endif  // AUDIO_CHANNEL_PROXY_H_
+#endif  // AUDIO_CHANNEL_SEND_PROXY_H_
diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h
index f6a2637..9d122c6 100644
--- a/audio/mock_voe_channel_proxy.h
+++ b/audio/mock_voe_channel_proxy.h
@@ -16,14 +16,51 @@
 #include <string>
 #include <vector>
 
-#include "audio/channel_proxy.h"
+#include "audio/channel_receive_proxy.h"
+#include "audio/channel_send_proxy.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "test/gmock.h"
 
 namespace webrtc {
 namespace test {
 
-class MockVoEChannelProxy : public voe::ChannelProxy {
+class MockChannelReceiveProxy : public voe::ChannelReceiveProxy {
+ public:
+  MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
+  MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets));
+  MOCK_METHOD1(RegisterReceiverCongestionControlObjects,
+               void(PacketRouter* packet_router));
+  MOCK_METHOD0(ResetReceiverCongestionControlObjects, void());
+  MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics());
+  MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
+  MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
+  MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int());
+  MOCK_CONST_METHOD0(GetTotalOutputEnergy, double());
+  MOCK_CONST_METHOD0(GetTotalOutputDuration, double());
+  MOCK_CONST_METHOD0(GetDelayEstimate, uint32_t());
+  MOCK_METHOD1(SetSink, void(AudioSinkInterface* sink));
+  MOCK_METHOD1(RegisterTransport, void(Transport* transport));
+  MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived& packet));
+  MOCK_METHOD2(ReceivedRTCPPacket, bool(const uint8_t* packet, size_t length));
+  MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
+  MOCK_METHOD2(GetAudioFrameWithInfo,
+               AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
+                                                  AudioFrame* audio_frame));
+  MOCK_CONST_METHOD0(PreferredSampleRate, int());
+  MOCK_METHOD1(AssociateSendChannel,
+               void(const voe::ChannelSendProxy& send_channel_proxy));
+  MOCK_METHOD0(DisassociateSendChannel, void());
+  MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
+  MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
+  MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
+  MOCK_METHOD1(SetReceiveCodecs,
+               void(const std::map<int, SdpAudioFormat>& codecs));
+  MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
+  MOCK_METHOD0(StartPlayout, void());
+  MOCK_METHOD0(StopPlayout, void());
+};
+
+class MockChannelSendProxy : public voe::ChannelSendProxy {
  public:
   // GMock doesn't like move-only types, like std::unique_ptr.
   virtual bool SetEncoder(int payload_type,
@@ -44,33 +81,17 @@
   MOCK_METHOD2(RegisterSenderCongestionControlObjects,
                void(RtpTransportControllerSendInterface* transport,
                     RtcpBandwidthObserver* bandwidth_observer));
-  MOCK_METHOD1(RegisterReceiverCongestionControlObjects,
-               void(PacketRouter* packet_router));
   MOCK_METHOD0(ResetSenderCongestionControlObjects, void());
-  MOCK_METHOD0(ResetReceiverCongestionControlObjects, void());
   MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics());
   MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector<ReportBlock>());
-  MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
-  MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
   MOCK_CONST_METHOD0(GetANAStatistics, ANAStats());
-  MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int());
-  MOCK_CONST_METHOD0(GetTotalOutputEnergy, double());
-  MOCK_CONST_METHOD0(GetTotalOutputDuration, double());
-  MOCK_CONST_METHOD0(GetDelayEstimate, uint32_t());
   MOCK_METHOD2(SetSendTelephoneEventPayloadType,
                bool(int payload_type, int payload_frequency));
   MOCK_METHOD2(SendTelephoneEventOutband, bool(int event, int duration_ms));
   MOCK_METHOD2(SetBitrate, void(int bitrate_bps, int64_t probing_interval_ms));
-  MOCK_METHOD1(SetSink, void(AudioSinkInterface* sink));
   MOCK_METHOD1(SetInputMute, void(bool muted));
   MOCK_METHOD1(RegisterTransport, void(Transport* transport));
-  MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived& packet));
   MOCK_METHOD2(ReceivedRTCPPacket, bool(const uint8_t* packet, size_t length));
-  MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
-  MOCK_METHOD2(GetAudioFrameWithInfo,
-               AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
-                                                  AudioFrame* audio_frame));
-  MOCK_CONST_METHOD0(PreferredSampleRate, int());
   // GMock doesn't like move-only types, like std::unique_ptr.
   virtual void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame) {
     ProcessAndEncodeAudioForMock(&audio_frame);
@@ -78,23 +99,12 @@
   MOCK_METHOD1(ProcessAndEncodeAudioForMock,
                void(std::unique_ptr<AudioFrame>* audio_frame));
   MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet));
-  MOCK_METHOD1(AssociateSendChannel,
-               void(const ChannelProxy& send_channel_proxy));
-  MOCK_METHOD0(DisassociateSendChannel, void());
   MOCK_CONST_METHOD0(GetRtpRtcp, RtpRtcp*());
-  MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
-  MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
-  MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
-  MOCK_METHOD1(SetReceiveCodecs,
-               void(const std::map<int, SdpAudioFormat>& codecs));
   MOCK_METHOD1(OnTwccBasedUplinkPacketLossRate, void(float packet_loss_rate));
   MOCK_METHOD1(OnRecoverableUplinkPacketLossRate,
                void(float recoverable_packet_loss_rate));
-  MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
   MOCK_METHOD0(StartSend, void());
   MOCK_METHOD0(StopSend, void());
-  MOCK_METHOD0(StartPlayout, void());
-  MOCK_METHOD0(StopPlayout, void());
 };
 }  // namespace test
 }  // namespace webrtc