Signal to NetEq Controller if arrived packets are DTX packets.

This CL also puts the arguments in a struct to allow for easier future additions.

Bug: webrtc:11005
Change-Id: I47bf664e7106b724eb1fc42299c42bbf022393ef
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188385
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32409}
diff --git a/api/neteq/neteq_controller.h b/api/neteq/neteq_controller.h
index 499b999..8344cd1 100644
--- a/api/neteq/neteq_controller.h
+++ b/api/neteq/neteq_controller.h
@@ -97,6 +97,14 @@
     size_t sync_buffer_samples;
   };
 
+  struct PacketArrivedInfo {
+    size_t packet_length_samples;
+    uint32_t main_timestamp;
+    uint16_t main_sequence_number;
+    bool is_cng_or_dtmf;
+    bool is_dtx;
+  };
+
   virtual ~NetEqController() = default;
 
   // Resets object to a clean state.
@@ -154,15 +162,33 @@
   // Returns the target buffer level in ms.
   virtual int TargetLevelMs() const = 0;
 
-  // Notify the NetEqController that a packet has arrived. Returns the relative
-  // arrival delay, if it can be computed.
+  // Deprecated.
+  // TODO(ivoc): Remove when downstream is updated.
   virtual absl::optional<int> PacketArrived(bool last_cng_or_dtmf,
                                             size_t packet_length_samples,
                                             bool should_update_stats,
                                             uint16_t main_sequence_number,
                                             uint32_t main_timestamp,
-                                            int fs_hz) = 0;
+                                            int fs_hz) {
+    PacketArrivedInfo info;
+    info.is_dtx = false;
+    info.is_cng_or_dtmf = last_cng_or_dtmf;
+    info.packet_length_samples = packet_length_samples;
+    info.main_sequence_number = main_sequence_number;
+    info.main_timestamp = main_timestamp;
+    return PacketArrived(fs_hz, should_update_stats, info);
+  }
 
+  // Notify the NetEqController that a packet has arrived. Returns the relative
+  // arrival delay, if it can be computed.
+  // TODO(ivoc): Make pure virtual when downstream is updated.
+  virtual absl::optional<int> PacketArrived(int fs_hz,
+                                            bool should_update_stats,
+                                            const PacketArrivedInfo& info) {
+    return PacketArrived(info.is_cng_or_dtmf, info.packet_length_samples,
+                         should_update_stats, info.main_sequence_number,
+                         info.main_timestamp, fs_hz);
+  }
   // Notify the NetEqController that we are currently in muted state.
   // TODO(ivoc): Make pure virtual when downstream is updated.
   virtual void NotifyMutedState() {}
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index a4de9b8..fb26b99 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -198,26 +198,24 @@
   }
 }
 
