- Introduce internal classes WebRtcAudio[Send|Receive]Stream in WebRtcVoiceMediaChannel.
- Remove WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
- Create webrtc::AudioSendStreams.

BUG=webrtc:4690

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

Cr-Commit-Position: refs/heads/master@{#10361}
diff --git a/talk/media/webrtc/fakewebrtccall.cc b/talk/media/webrtc/fakewebrtccall.cc
index a0386b0..6e2a88f 100644
--- a/talk/media/webrtc/fakewebrtccall.cc
+++ b/talk/media/webrtc/fakewebrtccall.cc
@@ -34,6 +34,20 @@
 #include "webrtc/base/gunit.h"
 
 namespace cricket {
+FakeAudioSendStream::FakeAudioSendStream(
+    const webrtc::AudioSendStream::Config& config) : config_(config) {
+  RTC_DCHECK(config.voe_channel_id != -1);
+}
+
+webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const {
+  return webrtc::AudioSendStream::Stats();
+}
+
+const webrtc::AudioSendStream::Config&
+    FakeAudioSendStream::GetConfig() const {
+  return config_;
+}
+
 FakeAudioReceiveStream::FakeAudioReceiveStream(
     const webrtc::AudioReceiveStream::Config& config)
     : config_(config), received_packets_(0) {
@@ -206,6 +220,7 @@
 
 FakeCall::~FakeCall() {
   EXPECT_EQ(0u, video_send_streams_.size());
+  EXPECT_EQ(0u, audio_send_streams_.size());
   EXPECT_EQ(0u, video_receive_streams_.size());
   EXPECT_EQ(0u, audio_receive_streams_.size());
 }
@@ -222,12 +237,25 @@
   return video_receive_streams_;
 }
 
+const std::vector<FakeAudioSendStream*>& FakeCall::GetAudioSendStreams() {
+  return audio_send_streams_;
+}
+
+const FakeAudioSendStream* FakeCall::GetAudioSendStream(uint32_t ssrc) {
+  for (const auto* p : GetAudioSendStreams()) {
+    if (p->GetConfig().rtp.ssrc == ssrc) {
+      return p;
+    }
+  }
+  return nullptr;
+}
+
 const std::vector<FakeAudioReceiveStream*>& FakeCall::GetAudioReceiveStreams() {
   return audio_receive_streams_;
 }
 
 const FakeAudioReceiveStream* FakeCall::GetAudioReceiveStream(uint32_t ssrc) {
-  for (const auto p : GetAudioReceiveStreams()) {
+  for (const auto* p : GetAudioReceiveStreams()) {
     if (p->GetConfig().rtp.remote_ssrc == ssrc) {
       return p;
     }
@@ -241,10 +269,22 @@
 
 webrtc::AudioSendStream* FakeCall::CreateAudioSendStream(
     const webrtc::AudioSendStream::Config& config) {
-  return nullptr;
+  FakeAudioSendStream* fake_stream = new FakeAudioSendStream(config);
+  audio_send_streams_.push_back(fake_stream);
+  ++num_created_send_streams_;
+  return fake_stream;
 }
 
 void FakeCall::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
+  auto it = std::find(audio_send_streams_.begin(),
+                      audio_send_streams_.end(),
+                      static_cast<FakeAudioSendStream*>(send_stream));
+  if (it == audio_send_streams_.end()) {
+    ADD_FAILURE() << "DestroyAudioSendStream called with unknown paramter.";
+  } else {
+    delete *it;
+    audio_send_streams_.erase(it);
+  }
 }
 
 webrtc::AudioReceiveStream* FakeCall::CreateAudioReceiveStream(
diff --git a/talk/media/webrtc/fakewebrtccall.h b/talk/media/webrtc/fakewebrtccall.h
index fb271f2..de56a03 100644
--- a/talk/media/webrtc/fakewebrtccall.h
+++ b/talk/media/webrtc/fakewebrtccall.h
@@ -25,6 +25,15 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// This file contains fake implementations, for use in unit tests, of the
+// following classes:
+//
+//   webrtc::Call
+//   webrtc::AudioSendStream
+//   webrtc::AudioReceiveStream
+//   webrtc::VideoSendStream
+//   webrtc::VideoReceiveStream
+
 #ifndef TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_
 #define TALK_MEDIA_WEBRTC_FAKEWEBRTCCALL_H_
 
@@ -32,11 +41,35 @@
 
 #include "webrtc/call.h"
 #include "webrtc/audio_receive_stream.h"
+#include "webrtc/audio_send_stream.h"
 #include "webrtc/video_frame.h"
 #include "webrtc/video_receive_stream.h"
 #include "webrtc/video_send_stream.h"
 
 namespace cricket {
+
+class FakeAudioSendStream : public webrtc::AudioSendStream {
+ public:
+  explicit FakeAudioSendStream(
+      const webrtc::AudioSendStream::Config& config);
+
+  // webrtc::AudioSendStream implementation.
+  webrtc::AudioSendStream::Stats GetStats() const override;
+
+  const webrtc::AudioSendStream::Config& GetConfig() const;
+
+ private:
+  // webrtc::SendStream implementation.
+  void Start() override {}
+  void Stop() override {}
+  void SignalNetworkState(webrtc::NetworkState state) override {}
+  bool DeliverRtcp(const uint8_t* packet, size_t length) override {
+    return true;
+  }
+
+  webrtc::AudioSendStream::Config config_;
+};
+
 class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
  public:
   explicit FakeAudioReceiveStream(
@@ -161,6 +194,8 @@
   const std::vector<FakeVideoSendStream*>& GetVideoSendStreams();
   const std::vector<FakeVideoReceiveStream*>& GetVideoReceiveStreams();
 
+  const std::vector<FakeAudioSendStream*>& GetAudioSendStreams();
+  const FakeAudioSendStream* GetAudioSendStream(uint32_t ssrc);
   const std::vector<FakeAudioReceiveStream*>& GetAudioReceiveStreams();
   const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc);
 
@@ -208,6 +243,7 @@
   rtc::SentPacket last_sent_packet_;
   webrtc::Call::Stats stats_;
   std::vector<FakeVideoSendStream*> video_send_streams_;
+  std::vector<FakeAudioSendStream*> audio_send_streams_;
   std::vector<FakeVideoReceiveStream*> video_receive_streams_;
   std::vector<FakeAudioReceiveStream*> audio_receive_streams_;
 
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index 5375358..eed1195 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -1313,15 +1313,25 @@
   return voe_wrapper_->base()->CreateChannel(voe_config_);
 }
 
-class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
+class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
     : public AudioRenderer::Sink {
  public:
-  WebRtcVoiceChannelRenderer(int ch,
-                             webrtc::AudioTransport* voe_audio_transport)
+  WebRtcAudioSendStream(int ch, webrtc::AudioTransport* voe_audio_transport,
+                        uint32_t ssrc, webrtc::Call* call)
       : channel_(ch),
         voe_audio_transport_(voe_audio_transport),
-        renderer_(NULL) {}
-  ~WebRtcVoiceChannelRenderer() override { Stop(); }
+        call_(call) {
+    RTC_DCHECK(call);
+    webrtc::AudioSendStream::Config config(nullptr);
+    config.voe_channel_id = channel_;
+    config.rtp.ssrc = ssrc;
+    stream_ = call_->CreateAudioSendStream(config);
+    RTC_DCHECK(stream_);
+  }
+  ~WebRtcAudioSendStream() override {
+    Stop();
+    call_->DestroyAudioSendStream(stream_);
+  }
 
   // Starts the rendering by setting a sink to the renderer to get data
   // callback.
@@ -1329,8 +1339,8 @@
   // TODO(xians): Make sure Start() is called only once.
   void Start(AudioRenderer* renderer) {
     rtc::CritScope lock(&lock_);
-    RTC_DCHECK(renderer != NULL);
-    if (renderer_ != NULL) {
+    RTC_DCHECK(renderer);
+    if (renderer_) {
       RTC_DCHECK(renderer_ == renderer);
       return;
     }
@@ -1338,14 +1348,14 @@
     renderer_ = renderer;
   }
 
-  // Stops rendering by setting the sink of the renderer to NULL. No data
+  // Stops rendering by setting the sink of the renderer to nullptr. No data
   // callback will be received after this method.
   // This method is called on the libjingle worker thread.
   void Stop() {
     rtc::CritScope lock(&lock_);
-    if (renderer_ != NULL) {
-      renderer_->SetSink(NULL);
-      renderer_ = NULL;
+    if (renderer_) {
+      renderer_->SetSink(nullptr);
+      renderer_ = nullptr;
     }
   }
 
@@ -1356,6 +1366,7 @@
               int sample_rate,
               int number_of_channels,
               size_t number_of_frames) override {
+    RTC_DCHECK(voe_audio_transport_);
     voe_audio_transport_->OnData(channel_,
                                  audio_data,
                                  bits_per_sample,
@@ -1368,25 +1379,42 @@
   // never been called, this callback won't be triggered.
   void OnClose() override {
     rtc::CritScope lock(&lock_);
-    // Set |renderer_| to NULL to make sure no more callback will get into
+    // Set |renderer_| to nullptr to make sure no more callback will get into
     // the renderer.
-    renderer_ = NULL;
+    renderer_ = nullptr;
   }
 
   // Accessor to the VoE channel ID.
   int channel() const { return channel_; }
 
  private:
-  const int channel_;
-  webrtc::AudioTransport* const voe_audio_transport_;
+  const int channel_ = -1;
+  webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
+  webrtc::Call* call_ = nullptr;
+  webrtc::AudioSendStream* stream_ = nullptr;
 
   // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
   // PeerConnection will make sure invalidating the pointer before the object
   // goes away.
-  AudioRenderer* renderer_;
+  AudioRenderer* renderer_ = nullptr;
 
   // Protects |renderer_| in Start(), Stop() and OnClose().
   rtc::CriticalSection lock_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
+};
+
+class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
+ public:
+  explicit WebRtcAudioReceiveStream(int voe_channel_id)
+      : channel_(voe_channel_id) {}
+
+  int channel() { return channel_; }
+
+ private:
+  int channel_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
 };
 
 // WebRtcVoiceMediaChannel
@@ -1417,8 +1445,8 @@
   LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
 
   // Remove any remaining send streams.
-  while (!send_channels_.empty()) {
-    RemoveSendStream(send_channels_.begin()->first);
+  while (!send_streams_.empty()) {
+    RemoveSendStream(send_streams_.begin()->first);
   }
 
   // Remove any remaining receive streams.
@@ -1481,6 +1509,7 @@
     }
   }
 
+  // TODO(solenberg): Don't recreate unless options changed.
   RecreateAudioReceiveStreams();
 
   LOG(LS_INFO) << "Set voice channel options.  Current options: "
@@ -1760,7 +1789,7 @@
 
   // Cache the codecs in order to configure the channel created later.
   send_codecs_ = codecs;
-  for (const auto& ch : send_channels_) {
+  for (const auto& ch : send_streams_) {
     if (!SetSendCodecs(ch.second->channel(), codecs)) {
       return false;
     }
@@ -1871,7 +1900,7 @@
     return true;
   }
 
-  for (const auto& ch : send_channels_) {
+  for (const auto& ch : send_streams_) {
     if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) {
       return false;
     }
@@ -1935,8 +1964,9 @@
 
 bool WebRtcVoiceMediaChannel::SetSend(SendFlags send) {
   desired_send_ = send;
-  if (!send_channels_.empty())
+  if (!send_streams_.empty()) {
     return ChangeSend(desired_send_);
+  }
   return true;
 }
 
@@ -1959,7 +1989,7 @@
   }
 
   // Change the settings on each send channel.
-  for (const auto& ch : send_channels_) {
+  for (const auto& ch : send_streams_) {
     if (!ChangeSend(ch.second->channel(), send)) {
       return false;
     }
@@ -2075,13 +2105,13 @@
     return false;
   }
 
-  // Save the channel to send_channels_, so that RemoveSendStream() can still
+  // Save the channel to send_streams_, so that RemoveSendStream() can still
   // delete the channel in case failure happens below.
   webrtc::AudioTransport* audio_transport =
       engine()->voe()->base()->audio_transport();
-  send_channels_.insert(
+  send_streams_.insert(
       std::make_pair(ssrc,
-                     new WebRtcVoiceChannelRenderer(channel, audio_transport)));
+          new WebRtcAudioSendStream(channel, audio_transport, ssrc, call_)));
 
   // Set the current codecs to be used for the new channel. We need to do this
   // after adding the channel to send_channels_, because of how max bitrate is
@@ -2094,7 +2124,7 @@
   // At this point the channel's local SSRC has been updated. If the channel is
   // the first send channel make sure that all the receive channels are updated
   // with the same SSRC in order to send receiver reports.
-  if (send_channels_.size() == 1) {
+  if (send_streams_.size() == 1) {
     receiver_reports_ssrc_ = ssrc;
     for (const auto& ch : receive_channels_) {
       int recv_channel = ch.second->channel();
@@ -2113,8 +2143,8 @@
 
 bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
-  ChannelMap::iterator it = send_channels_.find(ssrc);
-  if (it == send_channels_.end()) {
+  auto it = send_streams_.find(ssrc);
+  if (it == send_streams_.end()) {
     LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
                     << " which doesn't exist.";
     return false;
@@ -2126,7 +2156,7 @@
   // Delete the WebRtcVoiceChannelRenderer object connected to the channel,
   // this will disconnect the audio renderer with the send channel.
   delete it->second;
-  send_channels_.erase(it);
+  send_streams_.erase(it);
 
   // Clean up and delete the send channel.
   LOG(LS_INFO) << "Removing audio send stream " << ssrc
@@ -2134,7 +2164,7 @@
   if (!DeleteChannel(channel)) {
     return false;
   }
-  if (send_channels_.empty()) {
+  if (send_streams_.empty()) {
     ChangeSend(SEND_NOTHING);
   }
   return true;
@@ -2176,11 +2206,8 @@
     return false;
   }
 
-  webrtc::AudioTransport* audio_transport =
-      engine()->voe()->base()->audio_transport();
-  WebRtcVoiceChannelRenderer* channel_renderer =
-      new WebRtcVoiceChannelRenderer(channel, audio_transport);
-  receive_channels_.insert(std::make_pair(ssrc, channel_renderer));
+  WebRtcAudioReceiveStream* stream = new WebRtcAudioReceiveStream(channel);
+  receive_channels_.insert(std::make_pair(ssrc, stream));
   receive_stream_params_[ssrc] = sp;
   AddAudioReceiveStream(ssrc);
 
@@ -2249,7 +2276,7 @@
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
   LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
 
-  ChannelMap::iterator it = receive_channels_.find(ssrc);
+  auto it = receive_channels_.find(ssrc);
   if (it == receive_channels_.end()) {
     LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
                     << " which doesn't exist.";
@@ -2259,9 +2286,6 @@
   RemoveAudioReceiveStream(ssrc);
   receive_stream_params_.erase(ssrc);
 
-  // Delete the WebRtcVoiceChannelRenderer object connected to the channel, this
-  // will disconnect the audio renderer with the receive channel.
-  // Cache the channel before the deletion.
   const int channel = it->second->channel();
   delete it->second;
   receive_channels_.erase(it);
@@ -2278,8 +2302,8 @@
 
 bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc,
                                                AudioRenderer* renderer) {
-  ChannelMap::iterator it = send_channels_.find(ssrc);
-  if (it == send_channels_.end()) {
+  auto it = send_streams_.find(ssrc);
+  if (it == send_streams_.end()) {
     if (renderer) {
       // Return an error if trying to set a valid renderer with an invalid ssrc.
       LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc;
@@ -2388,8 +2412,8 @@
   if (flags & cricket::DF_SEND) {
     int channel = -1;
     if (ssrc == 0) {
-      if (send_channels_.size() > 0) {
-        channel = send_channels_.begin()->second->channel();
+      if (send_streams_.size() > 0) {
+        channel = send_streams_.begin()->second->channel();
       }
     } else {
       channel = GetSendChannelId(ssrc);
@@ -2499,7 +2523,7 @@
   // SR may continue RR and any RR entry may correspond to any one of the send
   // channels. So all RTCP packets must be forwarded all send channels. VoE
   // will filter out RR internally.
-  for (const auto& ch : send_channels_) {
+  for (const auto& ch : send_streams_) {
     engine()->voe()->network()->ReceivedRTCPPacket(
         ch.second->channel(), packet->data(), packet->size());
   }
@@ -2521,7 +2545,7 @@
   // the mic channel is muted/unmuted. We can't do it today because there
   // is no good way to know which stream is mapping to the mic channel.
   bool all_muted = muted;
-  for (const auto& ch : send_channels_) {
+  for (const auto& ch : send_streams_) {
     if (!all_muted) {
       break;
     }
@@ -2570,7 +2594,7 @@
   if (is_multi_rate) {
     // If codec is multi-rate then just set the bitrate.
     codec.rate = bps;
-    for (const auto& ch : send_channels_) {
+    for (const auto& ch : send_streams_) {
       if (!SetSendCodec(ch.second->channel(), codec)) {
         LOG(LS_INFO) << "Failed to set codec " << codec.plname
                      << " to bitrate " << bps << " bps.";
@@ -2630,7 +2654,7 @@
   webrtc::CodecInst codec;
   unsigned int level;
 
-  for (const auto& ch : send_channels_) {
+  for (const auto& ch : send_streams_) {
     const int channel = ch.second->channel();
 
     // Fill in the sender info, based on what we know, and what the
@@ -2791,7 +2815,7 @@
 
 int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
-  ChannelMap::const_iterator it = receive_channels_.find(ssrc);
+  const auto it = receive_channels_.find(ssrc);
   if (it != receive_channels_.end()) {
     return it->second->channel();
   }
@@ -2800,8 +2824,8 @@
 
 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
-  ChannelMap::const_iterator it = send_channels_.find(ssrc);
-  if (it != send_channels_.end()) {
+  const auto it = send_streams_.find(ssrc);
+  if (it != send_streams_.end()) {
     return it->second->channel();
   }
   return -1;
@@ -2927,8 +2951,8 @@
 
 void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
-  WebRtcVoiceChannelRenderer* channel = receive_channels_[ssrc];
-  RTC_DCHECK(channel != nullptr);
+  WebRtcAudioReceiveStream* stream = receive_channels_[ssrc];
+  RTC_DCHECK(stream != nullptr);
   RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end());
   webrtc::AudioReceiveStream::Config config;
   config.rtp.remote_ssrc = ssrc;
@@ -2936,7 +2960,7 @@
   config.rtp.extensions = recv_rtp_extensions_;
   config.combined_audio_video_bwe =
       options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false);
-  config.voe_channel_id = channel->channel();
+  config.voe_channel_id = stream->channel();
   config.sync_group = receive_stream_params_[ssrc].sync_label;
   webrtc::AudioReceiveStream* s = call_->CreateAudioReceiveStream(config);
   receive_streams_.insert(std::make_pair(ssrc, s));
diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h
index a8f3ec8..a708405 100644
--- a/talk/media/webrtc/webrtcvoiceengine.h
+++ b/talk/media/webrtc/webrtcvoiceengine.h
@@ -172,6 +172,8 @@
   Settable<bool> extended_filter_aec_;
   Settable<bool> delay_agnostic_aec_;
   Settable<bool> experimental_ns_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcVoiceEngine);
 };
 
 // WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses
@@ -265,11 +267,6 @@
   bool SetPlayout(int channel, bool playout);
   static Error WebRtcErrorToChannelError(int err_code);
 
-  class WebRtcVoiceChannelRenderer;
-  // Map of ssrc to WebRtcVoiceChannelRenderer object.  A new object of
-  // WebRtcVoiceChannelRenderer will be created for every new stream and
-  // will be destroyed when the stream goes away.
-  typedef std::map<uint32_t, WebRtcVoiceChannelRenderer*> ChannelMap;
   typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool,
       unsigned char);
 
@@ -327,12 +324,12 @@
   // send streams. See: https://code.google.com/p/webrtc/issues/detail?id=4740
   uint32_t receiver_reports_ssrc_ = 1;
 
-  // send_channels_ contains the channels which are being used for sending.
-  // When the default channel (default_send_channel_id) is used for sending, it
-  // is contained in send_channels_, otherwise not.
-  ChannelMap send_channels_;
+  class WebRtcAudioSendStream;
+  std::map<uint32_t, WebRtcAudioSendStream*> send_streams_;
   std::vector<RtpHeaderExtension> send_extensions_;
-  ChannelMap receive_channels_;
+
+  class WebRtcAudioReceiveStream;
+  std::map<uint32_t, WebRtcAudioReceiveStream*> receive_channels_;
   std::map<uint32_t, webrtc::AudioReceiveStream*> receive_streams_;
   std::map<uint32_t, StreamParams> receive_stream_params_;
   // receive_channels_ can be read from WebRtc callback thread.  Access from
@@ -340,6 +337,8 @@
   // Reads on the worker thread are ok.
   std::vector<RtpHeaderExtension> receive_extensions_;
   std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel);
 };
 
 }  // namespace cricket
diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index 85094f8..477369e 100644
--- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -59,6 +59,7 @@
 };
 static uint32_t kSsrc1 = 0x99;
 static uint32_t kSsrc2 = 0x98;
+static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
 
 class FakeVoEWrapper : public cricket::VoEWrapper {
  public:
@@ -1862,44 +1863,39 @@
 TEST_F(WebRtcVoiceEngineTestFake, CreateAndDeleteMultipleSendStreams) {
   SetupForMultiSendStream();
 
-  static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
-
   // Set the global state for sending.
   EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
 
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
+  for (uint32_t ssrc : kSsrcs4) {
     EXPECT_TRUE(channel_->AddSendStream(
-        cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
+        cricket::StreamParams::CreateLegacy(ssrc)));
+    EXPECT_NE(nullptr, call_.GetAudioSendStream(ssrc));
 
     // Verify that we are in a sending state for all the created streams.
-    int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]);
+    int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
     EXPECT_TRUE(voe_.GetSend(channel_num));
   }
+  EXPECT_EQ(ARRAY_SIZE(kSsrcs4), call_.GetAudioSendStreams().size());
 
-  // Remove the first send channel, which is the default channel. It will only
-  // recycle the default channel but not delete it.
-  EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[0]));
-  // Stream should already be Removed from the send stream list.
-  EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[0]));
-
-  // Delete the rest of send channel streams.
-  for (unsigned int i = 1; i < ARRAY_SIZE(kSsrcs4); ++i) {
-    EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[i]));
+  // Delete the send streams.
+  for (uint32_t ssrc : kSsrcs4) {
+    EXPECT_TRUE(channel_->RemoveSendStream(ssrc));
+    EXPECT_EQ(nullptr, call_.GetAudioSendStream(ssrc));
     // Stream should already be deleted.
-    EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[i]));
-    EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(kSsrcs4[i]));
+    EXPECT_FALSE(channel_->RemoveSendStream(ssrc));
+    EXPECT_EQ(-1, voe_.GetChannelFromLocalSsrc(ssrc));
   }
+  EXPECT_EQ(0u, call_.GetAudioSendStreams().size());
 }
 
 // Test SetSendCodecs correctly configure the codecs in all send streams.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) {
   SetupForMultiSendStream();
 
-  static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
   // Create send streams.
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
+  for (uint32_t ssrc : kSsrcs4) {
     EXPECT_TRUE(channel_->AddSendStream(
-        cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
+        cricket::StreamParams::CreateLegacy(ssrc)));
   }
 
   cricket::AudioSendParameters parameters;
@@ -1911,8 +1907,8 @@
 
   // Verify ISAC and VAD are corrected configured on all send channels.
   webrtc::CodecInst gcodec;
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
-    int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]);
+  for (uint32_t ssrc : kSsrcs4) {
+    int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
     EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
     EXPECT_STREQ("ISAC", gcodec.plname);
     EXPECT_TRUE(voe_.GetVAD(channel_num));
@@ -1922,8 +1918,8 @@
   // Change to PCMU(8K) and CN(16K). VAD should not be activated.
   parameters.codecs[0] = kPcmuCodec;
   EXPECT_TRUE(channel_->SetSendParameters(parameters));
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
-    int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]);
+  for (uint32_t ssrc : kSsrcs4) {
+    int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
     EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec));
     EXPECT_STREQ("PCMU", gcodec.plname);
     EXPECT_FALSE(voe_.GetVAD(channel_num));
@@ -1934,28 +1930,27 @@
 TEST_F(WebRtcVoiceEngineTestFake, SetSendWithMultipleSendStreams) {
   SetupForMultiSendStream();
 
-  static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
   // Create the send channels and they should be a SEND_NOTHING date.
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
+  for (uint32_t ssrc : kSsrcs4) {
     EXPECT_TRUE(channel_->AddSendStream(
-        cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
+        cricket::StreamParams::CreateLegacy(ssrc)));
     int channel_num = voe_.GetLastChannel();
     EXPECT_FALSE(voe_.GetSend(channel_num));
   }
 
   // Set the global state for starting sending.
   EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
+  for (uint32_t ssrc : kSsrcs4) {
     // Verify that we are in a sending state for all the send streams.
-    int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]);
+    int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
     EXPECT_TRUE(voe_.GetSend(channel_num));
   }
 
   // Set the global state for stopping sending.
   EXPECT_TRUE(channel_->SetSend(cricket::SEND_NOTHING));
-  for (unsigned int i = 1; i < ARRAY_SIZE(kSsrcs4); ++i) {
+  for (uint32_t ssrc : kSsrcs4) {
     // Verify that we are in a stop state for all the send streams.
-    int channel_num = voe_.GetChannelFromLocalSsrc(kSsrcs4[i]);
+    int channel_num = voe_.GetChannelFromLocalSsrc(ssrc);
     EXPECT_FALSE(voe_.GetSend(channel_num));
   }
 }
@@ -1964,11 +1959,10 @@
 TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
   SetupForMultiSendStream();
 
-  static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
   // Create send streams.
-  for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
+  for (uint32_t ssrc : kSsrcs4) {
     EXPECT_TRUE(channel_->AddSendStream(
-        cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
+        cricket::StreamParams::CreateLegacy(ssrc)));
   }
   // Create a receive stream to check that none of the send streams end up in
   // the receive stream stats.
@@ -1983,6 +1977,7 @@
   EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
 
   // Verify the statistic information is correct.
+  // TODO(solenberg): Make this loop ordering independent.
   for (unsigned int i = 0; i < ARRAY_SIZE(kSsrcs4); ++i) {
     EXPECT_EQ(kSsrcs4[i], info.senders[i].ssrc());
     EXPECT_EQ(kPcmuCodec.name, info.senders[i].codec_name);