Configure VoE NACK through AudioReceiveStream::Config, for receive streams. Also minor refactoring of WVoE unit test.

BUG=webrtc:4690

Review-Url: https://codereview.webrtc.org/2060813002
Cr-Commit-Position: refs/heads/master@{#13140}
diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc
index c6c9b30..15e4f61 100644
--- a/webrtc/audio/audio_receive_stream.cc
+++ b/webrtc/audio/audio_receive_stream.cc
@@ -50,6 +50,8 @@
   std::stringstream ss;
   ss << "{remote_ssrc: " << remote_ssrc;
   ss << ", local_ssrc: " << local_ssrc;
+  ss << ", transport_cc: " << (transport_cc ? "on" : "off");
+  ss << ", nack: " << nack.ToString();
   ss << ", extensions: [";
   for (size_t i = 0; i < extensions.size(); ++i) {
     ss << extensions[i].ToString();
@@ -58,7 +60,6 @@
     }
   }
   ss << ']';
-  ss << ", transport_cc: " << (transport_cc ? "on" : "off");
   ss << '}';
   return ss.str();
 }
@@ -93,6 +94,10 @@
   VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine());
   channel_proxy_ = voe_impl->GetChannelProxy(config_.voe_channel_id);
   channel_proxy_->SetLocalSSRC(config.rtp.local_ssrc);
+  // TODO(solenberg): Config NACK history window (which is a packet count),
+  // using the actual packet size for the configured codec.
+  channel_proxy_->SetNACKStatus(config_.rtp.nack.rtp_history_ms != 0,
+                                config_.rtp.nack.rtp_history_ms / 20);
 
   // TODO(ossu): This is where we'd like to set the decoder factory to
   // use. However, since it needs to be included when constructing Channel, we
diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc
index 9d6aa9b..2e789f9 100644
--- a/webrtc/audio/audio_receive_stream_unittest.cc
+++ b/webrtc/audio/audio_receive_stream_unittest.cc
@@ -85,6 +85,7 @@
           EXPECT_FALSE(channel_proxy_);
           channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
           EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
+          EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
           EXPECT_CALL(*channel_proxy_,
               SetReceiveAbsoluteSenderTimeStatus(true, kAbsSendTimeId))
                   .Times(1);
@@ -112,6 +113,7 @@
     stream_config_.voe_channel_id = kChannelId;
     stream_config_.rtp.local_ssrc = kLocalSsrc;
     stream_config_.rtp.remote_ssrc = kRemoteSsrc;
+    stream_config_.rtp.nack.rtp_history_ms = 300;
     stream_config_.rtp.extensions.push_back(
         RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId));
     stream_config_.rtp.extensions.push_back(
@@ -234,9 +236,9 @@
       RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId));
   config.voe_channel_id = kChannelId;
   EXPECT_EQ(
-      "{rtp: {remote_ssrc: 1234, local_ssrc: 5678, extensions: [{uri: "
-      "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 2}], "
-      "transport_cc: off}, "
+      "{rtp: {remote_ssrc: 1234, local_ssrc: 5678, transport_cc: off, "
+      "nack: {rtp_history_ms: 0}, extensions: [{uri: "
+      "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 2}]}, "
       "rtcp_send_transport: nullptr, "
       "voe_channel_id: 2}",
       config.ToString());
diff --git a/webrtc/audio_receive_stream.h b/webrtc/audio_receive_stream.h
index 9af84a7..16ed769 100644
--- a/webrtc/audio_receive_stream.h
+++ b/webrtc/audio_receive_stream.h
@@ -79,6 +79,9 @@
       // for details.
       bool transport_cc = false;
 
+      // See NackConfig for description.
+      NackConfig nack;
+
       // RTP header extensions used for the received stream.
       std::vector<RtpExtension> extensions;
     } rtp;
diff --git a/webrtc/media/engine/fakewebrtcvoiceengine.h b/webrtc/media/engine/fakewebrtcvoiceengine.h
index e15b2e6..5f0be5c9 100644
--- a/webrtc/media/engine/fakewebrtcvoiceengine.h
+++ b/webrtc/media/engine/fakewebrtcvoiceengine.h
@@ -134,10 +134,8 @@
     bool codec_fec = false;
     int max_encoding_bandwidth = 0;
     bool opus_dtx = false;
-    bool nack = false;
     int cn8_type = 13;
     int cn16_type = 105;
