/*
 *  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/audio/audio_processing_statistics.h"
#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_bitrate_allocator.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/mock_audio_processing.h"
#include "modules/rtp_rtcp/mocks/mock_network_link_rtcp_observer.h"
#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
#include "system_wrappers/include/clock.h"
#include "test/gtest.h"
#include "test/mock_audio_encoder.h"
#include "test/mock_audio_encoder_factory.h"
#include "test/scoped_key_value_config.h"
#include "test/time_controller/real_time_controller.h"

namespace webrtc {
namespace test {
namespace {

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Eq;
using ::testing::Field;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Ne;
using ::testing::NiceMock;
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};
constexpr int kFractionLost = 123;
constexpr int kCumulativeLost = 567;
constexpr uint32_t kInterarrivalJitter = 132;
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_METHOD(void,
              OnAllocationLimitsChanged,
              (BitrateAllocationLimits),
              (override));
};

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 =
      rtc::make_ref_counted<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,
               bool use_null_audio_processing)
      : stream_config_(/*send_transport=*/nullptr),
        audio_processing_(
            use_null_audio_processing
                ? nullptr
                : rtc::make_ref_counted<NiceMock<MockAudioProcessing>>()),
        audio_encoder_(nullptr) {
    using ::testing::Invoke;

    AudioState::Config config;
    config.audio_mixer = AudioMixerImpl::Create();
    config.audio_processing = audio_processing_;
    config.audio_device_module = rtc::make_ref_counted<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() {
    return std::unique_ptr<internal::AudioSendStream>(
        new internal::AudioSendStream(
            time_controller_.GetClock(), stream_config_, audio_state_,
            time_controller_.GetTaskQueueFactory(), &rtp_transport_,
            &bitrate_allocator_, &event_log_, absl::nullopt,
            std::unique_ptr<voe::ChannelSendInterface>(channel_send_),
            field_trials));
  }

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

  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(*channel_send_, SetEncoderToPacketizerFrameTransformer(_))
        .Times(1);
    EXPECT_CALL(rtp_rtcp_, SetExtmapAllowMixed(false)).Times(1);
    EXPECT_CALL(*channel_send_,
                SetSendAudioLevelIndicationStatus(true, kAudioLevelId))
        .Times(1);
    EXPECT_CALL(rtp_transport_, GetRtcpObserver)
        .WillRepeatedly(Return(&rtcp_observer_));
    if (audio_bwe_enabled) {
      EXPECT_CALL(rtp_rtcp_,
                  RegisterRtpHeaderExtension(TransportSequenceNumber::Uri(),
                                             kTransportSequenceNumberId))
          .Times(1);
    }
    EXPECT_CALL(*channel_send_,
                RegisterSenderCongestionControlObjects(&rtp_transport_))
        .Times(1);
    EXPECT_CALL(*channel_send_, ResetSenderCongestionControlObjects()).Times(1);
  }

  void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
    if (expect_set_encoder_call) {
      EXPECT_CALL(*channel_send_, SetEncoder)
          .WillOnce([this](int payload_type, const SdpAudioFormat& format,
                           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(bool use_null_audio_processing) {
    using ::testing::DoAll;
    using ::testing::SetArgPointee;
    using ::testing::SetArgReferee;

    std::vector<ReportBlockData> report_blocks;
    ReportBlockData block;
    block.set_source_ssrc(780);
    block.set_fraction_lost_raw(kFractionLost);
    block.set_cumulative_lost(kCumulativeLost);
    block.set_jitter(kInterarrivalJitter);
    report_blocks.push_back(block);  // Has wrong SSRC.
    block.set_source_ssrc(kSsrc);
    report_blocks.push_back(block);  // Correct block.
    block.set_fraction_lost_raw(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_, GetTargetBitrate()).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;
    if (!use_null_audio_processing) {
      ASSERT_TRUE(audio_processing_);
      EXPECT_CALL(*audio_processing_, GetStatistics(true))
          .WillRepeatedly(Return(audio_processing_stats_));
    }
  }

  test::ScopedKeyValueConfig field_trials;

 private:
  RealTimeController time_controller_;
  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<MockNetworkLinkRtcpObserver> rtcp_observer_;
  ::testing::NiceMock<MockRtcEventLog> event_log_;
  ::testing::NiceMock<MockRtpTransportControllerSend> rtp_transport_;
  ::testing::NiceMock<MockRtpRtcpInterface> rtp_rtcp_;
  ::testing::NiceMock<MockLimitObserver> limit_observer_;
  ::testing::NiceMock<MockBitrateAllocator> bitrate_allocator_;
  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.has_dscp = true;
  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.send_codec_spec->red_payload_type = 43;
  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, has "
      "audio_network_adaptor_config: false, has_dscp: true, "
      "send_codec_spec: {nack_enabled: true, transport_cc_enabled: false, "
      "enable_non_sender_rtt: false, cng_payload_type: 42, "
      "red_payload_type: 43, payload_type: 103, "
      "format: {name: isac, clockrate_hz: 16000, num_channels: 1, "
      "parameters: {}}}}",
      config.ToString());
}

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

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

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

TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
  }
}

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

