NetEq: Deprecate playout modes Fax, Off and Streaming

The playout modes other than Normal have not been reachable for a long
time, other than through tests. It is time to deprecate them.

The only meaningful use was that Fax mode was sometimes set from
tests, in order to avoid time-stretching operations (accelerate and
pre-emptive expand) from messing with the test results. With this CL,
a new config is added instead, which lets the user specify exactly
this: don't do time-stretching.

As a result of Fax and Off modes being removed, the following code
clean-up was done:
- Fold DecisionLogicNormal into DecisionLogic.
- Remove AudioRepetition and AlternativePlc operations, since they can
  no longer be reached.

Bug: webrtc:9421
Change-Id: I651458e9c1931a99f3b07e242817d303bac119df
Reviewed-on: https://webrtc-review.googlesource.com/84123
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23704}
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index cc58f04..afe25e1 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -10,47 +10,37 @@
 
 #include "modules/audio_coding/neteq/decision_logic.h"
 
+#include <assert.h>
 #include <algorithm>
+#include <limits>
 
 #include "modules/audio_coding/neteq/buffer_level_filter.h"
-#include "modules/audio_coding/neteq/decision_logic_fax.h"
-#include "modules/audio_coding/neteq/decision_logic_normal.h"
+#include "modules/audio_coding/neteq/decoder_database.h"
 #include "modules/audio_coding/neteq/delay_manager.h"
 #include "modules/audio_coding/neteq/expand.h"
 #include "modules/audio_coding/neteq/packet_buffer.h"
 #include "modules/audio_coding/neteq/sync_buffer.h"
 #include "modules/include/module_common_types.h"
