/*
 *  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/audio_send_stream.h"

#include <memory>
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include "api/task_queue/default_task_queue_factory.h"
#include "api/test/mock_frame_encryptor.h"
#include "audio/audio_state.h"
#include "audio/conversion.h"
#include "audio/mock_voe_channel_proxy.h"
#include "call/test/mock_rtp_transport_controller_send.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "modules/audio_device/include/mock_audio_device.h"
#include "modules/audio_mixer/audio_mixer_impl.h"
#include "modules/audio_mixer/sine_wave_generator.h"
#include "modules/audio_processing/include/audio_processing_statistics.h"
#include "modules/audio_processing/include/mock_audio_processing.h"
#include "modules/rtp_rtcp/mocks/mock_rtcp_bandwidth_observer.h"
#include "modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
#include "rtc_base/task_queue_for_test.h"
#include "system_wrappers/include/clock.h"
#include "test/field_trial.h"
#include "test/gtest.h"
#include "test/mock_audio_encoder.h"
#include "test/mock_audio_encoder_factory.h"

namespace webrtc {
namespace test {
namespace {

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Invoke;
using ::testing::Ne;
using ::testing::Return;
using ::testing::StrEq;

static const float kTolerance = 0.0001f;

const uint32_t kSsrc = 1234;
const char* kCName = "foo_name";
const int kAudioLevelId = 2;
const int kTransportSequenceNumberId = 4;
const int32_t kEchoDelayMedian = 254;
const int32_t kEchoDelayStdDev = -3;
const double kDivergentFilterFraction = 0.2f;
const double kEchoReturnLoss = -65;
const double kEchoReturnLossEnhancement = 101;
const double kResidualEchoLikelihood = -1.0f;
const double kResidualEchoLikelihoodMax = 23.0f;
const CallSendStatistics kCallStats = {112, 12, 13456, 17890};
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
const int kTelephoneEventPayloadType = 123;
const int kTelephoneEventPayloadFrequency = 65432;
const int kTelephoneEventCode = 45;
const int kTelephoneEventDuration = 6789;
constexpr int kIsacPayloadType = 103;
const SdpAudioFormat kIsacFormat = {"isac", 16000, 1};
const SdpAudioFormat kOpusFormat = {"opus", 48000, 2};
const SdpAudioFormat kG722Format = {"g722", 8000, 1};
const AudioCodecSpec kCodecSpecs[] = {
    {kIsacFormat, {16000, 1, 32000, 10000, 32000}},
    {kOpusFormat, {48000, 1, 32000, 6000, 510000}},
    {kG722Format, {16000, 1, 64000}}};

// TODO(dklee): This mirrors calculation in audio_send_stream.cc, which
// should be made more precise in the future. This can be changed when that
// logic is more accurate.
const DataSize kOverheadPerPacket = DataSize::Bytes(20 + 8 + 10 + 12);
const TimeDelta kMinFrameLength = TimeDelta::Millis(20);
const TimeDelta kMaxFrameLength = TimeDelta::Millis(120);
const DataRate kMinOverheadRate = kOverheadPerPacket / kMaxFrameLength;
const DataRate kMaxOverheadRate = kOverheadPerPacket / kMinFrameLength;

class MockLimitObserver : public BitrateAllocator::LimitObserver {
 public:
  MOCK_METHOD1(OnAllocationLimitsChanged, void(BitrateAllocationLimits));
};

std::unique_ptr<MockAudioEncoder> SetupAudioEncoderMock(
    int payload_type,
    const SdpAudioFormat& format) {
  for (const auto& spec : kCodecSpecs) {
    if (format == spec.format) {
      std::unique_ptr<MockAudioEncoder> encoder(
          new ::testing::NiceMock<MockAudioEncoder>());
      ON_CALL(*encoder.get(), SampleRateHz())
          .WillByDefault(Return(spec.info.sample_rate_hz));
      ON_CALL(*encoder.get(), NumChannels())
          .WillByDefault(Return(spec.info.num_channels));
      ON_CALL(*encoder.get(), RtpTimestampRateHz())
          .WillByDefault(Return(spec.format.clockrate_hz));
      ON_CALL(*encoder.get(), GetFrameLengthRange())
          .WillByDefault(Return(absl::optional<std::pair<TimeDelta, TimeDelta>>{
              {TimeDelta::Millis(20), TimeDelta::Millis(120)}}));
      return encoder;
    }
  }
  return nullptr;
}

rtc::scoped_refptr<MockAudioEncoderFactory> SetupEncoderFactoryMock() {
  rtc::scoped_refptr<MockAudioEncoderFactory> factory =
      new rtc::RefCountedObject<MockAudioEncoderFactory>();
  ON_CALL(*factory.get(), GetSupportedEncoders())
      .WillByDefault(Return(std::vector<AudioCodecSpec>(
          std::begin(kCodecSpecs), std::end(kCodecSpecs))));
  ON_CALL(*factory.get(), QueryAudioEncoder(_))
      .WillByDefault(Invoke(
          [](const SdpAudioFormat& format) -> absl::optional<AudioCodecInfo> {
            for (const auto& spec : kCodecSpecs) {
              if (format == spec.format) {
                return spec.info;
              }
            }
            return absl::nullopt;
          }));
  ON_CALL(*factory.get(), MakeAudioEncoderMock(_, _, _, _))
      .WillByDefault(Invoke([](int payload_type, const SdpAudioFormat& format,
                               absl::optional<AudioCodecPairId> codec_pair_id,
                               std::unique_ptr<AudioEncoder>* return_value) {
        *return_value = SetupAudioEncoderMock(payload_type, format);
      }));
  return factory;
}

struct ConfigHelper {
  ConfigHelper(bool audio_bwe_enabled, bool expect_set_encoder_call)
      : clock_(1000000),
        task_queue_factory_(CreateDefaultTaskQueueFactory()),
        stream_config_(/*send_transport=*/nullptr),
        audio_processing_(new rtc::RefCountedObject<MockAudioProcessing>()),
        bitrate_allocator_(&limit_observer_),
        worker_queue_(task_queue_factory_->CreateTaskQueue(
            "ConfigHelper_worker_queue",
            TaskQueueFactory::Priority::NORMAL)),
        audio_encoder_(nullptr) {
    using ::testing::Invoke;

    AudioState::Config config;
    config.audio_mixer = AudioMixerImpl::Create();
    config.audio_processing = audio_processing_;
    config.audio_device_module =
        new rtc::RefCountedObject<MockAudioDeviceModule>();
    audio_state_ = AudioState::Create(config);

    SetupDefaultChannelSend(audio_bwe_enabled);
    SetupMockForSetupSendCodec(expect_set_encoder_call);
    SetupMockForCallEncoder();

    // Use ISAC as default codec so as to prevent unnecessary |channel_proxy_|
    // calls from the default ctor behavior.
    stream_config_.send_codec_spec =
        AudioSendStream::Config::SendCodecSpec(kIsacPayloadType, kIsacFormat);
    stream_config_.rtp.ssrc = kSsrc;
    stream_config_.rtp.c_name = kCName;
    stream_config_.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
    if (audio_bwe_enabled) {
      AddBweToConfig(&stream_config_);
    }
    stream_config_.encoder_factory = SetupEncoderFactoryMock();
    stream_config_.min_bitrate_bps = 10000;
    stream_config_.max_bitrate_bps = 65000;
  }

  std::unique_ptr<internal::AudioSendStream> CreateAudioSendStream() {
    EXPECT_CALL(rtp_transport_, GetWorkerQueue())
        .WillRepeatedly(Return(&worker_queue_));
    return std::unique_ptr<internal::AudioSendStream>(
        new internal::AudioSendStream(
            Clock::GetRealTimeClock(), stream_config_, audio_state_,
            task_queue_factory_.get(), &rtp_transport_, &bitrate_allocator_,
            &event_log_, &rtcp_rtt_stats_, absl::nullopt,
            std::unique_ptr<voe::ChannelSendInterface>(channel_send_)));
  }

  AudioSendStream::Config& config() { return stream_config_; }
  MockAudioEncoderFactory& mock_encoder_factory() {
    return *static_cast<MockAudioEncoderFactory*>(
        stream_config_.encoder_factory.get());
  }
  MockRtpRtcp* rtp_rtcp() { return &rtp_rtcp_; }
  MockChannelSend* channel_send() { return channel_send_; }
  RtpTransportControllerSendInterface* transport() { return &rtp_transport_; }

  static void AddBweToConfig(AudioSendStream::Config* config) {
    config->rtp.extensions.push_back(RtpExtension(
        RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
    config->send_codec_spec->transport_cc_enabled = true;
  }

  void SetupDefaultChannelSend(bool audio_bwe_enabled) {
    EXPECT_TRUE(channel_send_ == nullptr);
    channel_send_ = new ::testing::StrictMock<MockChannelSend>();
    EXPECT_CALL(*channel_send_, GetRtpRtcp()).WillRepeatedly(Invoke([this]() {
      return &this->rtp_rtcp_;
    }));
    EXPECT_CALL(rtp_rtcp_, SSRC).WillRepeatedly(Return(kSsrc));
    EXPECT_CALL(*channel_send_, SetRTCP_CNAME(StrEq(kCName))).Times(1);
    EXPECT_CALL(*channel_send_, SetFrameEncryptor(_)).Times(1);
    EXPECT_CALL(rtp_rtcp_, SetExtmapAllowMixed(false)).Times(1);
    EXPECT_CALL(*channel_send_,
                SetSendAudioLevelIndicationStatus(true, kAudioLevelId))
        .Times(1);
    EXPECT_CALL(rtp_transport_, GetBandwidthObserver())
        .WillRepeatedly(Return(&bandwidth_observer_));
    if (audio_bwe_enabled) {
      EXPECT_CALL(rtp_rtcp_,
                  RegisterRtpHeaderExtension(TransportSequenceNumber::kUri,
                                             kTransportSequenceNumberId))
          .Times(1);
      EXPECT_CALL(*channel_send_,
                  RegisterSenderCongestionControlObjects(
                      &rtp_transport_, Eq(&bandwidth_observer_)))
          .Times(1);
    } else {
      EXPECT_CALL(*channel_send_, RegisterSenderCongestionControlObjects(
                                      &rtp_transport_, Eq(nullptr)))
          .Times(1);
    }
    EXPECT_CALL(*channel_send_, ResetSenderCongestionControlObjects()).Times(1);
    EXPECT_CALL(rtp_rtcp_, SetRid(std::string())).Times(1);
  }

  void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
    if (expect_set_encoder_call) {
      EXPECT_CALL(*channel_send_, SetEncoderForMock(_, _))
          .WillOnce(Invoke(
              [this](int payload_type, std::unique_ptr<AudioEncoder>* encoder) {
                this->audio_encoder_ = std::move(*encoder);
                return true;
              }));
    }
  }

  void SetupMockForCallEncoder() {
    // Let ModifyEncoder to invoke mock audio encoder.
    EXPECT_CALL(*channel_send_, CallEncoder(_))
        .WillRepeatedly(
            [this](rtc::FunctionView<void(AudioEncoder*)> modifier) {
              if (this->audio_encoder_)
                modifier(this->audio_encoder_.get());
            });
  }

  void SetupMockForSendTelephoneEvent() {
    EXPECT_TRUE(channel_send_);
    EXPECT_CALL(*channel_send_, SetSendTelephoneEventPayloadType(
                                    kTelephoneEventPayloadType,
                                    kTelephoneEventPayloadFrequency));
    EXPECT_CALL(
        *channel_send_,
        SendTelephoneEventOutband(kTelephoneEventCode, kTelephoneEventDuration))
        .WillOnce(Return(true));
  }

  void SetupMockForGetStats() {
    using ::testing::DoAll;
    using ::testing::SetArgPointee;
    using ::testing::SetArgReferee;

    std::vector<ReportBlock> report_blocks;
    webrtc::ReportBlock block = kReportBlock;
    report_blocks.push_back(block);  // Has wrong SSRC.
    block.source_SSRC = kSsrc;
    report_blocks.push_back(block);  // Correct block.
    block.fraction_lost = 0;
    report_blocks.push_back(block);  // Duplicate SSRC, bad fraction_lost.

    EXPECT_TRUE(channel_send_);
    EXPECT_CALL(*channel_send_, GetRTCPStatistics())
        .WillRepeatedly(Return(kCallStats));
    EXPECT_CALL(*channel_send_, GetRemoteRTCPReportBlocks())
        .WillRepeatedly(Return(report_blocks));
    EXPECT_CALL(*channel_send_, GetANAStatistics())
        .WillRepeatedly(Return(ANAStats()));
    EXPECT_CALL(*channel_send_, GetBitrate()).WillRepeatedly(Return(0));

    audio_processing_stats_.echo_return_loss = kEchoReturnLoss;
    audio_processing_stats_.echo_return_loss_enhancement =
        kEchoReturnLossEnhancement;
    audio_processing_stats_.delay_median_ms = kEchoDelayMedian;
    audio_processing_stats_.delay_standard_deviation_ms = kEchoDelayStdDev;
    audio_processing_stats_.divergent_filter_fraction =
        kDivergentFilterFraction;
    audio_processing_stats_.residual_echo_likelihood = kResidualEchoLikelihood;
    audio_processing_stats_.residual_echo_likelihood_recent_max =
        kResidualEchoLikelihoodMax;

    EXPECT_CALL(*audio_processing_, GetStatistics(true))
        .WillRepeatedly(Return(audio_processing_stats_));
  }
  TaskQueueForTest* worker() { return &worker_queue_; }

 private:
  SimulatedClock clock_;
  std::unique_ptr<TaskQueueFactory> task_queue_factory_;
  rtc::scoped_refptr<AudioState> audio_state_;
  AudioSendStream::Config stream_config_;
  ::testing::StrictMock<MockChannelSend>* channel_send_ = nullptr;
  rtc::scoped_refptr<MockAudioProcessing> audio_processing_;
  AudioProcessingStats audio_processing_stats_;
  ::testing::StrictMock<MockRtcpBandwidthObserver> bandwidth_observer_;
  ::testing::NiceMock<MockRtcEventLog> event_log_;
  ::testing::NiceMock<MockRtpTransportControllerSend> rtp_transport_;
  ::testing::NiceMock<MockRtpRtcp> rtp_rtcp_;
  MockRtcpRttStats rtcp_rtt_stats_;
  ::testing::NiceMock<MockLimitObserver> limit_observer_;
  BitrateAllocator bitrate_allocator_;
  // |worker_queue| is defined last to ensure all pending tasks are cancelled
  // and deleted before any other members.
  TaskQueueForTest worker_queue_;
  std::unique_ptr<AudioEncoder> audio_encoder_;
};