TEST(AudioSendStreamTest, GetStats) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
    helper.SetupMockForGetStats(use_null_audio_processing);
    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(stats.packets_lost, kCumulativeLost);
    EXPECT_FLOAT_EQ(stats.fraction_lost, Q8ToFloat(kFractionLost));
    EXPECT_EQ(kIsacFormat.name, stats.codec_name);
    EXPECT_EQ(stats.jitter_ms,
              static_cast<int32_t>(kInterarrivalJitter /
                                   (kIsacFormat.clockrate_hz / 1000)));
    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);

    if (!use_null_audio_processing) {
      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);
    }
  }
}

TEST(AudioSendStreamTest, GetStatsAudioLevel) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
    helper.SetupMockForGetStats(use_null_audio_processing);
    EXPECT_CALL(*helper.channel_send(), ProcessAndEncodeAudio)
        .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) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    helper.config().send_codec_spec =
        AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
    const std::string kAnaConfigString = "abcde";
    const std::string kAnaReconfigString = "12345";

    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, nullptr);
  }
}

TEST(AudioSendStreamTest, AudioNetworkAdaptorReceivesOverhead) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    helper.config().send_codec_spec =
        AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
    const std::string kAnaConfigString = "abcde";

    EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
        .WillOnce(Invoke(
            [&kAnaConfigString](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);
              InSequence s;
              EXPECT_CALL(
                  *mock_encoder,
                  OnReceivedOverhead(Eq(kOverheadPerPacket.bytes<size_t>())));
              EXPECT_CALL(*mock_encoder,
                          EnableAudioNetworkAdaptor(StrEq(kAnaConfigString), _))
                  .WillOnce(Return(true));
              // Note: Overhead is received AFTER ANA has been enabled.
              EXPECT_CALL(
                  *mock_encoder,
                  OnReceivedOverhead(Eq(kOverheadPerPacket.bytes<size_t>())))
                  .WillOnce(Return());
              *return_value = std::move(mock_encoder);
            }));
    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));

    auto send_stream = helper.CreateAudioSendStream();

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

    send_stream->Reconfigure(stream_config, nullptr);
  }
}

// VAD is applied when codec is mono and the CNG frequency matches the codec
// clock rate.
TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, false, use_null_audio_processing);
    helper.config().send_codec_spec =
        AudioSendStream::Config::SendCodecSpec(9, kG722Format);
    helper.config().send_codec_spec->cng_payload_type = 105;
    std::unique_ptr<AudioEncoder> stolen_encoder;
    EXPECT_CALL(*helper.channel_send(), SetEncoder)
        .WillOnce([&stolen_encoder](int payload_type,
                                    const SdpAudioFormat& format,
                                    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) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, SSBweTargetInRangeRespected) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, SSBweFieldTrialMinRespected) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    ScopedKeyValueConfig field_trials(
        helper.field_trials, "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, SSBweFieldTrialMaxRespected) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    ScopedKeyValueConfig field_trials(
        helper.field_trials, "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, SSBweWithOverhead) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    ScopedKeyValueConfig field_trials(helper.field_trials,
                                      "WebRTC-Audio-LegacyOverhead/Disabled/");
    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
    auto send_stream = helper.CreateAudioSendStream();
    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;
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, SSBweWithOverheadMinRespected) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    ScopedKeyValueConfig field_trials(
        helper.field_trials,
        "WebRTC-Audio-LegacyOverhead/Disabled/"
        "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
    auto send_stream = helper.CreateAudioSendStream();
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, SSBweWithOverheadMaxRespected) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(true, true, use_null_audio_processing);
    ScopedKeyValueConfig field_trials(
        helper.field_trials,
        "WebRTC-Audio-LegacyOverhead/Disabled/"
        "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
    auto send_stream = helper.CreateAudioSendStream();
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

TEST(AudioSendStreamTest, ProbingIntervalOnBitrateUpdated) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    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);
    send_stream->OnBitrateUpdated(update);
  }
}

// Test that AudioSendStream doesn't recreate the encoder unnecessarily.
TEST(AudioSendStreamTest, DontRecreateEncoder) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, false, use_null_audio_processing);
    // 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(), SetEncoder).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(), nullptr);
  }
}

TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
    auto new_config = helper.config();
    ConfigHelper::AddBweToConfig(&new_config);

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

    send_stream->Reconfigure(new_config, nullptr);
  }
}

