/*  Copyright (c) 2014 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 "modules/video_coding/timing/jitter_estimator.h"

#include <stdint.h>

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

#include "api/field_trials.h"
#include "api/units/data_size.h"
#include "api/units/frequency.h"
#include "api/units/time_delta.h"
#include "rtc_base/numerics/histogram_percentile_counter.h"
#include "system_wrappers/include/clock.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

// Generates some simple test data in the form of a sawtooth wave.
class ValueGenerator {
 public:
  explicit ValueGenerator(int32_t amplitude)
      : amplitude_(amplitude), counter_(0) {}

  virtual ~ValueGenerator() = default;

  TimeDelta Delay() const {
    return TimeDelta::Millis((counter_ % 11) - 5) * amplitude_;
  }

  DataSize FrameSize() const {
    return DataSize::Bytes(1000 + Delay().ms() / 5);
  }

  void Advance() { ++counter_; }

 private:
  const int32_t amplitude_;
  int64_t counter_;
};

class JitterEstimatorTest : public ::testing::Test {
 protected:
  explicit JitterEstimatorTest(const std::string& field_trials)
      : fake_clock_(0),
        field_trials_(FieldTrials::CreateNoGlobal(field_trials)),
        estimator_(&fake_clock_, *field_trials_) {}
  JitterEstimatorTest() : JitterEstimatorTest("") {}
  virtual ~JitterEstimatorTest() {}

  void Run(int duration_s, int framerate_fps, ValueGenerator& gen) {
    TimeDelta tick = 1 / Frequency::Hertz(framerate_fps);
    for (int i = 0; i < duration_s * framerate_fps; ++i) {
      estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
      fake_clock_.AdvanceTime(tick);
      gen.Advance();
    }
  }

  SimulatedClock fake_clock_;
  std::unique_ptr<FieldTrials> field_trials_;
  JitterEstimator estimator_;
};

TEST_F(JitterEstimatorTest, SteadyStateConvergence) {
  ValueGenerator gen(10);
  Run(/*duration_s=*/60, /*framerate_fps=*/30, gen);
  EXPECT_EQ(estimator_.GetJitterEstimate(0, std::nullopt).ms(), 54);
}

TEST_F(JitterEstimatorTest,
       SizeOutlierIsNotRejectedAndIncreasesJitterEstimate) {
  ValueGenerator gen(10);

  // Steady state.
  Run(/*duration_s=*/60, /*framerate_fps=*/30, gen);
  TimeDelta steady_state_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // A single outlier frame size...
  estimator_.UpdateEstimate(gen.Delay(), 10 * gen.FrameSize());
  TimeDelta outlier_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // ...changes the estimate.
  EXPECT_GT(outlier_jitter.ms(), 1.25 * steady_state_jitter.ms());
}

TEST_F(JitterEstimatorTest, LowFramerateDisablesJitterEstimator) {
  ValueGenerator gen(10);
  // At 5 fps, we disable jitter delay altogether.
  TimeDelta time_delta = 1 / Frequency::Hertz(5);
  for (int i = 0; i < 60; ++i) {
    estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
    fake_clock_.AdvanceTime(time_delta);
    if (i > 2)
      EXPECT_EQ(estimator_.GetJitterEstimate(0, std::nullopt),
                TimeDelta::Zero());
    gen.Advance();
  }
}