-absl::optional<int> DecisionLogic::PacketArrived(bool is_cng_or_dtmf,
-                                                 size_t packet_length_samples,
-                                                 bool should_update_stats,
-                                                 uint16_t main_sequence_number,
-                                                 uint32_t main_timestamp,
-                                                 int fs_hz) {
-  if (is_cng_or_dtmf) {
+absl::optional<int> DecisionLogic::PacketArrived(
+    int fs_hz,
+    bool should_update_stats,
+    const PacketArrivedInfo& info) {
+  if (info.is_cng_or_dtmf) {
     last_pack_cng_or_dtmf_ = true;
     return absl::nullopt;
   }
   if (!should_update_stats) {
     return absl::nullopt;
   }
-  if (packet_length_samples > 0 && fs_hz > 0 &&
-      packet_length_samples != packet_length_samples_) {
-    packet_length_samples_ = packet_length_samples;
+  if (info.packet_length_samples > 0 && fs_hz > 0 &&
+      info.packet_length_samples != packet_length_samples_) {
+    packet_length_samples_ = info.packet_length_samples;
     delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz);
   }
   auto relative_delay = delay_manager_->Update(
-      main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_);
+      info.main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_);
   last_pack_cng_or_dtmf_ = false;
   return relative_delay;
 }
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index d4d69ed..d69c249 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -72,12 +72,9 @@
 
   int TargetLevelMs() const override { return delay_manager_->TargetDelayMs(); }
 
-  absl::optional<int> PacketArrived(bool is_cng_or_dtmf,
-                                    size_t packet_length_samples,
+  absl::optional<int> PacketArrived(int fs_hz,
                                     bool should_update_stats,
-                                    uint16_t main_sequence_number,
-                                    uint32_t main_timestamp,
-                                    int fs_hz) override;
+                                    const PacketArrivedInfo& info) override;
 
   void RegisterEmptyPacket() override {}
 
diff --git a/modules/audio_coding/neteq/mock/mock_neteq_controller.h b/modules/audio_coding/neteq/mock/mock_neteq_controller.h
index ec348ca..b8ffbb2 100644
--- a/modules/audio_coding/neteq/mock/mock_neteq_controller.h
+++ b/modules/audio_coding/neteq/mock/mock_neteq_controller.h
@@ -51,6 +51,12 @@
                uint32_t main_timestamp,
                int fs_hz),
               (override));
+  MOCK_METHOD(absl::optional<int>,
+              PacketArrived,
+              (int fs_hz,
+               bool should_update_stats,
+               const PacketArrivedInfo& info),
+              (override));
   MOCK_METHOD(bool, PeakFound, (), (const, override));
   MOCK_METHOD(int, GetFilteredBufferLevel, (), (const, override));
   MOCK_METHOD(void, set_sample_memory, (int32_t value), (override));
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 61e4de6..ba6d9c1 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -680,6 +680,7 @@
   }
 
   PacketList parsed_packet_list;
