Reset encoder when audio send stream is stopped.

This is to clear any remaining buffers and other state such as the next packet timestamp.

Bug: webrtc:12397
Change-Id: I2ef9a6f7254d82a69a2896ec8aa619ced2694fb8
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291327
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39206}
diff --git a/audio/BUILD.gn b/audio/BUILD.gn
index 919140e..6ca47d4 100644
--- a/audio/BUILD.gn
+++ b/audio/BUILD.gn
@@ -151,6 +151,7 @@
       "audio_state_unittest.cc",
       "channel_receive_frame_transformer_delegate_unittest.cc",
       "channel_send_frame_transformer_delegate_unittest.cc",
+      "channel_send_unittest.cc",
       "mock_voe_channel_proxy.h",
       "remix_resample_unittest.cc",
       "test/audio_stats_test.cc",
@@ -165,8 +166,10 @@
       "../api:mock_audio_mixer",
       "../api:mock_frame_decryptor",
       "../api:mock_frame_encryptor",
+      "../api:scoped_refptr",
       "../api/audio:audio_frame_api",
       "../api/audio_codecs:audio_codecs_api",
+      "../api/audio_codecs:builtin_audio_encoder_factory",
       "../api/audio_codecs/opus:audio_decoder_opus",
       "../api/audio_codecs/opus:audio_encoder_opus",
       "../api/crypto:frame_decryptor_interface",
@@ -174,6 +177,7 @@
       "../api/task_queue:default_task_queue_factory",
       "../api/task_queue/test:mock_task_queue_base",
       "../api/units:time_delta",
+      "../api/units:timestamp",
       "../call:mock_bitrate_allocator",
       "../call:mock_call_interfaces",
       "../call:mock_rtp_interfaces",
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
index 361880d6..5b0858a 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -540,10 +540,12 @@
   sending_ = false;
   encoder_queue_is_active_.store(false);
 
-  // Wait until all pending encode tasks are executed.
+  // Wait until all pending encode tasks are executed and clear any remaining
+  // buffers in the encoder.
   rtc::Event flush;
   encoder_queue_.PostTask([this, &flush]() {
     RTC_DCHECK_RUN_ON(&encoder_queue_);
+    CallEncoder([](AudioEncoder* encoder) { encoder->Reset(); });
     flush.Set();
   });
   flush.Wait(rtc::Event::kForever);
diff --git a/audio/channel_send_unittest.cc b/audio/channel_send_unittest.cc
new file mode 100644
index 0000000..50d8368
--- /dev/null
+++ b/audio/channel_send_unittest.cc
@@ -0,0 +1,113 @@
+/*
+ *  Copyright 2023 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 "audio/channel_send.h"
+
+#include <utility>
+
+#include "api/audio/audio_frame.h"
+#include "api/audio_codecs/builtin_audio_encoder_factory.h"
+#include "api/rtc_event_log/rtc_event_log.h"
+#include "api/scoped_refptr.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
+#include "call/rtp_transport_controller_send.h"
+#include "test/gtest.h"
+#include "test/mock_transport.h"
+#include "test/scoped_key_value_config.h"
+#include "test/time_controller/simulated_time_controller.h"
+
+namespace webrtc {
+namespace voe {
+namespace {
+
+constexpr int kRtcpIntervalMs = 1000;
+constexpr int kSsrc = 333;
+constexpr int kPayloadType = 1;
+
+BitrateConstraints GetBitrateConfig() {
+  BitrateConstraints bitrate_config;
+  bitrate_config.min_bitrate_bps = 10000;
+  bitrate_config.start_bitrate_bps = 100000;
+  bitrate_config.max_bitrate_bps = 1000000;
+  return bitrate_config;
+}
+
+std::unique_ptr<AudioFrame> CreateAudioFrame() {
+  auto frame = std::make_unique<AudioFrame>();
+  frame->samples_per_channel_ = 480;
+  frame->sample_rate_hz_ = 48000;
+  frame->num_channels_ = 1;
+  return frame;
+}
+
+class ChannelSendTest : public ::testing::Test {
+ protected:
+  ChannelSendTest()
+      : time_controller_(Timestamp::Seconds(1)),
+        transport_controller_(
+            time_controller_.GetClock(),
+            RtpTransportConfig{
+                .bitrate_config = GetBitrateConfig(),
+                .event_log = &event_log_,
+                .task_queue_factory = time_controller_.GetTaskQueueFactory(),
+                .trials = &field_trials_,
+            }) {
+    transport_controller_.EnsureStarted();
+  }
+
+  std::unique_ptr<ChannelSendInterface> CreateChannelSend() {
+    return voe::CreateChannelSend(
+        time_controller_.GetClock(), time_controller_.GetTaskQueueFactory(),
+        &transport_, nullptr, &event_log_, nullptr, crypto_options_, false,
+        kRtcpIntervalMs, kSsrc, nullptr, nullptr, field_trials_);
+  }
+
+  GlobalSimulatedTimeController time_controller_;
+  webrtc::test::ScopedKeyValueConfig field_trials_;
+  RtcEventLogNull event_log_;
+  MockTransport transport_;
+  RtpTransportControllerSend transport_controller_;
+  CryptoOptions crypto_options_;
+};
+
+TEST_F(ChannelSendTest, StopSendShouldResetEncoder) {
+  std::unique_ptr<ChannelSendInterface> channel = CreateChannelSend();
+  rtc::scoped_refptr<AudioEncoderFactory> encoder_factory =
+      CreateBuiltinAudioEncoderFactory();
+  std::unique_ptr<AudioEncoder> encoder = encoder_factory->MakeAudioEncoder(
+      kPayloadType, SdpAudioFormat("opus", 48000, 2), {});
+  channel->SetEncoder(kPayloadType, std::move(encoder));
+  channel->RegisterSenderCongestionControlObjects(&transport_controller_,
+                                                  nullptr);
+  channel->StartSend();
+
+  // Insert two frames which should trigger a new packet.
+  EXPECT_CALL(transport_, SendRtp).Times(1);
+  channel->ProcessAndEncodeAudio(CreateAudioFrame());
+  time_controller_.AdvanceTime(webrtc::TimeDelta::Zero());
+  channel->ProcessAndEncodeAudio(CreateAudioFrame());
+  time_controller_.AdvanceTime(webrtc::TimeDelta::Zero());
+
+  EXPECT_CALL(transport_, SendRtp).Times(0);
+  channel->ProcessAndEncodeAudio(CreateAudioFrame());
+  time_controller_.AdvanceTime(webrtc::TimeDelta::Zero());
+  // StopSend should clear the previous audio frame stored in the encoder.
+  channel->StopSend();
+  channel->StartSend();
+  // The following frame should not trigger a new packet since the encoder
+  // needs 20 ms audio.
+  channel->ProcessAndEncodeAudio(CreateAudioFrame());
+  time_controller_.AdvanceTime(webrtc::TimeDelta::Zero());
+}
+
+}  // namespace
+}  // namespace voe
+}  // namespace webrtc