-    int nack_max_packets = 0;
     uint32_t send_ssrc = 0;
     int associate_send_channel = -1;
     std::vector<webrtc::CodecInst> recv_codecs;
@@ -176,12 +174,6 @@
   int GetMaxEncodingBandwidth(int channel) {
     return channels_[channel]->max_encoding_bandwidth;
   }
-  bool GetNACK(int channel) {
-    return channels_[channel]->nack;
-  }
-  int GetNACKMaxPackets(int channel) {
-    return channels_[channel]->nack_max_packets;
-  }
   int GetSendCNPayloadType(int channel, bool wideband) {
     return (wideband) ?
         channels_[channel]->cn16_type :
@@ -477,12 +469,7 @@
   WEBRTC_STUB(GetRTCPStatistics, (int channel, webrtc::CallStatistics& stats));
   WEBRTC_STUB(SetREDStatus, (int channel, bool enable, int redPayloadtype));
   WEBRTC_STUB(GetREDStatus, (int channel, bool& enable, int& redPayloadtype));
-  WEBRTC_FUNC(SetNACKStatus, (int channel, bool enable, int maxNoPackets)) {
-    WEBRTC_CHECK_CHANNEL(channel);
-    channels_[channel]->nack = enable;
-    channels_[channel]->nack_max_packets = maxNoPackets;
-    return 0;
-  }
+  WEBRTC_STUB(SetNACKStatus, (int channel, bool enable, int maxNoPackets));
 
   // webrtc::VoEVolumeControl
   WEBRTC_STUB(SetSpeakerVolume, (unsigned int));
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index 7b3e0ef..a4a5e13 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -61,9 +61,6 @@
 const int kDefaultAudioDeviceId = 0;
 #endif
 
-// Parameter used for NACK.
-// This value is equivalent to 5 seconds of audio data at 20 ms per packet.
-const int kNackMaxPackets = 250;
 constexpr int kNackRtpHistoryMs = 5000;
 
 // Codec parameters for Opus.
@@ -1267,6 +1264,7 @@
       uint32_t remote_ssrc,
       uint32_t local_ssrc,
       bool use_transport_cc,
+      bool use_nack,
       const std::string& sync_group,
       const std::vector<webrtc::RtpExtension>& extensions,
       webrtc::Call* call,
@@ -1281,7 +1279,7 @@
     config_.voe_channel_id = ch;
     config_.sync_group = sync_group;
     config_.decoder_factory = decoder_factory;
-    RecreateAudioReceiveStream(use_transport_cc, extensions);
+    RecreateAudioReceiveStream(use_transport_cc, use_nack, extensions);
   }
 
   ~WebRtcAudioReceiveStream() {
@@ -1292,11 +1290,16 @@
   void RecreateAudioReceiveStream(
       const std::vector<webrtc::RtpExtension>& extensions) {
     RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-    RecreateAudioReceiveStream(config_.rtp.transport_cc, extensions);
+    RecreateAudioReceiveStream(config_.rtp.transport_cc,
+                               config_.rtp.nack.rtp_history_ms != 0,
+                               extensions);
   }
-  void RecreateAudioReceiveStream(bool use_transport_cc) {
+
+  void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
     RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-    RecreateAudioReceiveStream(use_transport_cc, config_.rtp.extensions);
+    RecreateAudioReceiveStream(use_transport_cc,
+                               use_nack,
+                               config_.rtp.extensions);
   }
 
   webrtc::AudioReceiveStream::Stats GetStats() const {
@@ -1318,14 +1321,16 @@
  private:
   void RecreateAudioReceiveStream(
       bool use_transport_cc,
+      bool use_nack,
       const std::vector<webrtc::RtpExtension>& extensions) {
     RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
     if (stream_) {
       call_->DestroyAudioReceiveStream(stream_);
       stream_ = nullptr;
     }
-    config_.rtp.extensions = extensions;
     config_.rtp.transport_cc = use_transport_cc;
+    config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
+    config_.rtp.extensions = extensions;
     RTC_DCHECK(!stream_);
     stream_ = call_->CreateAudioReceiveStream(config_);
     RTC_CHECK(stream_);
@@ -1730,19 +1735,17 @@
     }
   }
 
-  // Set nack status on receive channels.
-  for (const auto& kv : recv_streams_) {
-    SetNack(kv.second->channel(), send_codec_spec_.nack_enabled);
-  }
-
-  // Check if the transport cc feedback has changed on the preferred send codec,
-  // and in that case reconfigure all receive streams.
-  if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) {
+  // Check if the transport cc feedback or NACK status has changed on the
+  // preferred send codec, and in that case reconfigure all receive streams.
+  if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled ||
+      recv_nack_enabled_ != send_codec_spec_.nack_enabled) {
     LOG(LS_INFO) << "Recreate all the receive streams because the send "
                     "codec has changed.";
     recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled;
+    recv_nack_enabled_ = send_codec_spec_.nack_enabled;
     for (auto& kv : recv_streams_) {
-      kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_);
+      kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
+                                            recv_nack_enabled_);
     }
   }
 