// The audio level ranges linearly [0,32767].
std::unique_ptr<AudioFrame> CreateAudioFrame1kHzSineWave(int16_t audio_level,
                                                         int duration_ms,
                                                         int sample_rate_hz,
                                                         size_t num_channels) {
  size_t samples_per_channel = sample_rate_hz / (1000 / duration_ms);
  std::vector<int16_t> audio_data(samples_per_channel * num_channels, 0);
  std::unique_ptr<AudioFrame> audio_frame = std::make_unique<AudioFrame>();
  audio_frame->UpdateFrame(0 /* RTP timestamp */, &audio_data[0],
                           samples_per_channel, sample_rate_hz,
                           AudioFrame::SpeechType::kNormalSpeech,
                           AudioFrame::VADActivity::kVadUnknown, num_channels);
  SineWaveGenerator wave_generator(1000.0, audio_level);
  wave_generator.GenerateNextFrame(audio_frame.get());
  return audio_frame;
}

}  // namespace

TEST(AudioSendStreamTest, ConfigToString) {
  AudioSendStream::Config config(/*send_transport=*/nullptr);
  config.rtp.ssrc = kSsrc;
  config.rtp.c_name = kCName;
  config.min_bitrate_bps = 12000;
  config.max_bitrate_bps = 34000;
  config.send_codec_spec =
      AudioSendStream::Config::SendCodecSpec(kIsacPayloadType, kIsacFormat);
  config.send_codec_spec->nack_enabled = true;
  config.send_codec_spec->transport_cc_enabled = false;
  config.send_codec_spec->cng_payload_type = 42;
  config.encoder_factory = MockAudioEncoderFactory::CreateUnusedFactory();
  config.rtp.extmap_allow_mixed = true;
  config.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
  config.rtcp_report_interval_ms = 2500;
  EXPECT_EQ(
      "{rtp: {ssrc: 1234, extmap-allow-mixed: true, extensions: [{uri: "
      "urn:ietf:params:rtp-hdrext:ssrc-audio-level, id: 2}], "
      "c_name: foo_name}, rtcp_report_interval_ms: 2500, "
      "send_transport: null, "
      "min_bitrate_bps: 12000, max_bitrate_bps: 34000, "
      "send_codec_spec: {nack_enabled: true, transport_cc_enabled: false, "
      "cng_payload_type: 42, payload_type: 103, "
      "format: {name: isac, clockrate_hz: 16000, num_channels: 1, "
      "parameters: {}}}}",
      config.ToString());
}