+#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
 DecisionLogic* DecisionLogic::Create(int fs_hz,
                                      size_t output_size_samples,
-                                     NetEqPlayoutMode playout_mode,
+                                     bool disallow_time_stretching,
                                      DecoderDatabase* decoder_database,
                                      const PacketBuffer& packet_buffer,
                                      DelayManager* delay_manager,
                                      BufferLevelFilter* buffer_level_filter,
                                      const TickTimer* tick_timer) {
-  switch (playout_mode) {
-    case kPlayoutOn:
-    case kPlayoutStreaming:
-      return new DecisionLogicNormal(
-          fs_hz, output_size_samples, playout_mode, decoder_database,
-          packet_buffer, delay_manager, buffer_level_filter, tick_timer);
-    case kPlayoutFax:
-    case kPlayoutOff:
-      return new DecisionLogicFax(
-          fs_hz, output_size_samples, playout_mode, decoder_database,
-          packet_buffer, delay_manager, buffer_level_filter, tick_timer);
-  }
-  // This line cannot be reached, but must be here to avoid compiler errors.
-  assert(false);
-  return NULL;
+  return new DecisionLogic(fs_hz, output_size_samples, disallow_time_stretching,
+                           decoder_database, packet_buffer, delay_manager,
+                           buffer_level_filter, tick_timer);
 }
 
 DecisionLogic::DecisionLogic(int fs_hz,
                              size_t output_size_samples,
-                             NetEqPlayoutMode playout_mode,
+                             bool disallow_time_stretching,
                              DecoderDatabase* decoder_database,
                              const PacketBuffer& packet_buffer,
                              DelayManager* delay_manager,
@@ -65,11 +55,13 @@
       packet_length_samples_(0),
       sample_memory_(0),
       prev_time_scale_(false),
+      disallow_time_stretching_(disallow_time_stretching),
       timescale_countdown_(
           tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
       num_consecutive_expands_(0),
-      playout_mode_(playout_mode) {
-  delay_manager_->set_streaming_mode(playout_mode_ == kPlayoutStreaming);
+      postpone_decoding_after_expand_(field_trial::IsEnabled(
+          "WebRTC-Audio-NetEqPostponeDecodingAfterExpand")) {
+  delay_manager_->set_streaming_mode(false);
   SetSampleRate(fs_hz, output_size_samples);
 }
 
@@ -168,4 +160,228 @@
   }
 }
 
+Operations DecisionLogic::GetDecisionSpecialized(const SyncBuffer& sync_buffer,
+                                                 const Expand& expand,
+                                                 size_t decoder_frame_length,
+                                                 const Packet* next_packet,
+                                                 Modes prev_mode,
+                                                 bool play_dtmf,
+                                                 bool* reset_decoder,
+                                                 size_t generated_noise_samples,
+                                                 size_t cur_size_samples) {
+  // Guard for errors, to avoid getting stuck in error mode.
+  if (prev_mode == kModeError) {
+    if (!next_packet) {
+      return kExpand;
+    } else {
+      return kUndefined;  // Use kUndefined to flag for a reset.
+    }
+  }
+
+  uint32_t target_timestamp = sync_buffer.end_timestamp();
+  uint32_t available_timestamp = 0;
+  bool is_cng_packet = false;
+  if (next_packet) {
+    available_timestamp = next_packet->timestamp;
+    is_cng_packet =
+        decoder_database_->IsComfortNoise(next_packet->payload_type);
+  }
+
+  if (is_cng_packet) {
+    return CngOperation(prev_mode, target_timestamp, available_timestamp,
+                        generated_noise_samples);
+  }
+
+  // Handle the case with no packet at all available (except maybe DTMF).
+  if (!next_packet) {
+    return NoPacket(play_dtmf);
+  }
+
+  // If the expand period was very long, reset NetEQ since it is likely that the
+  // sender was restarted.
+  if (num_consecutive_expands_ > kReinitAfterExpands) {
+    *reset_decoder = true;
+    return kNormal;
+  }
+
+  // Make sure we don't restart audio too soon after an expansion to avoid
+  // running out of data right away again. We should only wait if there are no
+  // DTX or CNG packets in the buffer (otherwise we should just play out what we
+  // have, since we cannot know the exact duration of DTX or CNG packets), and
+  // if the mute factor is low enough (otherwise the expansion was short enough
+  // to not be noticable).
+  // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
+  if (postpone_decoding_after_expand_ && prev_mode == kModeExpand &&
+      !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_) &&
+      cur_size_samples<static_cast<size_t>(delay_manager_->TargetLevel() *
+                                           packet_length_samples_)>> 8 &&
+      expand.MuteFactor(0) < 16384 / 2) {
+    return kExpand;
+  }
+
+  const uint32_t five_seconds_samples =
+      static_cast<uint32_t>(5 * 8000 * fs_mult_);
+  // Check if the required packet is available.
+  if (target_timestamp == available_timestamp) {
+    return ExpectedPacketAvailable(prev_mode, play_dtmf);
+  } else if (!PacketBuffer::IsObsoleteTimestamp(
+                 available_timestamp, target_timestamp, five_seconds_samples)) {
+    return FuturePacketAvailable(
+        sync_buffer, expand, decoder_frame_length, prev_mode, target_timestamp,
+        available_timestamp, play_dtmf, generated_noise_samples);
+  } else {
+    // This implies that available_timestamp < target_timestamp, which can
+    // happen when a new stream or codec is received. Signal for a reset.
+    return kUndefined;
+  }
+}
+
+Operations DecisionLogic::CngOperation(Modes prev_mode,
+                                       uint32_t target_timestamp,
+                                       uint32_t available_timestamp,
+                                       size_t generated_noise_samples) {
+  // Signed difference between target and available timestamp.
+  int32_t timestamp_diff = static_cast<int32_t>(
+      static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
+      available_timestamp);
+  int32_t optimal_level_samp = static_cast<int32_t>(
+      (delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
+  const int64_t excess_waiting_time_samp =
+      -static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
+
+  if (excess_waiting_time_samp > optimal_level_samp / 2) {
+    // The waiting time for this packet will be longer than 1.5
+    // times the wanted buffer delay. Apply fast-forward to cut the
+    // waiting time down to the optimal.
+    noise_fast_forward_ = rtc::dchecked_cast<size_t>(noise_fast_forward_ +
+                                                     excess_waiting_time_samp);
+    timestamp_diff =
+        rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
+  }
+
+  if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
+    // Not time to play this packet yet. Wait another round before using this
+    // packet. Keep on playing CNG from previous CNG parameters.
+    return kRfc3389CngNoPacket;
+  } else {
+    // Otherwise, go for the CNG packet now.
+    noise_fast_forward_ = 0;
+    return kRfc3389Cng;
+  }
+}
+
+Operations DecisionLogic::NoPacket(bool play_dtmf) {
+  if (cng_state_ == kCngRfc3389On) {
+    // Keep on playing comfort noise.
+    return kRfc3389CngNoPacket;
+  } else if (cng_state_ == kCngInternalOn) {
+    // Keep on playing codec internal comfort noise.
+    return kCodecInternalCng;
+  } else if (play_dtmf) {
+    return kDtmf;
+  } else {
+    // Nothing to play, do expand.
+    return kExpand;
+  }
+}
+
+Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
+                                                  bool play_dtmf) {
+  if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
+    // Check criterion for time-stretching.
+    int low_limit, high_limit;
+    delay_manager_->BufferLimits(&low_limit, &high_limit);
+    if (buffer_level_filter_->filtered_current_level() >= high_limit << 2)
+      return kFastAccelerate;
+    if (TimescaleAllowed()) {
+      if (buffer_level_filter_->filtered_current_level() >= high_limit)
+        return kAccelerate;
+      if (buffer_level_filter_->filtered_current_level() < low_limit)
+        return kPreemptiveExpand;
+    }
+  }
+  return kNormal;
+}
+
+Operations DecisionLogic::FuturePacketAvailable(
+    const SyncBuffer& sync_buffer,
+    const Expand& expand,
+    size_t decoder_frame_length,
+    Modes prev_mode,
+    uint32_t target_timestamp,
+    uint32_t available_timestamp,
+    bool play_dtmf,
+    size_t generated_noise_samples) {
+  // Required packet is not available, but a future packet is.
+  // Check if we should continue with an ongoing expand because the new packet
+  // is too far into the future.
+  uint32_t timestamp_leap = available_timestamp - target_timestamp;
+  if ((prev_mode == kModeExpand) && !ReinitAfterExpands(timestamp_leap) &&
+      !MaxWaitForPacket() && PacketTooEarly(timestamp_leap) &&
+      UnderTargetLevel()) {
+    if (play_dtmf) {
+      // Still have DTMF to play, so do not do expand.
+      return kDtmf;
+    } else {
+      // Nothing to play.
+      return kExpand;
+    }
+  }
+
+  const size_t samples_left =
+      sync_buffer.FutureLength() - expand.overlap_length();
+  const size_t cur_size_samples =
+      samples_left + packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
+
+  // If previous was comfort noise, then no merge is needed.
+  if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
+    // Keep the same delay as before the CNG, but make sure that the number of
+    // samples in buffer is no higher than 4 times the optimal level. (Note that
+    // TargetLevel() is in Q8.)
+    if (static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
+            available_timestamp ||
+        cur_size_samples >
+            ((delay_manager_->TargetLevel() * packet_length_samples_) >> 8) *
+                4) {
+      // Time to play this new packet.
+      return kNormal;
+    } else {
+      // Too early to play this new packet; keep on playing comfort noise.
+      if (prev_mode == kModeRfc3389Cng) {
+        return kRfc3389CngNoPacket;
+      } else {  // prevPlayMode == kModeCodecInternalCng.
+        return kCodecInternalCng;
+      }
+    }
+  }
+  // Do not merge unless we have done an expand before.
+  if (prev_mode == kModeExpand) {
+    return kMerge;
+  } else if (play_dtmf) {
+    // Play DTMF instead of expand.
+    return kDtmf;
+  } else {
+    return kExpand;
+  }
+}
+
+bool DecisionLogic::UnderTargetLevel() const {
+  return buffer_level_filter_->filtered_current_level() <=
+         delay_manager_->TargetLevel();
+}
+
+bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
+  return timestamp_leap >=
+         static_cast<uint32_t>(output_size_samples_ * kReinitAfterExpands);
+}
+
+bool DecisionLogic::PacketTooEarly(uint32_t timestamp_leap) const {
+  return timestamp_leap >
+         static_cast<uint32_t>(output_size_samples_ * num_consecutive_expands_);
+}
+
+bool DecisionLogic::MaxWaitForPacket() const {
+  return num_consecutive_expands_ >= kMaxWaitForPacket;
+}
+
 }  // namespace webrtc