@@ -1856,16 +1859,6 @@
   return true;
 }
 
-void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
-  if (nack_enabled) {
-    LOG(LS_INFO) << "Enabling NACK for channel " << channel;
-    engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
-  } else {
-    LOG(LS_INFO) << "Disabling NACK for channel " << channel;
-    engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
-  }
-}
-
 bool WebRtcVoiceMediaChannel::SetSendCodec(
     int channel, const webrtc::CodecInst& send_codec) {
   LOG(LS_INFO) << "Send channel " << channel <<  " selected voice codec "
@@ -2137,11 +2130,10 @@
   recv_streams_.insert(std::make_pair(
       ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_,
                                          recv_transport_cc_enabled_,
+                                         recv_nack_enabled_,
                                          sp.sync_label, recv_rtp_extensions_,
                                          call_, this,
                                          engine()->decoder_factory_)));
-
-  SetNack(channel, send_codec_spec_.nack_enabled);
   SetPlayout(channel, playout_);
 
   return true;
diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h
index d2fad70..52983fa 100644
--- a/webrtc/media/engine/webrtcvoiceengine.h
+++ b/webrtc/media/engine/webrtcvoiceengine.h
@@ -244,7 +244,6 @@
   bool SetRecvCodecs(const std::vector<AudioCodec>& codecs);
   bool SetSendCodecs(const std::vector<AudioCodec>& codecs);
   bool SetSendCodecs(int channel, const webrtc::RtpParameters& rtp_parameters);
-  void SetNack(int channel, bool nack_enabled);
   bool SetSendCodec(int channel, const webrtc::CodecInst& send_codec);
   bool SetLocalSource(uint32_t ssrc, AudioSource* source);
   bool MuteStream(uint32_t ssrc, bool mute);
@@ -279,6 +278,7 @@
   rtc::Optional<int> dtmf_payload_type_;
   bool desired_playout_ = false;
   bool recv_transport_cc_enabled_ = false;
+  bool recv_nack_enabled_ = false;
   bool playout_ = false;
   bool send_ = false;
   webrtc::Call* const call_ = nullptr;
diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
index fe265ed..98495af 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -107,18 +107,20 @@
     send_parameters_.codecs.push_back(kPcmuCodec);
     recv_parameters_.codecs.push_back(kPcmuCodec);
   }
+
   bool SetupChannel() {
     channel_ = engine_->CreateChannel(&call_, cricket::MediaConfig(),
                                       cricket::AudioOptions());
     return (channel_ != nullptr);
   }
+
   bool SetupRecvStream() {
     if (!SetupChannel()) {
       return false;
     }
-    return channel_->AddRecvStream(
-        cricket::StreamParams::CreateLegacy(kSsrc1));
+    return AddRecvStream(kSsrc1);
   }
+
   bool SetupSendStream() {
     if (!SetupChannel()) {
       return false;
@@ -128,6 +130,12 @@
     }
     return channel_->SetAudioSend(kSsrc1, true, nullptr, &fake_source_);
   }
+
+  bool AddRecvStream(uint32_t ssrc) {
+    EXPECT_TRUE(channel_);
+    return channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(ssrc));
+  }
+
   void SetupForMultiSendStream() {
     EXPECT_TRUE(SetupSendStream());
     // Remove stream added in Setup.
@@ -136,10 +144,12 @@
     // Verify the channel does not exist.
     EXPECT_FALSE(call_.GetAudioSendStream(kSsrc1));
   }
+
   void DeliverPacket(const void* data, int len) {
     rtc::CopyOnWriteBuffer packet(reinterpret_cast<const uint8_t*>(data), len);
     channel_->OnPacketReceived(&packet, rtc::PacketTime());
   }