TEST(AudioSendStreamTest, ConstructDestruct) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
}

TEST(AudioSendStreamTest, SendTelephoneEvent) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  helper.SetupMockForSendTelephoneEvent();
  EXPECT_TRUE(send_stream->SendTelephoneEvent(
      kTelephoneEventPayloadType, kTelephoneEventPayloadFrequency,
      kTelephoneEventCode, kTelephoneEventDuration));
}

TEST(AudioSendStreamTest, SetMuted) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.channel_send(), SetInputMute(true));
  send_stream->SetMuted(true);
}

TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
}

TEST(AudioSendStreamTest, NoAudioBweCorrectObjectsOnChannelProxy) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
}

TEST(AudioSendStreamTest, GetStats) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  helper.SetupMockForGetStats();
  AudioSendStream::Stats stats = send_stream->GetStats(true);
  EXPECT_EQ(kSsrc, stats.local_ssrc);
  EXPECT_EQ(kCallStats.payload_bytes_sent, stats.payload_bytes_sent);
  EXPECT_EQ(kCallStats.header_and_padding_bytes_sent,
            stats.header_and_padding_bytes_sent);
  EXPECT_EQ(kCallStats.packetsSent, stats.packets_sent);
  EXPECT_EQ(kReportBlock.cumulative_num_packets_lost, stats.packets_lost);
  EXPECT_EQ(Q8ToFloat(kReportBlock.fraction_lost), stats.fraction_lost);
  EXPECT_EQ(kIsacFormat.name, stats.codec_name);
  EXPECT_EQ(static_cast<int32_t>(kReportBlock.interarrival_jitter /
                                 (kIsacFormat.clockrate_hz / 1000)),
            stats.jitter_ms);
  EXPECT_EQ(kCallStats.rttMs, stats.rtt_ms);
  EXPECT_EQ(0, stats.audio_level);
  EXPECT_EQ(0, stats.total_input_energy);
  EXPECT_EQ(0, stats.total_input_duration);
  EXPECT_EQ(kEchoDelayMedian, stats.apm_statistics.delay_median_ms);
  EXPECT_EQ(kEchoDelayStdDev, stats.apm_statistics.delay_standard_deviation_ms);
  EXPECT_EQ(kEchoReturnLoss, stats.apm_statistics.echo_return_loss);
  EXPECT_EQ(kEchoReturnLossEnhancement,
            stats.apm_statistics.echo_return_loss_enhancement);
  EXPECT_EQ(kDivergentFilterFraction,
            stats.apm_statistics.divergent_filter_fraction);
  EXPECT_EQ(kResidualEchoLikelihood,
            stats.apm_statistics.residual_echo_likelihood);
  EXPECT_EQ(kResidualEchoLikelihoodMax,
            stats.apm_statistics.residual_echo_likelihood_recent_max);
  EXPECT_FALSE(stats.typing_noise_detected);
}