+  bool is_dtx = false;
   while (!packet_list.empty()) {
     Packet& packet = packet_list.front();
     const DecoderDatabase::DecoderInfo* info =
@@ -720,6 +721,7 @@
         for (auto& result : results) {
           RTC_DCHECK(result.frame);
           RTC_DCHECK_GE(result.priority, 0);
+          is_dtx = is_dtx || result.frame->IsDtxPacket();
           if (first) {
             // Re-use the node and move it to parsed_packet_list.
             packet_list.front() = packet_from_result(result);
@@ -801,10 +803,13 @@
       decoder_database_->GetDecoderInfo(main_payload_type);
   assert(dec_info);  // Already checked that the payload type is known.
 
-  const bool last_cng_or_dtmf =
-      dec_info->IsComfortNoise() || dec_info->IsDtmf();
-  const size_t packet_length_samples =
+  NetEqController::PacketArrivedInfo info;
+  info.is_cng_or_dtmf = dec_info->IsComfortNoise() || dec_info->IsDtmf();
+  info.packet_length_samples =
       number_of_primary_packets * decoder_frame_length_;
+  info.main_timestamp = main_timestamp;
+  info.main_sequence_number = main_sequence_number;
+  info.is_dtx = is_dtx;
   // Only update statistics if incoming packet is not older than last played
   // out packet or RTX handling is enabled, and if new codec flag is not
   // set.
@@ -813,9 +818,8 @@
        static_cast<int32_t>(main_timestamp - timestamp_) >= 0) &&
       !new_codec_;
 
-  auto relative_delay = controller_->PacketArrived(
-      last_cng_or_dtmf, packet_length_samples, should_update_stats,
-      main_sequence_number, main_timestamp, fs_hz_);
+  auto relative_delay =
+      controller_->PacketArrived(fs_hz_, should_update_stats, info);
   if (relative_delay) {
     stats_->RelativePacketArrivalDelay(relative_delay.value());
   }
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 44660fc..28dd8f0 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -284,6 +284,8 @@
 }
 
 TEST_F(NetEqImplTest, InsertPacket) {
+  using ::testing::AllOf;
+  using ::testing::Field;
   CreateInstance();
   const size_t kPayloadLength = 100;
   const uint8_t kPayloadType = 0;
@@ -347,20 +349,32 @@
     // All expectations within this block must be called in this specific order.
     InSequence sequence;  // Dummy variable.
     // Expectations when the first packet is inserted.
-    EXPECT_CALL(*mock_neteq_controller_,
-                PacketArrived(/*last_cng_or_dtmf*/ false,
-                              /*packet_length_samples*/ _,
-                              /*should_update_stats*/ _,
-                              /*main_sequence_number*/ kFirstSequenceNumber,
-                              /*main_timestamp*/ kFirstTimestamp,
-                              /*fs_hz*/ 8000));
-    EXPECT_CALL(*mock_neteq_controller_,
-                PacketArrived(/*last_cng_or_dtmf*/ false,
-                              /*packet_length_samples*/ _,
-                              /*should_update_stats*/ _,
-                              /*main_sequence_number*/ kFirstSequenceNumber + 1,
-                              /*main_timestamp*/ kFirstTimestamp + 160,
-                              /*fs_hz*/ 8000));
+    EXPECT_CALL(
+        *mock_neteq_controller_,
+        PacketArrived(
+            /*fs_hz*/ 8000,
+            /*should_update_stats*/ _,
+            /*info*/
+            AllOf(
+                Field(&NetEqController::PacketArrivedInfo::is_cng_or_dtmf,
+                      false),
+                Field(&NetEqController::PacketArrivedInfo::main_sequence_number,
+                      kFirstSequenceNumber),
+                Field(&NetEqController::PacketArrivedInfo::main_timestamp,
+                      kFirstTimestamp))));
+    EXPECT_CALL(
+        *mock_neteq_controller_,
+        PacketArrived(
+            /*fs_hz*/ 8000,
+            /*should_update_stats*/ _,
+            /*info*/
+            AllOf(
+                Field(&NetEqController::PacketArrivedInfo::is_cng_or_dtmf,
+                      false),
+                Field(&NetEqController::PacketArrivedInfo::main_sequence_number,
+                      kFirstSequenceNumber + 1),
+                Field(&NetEqController::PacketArrivedInfo::main_timestamp,
+                      kFirstTimestamp + 160))));
   }
 
   // Insert first packet.
@@ -1517,6 +1531,8 @@
 }
 
 TEST_F(NetEqImplTest, EnableRtxHandling) {
+  using ::testing::AllOf;
+  using ::testing::Field;
   UseNoMocks();
   use_mock_neteq_controller_ = true;
   config_.enable_rtx_handling = true;
@@ -1545,14 +1561,19 @@
   // Insert second packet that was sent before the first packet.
   rtp_header.sequenceNumber -= 1;
   rtp_header.timestamp -= kPayloadLengthSamples;
-  EXPECT_CALL(*mock_neteq_controller_,
-              PacketArrived(
-                  /*last_cng_or_dtmf*/ _,
-                  /*packet_length_samples*/ kPayloadLengthSamples,
-                  /*should_update_stats*/ _,
-                  /*main_sequence_number*/ rtp_header.sequenceNumber,
-                  /*main_timestamp*/ rtp_header.timestamp,
-                  /*fs_hz*/ 8000));
+  EXPECT_CALL(
+      *mock_neteq_controller_,
+      PacketArrived(
+          /*fs_hz*/ 8000,
+          /*should_update_stats*/ _,
+          /*info*/
+          AllOf(
+              Field(&NetEqController::PacketArrivedInfo::packet_length_samples,
+                    kPayloadLengthSamples),
+              Field(&NetEqController::PacketArrivedInfo::main_sequence_number,
+                    rtp_header.sequenceNumber),
+              Field(&NetEqController::PacketArrivedInfo::main_timestamp,
+                    rtp_header.timestamp))));
 
   EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
 }