+
   void TearDown() override {
     delete channel_;
   }
@@ -351,8 +361,7 @@
     EXPECT_EQ(id, GetRecvStreamConfig(kSsrc1).rtp.extensions[0].id);
 
     // Ensure extension is set properly on new stream.
-    EXPECT_TRUE(channel_->AddRecvStream(
-        cricket::StreamParams::CreateLegacy(kSsrc2)));
+    EXPECT_TRUE(AddRecvStream(kSsrc2));
     EXPECT_NE(call_.GetAudioReceiveStream(kSsrc1),
               call_.GetAudioReceiveStream(kSsrc2));
     EXPECT_EQ(1u, GetRecvStreamConfig(kSsrc2).rtp.extensions.size());
@@ -511,8 +520,7 @@
 // Test that we can add a receive stream and that it has the correct defaults.
 TEST_F(WebRtcVoiceEngineTestFake, CreateRecvStream) {
   EXPECT_TRUE(SetupChannel());
-  EXPECT_TRUE(
-      channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   const webrtc::AudioReceiveStream::Config& config =
       GetRecvStreamConfig(kSsrc1);
   EXPECT_EQ(kSsrc1, config.rtp.remote_ssrc);
@@ -596,8 +604,7 @@
   parameters.codecs[0].id = 106;  // collide with existing telephone-event
   parameters.codecs[2].id = 126;
   EXPECT_TRUE(channel_->SetRecvParameters(parameters));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_num = voe_.GetLastChannel();
   webrtc::CodecInst gcodec;
   rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
@@ -640,8 +647,7 @@
   parameters.codecs.push_back(kPcmuCodec);
   parameters.codecs.push_back(kOpusCodec);
   EXPECT_TRUE(channel_->SetRecvParameters(parameters));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_num = voe_.GetLastChannel();
   webrtc::CodecInst opus;
   cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
@@ -663,8 +669,7 @@
   parameters.codecs.push_back(kOpusCodec);
   parameters.codecs[2].params["stereo"] = "0";
   EXPECT_TRUE(channel_->SetRecvParameters(parameters));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_num2 = voe_.GetLastChannel();
   webrtc::CodecInst opus;
   cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
@@ -686,8 +691,7 @@
   parameters.codecs.push_back(kOpusCodec);
   parameters.codecs[2].params["stereo"] = "1";
   EXPECT_TRUE(channel_->SetRecvParameters(parameters));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_num2 = voe_.GetLastChannel();
   webrtc::CodecInst opus;
   cricket::WebRtcVoiceEngine::ToCodecInst(kOpusCodec, &opus);
@@ -709,8 +713,7 @@
   parameters.codecs[0].id = 106;  // collide with existing telephone-event
   parameters.codecs[2].id = 126;
   EXPECT_TRUE(channel_->SetRecvParameters(parameters));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_num2 = voe_.GetLastChannel();
   webrtc::CodecInst gcodec;
   rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "ISAC");
@@ -1373,16 +1376,15 @@
 // Test that we can enable NACK with opus as callee.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNackAsCallee) {
   EXPECT_TRUE(SetupRecvStream());
-  int channel_num = voe_.GetLastChannel();
   cricket::AudioSendParameters parameters;
   parameters.codecs.push_back(kOpusCodec);
   parameters.codecs[0].AddFeedbackParam(
       cricket::FeedbackParam(cricket::kRtcpFbParamNack,
                              cricket::kParamValueEmpty));
-  EXPECT_FALSE(voe_.GetNACK(channel_num));
+  EXPECT_EQ(0, GetRecvStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
   EXPECT_TRUE(channel_->SetSendParameters(parameters));
   // NACK should be enabled even with no send stream.
-  EXPECT_TRUE(voe_.GetNACK(channel_num));
+  EXPECT_EQ(kRtpHistoryMs, GetRecvStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
 
   EXPECT_TRUE(channel_->AddSendStream(
       cricket::StreamParams::CreateLegacy(kSsrc1)));
@@ -1392,18 +1394,17 @@
 // Test that we can enable NACK on receive streams.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecEnableNackRecvStreams) {
   EXPECT_TRUE(SetupSendStream());
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
-  int channel_num2 = voe_.GetLastChannel();
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
   cricket::AudioSendParameters parameters;
   parameters.codecs.push_back(kOpusCodec);
   parameters.codecs[0].AddFeedbackParam(
       cricket::FeedbackParam(cricket::kRtcpFbParamNack,
                              cricket::kParamValueEmpty));
   EXPECT_EQ(0, GetSendStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
-  EXPECT_FALSE(voe_.GetNACK(channel_num2));
+  EXPECT_EQ(0, GetRecvStreamConfig(kSsrc2).rtp.nack.rtp_history_ms);
   EXPECT_TRUE(channel_->SetSendParameters(parameters));
   EXPECT_EQ(kRtpHistoryMs, GetSendStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
-  EXPECT_TRUE(voe_.GetNACK(channel_num2));
+  EXPECT_EQ(kRtpHistoryMs, GetRecvStreamConfig(kSsrc2).rtp.nack.rtp_history_ms);
 }
 
 // Test that we can disable NACK.
@@ -1426,8 +1427,7 @@
 // Test that we can disable NACK on receive streams.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecDisableNackRecvStreams) {
   EXPECT_TRUE(SetupSendStream());
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
-  int channel_num2 = voe_.GetLastChannel();
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
   cricket::AudioSendParameters parameters;
   parameters.codecs.push_back(kOpusCodec);
   parameters.codecs[0].AddFeedbackParam(
@@ -1435,13 +1435,13 @@
                              cricket::kParamValueEmpty));
   EXPECT_TRUE(channel_->SetSendParameters(parameters));
   EXPECT_EQ(kRtpHistoryMs, GetSendStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
-  EXPECT_TRUE(voe_.GetNACK(channel_num2));
+  EXPECT_EQ(kRtpHistoryMs, GetRecvStreamConfig(kSsrc2).rtp.nack.rtp_history_ms);
 
   parameters.codecs.clear();
   parameters.codecs.push_back(kOpusCodec);
   EXPECT_TRUE(channel_->SetSendParameters(parameters));
   EXPECT_EQ(0, GetSendStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
-  EXPECT_FALSE(voe_.GetNACK(channel_num2));
+  EXPECT_EQ(0, GetRecvStreamConfig(kSsrc2).rtp.nack.rtp_history_ms);
 }
 
 // Test that NACK is enabled on a new receive stream.
@@ -1456,12 +1456,10 @@
   EXPECT_TRUE(channel_->SetSendParameters(parameters));
   EXPECT_EQ(kRtpHistoryMs, GetSendStreamConfig(kSsrc1).rtp.nack.rtp_history_ms);
 
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
-  int channel_num = voe_.GetLastChannel();
-  EXPECT_TRUE(voe_.GetNACK(channel_num));
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
-  channel_num = voe_.GetLastChannel();
-  EXPECT_TRUE(voe_.GetNACK(channel_num));
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
+  EXPECT_EQ(kRtpHistoryMs, GetRecvStreamConfig(kSsrc2).rtp.nack.rtp_history_ms);
+  EXPECT_TRUE(AddRecvStream(kSsrc3));
+  EXPECT_EQ(kRtpHistoryMs, GetRecvStreamConfig(kSsrc3).rtp.nack.rtp_history_ms);
 }
 
 // Test that without useinbandfec, Opus FEC is off.
@@ -1570,8 +1568,7 @@
   cricket::AudioRecvParameters recv_parameters;
   recv_parameters.codecs.push_back(kIsacCodec);
   EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters));
-  EXPECT_TRUE(
-      channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   ASSERT_TRUE(call_.GetAudioReceiveStream(kSsrc1) != nullptr);
   EXPECT_FALSE(
       call_.GetAudioReceiveStream(kSsrc1)->GetConfig().rtp.transport_cc);
@@ -2276,8 +2273,7 @@
 
   // Create a receive stream to check that none of the send streams end up in
   // the receive stream stats.
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc2)));
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
 
   // We need send codec to be set to get all stats.
   EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