TEST(AudioSendStreamTest, GetStatsAudioLevel) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  helper.SetupMockForGetStats();
  EXPECT_CALL(*helper.channel_send(), ProcessAndEncodeAudioForMock(_))
      .Times(AnyNumber());

  constexpr int kSampleRateHz = 48000;
  constexpr size_t kNumChannels = 1;

  constexpr int16_t kSilentAudioLevel = 0;
  constexpr int16_t kMaxAudioLevel = 32767;  // Audio level is [0,32767].
  constexpr int kAudioFrameDurationMs = 10;

  // Process 10 audio frames (100 ms) of silence. After this, on the next
  // (11-th) frame, the audio level will be updated with the maximum audio level
  // of the first 11 frames. See AudioLevel.
  for (size_t i = 0; i < 10; ++i) {
    send_stream->SendAudioData(CreateAudioFrame1kHzSineWave(
        kSilentAudioLevel, kAudioFrameDurationMs, kSampleRateHz, kNumChannels));
  }
  AudioSendStream::Stats stats = send_stream->GetStats();
  EXPECT_EQ(kSilentAudioLevel, stats.audio_level);
  EXPECT_NEAR(0.0f, stats.total_input_energy, kTolerance);
  EXPECT_NEAR(0.1f, stats.total_input_duration, kTolerance);  // 100 ms = 0.1 s

  // Process 10 audio frames (100 ms) of maximum audio level.
  // Note that AudioLevel updates the audio level every 11th frame, processing
  // 10 frames above was needed to see a non-zero audio level here.
  for (size_t i = 0; i < 10; ++i) {
    send_stream->SendAudioData(CreateAudioFrame1kHzSineWave(
        kMaxAudioLevel, kAudioFrameDurationMs, kSampleRateHz, kNumChannels));
  }
  stats = send_stream->GetStats();
  EXPECT_EQ(kMaxAudioLevel, stats.audio_level);
  // Energy increases by energy*duration, where energy is audio level in [0,1].
  EXPECT_NEAR(0.1f, stats.total_input_energy, kTolerance);    // 0.1 s of max
  EXPECT_NEAR(0.2f, stats.total_input_duration, kTolerance);  // 200 ms = 0.2 s
}

