[M148] Always release VideoEncoders before destruction.

Original change's description:
> Always release VideoEncoders before destruction.
>
> Without a `Release()` call there is a potential for race conditions
> between asynchronous encoder callbacks and the destructor sequence.
>
> Bug: chromium:504620824
> Change-Id: I1fba23ef3a4a238503cdf8d2ea5831e815d7b902
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/465582
> Auto-Submit: Erik Språng <sprang@webrtc.org>
> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#47495}

(cherry picked from commit 21d9744bd599d106da9171fbb1ed09047d7178ca)

Bug: chromium:505251595,chromium:504620824
Change-Id: I1fba23ef3a4a238503cdf8d2ea5831e815d7b902
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/468940
Auto-Submit: Chrome Cherry Picker <chrome-cherry-picker@chops-service-accounts.iam.gserviceaccount.com>
Commit-Queue: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/7778@{#7}
Cr-Branched-From: ca896b7ffef011bbf6957c99d413c5aac602c99f-refs/heads/main@{#47319}
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 4faf80c..cbed7af 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -1079,6 +1079,7 @@
     // Destroy existing encoder instance before creating a new one. Otherwise
     // attempt to create another instance will fail if encoder factory
     // supports only single instance of encoder of given type.
+    ReleaseEncoder();
     encoder_.reset();
 
     encoder_ = MaybeCreateFrameDumpingEncoderWrapper(
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 64468c3..09c1097 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -28,6 +28,7 @@
 #include "api/adaptation/resource.h"
 #include "api/environment/environment.h"
 #include "api/environment/environment_factory.h"
+#include "api/fec_controller_override.h"
 #include "api/field_trials.h"
 #include "api/field_trials_view.h"
 #include "api/location.h"
@@ -42,6 +43,7 @@
 #include "api/test/mock_video_encoder_factory.h"
 #include "api/test/rtc_error_matchers.h"
 #include "api/test/time_controller.h"
+#include "api/test/video/function_video_encoder_factory.h"
 #include "api/units/data_rate.h"
 #include "api/units/data_size.h"
 #include "api/units/frequency.h"
@@ -2377,6 +2379,96 @@
   video_stream_encoder_->Stop();
 }
 
+TEST_F(VideoStreamEncoderTest,
+       EncoderReleasedBeforeDestructionOnReconfiguration) {
+  class ReleaseCheckEncoderProxy : public VideoEncoder {
+   public:
+    ReleaseCheckEncoderProxy(VideoEncoder* encoder, bool& released)
+        : encoder_(encoder), released_(released) {}
+    ~ReleaseCheckEncoderProxy() override = default;
+
+    int32_t Encode(const VideoFrame& input_image,
+                   const std::vector<VideoFrameType>* frame_types) override {
+      return encoder_->Encode(input_image, frame_types);
+    }
+
+    int32_t InitEncode(const VideoCodec* config,
+                       const Settings& settings) override {
+      return encoder_->InitEncode(config, settings);
+    }
+
+    int32_t RegisterEncodeCompleteCallback(
+        EncodedImageCallback* callback) override {
+      return encoder_->RegisterEncodeCompleteCallback(callback);
+    }
+
+    int32_t Release() override {
+      released_ = true;
+      return encoder_->Release();
+    }
+
+    void SetRates(const RateControlParameters& parameters) override {
+      encoder_->SetRates(parameters);
+    }
+
+    VideoEncoder::EncoderInfo GetEncoderInfo() const override {
+      return encoder_->GetEncoderInfo();
+    }
+
+    void SetFecControllerOverride(
+        FecControllerOverride* fec_controller_override) override {
+      encoder_->SetFecControllerOverride(fec_controller_override);
+    }
+
+   private:
+    VideoEncoder* const encoder_;
+    bool& released_;
+  };
+
+  bool released[2] = {false, false};
+  int instance_count = 0;
+
+  test::FunctionVideoEncoderFactory factory(
+      [this, &instance_count, &released](const Environment& env,
+                                         const SdpVideoFormat& format) {
+        RTC_CHECK_LT(instance_count, 2);
+        bool& r = released[instance_count++];
+        return std::make_unique<ReleaseCheckEncoderProxy>(&fake_encoder_, r);
+      });
+
+  video_send_config_.encoder_settings.encoder_factory = &factory;
+  ConfigureEncoder(video_encoder_config_.Copy());
+
+  video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
+      kTargetBitrate, kTargetBitrate, 0, 0, 0);
+
+  // Capture a frame and wait for it to synchronize with the encoder thread.
+  video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
+  WaitForEncodedFrame(1);
+
+  EXPECT_EQ(instance_count, 1);
+  EXPECT_FALSE(released[0]);
+
+  VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
+  // Changing the max payload data length recreates encoder.
+  video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+                                          kMaxPayloadLength / 2);
+
+  // Capture a frame and wait for it to synchronize with the encoder thread.
+  video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
+  WaitForEncodedFrame(2);
+
+  // We expect that two encoders were created.
+  EXPECT_EQ(instance_count, 2);
+  // The first encoder should have been released before destruction.
+  EXPECT_TRUE(released[0]);
+
+  video_stream_encoder_->Stop();
+
+  // The second encoder should also be released after Stop().
+  EXPECT_TRUE(released[1]);
+}
+
 TEST_F(VideoStreamEncoderTest, BitrateLimitsChangeReconfigureRateAllocator) {
   video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
       kTargetBitrate, kTargetBitrate, 0, 0, 0);