TEST(AudioSendStreamTest, OnTransportOverheadChanged) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
    auto new_config = helper.config();

    // CallEncoder will be called on overhead change.
    EXPECT_CALL(*helper.channel_send(), CallEncoder);

    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, DoesntCallEncoderWhenOverheadUnchanged) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
    auto new_config = helper.config();

    // CallEncoder will be called on overhead change.
    EXPECT_CALL(*helper.channel_send(), CallEncoder);
    const size_t transport_overhead_per_packet_bytes = 333;
    send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);

    // Set the same overhead again, CallEncoder should not be called again.
    EXPECT_CALL(*helper.channel_send(), CallEncoder).Times(0);
    send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);

    // New overhead, call CallEncoder again
    EXPECT_CALL(*helper.channel_send(), CallEncoder);
    send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes + 1);
  }
}

TEST(AudioSendStreamTest, AudioOverheadChanged) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    const size_t audio_overhead_per_packet_bytes = 555;
    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(audio_overhead_per_packet_bytes));
    auto send_stream = helper.CreateAudioSendStream();

    BitrateAllocationUpdate update;
    update.target_bitrate =
        DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
        kMaxOverheadRate;
    EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
    send_stream->OnBitrateUpdated(update);

    EXPECT_EQ(audio_overhead_per_packet_bytes,
              send_stream->TestOnlyGetPerPacketOverheadBytes());

    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(audio_overhead_per_packet_bytes + 20));
    // RTP overhead can only change in response to RTCP or configuration change.
    send_stream->Reconfigure(helper.config(), nullptr);
    EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
    send_stream->OnBitrateUpdated(update);

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

TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    const size_t audio_overhead_per_packet_bytes = 555;
    EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
        .WillRepeatedly(Return(audio_overhead_per_packet_bytes));
    auto send_stream = helper.CreateAudioSendStream();
    auto new_config = helper.config();

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

    BitrateAllocationUpdate update;
    update.target_bitrate =
        DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
        kMaxOverheadRate;
    EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
    send_stream->OnBitrateUpdated(update);

    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) {
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(false, true, use_null_audio_processing);
    auto send_stream = helper.CreateAudioSendStream();
    auto new_config = helper.config();

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

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

    // Updating frame encryptor to a new object should force a call to the
    // proxy.
    rtc::scoped_refptr<FrameEncryptorInterface> mock_frame_encryptor_1(
        rtc::make_ref_counted<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, nullptr);
  }
}

TEST(AudioSendStreamTest, DefaultsHonorsPriorityBitrate) {
  ConfigHelper helper(true, true, true);
  ScopedKeyValueConfig field_trials(helper.field_trials,
                                    "WebRTC-Audio-Allocation/prio_rate:20/");
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _))
      .WillOnce(Invoke(
          [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
            EXPECT_EQ(config.priority_bitrate_bps, 20000);
          }));
  EXPECT_CALL(*helper.channel_send(), StartSend());
  send_stream->Start();
  EXPECT_CALL(*helper.channel_send(), StopSend());
  send_stream->Stop();
}

TEST(AudioSendStreamTest, OverridesPriorityBitrate) {
  ConfigHelper helper(true, true, true);
  ScopedKeyValueConfig field_trials(helper.field_trials,
                                    "WebRTC-Audio-Allocation/prio_rate:20/"
                                    "WebRTC-Audio-PriorityBitrate/Disabled/");
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _))
      .WillOnce(Invoke(
          [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
            EXPECT_EQ(config.priority_bitrate_bps, 0);
          }));
  EXPECT_CALL(*helper.channel_send(), StartSend());
  send_stream->Start();
  EXPECT_CALL(*helper.channel_send(), StopSend());
  send_stream->Stop();
}

TEST(AudioSendStreamTest, UseEncoderBitrateRange) {
  ConfigHelper helper(true, true, true);
  std::pair<DataRate, DataRate> bitrate_range{DataRate::BitsPerSec(5000),
                                              DataRate::BitsPerSec(10000)};
  EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
      .WillOnce(Invoke([&](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, GetBitrateRange())
            .WillRepeatedly(Return(bitrate_range));
        *return_value = std::move(mock_encoder);
      }));
  auto send_stream = helper.CreateAudioSendStream();
  EXPECT_CALL(*helper.bitrate_allocator(), AddObserver(send_stream.get(), _))
      .WillOnce(Invoke(
          [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
            EXPECT_EQ(config.min_bitrate_bps, bitrate_range.first.bps());
            EXPECT_EQ(config.max_bitrate_bps, bitrate_range.second.bps());
          }));
  EXPECT_CALL(*helper.channel_send(), StartSend());
  send_stream->Start();
  EXPECT_CALL(*helper.channel_send(), StopSend());
  send_stream->Stop();
}

}  // namespace test
}  // namespace webrtc
