Added support for skipping get_audio events, adding dummy packets and setting a field trial string.

Bug: webrtc:10337
Change-Id: I0507da4d955daa914af774c946be16a4168be21a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/150780
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29392}
diff --git a/api/test/neteq_simulator_factory.cc b/api/test/neteq_simulator_factory.cc
index 112d55a..9a751a4 100644
--- a/api/test/neteq_simulator_factory.cc
+++ b/api/test/neteq_simulator_factory.cc
@@ -60,6 +60,9 @@
   NetEqTestFactory::Config config;
   config.replacement_audio_file = std::string(replacement_audio_filename);
   config.max_nr_packets_in_buffer = simulation_config.max_nr_packets_in_buffer;
+  config.initial_dummy_packets = simulation_config.initial_dummy_packets;
+  config.skip_get_audio_events = simulation_config.skip_get_audio_events;
+  config.field_trial_string = simulation_config.field_trial_string;
   return factory_->InitializeTestFromFile(std::string(event_log_filename),
                                           config);
 }
@@ -72,6 +75,9 @@
   NetEqTestFactory::Config config;
   config.replacement_audio_file = std::string(replacement_audio_filename);
   config.max_nr_packets_in_buffer = simulation_config.max_nr_packets_in_buffer;
+  config.initial_dummy_packets = simulation_config.initial_dummy_packets;
+  config.skip_get_audio_events = simulation_config.skip_get_audio_events;
+  config.field_trial_string = simulation_config.field_trial_string;
   return factory_->InitializeTestFromString(
       std::string(event_log_file_contents), config);
 }
diff --git a/api/test/neteq_simulator_factory.h b/api/test/neteq_simulator_factory.h
index 245162f..3c0cbe0 100644
--- a/api/test/neteq_simulator_factory.h
+++ b/api/test/neteq_simulator_factory.h
@@ -27,7 +27,19 @@
   NetEqSimulatorFactory();
   ~NetEqSimulatorFactory();
   struct Config {
+    // The maximum allowed number of packets in the jitter buffer.
     int max_nr_packets_in_buffer = 0;
+    // The number of audio packets to insert at the start of the simulation.
+    // Since the simulation is done with a replacement audio file, these
+    // artificial packets will take a small piece of that replacement audio.
+    int initial_dummy_packets = 0;
+    // The number of simulation steps to skip at the start of the simulation.
+    // This removes incoming packets and GetAudio events from the start of the
+    // simulation, until the requested number of GetAudio events has been
+    // removed.
+    int skip_get_audio_events = 0;
+    // A WebRTC field trial string to be used during the simulation.
+    std::string field_trial_string;
   };
   // This function takes the same arguments as the neteq_rtpplay utility.
   std::unique_ptr<NetEqSimulator> CreateSimulator(int argc, char* argv[]);
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index e90ffc8..06bcbde 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -1070,6 +1070,8 @@
     "neteq/tools/audio_loop.h",
     "neteq/tools/constant_pcm_packet_source.cc",
     "neteq/tools/constant_pcm_packet_source.h",
+    "neteq/tools/initial_packet_inserter_neteq_input.cc",
+    "neteq/tools/initial_packet_inserter_neteq_input.h",
     "neteq/tools/neteq_packet_source_input.cc",
     "neteq/tools/neteq_packet_source_input.h",
     "neteq/tools/output_audio_file.h",
@@ -1466,6 +1468,7 @@
         "../../api/audio_codecs:builtin_audio_decoder_factory",
         "../../rtc_base:rtc_base_approved",
         "../../test:audio_codec_mocks",
+        "../../test:field_trial",
         "../../test:test_support",
       ]
     }
