Make Opus PLC always output 10ms audio.

BUG: b/143582588
Change-Id: I41ad5f4f91d9af3f595666a8f32b7ab5382605bd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158672
Commit-Queue: Minyue Li <minyue@webrtc.org>
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29733}
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index 6f49cfe..909bc75 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -840,6 +840,7 @@
     "../../rtc_base:checks",
     "../../rtc_base:ignore_wundef",
     "../../rtc_base:rtc_base_approved",
+    "../../system_wrappers:field_trial",
   ]
 }
 
diff --git a/modules/audio_coding/codecs/opus/opus_fec_test.cc b/modules/audio_coding/codecs/opus/opus_fec_test.cc
index 47e40c6..1923647 100644
--- a/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -154,8 +154,13 @@
           WebRtcOpus_DecodeFec(opus_decoder_, &bit_stream_[0], encoded_bytes_,
                                &out_data_[0], &audio_type);
     } else {
-      value_1 =
-          WebRtcOpus_Decode(opus_decoder_, NULL, 0, &out_data_[0], &audio_type);
+      // Call decoder PLC.
+      while (value_1 < static_cast<int>(block_length_sample_)) {
+        int ret = WebRtcOpus_Decode(opus_decoder_, NULL, 0, &out_data_[value_1],
+                                    &audio_type);
+        EXPECT_EQ(ret, sampling_khz_ * 10);  // Should return 10 ms of samples.
+        value_1 += ret;
+      }
     }
     EXPECT_EQ(static_cast<int>(block_length_sample_), value_1);
   }
diff --git a/modules/audio_coding/codecs/opus/opus_inst.h b/modules/audio_coding/codecs/opus/opus_inst.h
index 9c3acb3b..148baa2 100644
--- a/modules/audio_coding/codecs/opus/opus_inst.h
+++ b/modules/audio_coding/codecs/opus/opus_inst.h
@@ -31,6 +31,7 @@
   OpusDecoder* decoder;
   OpusMSDecoder* multistream_decoder;
   int prev_decoded_samples;
+  bool plc_use_prev_decoded_samples;
   size_t channels;
   int in_dtx_mode;
   int sample_rate_hz;
diff --git a/modules/audio_coding/codecs/opus/opus_interface.cc b/modules/audio_coding/codecs/opus/opus_interface.cc
index fc3d3ff..2f475cb 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.cc
+++ b/modules/audio_coding/codecs/opus/opus_interface.cc
@@ -11,6 +11,7 @@
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 
 #include "rtc_base/checks.h"
+#include "system_wrappers/include/field_trial.h"
 
 enum {
 #if WEBRTC_OPUS_SUPPORT_120MS_PTIME
@@ -25,8 +26,14 @@
    * side, we must allow for packets of that size. NetEq is currently limited
    * to 60 ms on the receive side. */
   kWebRtcOpusMaxDecodeFrameSizeMs = 120,
+
+  // Duration of audio that each call to packet loss concealment covers.
+  kWebRtcOpusPlcFrameSizeMs = 10,
 };
 