TEST(AudioSendStreamTest, SendCodecAppliesAudioNetworkAdaptor) {
  ConfigHelper helper(false, true);
  helper.config().send_codec_spec =
      AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
  const std::string kAnaConfigString = "abcde";
  const std::string kAnaReconfigString = "12345";

  helper.config().rtp.extensions.push_back(RtpExtension(
      RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
  helper.config().audio_network_adaptor_config = kAnaConfigString;

  EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
      .WillOnce(Invoke([&kAnaConfigString, &kAnaReconfigString](
                           int payload_type, const SdpAudioFormat& format,
                           absl::optional<AudioCodecPairId> codec_pair_id,
                           std::unique_ptr<AudioEncoder>* return_value) {
        auto mock_encoder = SetupAudioEncoderMock(payload_type, format);
        EXPECT_CALL(*mock_encoder,
                    EnableAudioNetworkAdaptor(StrEq(kAnaConfigString), _))
            .WillOnce(Return(true));
        EXPECT_CALL(*mock_encoder,
                    EnableAudioNetworkAdaptor(StrEq(kAnaReconfigString), _))
            .WillOnce(Return(true));
        *return_value = std::move(mock_encoder);
      }));

  auto send_stream = helper.CreateAudioSendStream();

  auto stream_config = helper.config();
  stream_config.audio_network_adaptor_config = kAnaReconfigString;

  send_stream->Reconfigure(stream_config);
}

// VAD is applied when codec is mono and the CNG frequency matches the codec
// clock rate.
TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
  ConfigHelper helper(false, false);
  helper.config().send_codec_spec =
      AudioSendStream::Config::SendCodecSpec(9, kG722Format);
  helper.config().send_codec_spec->cng_payload_type = 105;
  using ::testing::Invoke;
  std::unique_ptr<AudioEncoder> stolen_encoder;
  EXPECT_CALL(*helper.channel_send(), SetEncoderForMock(_, _))
      .WillOnce(
          Invoke([&stolen_encoder](int payload_type,
                                   std::unique_ptr<AudioEncoder>* encoder) {
            stolen_encoder = std::move(*encoder);
            return true;
          }));
  EXPECT_CALL(*helper.channel_send(), RegisterCngPayloadType(105, 8000));

  auto send_stream = helper.CreateAudioSendStream();

  // We cannot truly determine if the encoder created is an AudioEncoderCng.  It
  // is the only reasonable implementation that will return something from
  // ReclaimContainedEncoders, though.
  ASSERT_TRUE(stolen_encoder);
  EXPECT_FALSE(stolen_encoder->ReclaimContainedEncoders().empty());
}

TEST(AudioSendStreamTest, DoesNotPassHigherBitrateThanMaxBitrate) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.channel_send(),
              OnBitrateAllocation(Field(
                  &BitrateAllocationUpdate::target_bitrate,
                  Eq(DataRate::BitsPerSec(helper.config().max_bitrate_bps)))));
  BitrateAllocationUpdate update;
  update.target_bitrate =
      DataRate::BitsPerSec(helper.config().max_bitrate_bps + 5000);
  update.packet_loss_ratio = 0;
  update.round_trip_time = TimeDelta::Millis(50);
  update.bwe_period = TimeDelta::Millis(6000);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, SSBweTargetInRangeRespected) {
  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(
      *helper.channel_send(),
      OnBitrateAllocation(Field(
          &BitrateAllocationUpdate::target_bitrate,
          Eq(DataRate::BitsPerSec(helper.config().max_bitrate_bps - 5000)))));
  BitrateAllocationUpdate update;
  update.target_bitrate =
      DataRate::BitsPerSec(helper.config().max_bitrate_bps - 5000);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, SSBweFieldTrialMinRespected) {
  ScopedFieldTrials field_trials(
      "WebRTC-Audio-SendSideBwe/Enabled/"
      "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(
      *helper.channel_send(),
      OnBitrateAllocation(Field(&BitrateAllocationUpdate::target_bitrate,
                                Eq(DataRate::KilobitsPerSec(6)))));
  BitrateAllocationUpdate update;
  update.target_bitrate = DataRate::KilobitsPerSec(1);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, SSBweFieldTrialMaxRespected) {
  ScopedFieldTrials field_trials(
      "WebRTC-Audio-SendSideBwe/Enabled/"
      "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(
      *helper.channel_send(),
      OnBitrateAllocation(Field(&BitrateAllocationUpdate::target_bitrate,
                                Eq(DataRate::KilobitsPerSec(64)))));
  BitrateAllocationUpdate update;
  update.target_bitrate = DataRate::KilobitsPerSec(128);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, SSBweWithOverhead) {
  ScopedFieldTrials field_trials(
      "WebRTC-Audio-SendSideBwe/Enabled/"
      "WebRTC-SendSideBwe-WithOverhead/Enabled/"
      "WebRTC-Audio-LegacyOverhead/Disabled/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.channel_send(), CallEncoder(_)).Times(1);
  send_stream->OnOverheadChanged(kOverheadPerPacket.bytes<size_t>());
  const DataRate bitrate =
      DataRate::BitsPerSec(helper.config().max_bitrate_bps) + kMaxOverheadRate;
  EXPECT_CALL(*helper.channel_send(),
              OnBitrateAllocation(Field(
                  &BitrateAllocationUpdate::target_bitrate, Eq(bitrate))));
  BitrateAllocationUpdate update;
  update.target_bitrate = bitrate;
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, SSBweWithOverheadMinRespected) {
  ScopedFieldTrials field_trials(
      "WebRTC-Audio-SendSideBwe/Enabled/"
      "WebRTC-SendSideBwe-WithOverhead/Enabled/"
      "WebRTC-Audio-LegacyOverhead/Disabled/"
      "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.channel_send(), CallEncoder(_)).Times(1);
  send_stream->OnOverheadChanged(kOverheadPerPacket.bytes<size_t>());
  const DataRate bitrate = DataRate::KilobitsPerSec(6) + kMinOverheadRate;
  EXPECT_CALL(*helper.channel_send(),
              OnBitrateAllocation(Field(
                  &BitrateAllocationUpdate::target_bitrate, Eq(bitrate))));
  BitrateAllocationUpdate update;
  update.target_bitrate = DataRate::KilobitsPerSec(1);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, SSBweWithOverheadMaxRespected) {
  ScopedFieldTrials field_trials(
      "WebRTC-Audio-SendSideBwe/Enabled/"
      "WebRTC-SendSideBwe-WithOverhead/Enabled/"
      "WebRTC-Audio-LegacyOverhead/Disabled/"
      "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
  ConfigHelper helper(true, true);
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.channel_send(), CallEncoder(_)).Times(1);
  send_stream->OnOverheadChanged(kOverheadPerPacket.bytes<size_t>());
  const DataRate bitrate = DataRate::KilobitsPerSec(64) + kMaxOverheadRate;
  EXPECT_CALL(*helper.channel_send(),
              OnBitrateAllocation(Field(
                  &BitrateAllocationUpdate::target_bitrate, Eq(bitrate))));
  BitrateAllocationUpdate update;
  update.target_bitrate = DataRate::KilobitsPerSec(128);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

TEST(AudioSendStreamTest, ProbingIntervalOnBitrateUpdated) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();

  EXPECT_CALL(*helper.channel_send(),
              OnBitrateAllocation(Field(&BitrateAllocationUpdate::bwe_period,
                                        Eq(TimeDelta::Millis(5000)))));
  BitrateAllocationUpdate update;
  update.target_bitrate =
      DataRate::BitsPerSec(helper.config().max_bitrate_bps + 5000);
  update.packet_loss_ratio = 0;
  update.round_trip_time = TimeDelta::Millis(50);
  update.bwe_period = TimeDelta::Millis(5000);
  helper.worker()->SendTask([&] { send_stream->OnBitrateUpdated(update); },
                            RTC_FROM_HERE);
}

// Test that AudioSendStream doesn't recreate the encoder unnecessarily.
TEST(AudioSendStreamTest, DontRecreateEncoder) {
  ConfigHelper helper(false, false);
  // WillOnce is (currently) the default used by ConfigHelper if asked to set an
  // expectation for SetEncoder. Since this behavior is essential for this test
  // to be correct, it's instead set-up manually here. Otherwise a simple change
  // to ConfigHelper (say to WillRepeatedly) would silently make this test
  // useless.
  EXPECT_CALL(*helper.channel_send(), SetEncoderForMock(_, _))
      .WillOnce(Return());

  EXPECT_CALL(*helper.channel_send(), RegisterCngPayloadType(105, 8000));

  helper.config().send_codec_spec =
      AudioSendStream::Config::SendCodecSpec(9, kG722Format);
  helper.config().send_codec_spec->cng_payload_type = 105;
  auto send_stream = helper.CreateAudioSendStream();
  send_stream->Reconfigure(helper.config());
}

TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  auto new_config = helper.config();
  ConfigHelper::AddBweToConfig(&new_config);

  EXPECT_CALL(*helper.rtp_rtcp(),
              RegisterRtpHeaderExtension(TransportSequenceNumber::kUri,
                                         kTransportSequenceNumberId))
      .Times(1);
  {
    ::testing::InSequence seq;
    EXPECT_CALL(*helper.channel_send(), ResetSenderCongestionControlObjects())
        .Times(1);
    EXPECT_CALL(*helper.channel_send(), RegisterSenderCongestionControlObjects(
                                            helper.transport(), Ne(nullptr)))
        .Times(1);
  }

  send_stream->Reconfigure(new_config);
}

TEST(AudioSendStreamTest, OnTransportOverheadChanged) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  auto new_config = helper.config();

  // CallEncoder will be called on overhead change.
  EXPECT_CALL(*helper.channel_send(), CallEncoder(::testing::_)).Times(1);

  const size_t transport_overhead_per_packet_bytes = 333;
  send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);

  EXPECT_EQ(transport_overhead_per_packet_bytes,
            send_stream->TestOnlyGetPerPacketOverheadBytes());
}