diff --git a/modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.cc b/modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.cc
new file mode 100644
index 0000000..3c33aab
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.cc
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2019 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/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h"
+
+#include <limits>
+#include <memory>
+#include <utility>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace test {
+
+InitialPacketInserterNetEqInput::InitialPacketInserterNetEqInput(
+    std::unique_ptr<NetEqInput> source,
+    int number_of_initial_packets,
+    int sample_rate_hz)
+    : source_(std::move(source)),
+      packets_to_insert_(number_of_initial_packets),
+      sample_rate_hz_(sample_rate_hz) {}
+
+absl::optional<int64_t> InitialPacketInserterNetEqInput::NextPacketTime()
+    const {
+  return source_->NextPacketTime();
+}
+
+absl::optional<int64_t> InitialPacketInserterNetEqInput::NextOutputEventTime()
+    const {
+  return source_->NextOutputEventTime();
+}
+
+std::unique_ptr<InitialPacketInserterNetEqInput::PacketData>
+InitialPacketInserterNetEqInput::PopPacket() {
+  if (!first_packet_) {
+    first_packet_ = source_->PopPacket();
+    if (!first_packet_) {
+      // The source has no packets, so we should not insert any dummy packets.
+      packets_to_insert_ = 0;
+    }
+  }
+  if (packets_to_insert_ > 0) {
+    RTC_CHECK(first_packet_);
+    auto dummy_packet = std::unique_ptr<PacketData>(new PacketData());
+    dummy_packet->header = first_packet_->header;
+    dummy_packet->payload = rtc::Buffer(first_packet_->payload.data(),
+                                        first_packet_->payload.size());
+    dummy_packet->time_ms = first_packet_->time_ms;
+    dummy_packet->header.sequenceNumber -= packets_to_insert_;
+    // This assumes 20ms per packet.
+    dummy_packet->header.timestamp -=
+        20 * sample_rate_hz_ * packets_to_insert_ / 1000;
+    packets_to_insert_--;
+    return dummy_packet;
+  }
+  return source_->PopPacket();
+}
+
+void InitialPacketInserterNetEqInput::AdvanceOutputEvent() {
+  source_->AdvanceOutputEvent();
+}
+
+bool InitialPacketInserterNetEqInput::ended() const {
+  return source_->ended();
+}
+
+absl::optional<RTPHeader> InitialPacketInserterNetEqInput::NextHeader() const {
+  return source_->NextHeader();
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h b/modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h
new file mode 100644
index 0000000..bd20a7a
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2019 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.
+ */
+
+#ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_INITIAL_PACKET_INSERTER_NETEQ_INPUT_H_
+#define MODULES_AUDIO_CODING_NETEQ_TOOLS_INITIAL_PACKET_INSERTER_NETEQ_INPUT_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "modules/audio_coding/neteq/tools/neteq_input.h"
+
+namespace webrtc {
+namespace test {
+
+// Wrapper class that can insert a number of packets at the start of the
+// simulation.
+class InitialPacketInserterNetEqInput final : public NetEqInput {
+ public:
+  InitialPacketInserterNetEqInput(std::unique_ptr<NetEqInput> source,
+                                  int number_of_initial_packets,
+                                  int sample_rate_hz);
+  absl::optional<int64_t> NextPacketTime() const override;
+  absl::optional<int64_t> NextOutputEventTime() const override;
+  std::unique_ptr<PacketData> PopPacket() override;
+  void AdvanceOutputEvent() override;
+  bool ended() const override;
+  absl::optional<RTPHeader> NextHeader() const override;
+
+ private:
+  const std::unique_ptr<NetEqInput> source_;
+  int packets_to_insert_;
+  const int sample_rate_hz_;
+  std::unique_ptr<PacketData> first_packet_;
+};
+
+}  // namespace test
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_NETEQ_TOOLS_INITIAL_PACKET_INSERTER_NETEQ_INPUT_H_
diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.cc b/modules/audio_coding/neteq/tools/neteq_test_factory.cc
index 3c3add4..c50f7d9 100644
--- a/modules/audio_coding/neteq/tools/neteq_test_factory.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test_factory.cc
@@ -26,6 +26,7 @@
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
 #include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
+#include "modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/neteq_delay_analyzer.h"
 #include "modules/audio_coding/neteq/tools/neteq_event_log_input.h"
@@ -156,6 +157,35 @@
     return nullptr;
   }
 
+  if (!config.field_trial_string.empty()) {
+    field_trials_ =
+        std::make_unique<ScopedFieldTrials>(config.field_trial_string);
+  }
+
+  // Skip some initial events/packets if requested.
+  if (config.skip_get_audio_events > 0) {
+    std::cout << "Skipping " << config.skip_get_audio_events
+              << " get_audio events" << std::endl;
+    if (!input->NextPacketTime() || !input->NextOutputEventTime()) {
+      std::cerr << "No events found" << std::endl;
+      return nullptr;
+    }
+    for (int i = 0; i < config.skip_get_audio_events; i++) {
+      input->AdvanceOutputEvent();
+      if (!input->NextOutputEventTime()) {
+        std::cerr << "Not enough get_audio events found" << std::endl;
+        return nullptr;
+      }
+    }
+    while (*input->NextPacketTime() < *input->NextOutputEventTime()) {
+      input->PopPacket();
+      if (!input->NextPacketTime()) {
+        std::cerr << "Not enough incoming packets found" << std::endl;
+        return nullptr;
+      }
+    }
+  }
+
   // Check the sample rate.
   absl::optional<int> sample_rate_hz;
   std::set<std::pair<int, uint32_t>> discarded_pt_and_ssrc;
@@ -167,6 +197,12 @@
                 << static_cast<int>(first_rtp_header->payloadType)
                 << " and SSRC 0x" << std::hex << first_rtp_header->ssrc
                 << std::dec << std::endl;
+      if (config.initial_dummy_packets > 0) {
+        std::cout << "Nr of initial dummy packets: "
+                  << config.initial_dummy_packets << std::endl;
+        input = std::make_unique<InitialPacketInserterNetEqInput>(
+            std::move(input), config.initial_dummy_packets, *sample_rate_hz);
+      }
       break;
     }
     // Discard this packet and move to the next. Keep track of discarded payload
diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.h b/modules/audio_coding/neteq/tools/neteq_test_factory.h
index 34b7c77..3f59f6b 100644
--- a/modules/audio_coding/neteq/tools/neteq_test_factory.h
+++ b/modules/audio_coding/neteq/tools/neteq_test_factory.h
@@ -16,6 +16,7 @@
 
 #include "absl/types/optional.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
+#include "test/field_trial.h"
 
 namespace webrtc {
 namespace test {
@@ -122,6 +123,13 @@
     // Maximum allowed number of packets in the buffer.
     static constexpr int default_max_nr_packets_in_buffer() { return 50; }
     int max_nr_packets_in_buffer = default_max_nr_packets_in_buffer();
+    // Number of dummy packets to put in the packet buffer at the start of the
+    // simulation.
+    static constexpr int default_initial_dummy_packets() { return 0; }
+    int initial_dummy_packets = default_initial_dummy_packets();
+    // Number of getAudio events to skip at the start of the simulation.
+    static constexpr int default_skip_get_audio_events() { return 0; }
+    int skip_get_audio_events = default_skip_get_audio_events();
     // Enables jitter buffer fast accelerate.
     bool enable_fast_accelerate = false;
     // Path to the output text log file that describes the simulation on a
@@ -131,6 +139,8 @@
     absl::optional<std::string> plot_scripts_basename;
     // Path to the output audio file.
     absl::optional<std::string> output_audio_filename;
+    // Field trials to use during the simulation.
+    std::string field_trial_string;
   };
 
   std::unique_ptr<NetEqTest> InitializeTestFromFile(
@@ -145,6 +155,9 @@
                                             const Config& config);
   std::unique_ptr<SsrcSwitchDetector> ssrc_switch_detector_;
   std::unique_ptr<NetEqStatsPlotter> stats_plotter_;
+  // The field trials are stored in the test factory, because neteq_test is not
+  // in a testonly target, and therefore cannot use ScopedFieldTrials.
+  std::unique_ptr<ScopedFieldTrials> field_trials_;
 };
 
 }  // namespace test