+constexpr char kPlcUsePrevDecodedSamplesFieldTrial[] =
+    "WebRTC-Audio-OpusPlcUsePrevDecodedSamples";
+
 static int FrameSizePerChannel(int frame_size_ms, int sample_rate_hz) {
   RTC_DCHECK_GT(frame_size_ms, 0);
   RTC_DCHECK_EQ(frame_size_ms % 10, 0);
@@ -381,9 +388,14 @@
     if (error == OPUS_OK && state->decoder) {
       // Creation of memory all ok.
       state->channels = channels;
-      state->prev_decoded_samples = DefaultFrameSizePerChannel(sample_rate_hz);
-      state->in_dtx_mode = 0;
       state->sample_rate_hz = sample_rate_hz;
+      state->plc_use_prev_decoded_samples =
+          webrtc::field_trial::IsEnabled(kPlcUsePrevDecodedSamplesFieldTrial);
+      if (state->plc_use_prev_decoded_samples) {
+        state->prev_decoded_samples =
+            DefaultFrameSizePerChannel(state->sample_rate_hz);
+      }
+      state->in_dtx_mode = 0;
       *inst = state;
       return 0;
     }
@@ -420,9 +432,14 @@
     if (error == OPUS_OK && state->multistream_decoder) {
       // Creation of memory all ok.
       state->channels = channels;
-      state->prev_decoded_samples = DefaultFrameSizePerChannel(48000);
-      state->in_dtx_mode = 0;
       state->sample_rate_hz = 48000;
+      state->plc_use_prev_decoded_samples =
+          webrtc::field_trial::IsEnabled(kPlcUsePrevDecodedSamplesFieldTrial);
+      if (state->plc_use_prev_decoded_samples) {
+        state->prev_decoded_samples =
+            DefaultFrameSizePerChannel(state->sample_rate_hz);
+      }
+      state->in_dtx_mode = 0;
       *inst = state;
       return 0;
     }
@@ -517,17 +534,20 @@
 static int DecodePlc(OpusDecInst* inst, int16_t* decoded) {
   int16_t audio_type = 0;
   int decoded_samples;
-  int plc_samples;
+  int plc_samples =
+      FrameSizePerChannel(kWebRtcOpusPlcFrameSizeMs, inst->sample_rate_hz);
 
-  /* The number of samples we ask for is |number_of_lost_frames| times
-   * |prev_decoded_samples_|. Limit the number of samples to maximum
-   * |MaxFrameSizePerChannel()|. */
-  plc_samples = inst->prev_decoded_samples;
-  const int max_samples_per_channel =
-      MaxFrameSizePerChannel(inst->sample_rate_hz);
-  plc_samples = plc_samples <= max_samples_per_channel
-                    ? plc_samples
-                    : max_samples_per_channel;
+  if (inst->plc_use_prev_decoded_samples) {
+    /* The number of samples we ask for is |number_of_lost_frames| times
+     * |prev_decoded_samples_|. Limit the number of samples to maximum
+     * |MaxFrameSizePerChannel()|. */
+    plc_samples = inst->prev_decoded_samples;
+    const int max_samples_per_channel =
+        MaxFrameSizePerChannel(inst->sample_rate_hz);
+    plc_samples = plc_samples <= max_samples_per_channel
+                      ? plc_samples
+                      : max_samples_per_channel;
+  }
   decoded_samples =
       DecodeNative(inst, NULL, 0, plc_samples, decoded, &audio_type, 0);
   if (decoded_samples < 0) {
@@ -556,8 +576,10 @@
     return -1;
   }
 
-  /* Update decoded sample memory, to be used by the PLC in case of losses. */
-  inst->prev_decoded_samples = decoded_samples;
+  if (inst->plc_use_prev_decoded_samples) {
+    /* Update decoded sample memory, to be used by the PLC in case of losses. */
+    inst->prev_decoded_samples = decoded_samples;
+  }
 
   return decoded_samples;
 }
@@ -612,14 +634,17 @@
 }
 
 int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
-  /* The number of samples we ask for is |number_of_lost_frames| times
-   * |prev_decoded_samples_|. Limit the number of samples to maximum
-   * |MaxFrameSizePerChannel()|. */
-  const int plc_samples = inst->prev_decoded_samples;
-  const int max_samples_per_channel =
-      MaxFrameSizePerChannel(inst->sample_rate_hz);
-  return plc_samples <= max_samples_per_channel ? plc_samples
-                                                : max_samples_per_channel;
+  if (inst->plc_use_prev_decoded_samples) {
+    /* The number of samples we ask for is |number_of_lost_frames| times
+     * |prev_decoded_samples_|. Limit the number of samples to maximum
+     * |MaxFrameSizePerChannel()|. */
+    const int plc_samples = inst->prev_decoded_samples;
+    const int max_samples_per_channel =
+        MaxFrameSizePerChannel(inst->sample_rate_hz);
+    return plc_samples <= max_samples_per_channel ? plc_samples
+                                                  : max_samples_per_channel;
+  }
+  return FrameSizePerChannel(kWebRtcOpusPlcFrameSizeMs, inst->sample_rate_hz);
 }
 
 int WebRtcOpus_FecDurationEst(const uint8_t* payload,
diff --git a/modules/audio_coding/codecs/opus/opus_unittest.cc b/modules/audio_coding/codecs/opus/opus_unittest.cc
index 10897fb..0cc4f25 100644
--- a/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -213,17 +213,34 @@
                            WebRtcOpusDecInst* decoder,
                            int16_t* output_audio,
                            int16_t* audio_type) {
+  const int input_samples_per_channel =
+      rtc::CheckedDivExact(input_audio.size(), channels_);
   int encoded_bytes_int =
-      WebRtcOpus_Encode(encoder, input_audio.data(),
-                        rtc::CheckedDivExact(input_audio.size(), channels_),
+      WebRtcOpus_Encode(encoder, input_audio.data(), input_samples_per_channel,
                         kMaxBytes, bitstream_);
   EXPECT_GE(encoded_bytes_int, 0);
   encoded_bytes_ = static_cast<size_t>(encoded_bytes_int);
-  int est_len = WebRtcOpus_DurationEst(decoder, bitstream_, encoded_bytes_);
-  int act_len = WebRtcOpus_Decode(decoder, bitstream_, encoded_bytes_,
-                                  output_audio, audio_type);
-  EXPECT_EQ(est_len, act_len);
-  return act_len;
+  if (encoded_bytes_ != 0) {
+    int est_len = WebRtcOpus_DurationEst(decoder, bitstream_, encoded_bytes_);
+    int act_len = WebRtcOpus_Decode(decoder, bitstream_, encoded_bytes_,
+                                    output_audio, audio_type);
+    EXPECT_EQ(est_len, act_len);
+    return act_len;
+  } else {
+    int total_dtx_len = 0;
+    const int output_samples_per_channel = input_samples_per_channel *
+                                           decoder_sample_rate_hz_ /
+                                           encoder_sample_rate_hz_;
+    while (total_dtx_len < output_samples_per_channel) {
+      int est_len = WebRtcOpus_DurationEst(decoder, NULL, 0);
+      int act_len = WebRtcOpus_Decode(decoder, NULL, 0,
+                                      &output_audio[total_dtx_len * channels_],
+                                      audio_type);
+      EXPECT_EQ(est_len, act_len);
+      total_dtx_len += act_len;
+    }
+    return total_dtx_len;
+  }
 }
 
 // Test if encoder/decoder can enter DTX mode properly and do not enter DTX when
@@ -808,8 +825,10 @@
                          opus_decoder_, output_data_decode, &audio_type));
 
   // Call decoder PLC.