TEST(AudioSendStreamTest, OnAudioOverheadChanged) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  auto new_config = helper.config();

  // CallEncoder will be called on overhead change.
  EXPECT_CALL(*helper.channel_send(), CallEncoder(::testing::_)).Times(1);

  const size_t audio_overhead_per_packet_bytes = 555;
  send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
  EXPECT_EQ(audio_overhead_per_packet_bytes,
            send_stream->TestOnlyGetPerPacketOverheadBytes());
}

TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  auto new_config = helper.config();

  // CallEncoder will be called when each of overhead changes.
  EXPECT_CALL(*helper.channel_send(), CallEncoder(::testing::_)).Times(2);

  const size_t transport_overhead_per_packet_bytes = 333;
  send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);

  const size_t audio_overhead_per_packet_bytes = 555;
  send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);

  EXPECT_EQ(
      transport_overhead_per_packet_bytes + audio_overhead_per_packet_bytes,
      send_stream->TestOnlyGetPerPacketOverheadBytes());
}

// Validates that reconfiguring the AudioSendStream with a Frame encryptor
// correctly reconfigures on the object without crashing.
TEST(AudioSendStreamTest, ReconfigureWithFrameEncryptor) {
  ConfigHelper helper(false, true);
  auto send_stream = helper.CreateAudioSendStream();
  auto new_config = helper.config();

  rtc::scoped_refptr<FrameEncryptorInterface> mock_frame_encryptor_0(
      new rtc::RefCountedObject<MockFrameEncryptor>());
  new_config.frame_encryptor = mock_frame_encryptor_0;
  EXPECT_CALL(*helper.channel_send(), SetFrameEncryptor(Ne(nullptr))).Times(1);
  send_stream->Reconfigure(new_config);

  // Not updating the frame encryptor shouldn't force it to reconfigure.
  EXPECT_CALL(*helper.channel_send(), SetFrameEncryptor(_)).Times(0);
  send_stream->Reconfigure(new_config);

  // Updating frame encryptor to a new object should force a call to the proxy.
  rtc::scoped_refptr<FrameEncryptorInterface> mock_frame_encryptor_1(
      new rtc::RefCountedObject<MockFrameEncryptor>());
  new_config.frame_encryptor = mock_frame_encryptor_1;
  new_config.crypto_options.sframe.require_frame_encryption = true;
  EXPECT_CALL(*helper.channel_send(), SetFrameEncryptor(Ne(nullptr))).Times(1);
  send_stream->Reconfigure(new_config);
}
}  // namespace test
}  // namespace webrtc