@@ -2334,8 +2330,7 @@
   EXPECT_FALSE(voe_.GetPlayout(channel_num1));
 
   // Adding another stream should enable playout on the new stream only.
-  EXPECT_TRUE(
-      channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc2)));
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
   int channel_num2 = voe_.GetLastChannel();
   SetSend(channel_, true);
   EXPECT_TRUE(GetSendStream(kSsrc1).IsSending());
@@ -2345,8 +2340,7 @@
   EXPECT_TRUE(voe_.GetPlayout(channel_num2));
 
   // Adding yet another stream should have stream 2 and 3 enabled for playout.
-  EXPECT_TRUE(
-      channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc3)));
+  EXPECT_TRUE(AddRecvStream(kSsrc3));
   int channel_num3 = voe_.GetLastChannel();
   EXPECT_FALSE(voe_.GetPlayout(channel_num1));
   EXPECT_TRUE(voe_.GetPlayout(channel_num2));
@@ -2442,8 +2436,7 @@
   EXPECT_TRUE(SetupSendStream());
   // SetupSendStream adds a send stream with kSsrc1, so the receive
   // stream has to use a different SSRC.
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc2)));
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
   EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
   EXPECT_TRUE(channel_->SetRecvParameters(recv_parameters_));
   SetAudioSendStreamStats();