TEST_F(JitterEstimatorTest, RttMultAddCap) {
  std::vector<std::pair<TimeDelta, HistogramPercentileCounter>>
      jitter_by_rtt_mult_cap;
  jitter_by_rtt_mult_cap.emplace_back(
      /*rtt_mult_add_cap=*/TimeDelta::Millis(10), /*long_tail_boundary=*/1000);
  jitter_by_rtt_mult_cap.emplace_back(
      /*rtt_mult_add_cap=*/TimeDelta::Millis(200), /*long_tail_boundary=*/1000);

  for (auto& [rtt_mult_add_cap, jitter] : jitter_by_rtt_mult_cap) {
    estimator_.Reset();

    ValueGenerator gen(50);
    TimeDelta time_delta = 1 / Frequency::Hertz(30);
    constexpr TimeDelta kRtt = TimeDelta::Millis(250);
    for (int i = 0; i < 100; ++i) {
      estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
      fake_clock_.AdvanceTime(time_delta);
      estimator_.FrameNacked();
      estimator_.UpdateRtt(kRtt);
      jitter.Add(
          estimator_.GetJitterEstimate(/*rtt_mult=*/1.0, rtt_mult_add_cap)
              .ms());
      gen.Advance();
    }
  }

  // 200ms cap should result in at least 25% higher max compared to 10ms.
  EXPECT_GT(*jitter_by_rtt_mult_cap[1].second.GetPercentile(1.0),
            *jitter_by_rtt_mult_cap[0].second.GetPercentile(1.0) * 1.25);
}

// By default, the `JitterEstimator` is not robust against single large frames.
TEST_F(JitterEstimatorTest, Single2xFrameSizeImpactsJitterEstimate) {
  ValueGenerator gen(10);

  // Steady state.
  Run(/*duration_s=*/60, /*framerate_fps=*/30, gen);
  TimeDelta steady_state_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // A single outlier frame size...
  estimator_.UpdateEstimate(gen.Delay(), 2 * gen.FrameSize());
  TimeDelta outlier_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // ...impacts the estimate.
  EXPECT_GT(outlier_jitter.ms(), steady_state_jitter.ms());
}

// Under the default config, congested frames are used when calculating the
// noise variance, meaning that they will impact the final jitter estimate.
TEST_F(JitterEstimatorTest, CongestedFrameImpactsJitterEstimate) {
  ValueGenerator gen(10);

  // Steady state.
  Run(/*duration_s=*/10, /*framerate_fps=*/30, gen);
  TimeDelta steady_state_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // Congested frame...
  estimator_.UpdateEstimate(-10 * gen.Delay(), 0.1 * gen.FrameSize());
  TimeDelta outlier_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // ...impacts the estimate.
  EXPECT_GT(outlier_jitter.ms(), steady_state_jitter.ms());
}

TEST_F(JitterEstimatorTest, EmptyFieldTrialsParsesToUnsetConfig) {
  JitterEstimator::Config config = estimator_.GetConfigForTest();
  EXPECT_FALSE(config.avg_frame_size_median);
  EXPECT_FALSE(config.max_frame_size_percentile.has_value());
  EXPECT_FALSE(config.frame_size_window.has_value());
  EXPECT_FALSE(config.num_stddev_delay_clamp.has_value());
  EXPECT_FALSE(config.num_stddev_delay_outlier.has_value());
  EXPECT_FALSE(config.num_stddev_size_outlier.has_value());
  EXPECT_FALSE(config.congestion_rejection_factor.has_value());
  EXPECT_TRUE(config.estimate_noise_when_congested);
}

class FieldTrialsOverriddenJitterEstimatorTest : public JitterEstimatorTest {
 protected:
  FieldTrialsOverriddenJitterEstimatorTest()
      : JitterEstimatorTest(
            "WebRTC-JitterEstimatorConfig/"
            "avg_frame_size_median:true,"
            "max_frame_size_percentile:0.9,"
            "frame_size_window:30,"
            "num_stddev_delay_clamp:1.1,"
            "num_stddev_delay_outlier:2,"
            "num_stddev_size_outlier:3.1,"
            "congestion_rejection_factor:-1.55,"
            "estimate_noise_when_congested:false/") {}
  ~FieldTrialsOverriddenJitterEstimatorTest() {}
};

TEST_F(FieldTrialsOverriddenJitterEstimatorTest, FieldTrialsParsesCorrectly) {
  JitterEstimator::Config config = estimator_.GetConfigForTest();
  EXPECT_TRUE(config.avg_frame_size_median);
  EXPECT_EQ(*config.max_frame_size_percentile, 0.9);
  EXPECT_EQ(*config.frame_size_window, 30);
  EXPECT_EQ(*config.num_stddev_delay_clamp, 1.1);
  EXPECT_EQ(*config.num_stddev_delay_outlier, 2.0);
  EXPECT_EQ(*config.num_stddev_size_outlier, 3.1);
  EXPECT_EQ(*config.congestion_rejection_factor, -1.55);
  EXPECT_FALSE(config.estimate_noise_when_congested);
}