-  int16_t* plc_buffer = new int16_t[decode_samples_per_channel * channels_];
-  EXPECT_EQ(decode_samples_per_channel,
+  constexpr int kPlcDurationMs = 10;
+  const int plc_samples = decoder_sample_rate_hz_ * kPlcDurationMs / 1000;
+  int16_t* plc_buffer = new int16_t[plc_samples * channels_];
+  EXPECT_EQ(plc_samples,
             WebRtcOpus_Decode(opus_decoder_, NULL, 0, plc_buffer, &audio_type));
 
   // Free memory.
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index a192611..58177dc 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -508,11 +508,11 @@
       webrtc::test::ResourcePath("audio_coding/neteq_opus_dtx", "rtp");
 
   const std::string maybe_sse =
-      "713af6c92881f5aab1285765ee6680da9d1c06ce|"
-      "2ac10c4e79aeedd0df2863b079da5848b40f00b5";
+      "0bdeb4ccf95a2577e38274360903ad099fc46787|"
+      "f7bbf5d92a0595a2a3445ffbaddfb20e98b6e94e";
   const std::string output_checksum = PlatformChecksum(
-      maybe_sse, "3ec991b96872123f1554c03c543ca5d518431e46",
-      "da9f9a2d94e0c2d67342fad4965d7b91cda50b25", maybe_sse, maybe_sse);
+      maybe_sse, "6d200cc51a001b6137abf67db2bb8eeb0375cdee",
+      "36d43761de86b12520cf2e63f97372a2b7c6f939", maybe_sse, maybe_sse);
 
   const std::string network_stats_checksum =
       "8caf49765f35b6862066d3f17531ce44d8e25f60";
diff --git a/modules/audio_coding/test/opus_test.cc b/modules/audio_coding/test/opus_test.cc
index 10644e2..e110924 100644
--- a/modules/audio_coding/test/opus_test.cc
+++ b/modules/audio_coding/test/opus_test.cc
@@ -299,9 +299,19 @@
                 opus_mono_decoder_, bitstream, bitstream_len_byte,
                 &out_audio[decoded_samples * channels], &audio_type);
           } else {
-            decoded_samples += WebRtcOpus_Decode(
-                opus_mono_decoder_, NULL, 0,
-                &out_audio[decoded_samples * channels], &audio_type);
+            // Call decoder PLC.
+            constexpr int kPlcDurationMs = 10;
+            constexpr int kPlcSamples = 48 * kPlcDurationMs;
+            size_t total_plc_samples = 0;
+            while (total_plc_samples < frame_length) {
+              int ret = WebRtcOpus_Decode(
+                  opus_mono_decoder_, NULL, 0,
+                  &out_audio[decoded_samples * channels], &audio_type);
+              EXPECT_EQ(ret, kPlcSamples);
+              decoded_samples += ret;
+              total_plc_samples += ret;
+            }
+            EXPECT_EQ(total_plc_samples, frame_length);
           }
         } else {
           if (!lost_packet) {
@@ -309,9 +319,19 @@
                 opus_stereo_decoder_, bitstream, bitstream_len_byte,
                 &out_audio[decoded_samples * channels], &audio_type);
           } else {
-            decoded_samples += WebRtcOpus_Decode(
-                opus_stereo_decoder_, NULL, 0,
-                &out_audio[decoded_samples * channels], &audio_type);
+            // Call decoder PLC.
+            constexpr int kPlcDurationMs = 10;
+            constexpr int kPlcSamples = 48 * kPlcDurationMs;
+            size_t total_plc_samples = 0;
+            while (total_plc_samples < frame_length) {
+              int ret = WebRtcOpus_Decode(
+                  opus_stereo_decoder_, NULL, 0,
+                  &out_audio[decoded_samples * channels], &audio_type);
+              EXPECT_EQ(ret, kPlcSamples);
+              decoded_samples += ret;
+              total_plc_samples += ret;
+            }
+            EXPECT_EQ(total_plc_samples, frame_length);
           }
         }