@@ -2496,8 +2489,7 @@
 TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcWithMultipleStreams) {
   EXPECT_TRUE(SetupSendStream());
   EXPECT_TRUE(call_.GetAudioSendStream(kSsrc1));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc2)));
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
   EXPECT_EQ(kSsrc1, GetRecvStreamConfig(kSsrc2).rtp.local_ssrc);
 }
 
@@ -2505,7 +2497,7 @@
 // receive channel is created before the send channel.
 TEST_F(WebRtcVoiceEngineTestFake, SetSendSsrcAfterCreatingReceiveChannel) {
   EXPECT_TRUE(SetupChannel());
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+  EXPECT_TRUE(AddRecvStream(1));
   int receive_channel_num = voe_.GetLastChannel();
   EXPECT_TRUE(channel_->AddSendStream(
       cricket::StreamParams::CreateLegacy(1234)));
@@ -2517,7 +2509,7 @@
 // Test that we can properly receive packets.
 TEST_F(WebRtcVoiceEngineTestFake, Recv) {
   EXPECT_TRUE(SetupChannel());
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+  EXPECT_TRUE(AddRecvStream(1));
   DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
 
   EXPECT_TRUE(GetRecvStream(1).VerifyLastPacket(kPcmuFrame,
@@ -2530,12 +2522,9 @@
   const uint32_t ssrc1 = 1;
   const uint32_t ssrc2 = 2;
   const uint32_t ssrc3 = 3;
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(ssrc1)));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(ssrc2)));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(ssrc3)));
+  EXPECT_TRUE(AddRecvStream(ssrc1));
+  EXPECT_TRUE(AddRecvStream(ssrc2));
+  EXPECT_TRUE(AddRecvStream(ssrc3));
   // Create packets with the right SSRCs.
   unsigned char packets[4][sizeof(kPcmuFrame)];
   for (size_t i = 0; i < arraysize(packets); ++i) {
@@ -2630,8 +2619,7 @@
   // Add a known stream, send packet and verify we got it.
   const uint32_t signaled_ssrc = 1;
   rtc::SetBE32(&packet[8], signaled_ssrc);
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(signaled_ssrc)));
+  EXPECT_TRUE(AddRecvStream(signaled_ssrc));
   DeliverPacket(packet, sizeof(packet));
   EXPECT_TRUE(GetRecvStream(signaled_ssrc).VerifyLastPacket(
       packet, sizeof(packet)));
@@ -2658,7 +2646,7 @@
 TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamFail) {
   EXPECT_TRUE(SetupChannel());
   voe_.set_fail_create_channel(true);
-  EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
+  EXPECT_FALSE(AddRecvStream(2));
 }
 
 // Test that we properly handle failures to add a send stream.
@@ -2672,7 +2660,7 @@
 TEST_F(WebRtcVoiceEngineTestFake, AddRecvStream) {
   EXPECT_TRUE(SetupRecvStream());
   int channel_num = voe_.GetLastChannel();
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+  EXPECT_TRUE(AddRecvStream(1));
   EXPECT_NE(channel_num, voe_.GetLastChannel());
 }
 
@@ -2684,8 +2672,7 @@
   parameters.codecs.push_back(kIsacCodec);
   parameters.codecs.push_back(kPcmuCodec);
   EXPECT_TRUE(channel_->SetRecvParameters(parameters));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_num2 = voe_.GetLastChannel();
   webrtc::CodecInst gcodec;
   rtc::strcpyn(gcodec.plname, arraysize(gcodec.plname), "opus");