TEST_F(FieldTrialsOverriddenJitterEstimatorTest,
       DelayOutlierIsRejectedAndMaintainsJitterEstimate) {
  ValueGenerator gen(10);

  // Steady state.
  Run(/*duration_s=*/60, /*framerate_fps=*/30, gen);
  TimeDelta steady_state_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // A single outlier frame size...
  estimator_.UpdateEstimate(10 * gen.Delay(), gen.FrameSize());
  TimeDelta outlier_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // ...does not change the estimate.
  EXPECT_EQ(outlier_jitter.ms(), steady_state_jitter.ms());
}

// The field trial is configured to be robust against the `(1 - 0.9) = 10%`
// largest frames over a window of length `30`.
TEST_F(FieldTrialsOverriddenJitterEstimatorTest,
       Four2xFrameSizesImpactJitterEstimate) {
  ValueGenerator gen(10);

  // Steady state.
  Run(/*duration_s=*/60, /*framerate_fps=*/30, gen);
  TimeDelta steady_state_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // Three outlier frames do not impact the jitter estimate.
  for (int i = 0; i < 3; ++i) {
    estimator_.UpdateEstimate(gen.Delay(), 2 * gen.FrameSize());
  }
  TimeDelta outlier_jitter_3x = estimator_.GetJitterEstimate(0, std::nullopt);
  EXPECT_EQ(outlier_jitter_3x.ms(), steady_state_jitter.ms());

  // Four outlier frames do impact the jitter estimate.
  estimator_.UpdateEstimate(gen.Delay(), 2 * gen.FrameSize());
  TimeDelta outlier_jitter_4x = estimator_.GetJitterEstimate(0, std::nullopt);
  EXPECT_GT(outlier_jitter_4x.ms(), outlier_jitter_3x.ms());
}

// When so configured, congested frames are NOT used when calculating the
// noise variance, meaning that they will NOT impact the final jitter estimate.
TEST_F(FieldTrialsOverriddenJitterEstimatorTest,
       CongestedFrameDoesNotImpactJitterEstimate) {
  ValueGenerator gen(10);

  // Steady state.
  Run(/*duration_s=*/10, /*framerate_fps=*/30, gen);
  TimeDelta steady_state_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // Congested frame...
  estimator_.UpdateEstimate(-10 * gen.Delay(), 0.1 * gen.FrameSize());
  TimeDelta outlier_jitter = estimator_.GetJitterEstimate(0, std::nullopt);

  // ...does not impact the estimate.
  EXPECT_EQ(outlier_jitter.ms(), steady_state_jitter.ms());
}

class MisconfiguredFieldTrialsJitterEstimatorTest : public JitterEstimatorTest {
 protected:
  MisconfiguredFieldTrialsJitterEstimatorTest()
      : JitterEstimatorTest(
            "WebRTC-JitterEstimatorConfig/"
            "max_frame_size_percentile:-0.9,"
            "frame_size_window:-1,"
            "num_stddev_delay_clamp:-1.9,"
            "num_stddev_delay_outlier:-2,"
            "num_stddev_size_outlier:-23.1/") {}
  ~MisconfiguredFieldTrialsJitterEstimatorTest() {}
};

TEST_F(MisconfiguredFieldTrialsJitterEstimatorTest, FieldTrialsAreValidated) {
  JitterEstimator::Config config = estimator_.GetConfigForTest();
  EXPECT_EQ(*config.max_frame_size_percentile, 0.0);
  EXPECT_EQ(*config.frame_size_window, 1);
  EXPECT_EQ(*config.num_stddev_delay_clamp, 0.0);
  EXPECT_EQ(*config.num_stddev_delay_outlier, 0.0);
  EXPECT_EQ(*config.num_stddev_size_outlier, 0.0);
}

}  // namespace
}  // namespace webrtc