@@ -2699,8 +2686,8 @@
 TEST_F(WebRtcVoiceEngineTestFake, StreamCleanup) {
   EXPECT_TRUE(SetupSendStream());
   EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
+  EXPECT_TRUE(AddRecvStream(1));
+  EXPECT_TRUE(AddRecvStream(2));
   EXPECT_EQ(3, voe_.GetNumChannels());  // default channel + 2 added
   delete channel_;
   channel_ = NULL;
@@ -2709,17 +2696,17 @@
 
 TEST_F(WebRtcVoiceEngineTestFake, TestAddRecvStreamFailWithZeroSsrc) {
   EXPECT_TRUE(SetupSendStream());
-  EXPECT_FALSE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(0)));
+  EXPECT_FALSE(AddRecvStream(0));
 }
 
 TEST_F(WebRtcVoiceEngineTestFake, TestNoLeakingWhenAddRecvStreamFail) {
   EXPECT_TRUE(SetupChannel());
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+  EXPECT_TRUE(AddRecvStream(1));
   // Manually delete channel to simulate a failure.
   int channel = voe_.GetLastChannel();
   EXPECT_EQ(0, voe_.DeleteChannel(channel));
   // Add recv stream 2 should work.
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
+  EXPECT_TRUE(AddRecvStream(2));
   int new_channel = voe_.GetLastChannel();
   EXPECT_NE(channel, new_channel);
   // The last created channel is deleted too.
@@ -2750,8 +2737,8 @@
   EXPECT_TRUE(SetupSendStream());
   EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
   SetSend(channel_, true);
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(2)));
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
+  EXPECT_TRUE(AddRecvStream(2));
+  EXPECT_TRUE(AddRecvStream(3));
   EXPECT_TRUE(channel_->SetPlayout(true));
   voe_.set_playout_fail_channel(voe_.GetLastChannel() - 1);
   EXPECT_TRUE(channel_->SetPlayout(false));
@@ -3104,13 +3091,11 @@
   cricket::WebRtcVoiceMediaChannel* media_channel =
         static_cast<cricket::WebRtcVoiceMediaChannel*>(channel_);
   EXPECT_EQ(-1, media_channel->GetReceiveChannelId(0));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   int channel_id = voe_.GetLastChannel();
   EXPECT_EQ(channel_id, media_channel->GetReceiveChannelId(kSsrc1));
   EXPECT_EQ(-1, media_channel->GetReceiveChannelId(kSsrc2));
-  EXPECT_TRUE(channel_->AddRecvStream(
-      cricket::StreamParams::CreateLegacy(kSsrc2)));
+  EXPECT_TRUE(AddRecvStream(kSsrc2));
   int channel_id2 = voe_.GetLastChannel();
   EXPECT_EQ(channel_id2, media_channel->GetReceiveChannelId(kSsrc2));
 }
@@ -3268,13 +3253,13 @@
   EXPECT_TRUE(SetupSendStream());
   EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
   int default_channel = voe_.GetLastChannel();
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+  EXPECT_TRUE(AddRecvStream(1));
   int recv_ch = voe_.GetLastChannel();
   EXPECT_NE(recv_ch, default_channel);
   EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), default_channel);
   EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(2)));
   EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), default_channel);
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(3)));
+  EXPECT_TRUE(AddRecvStream(3));
   recv_ch = voe_.GetLastChannel();
   EXPECT_NE(recv_ch, default_channel);
   EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), default_channel);
@@ -3284,7 +3269,7 @@
   EXPECT_TRUE(SetupSendStream());
   EXPECT_TRUE(channel_->SetSendParameters(send_parameters_));
 
-  EXPECT_TRUE(channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(1)));
+  EXPECT_TRUE(AddRecvStream(1));
   int recv_ch = voe_.GetLastChannel();
 
   EXPECT_TRUE(channel_->AddSendStream(cricket::StreamParams::CreateLegacy(2)));
@@ -3309,8 +3294,7 @@
 
   // Setting the sink before a recv stream exists should do nothing.
   channel_->SetRawAudioSink(kSsrc1, std::move(fake_sink_1));
-  EXPECT_TRUE(
-      channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(AddRecvStream(kSsrc1));
   EXPECT_EQ(nullptr, GetRecvStream(kSsrc1).sink());
 
   // Now try actually setting the sink.