[WebCodecs] Feed VideoEncoderInfo to blink::VideoEncoder

Expose VideoEncoderInfo via media::VideoEncoder so that it can be
consumed by blink::VideoEncoder for all underlying encoder
implementations in a uniform way.

Use VideoEncoderInfo to inform blink::VideoEncoder about the underlying
encoder's frame delay and input capacity. This allows us to fix an issue
that occurred on macOS with the VideoToolbox encoder in SW mode for the
Main and High H.264 profiles. In this case, the encoder frame delay
exceeded the hard-coded limit on encodes in flight within
blink::VideoEncoder, preventing it from obtaining any output from
VideoToolbox.

Bug: 1383643,1378157
Change-Id: Ie244b07d19e1cc3296ebc40a8e41e8e275716765
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4075957
Reviewed-by: Brian Sheedy <bsheedy@chromium.org>
Commit-Queue: Wojciech Dzier┼╝anowski <wdzierzanowski@opera.com>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1085834}
diff --git a/chromeos/ash/services/recording/recording_encoder_muxer.cc b/chromeos/ash/services/recording/recording_encoder_muxer.cc
index 29d3722..eb33546 100644
--- a/chromeos/ash/services/recording/recording_encoder_muxer.cc
+++ b/chromeos/ash/services/recording/recording_encoder_muxer.cc
@@ -255,6 +255,7 @@
   video_encoder_ = std::make_unique<media::VpxVideoEncoder>();
   video_encoder_->Initialize(
       media::VP8PROFILE_ANY, video_encoder_options,
+      /*info_cb=*/base::DoNothing(),
       base::BindRepeating(&RecordingEncoderMuxer::OnVideoEncoderOutput,
                           weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&RecordingEncoderMuxer::OnVideoEncoderInitialized,
diff --git a/content/test/gpu/gpu_tests/webcodecs_integration_test.py b/content/test/gpu/gpu_tests/webcodecs_integration_test.py
index ba5e515..858623e 100644
--- a/content/test/gpu/gpu_tests/webcodecs_integration_test.py
+++ b/content/test/gpu/gpu_tests/webcodecs_integration_test.py
@@ -114,7 +114,9 @@
                  }])
 
     for source_type in frame_sources:
-      for codec in video_codecs:
+      # Also verify we can deal with the encoder's frame delay that we can
+      # encounter for the AVC High profile (avc1.64).
+      for codec in video_codecs + ['avc1.64001E']:
         for acc in accelerations:
           args = (source_type, codec, acc)
           yield ('WebCodecs_Encode_%s_%s_%s' % args, 'encode.html', [{
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 6ee53a5..c00130f 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -253,8 +253,6 @@
     "null_video_sink.h",
     "offloading_audio_encoder.cc",
     "offloading_audio_encoder.h",
-    "offloading_video_encoder.cc",
-    "offloading_video_encoder.h",
     "output_device_info.cc",
     "output_device_info.h",
     "overlay_info.cc",
@@ -611,7 +609,6 @@
     "multi_channel_resampler_unittest.cc",
     "null_video_sink_unittest.cc",
     "offloading_audio_encoder_unittest.cc",
-    "offloading_video_encoder_unittest.cc",
     "pipeline_impl_unittest.cc",
     "ranges_unittest.cc",
     "reentrancy_checker_unittest.cc",
diff --git a/media/base/async_destroy_video_encoder.h b/media/base/async_destroy_video_encoder.h
index d6ab762..39ae18ac 100644
--- a/media/base/async_destroy_video_encoder.h
+++ b/media/base/async_destroy_video_encoder.h
@@ -38,11 +38,12 @@
 
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override {
     DCHECK(wrapped_encoder_);
-    wrapped_encoder_->Initialize(profile, options, std::move(output_cb),
-                                 std::move(done_cb));
+    wrapped_encoder_->Initialize(profile, options, std::move(info_cb),
+                                 std::move(output_cb), std::move(done_cb));
   }
 
   void Encode(scoped_refptr<VideoFrame> frame,
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index d6ffeb6..78c84f1 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -296,19 +296,19 @@
   // AudioEncoder implementation.
   MOCK_METHOD(void,
               Initialize,
-              (const AudioEncoder::Options& options,
-               AudioEncoder::OutputCB output_cb,
-               AudioEncoder::EncoderStatusCB done_cb),
+              (const Options& options,
+               OutputCB output_cb,
+               EncoderStatusCB done_cb),
               (override));
 
   MOCK_METHOD(void,
               Encode,
               (std::unique_ptr<AudioBus> audio_bus,
                base::TimeTicks capture_time,
-               AudioEncoder::EncoderStatusCB done_cb),
+               EncoderStatusCB done_cb),
               (override));
 
-  MOCK_METHOD(void, Flush, (AudioEncoder::EncoderStatusCB done_cb), (override));
+  MOCK_METHOD(void, Flush, (EncoderStatusCB done_cb), (override));
   MOCK_METHOD(void, DisablePostedCallbacks, (), (override));
 
   // A function for mocking destructor calls
@@ -328,26 +328,27 @@
   MOCK_METHOD(void,
               Initialize,
               (VideoCodecProfile profile,
-               const VideoEncoder::Options& options,
-               VideoEncoder::OutputCB output_cb,
-               VideoEncoder::EncoderStatusCB done_cb),
+               const Options& options,
+               EncoderInfoCB info_cb,
+               OutputCB output_cb,
+               EncoderStatusCB done_cb),
               (override));
 
   MOCK_METHOD(void,
               Encode,
               (scoped_refptr<VideoFrame> frame,
                bool key_frame,
-               VideoEncoder::EncoderStatusCB done_cb),
+               EncoderStatusCB done_cb),
               (override));
 
   MOCK_METHOD(void,
               ChangeOptions,
-              (const VideoEncoder::Options& options,
-               VideoEncoder::OutputCB output_cb,
-               VideoEncoder::EncoderStatusCB done_cb),
+              (const Options& options,
+               OutputCB output_cb,
+               EncoderStatusCB done_cb),
               (override));
 
-  MOCK_METHOD(void, Flush, (VideoEncoder::EncoderStatusCB done_cb), (override));
+  MOCK_METHOD(void, Flush, (EncoderStatusCB done_cb), (override));
   MOCK_METHOD(void, DisablePostedCallbacks, (), (override));
 
   // A function for mocking destructor calls
diff --git a/media/base/video_encoder.cc b/media/base/video_encoder.cc
index 3f0b7e22..20817f1d 100644
--- a/media/base/video_encoder.cc
+++ b/media/base/video_encoder.cc
@@ -6,7 +6,6 @@
 
 #include "base/cxx17_backports.h"
 #include "base/numerics/clamped_math.h"
-#include "media/base/bind_to_current_loop.h"
 #include "media/base/video_frame.h"
 
 namespace media {
@@ -47,16 +46,4 @@
   post_callbacks_ = false;
 }
 
-VideoEncoder::OutputCB VideoEncoder::BindCallbackToCurrentLoopIfNeeded(
-    OutputCB&& callback) {
-  return post_callbacks_ ? BindToCurrentLoop(std::move(callback))
-                         : std::move(callback);
-}
-
-VideoEncoder::EncoderStatusCB VideoEncoder::BindCallbackToCurrentLoopIfNeeded(
-    EncoderStatusCB&& callback) {
-  return post_callbacks_ ? BindToCurrentLoop(std::move(callback))
-                         : std::move(callback);
-}
-
 }  // namespace media
diff --git a/media/base/video_encoder.h b/media/base/video_encoder.h
index 1678a7c..83456ee 100644
--- a/media/base/video_encoder.h
+++ b/media/base/video_encoder.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/time/time.h"
+#include "media/base/bind_to_current_loop.h"
 #include "media/base/bitrate.h"
 #include "media/base/encoder_status.h"
 #include "media/base/media_export.h"
@@ -18,6 +19,7 @@
 
 namespace media {
 
+struct VideoEncoderInfo;
 class VideoFrame;
 
 MEDIA_EXPORT uint32_t GetDefaultVideoEncodeBitrate(gfx::Size frame_size,
@@ -84,6 +86,11 @@
   // decoder config.
   using CodecDescription = std::vector<uint8_t>;
 
+  // Provides the VideoEncoder client with information about the specific
+  // encoder implementation.
+  using EncoderInfoCB =
+      base::RepeatingCallback<void(const VideoEncoderInfo& encoder_info)>;
+
   // Callback for VideoEncoder to report an encoded video frame whenever it
   // becomes available.
   using OutputCB =
@@ -116,6 +123,7 @@
   // 2) No VideoEncoder calls should be made before |done_cb| is executed.
   virtual void Initialize(VideoCodecProfile profile,
                           const Options& options,
+                          EncoderInfoCB info_cb,
                           OutputCB output_cb,
                           EncoderStatusCB done_cb) = 0;
 
@@ -150,17 +158,20 @@
   // produced via |output_cb| and calls |dene_cb| after that.
   virtual void Flush(EncoderStatusCB done_cb) = 0;
 
-  // Normally VideoEncoder implementations aren't supposed to call OutputCB and
-  // EncoderStatusCB directly from inside any of VideoEncoder's methods.
-  // This method tells VideoEncoder that all callbacks can be called directly
-  // from within its methods. It saves extra thread hops if it's known that
-  // all callbacks already point to a task runner different from
-  // the current one.
+  // Normally VideoEncoder implementations aren't supposed to call
+  // EncoderInfoCB, OutputCB, and EncoderStatusCB directly from inside any of
+  // VideoEncoder's methods.  This method tells VideoEncoder that all callbacks
+  // can be called directly from within its methods. It saves extra thread hops
+  // if it's known that all callbacks already point to a task runner different
+  // from the current one.
   virtual void DisablePostedCallbacks();
 
  protected:
-  OutputCB BindCallbackToCurrentLoopIfNeeded(OutputCB&& callback);
-  EncoderStatusCB BindCallbackToCurrentLoopIfNeeded(EncoderStatusCB&& callback);
+  template <typename Callback>
+  Callback BindCallbackToCurrentLoopIfNeeded(Callback callback) {
+    return post_callbacks_ ? BindToCurrentLoop(std::move(callback))
+                           : std::move(callback);
+  }
 
  private:
   bool post_callbacks_ = true;
diff --git a/media/capture/video/video_capture_buffer_pool_util.cc b/media/capture/video/video_capture_buffer_pool_util.cc
index 0cd22f1..0af0a15 100644
--- a/media/capture/video/video_capture_buffer_pool_util.cc
+++ b/media/capture/video/video_capture_buffer_pool_util.cc
@@ -23,7 +23,9 @@
 #if BUILDFLAG(IS_MAC)
   // On macOS, we allow a few more buffers as it's routinely observed that it
   // runs out of three when just displaying 60 FPS media in a video element.
-  max_buffer_count = 10;
+  // Also, this must be greater than the frame delay of VideoToolbox encoder
+  // for AVC High Profile.
+  max_buffer_count = 15;
 #elif BUILDFLAG(IS_CHROMEOS_ASH)
   // On Chrome OS with MIPI cameras running on HAL v3, there can be four
   // concurrent streams of camera pipeline depth ~6. We allow at most 36 buffers
diff --git a/media/gpu/mac/vt_video_encode_accelerator_mac.cc b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
index 0e0a05720..46a570a 100644
--- a/media/gpu/mac/vt_video_encode_accelerator_mac.cc
+++ b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
@@ -145,6 +145,56 @@
   return result;
 }
 
+VideoEncoderInfo GetVideoEncoderInfo(VTSessionRef compression_session,
+                                     VideoCodecProfile profile) {
+  VideoEncoderInfo info;
+  info.implementation_name = "VideoToolbox";
+  info.is_hardware_accelerated = false;
+
+  base::ScopedCFTypeRef<CFBooleanRef> cf_using_hardware;
+  if (VTSessionCopyProperty(
+          compression_session,
+          kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder,
+          kCFAllocatorDefault, cf_using_hardware.InitializeInto()) == 0) {
+    info.is_hardware_accelerated = CFBooleanGetValue(cf_using_hardware);
+  }
+
+  absl::optional<int> max_frame_delay_property;
+  base::ScopedCFTypeRef<CFNumberRef> max_frame_delay_count;
+  if (VTSessionCopyProperty(
+          compression_session, kVTCompressionPropertyKey_MaxFrameDelayCount,
+          kCFAllocatorDefault, max_frame_delay_count.InitializeInto()) == 0) {
+    int32_t frame_delay;
+    if (CFNumberGetValue(max_frame_delay_count, kCFNumberSInt32Type,
+                         &frame_delay) &&
+        frame_delay != kVTUnlimitedFrameDelayCount) {
+      max_frame_delay_property = frame_delay;
+    }
+  }
+  // Not all VideoToolbox encoders are created equal. The numbers below match
+  // the characteristics of an Apple Silicon M1 laptop. It has been noted that,
+  // for example, the HW encoder in a 2014 (Intel) machine has a smaller
+  // capacity. And while overestimating the capacity is not a problem,
+  // underestimating the frame delay is, so these numbers might need tweaking
+  // in the face of new evidence.
+  if (info.is_hardware_accelerated) {
+    info.frame_delay = 0;
+    info.input_capacity = 10;
+  } else {
+    info.frame_delay =
+        profile == H264PROFILE_BASELINE || profile == HEVCPROFILE_MAIN ? 0 : 13;
+    info.input_capacity = info.frame_delay.value() + 4;
+  }
+  if (max_frame_delay_property.has_value()) {
+    info.frame_delay =
+        std::min(info.frame_delay.value(), max_frame_delay_property.value());
+    info.input_capacity =
+        std::min(info.input_capacity.value(), max_frame_delay_property.value());
+  }
+
+  return info;
+}
+
 }  // namespace
 
 struct VTVideoEncodeAccelerator::InProgressFrameEncode {
@@ -364,21 +414,19 @@
     return false;
   }
 
-  // Report whether hardware decode is being used.
-  bool using_hardware = false;
-  base::ScopedCFTypeRef<CFBooleanRef> cf_using_hardware;
-  if (VTSessionCopyProperty(
-          compression_session_,
-          kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder,
-          kCFAllocatorDefault, cf_using_hardware.InitializeInto()) == 0) {
-    using_hardware = CFBooleanGetValue(cf_using_hardware);
-  }
-  if (!using_hardware) {
+  auto encoder_info = GetVideoEncoderInfo(compression_session_, profile_);
+
+  // Report whether hardware encode is being used.
+  if (!encoder_info.is_hardware_accelerated) {
     MEDIA_LOG(INFO, media_log.get())
         << "VideoToolbox selected a software encoder.";
   }
 
   client_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&Client::NotifyEncoderInfoChange, client_, encoder_info));
+
+  client_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&Client::RequireBitstreamBuffers, client_,
                                 kNumInputBuffers, input_visible_size_,
                                 bitstream_buffer_size_));
diff --git a/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc b/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc
index 23433a6..6ff4e7b 100644
--- a/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc
+++ b/media/mojo/mojom/video_encode_accelerator_mojom_traits_unittest.cc
@@ -35,6 +35,8 @@
 TEST(VideoEncoderInfoStructTraitTest, RoundTrip) {
   ::media::VideoEncoderInfo input;
   input.implementation_name = "FakeVideoEncodeAccelerator";
+  // Set `frame_delay` but leave `input_capacity` empty.
+  input.frame_delay = 3;
   // FPS allocation.
   for (size_t i = 0; i < ::media::VideoEncoderInfo::kMaxSpatialLayers; ++i)
     input.fps_allocation[i] = {5, 5, 10};
diff --git a/media/mojo/mojom/video_encoder_info.mojom b/media/mojo/mojom/video_encoder_info.mojom
index fa97eac..e102edc 100644
--- a/media/mojo/mojom/video_encoder_info.mojom
+++ b/media/mojo/mojom/video_encoder_info.mojom
@@ -15,9 +15,16 @@
   int32 max_bitrate_bps;
 };
 
+// TODO(crbug.com/657632): Remove |has_*| values and use nullable types.
 struct VideoEncoderInfo {
   string implementation_name;
 
+  bool has_frame_delay = false;
+  int32 frame_delay;
+
+  bool has_input_capacity = false;
+  int32 input_capacity;
+
   bool supports_native_handle;
   bool has_trusted_rate_controller;
   bool is_hardware_accelerated;
diff --git a/media/mojo/mojom/video_encoder_info_mojom_traits.cc b/media/mojo/mojom/video_encoder_info_mojom_traits.cc
index 405fd906..6eeca02 100644
--- a/media/mojo/mojom/video_encoder_info_mojom_traits.cc
+++ b/media/mojo/mojom/video_encoder_info_mojom_traits.cc
@@ -4,6 +4,8 @@
 
 #include "media/mojo/mojom/video_encoder_info_mojom_traits.h"
 
+#include "media/mojo/mojom/video_encoder_info.mojom.h"
+
 namespace mojo {
 
 // static
@@ -36,6 +38,16 @@
   if (!data.ReadImplementationName(&out->implementation_name))
     return false;
 
+  if (data.has_frame_delay())
+    out->frame_delay = data.frame_delay();
+  else
+    out->frame_delay.reset();
+
+  if (data.has_input_capacity())
+    out->input_capacity = data.input_capacity();
+  else
+    out->input_capacity.reset();
+
   base::span<std::vector<uint8_t>> fps_allocation(out->fps_allocation);
   if (!data.ReadFpsAllocation(&fps_allocation))
     return false;
diff --git a/media/mojo/mojom/video_encoder_info_mojom_traits.h b/media/mojo/mojom/video_encoder_info_mojom_traits.h
index 63de9bd..5e0da7b6b 100644
--- a/media/mojo/mojom/video_encoder_info_mojom_traits.h
+++ b/media/mojo/mojom/video_encoder_info_mojom_traits.h
@@ -44,6 +44,22 @@
       const media::VideoEncoderInfo& video_encoder_info) {
     return video_encoder_info.implementation_name;
   }
+  static bool has_frame_delay(
+      const media::VideoEncoderInfo& video_encoder_info) {
+    return video_encoder_info.frame_delay.has_value();
+  }
+  static int32_t frame_delay(
+      const media::VideoEncoderInfo& video_encoder_info) {
+    return video_encoder_info.frame_delay.value_or(0);
+  }
+  static bool has_input_capacity(
+      const media::VideoEncoderInfo& video_encoder_info) {
+    return video_encoder_info.input_capacity.has_value();
+  }
+  static int32_t input_capacity(
+      const media::VideoEncoderInfo& video_encoder_info) {
+    return video_encoder_info.input_capacity.value_or(0);
+  }
   static bool supports_native_handle(
       const media::VideoEncoderInfo& video_encoder_info) {
     return video_encoder_info.supports_native_handle;
diff --git a/media/video/BUILD.gn b/media/video/BUILD.gn
index ce155164..fc45b5c 100644
--- a/media/video/BUILD.gn
+++ b/media/video/BUILD.gn
@@ -30,6 +30,8 @@
     "h264_poc.h",
     "half_float_maker.cc",
     "half_float_maker.h",
+    "offloading_video_encoder.cc",
+    "offloading_video_encoder.h",
     "picture.cc",
     "picture.h",
     "renderable_gpu_memory_buffer_video_frame_pool.cc",
@@ -143,6 +145,7 @@
     "h264_parser_unittest.cc",
     "h264_poc_unittest.cc",
     "half_float_maker_unittest.cc",
+    "offloading_video_encoder_unittest.cc",
     "renderable_gpu_memory_buffer_video_frame_pool_unittest.cc",
     "software_video_encoder_test.cc",
     "video_encode_accelerator_adapter_test.cc",
diff --git a/media/video/av1_video_encoder.cc b/media/video/av1_video_encoder.cc
index b5a075a..9593234 100644
--- a/media/video/av1_video_encoder.cc
+++ b/media/video/av1_video_encoder.cc
@@ -18,6 +18,7 @@
 #include "media/base/video_color_space.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
+#include "media/video/video_encoder_info.h"
 #include "third_party/libaom/source/libaom/aom/aomcx.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
 
@@ -176,6 +177,7 @@
 
 void Av1VideoEncoder::Initialize(VideoCodecProfile profile,
                                  const Options& options,
+                                 EncoderInfoCB info_cb,
                                  OutputCB output_cb,
                                  EncoderStatusCB done_cb) {
   done_cb = BindCallbackToCurrentLoopIfNeeded(std::move(done_cb));
@@ -278,6 +280,12 @@
   originally_configured_size_ = options.frame_size;
   output_cb_ = BindCallbackToCurrentLoopIfNeeded(std::move(output_cb));
   codec_ = std::move(codec);
+
+  VideoEncoderInfo info;
+  info.implementation_name = "Av1VideoEncoder";
+  info.is_hardware_accelerated = false;
+  BindCallbackToCurrentLoopIfNeeded(std::move(info_cb)).Run(info);
+
   std::move(done_cb).Run(EncoderStatus::Codes::kOk);
 }
 
diff --git a/media/video/av1_video_encoder.h b/media/video/av1_video_encoder.h
index c6080ceb..a07e124 100644
--- a/media/video/av1_video_encoder.h
+++ b/media/video/av1_video_encoder.h
@@ -27,6 +27,7 @@
   // VideoDecoder implementation.
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override;
   void Encode(scoped_refptr<VideoFrame> frame,
diff --git a/media/video/fake_video_encode_accelerator.cc b/media/video/fake_video_encode_accelerator.cc
index ad1b941..845db97 100644
--- a/media/video/fake_video_encode_accelerator.cc
+++ b/media/video/fake_video_encode_accelerator.cc
@@ -115,6 +115,19 @@
   will_encoding_succeed_ = will_encoding_succeed;
 }
 
+void FakeVideoEncodeAccelerator::NotifyEncoderInfoChange(
+    const VideoEncoderInfo& info) {
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&FakeVideoEncodeAccelerator::DoNotifyEncoderInfoChange,
+                     weak_this_factory_.GetWeakPtr(), info));
+}
+
+void FakeVideoEncodeAccelerator::DoNotifyEncoderInfoChange(
+    const VideoEncoderInfo& info) {
+  client_->NotifyEncoderInfoChange(info);
+}
+
 void FakeVideoEncodeAccelerator::DoRequireBitstreamBuffers(
     unsigned int input_count,
     const gfx::Size& input_coded_size,
diff --git a/media/video/fake_video_encode_accelerator.h b/media/video/fake_video_encode_accelerator.h
index 693ac30..1e657df 100644
--- a/media/video/fake_video_encode_accelerator.h
+++ b/media/video/fake_video_encode_accelerator.h
@@ -84,7 +84,10 @@
 
   void SupportResize() { resize_supported_ = true; }
 
+  void NotifyEncoderInfoChange(const VideoEncoderInfo& info);
+
  private:
+  void DoNotifyEncoderInfoChange(const VideoEncoderInfo& info);
   void DoRequireBitstreamBuffers(unsigned int input_count,
                                  const gfx::Size& input_coded_size,
                                  size_t output_buffer_size) const;
diff --git a/media/base/offloading_video_encoder.cc b/media/video/offloading_video_encoder.cc
similarity index 94%
rename from media/base/offloading_video_encoder.cc
rename to media/video/offloading_video_encoder.cc
index 6aad9a9..dfa160e7 100644
--- a/media/base/offloading_video_encoder.cc
+++ b/media/video/offloading_video_encoder.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "media/base/offloading_video_encoder.h"
+#include "media/video/offloading_video_encoder.h"
 
 #include "base/task/bind_post_task.h"
 #include "base/task/sequenced_task_runner.h"
@@ -10,6 +10,7 @@
 #include "base/task/thread_pool.h"
 #include "base/trace_event/trace_event.h"
 #include "media/base/video_frame.h"
+#include "media/video/video_encoder_info.h"
 
 namespace media {
 
@@ -40,6 +41,7 @@
 
 void OffloadingVideoEncoder::Initialize(VideoCodecProfile profile,
                                         const Options& options,
+                                        EncoderInfoCB info_cb,
                                         OutputCB output_cb,
                                         EncoderStatusCB done_cb) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -47,6 +49,7 @@
       FROM_HERE,
       base::BindOnce(&VideoEncoder::Initialize,
                      base::Unretained(wrapped_encoder_.get()), profile, options,
+                     WrapCallback(std::move(info_cb)),
                      WrapCallback(std::move(output_cb)),
                      WrapCallback(std::move(done_cb))));
 }
diff --git a/media/base/offloading_video_encoder.h b/media/video/offloading_video_encoder.h
similarity index 91%
rename from media/base/offloading_video_encoder.h
rename to media/video/offloading_video_encoder.h
index 6012988..3864493 100644
--- a/media/base/offloading_video_encoder.h
+++ b/media/video/offloading_video_encoder.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef MEDIA_BASE_OFFLOADING_VIDEO_ENCODER_H_
-#define MEDIA_BASE_OFFLOADING_VIDEO_ENCODER_H_
+#ifndef MEDIA_VIDEO_OFFLOADING_VIDEO_ENCODER_H_
+#define MEDIA_VIDEO_OFFLOADING_VIDEO_ENCODER_H_
 
 #include <memory>
 #include <type_traits>
@@ -39,6 +39,7 @@
 
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override;
 
@@ -64,4 +65,4 @@
 
 }  // namespace media
 
-#endif  // MEDIA_BASE_OFFLOADING_VIDEO_ENCODER_H_
+#endif  // MEDIA_VIDEO_OFFLOADING_VIDEO_ENCODER_H_
diff --git a/media/base/offloading_video_encoder_unittest.cc b/media/video/offloading_video_encoder_unittest.cc
similarity index 89%
rename from media/base/offloading_video_encoder_unittest.cc
rename to media/video/offloading_video_encoder_unittest.cc
index 2ceab217..2d0ac3c 100644
--- a/media/base/offloading_video_encoder_unittest.cc
+++ b/media/video/offloading_video_encoder_unittest.cc
@@ -16,8 +16,9 @@
 #include "base/test/task_environment.h"
 #include "media/base/media_util.h"
 #include "media/base/mock_filters.h"
-#include "media/base/offloading_video_encoder.h"
 #include "media/base/video_types.h"
+#include "media/video/offloading_video_encoder.h"
+#include "media/video/video_encoder_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::base::test::RunCallback;
@@ -54,10 +55,16 @@
 };
 
 TEST_F(OffloadingVideoEncoderTest, Initialize) {
+  bool called_info = false;
   bool called_done = false;
   bool called_output = false;
   VideoEncoder::Options options;
   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
+  VideoEncoder::EncoderInfoCB info_cb =
+      base::BindLambdaForTesting([&](const VideoEncoderInfo& info) {
+        EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence());
+        called_info = true;
+      });
   VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
       [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
         EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence());
@@ -69,18 +76,20 @@
         called_done = true;
       });
 
-  EXPECT_CALL(*mock_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*mock_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([this](VideoCodecProfile profile,
                               const VideoEncoder::Options& options,
+                              VideoEncoder::EncoderInfoCB info_cb,
                               VideoEncoder::OutputCB output_cb,
                               VideoEncoder::EncoderStatusCB done_cb) {
         EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence());
+        info_cb.Run(VideoEncoderInfo());
         std::move(done_cb).Run(EncoderStatus::Codes::kOk);
         std::move(output_cb).Run(VideoEncoderOutput(), {});
       }));
 
-  offloading_encoder_->Initialize(profile, options, std::move(output_cb),
-                                  std::move(done_cb));
+  offloading_encoder_->Initialize(profile, options, std::move(info_cb),
+                                  std::move(output_cb), std::move(done_cb));
   RunLoop();
   EXPECT_TRUE(called_done);
   EXPECT_TRUE(called_output);
diff --git a/media/video/openh264_video_encoder.cc b/media/video/openh264_video_encoder.cc
index 3e178a23..ce4aceb 100644
--- a/media/video/openh264_video_encoder.cc
+++ b/media/video/openh264_video_encoder.cc
@@ -15,6 +15,7 @@
 #include "media/base/svc_scalability_mode.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
+#include "media/video/video_encoder_info.h"
 
 namespace media {
 
@@ -126,6 +127,7 @@
 
 void OpenH264VideoEncoder::Initialize(VideoCodecProfile profile,
                                       const Options& options,
+                                      EncoderInfoCB info_cb,
                                       OutputCB output_cb,
                                       EncoderStatusCB done_cb) {
   done_cb = BindCallbackToCurrentLoopIfNeeded(std::move(done_cb));
@@ -195,6 +197,12 @@
   options_ = options;
   output_cb_ = BindCallbackToCurrentLoopIfNeeded(std::move(output_cb));
   codec_ = std::move(codec);
+
+  VideoEncoderInfo info;
+  info.implementation_name = "OpenH264VideoEncoder";
+  info.is_hardware_accelerated = false;
+  BindCallbackToCurrentLoopIfNeeded(std::move(info_cb)).Run(info);
+
   std::move(done_cb).Run(EncoderStatus::Codes::kOk);
 }
 
diff --git a/media/video/openh264_video_encoder.h b/media/video/openh264_video_encoder.h
index 44bc4d16..4986c6b 100644
--- a/media/video/openh264_video_encoder.h
+++ b/media/video/openh264_video_encoder.h
@@ -25,6 +25,7 @@
   // VideoDecoder implementation.
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override;
   void Encode(scoped_refptr<VideoFrame> frame,
diff --git a/media/video/software_video_encoder_test.cc b/media/video/software_video_encoder_test.cc
index fa3e7435..4a026cbc 100644
--- a/media/video/software_video_encoder_test.cc
+++ b/media/video/software_video_encoder_test.cc
@@ -319,8 +319,8 @@
 
   VideoEncoder::EncoderStatusCB flush_cb = base::BindLambdaForTesting(
       [&](EncoderStatus error) { flush_called = true; });
-  encoder_->Initialize(profile_, options, VideoEncoder::OutputCB(),
-                       std::move(init_cb));
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       /*output_cb=*/base::DoNothing(), std::move(init_cb));
   encoder_->Flush(std::move(flush_cb));
   EXPECT_TRUE(init_called);
   EXPECT_TRUE(flush_called);
@@ -335,8 +335,8 @@
         output_called = true;
       });
 
-  encoder_->Initialize(profile_, options, std::move(output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(output_cb), ValidatingStatusCB());
   RunUntilIdle();
   encoder_->Flush(ValidatingStatusCB());
   RunUntilIdle();
@@ -357,8 +357,8 @@
         outputs_count++;
       });
 
-  encoder_->Initialize(profile_, options, std::move(output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   for (int i = 0; i < frames; i++) {
@@ -384,8 +384,8 @@
         outputs_count++;
       });
 
-  encoder_->Initialize(profile_, options, std::move(output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   auto frame1 = CreateFrame(gfx::Size(320, 200), pixel_format_, 0 * sec);
@@ -420,8 +420,8 @@
         outputs_count++;
       });
 
-  encoder_->Initialize(profile_, options, std::move(output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(output_cb), ValidatingStatusCB());
 
   RunUntilIdle();
   uint32_t color = 0x964050;
@@ -472,8 +472,8 @@
 
   PrepareDecoder(options.frame_size, std::move(decoder_output_cb));
 
-  encoder_->Initialize(profile_, options, std::move(encoder_output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(encoder_output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   uint32_t color = 0x964050;
@@ -526,8 +526,8 @@
         chunks.push_back(std::move(output));
       });
 
-  encoder_->Initialize(profile_, options, std::move(encoder_output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(encoder_output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   uint32_t color = 0x964050;
@@ -618,8 +618,8 @@
         chunks.push_back({std::move(output), options.frame_size});
       });
 
-  encoder_->Initialize(profile_, options, std::move(encoder_output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(encoder_output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   uint32_t color = 0x0080FF;
@@ -725,8 +725,8 @@
         outputs_count++;
       });
 
-  encoder_->Initialize(profile_, options, std::move(output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   auto frame1 = CreateFrame(options.frame_size, pixel_format_, 0 * sec);
@@ -764,8 +764,8 @@
         outputs_count++;
       });
 
-  encoder_->Initialize(profile_, options, std::move(output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   auto frame1 = CreateFrame(options.frame_size, pixel_format_, 0 * sec);
@@ -806,8 +806,8 @@
         chunks.push_back({std::move(output), std::move(desc)});
       });
 
-  encoder_->Initialize(profile_, options, std::move(encoder_output_cb),
-                       ValidatingStatusCB());
+  encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                       std::move(encoder_output_cb), ValidatingStatusCB());
   RunUntilIdle();
 
   uint32_t color = 0x964050;
diff --git a/media/video/video_encode_accelerator_adapter.cc b/media/video/video_encode_accelerator_adapter.cc
index 00a47d4..43f6817 100644
--- a/media/video/video_encode_accelerator_adapter.cc
+++ b/media/video/video_encode_accelerator_adapter.cc
@@ -34,6 +34,7 @@
         // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
 #include "media/video/gpu_video_accelerator_factories.h"
+#include "media/video/video_encoder_info.h"
 
 namespace media {
 
@@ -334,6 +335,7 @@
 
 void VideoEncodeAcceleratorAdapter::Initialize(VideoCodecProfile profile,
                                                const Options& options,
+                                               EncoderInfoCB info_cb,
                                                OutputCB output_cb,
                                                EncoderStatusCB done_cb) {
   DCHECK(!accelerator_task_runner_->RunsTasksInCurrentSequence());
@@ -342,13 +344,14 @@
       base::BindOnce(
           &VideoEncodeAcceleratorAdapter::InitializeOnAcceleratorThread,
           base::Unretained(this), profile, options,
-          WrapCallback(std::move(output_cb)),
+          WrapCallback(std::move(info_cb)), WrapCallback(std::move(output_cb)),
           WrapCallback(std::move(done_cb))));
 }
 
 void VideoEncodeAcceleratorAdapter::InitializeOnAcceleratorThread(
     VideoCodecProfile profile,
     const Options& options,
+    EncoderInfoCB info_cb,
     OutputCB output_cb,
     EncoderStatusCB done_cb) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_);
@@ -410,6 +413,7 @@
   profile_ = profile;
   supported_rc_modes_ = supported_rc_modes;
   options_ = options;
+  info_cb_ = std::move(info_cb);
   output_cb_ = std::move(output_cb);
   state_ = State::kWaitingForFirstFrame;
 
@@ -879,11 +883,8 @@
 
 void VideoEncodeAcceleratorAdapter::NotifyEncoderInfoChange(
     const VideoEncoderInfo& info) {
-  // TODO(crbug.com/1378157): More VideoEncoderInfo can be fetched from VEA
-  // beneath. Here the accurate encoder name is updated to MediaLog. So things
-  // like media tab in Developer tools can show the actual encoder name.
-  media_log_->SetProperty<media::MediaLogProperty::kVideoEncoderName>(
-      info.implementation_name);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_);
+  info_cb_.Run(info);
 }
 
 void VideoEncodeAcceleratorAdapter::InitCompleted(EncoderStatus status) {
diff --git a/media/video/video_encode_accelerator_adapter.h b/media/video/video_encode_accelerator_adapter.h
index 4cf209fb0..1f9ca9c 100644
--- a/media/video/video_encode_accelerator_adapter.h
+++ b/media/video/video_encode_accelerator_adapter.h
@@ -61,6 +61,7 @@
   // VideoEncoder implementation.
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override;
   void Encode(scoped_refptr<VideoFrame> frame,
@@ -109,6 +110,7 @@
   void InitCompleted(EncoderStatus status);
   void InitializeOnAcceleratorThread(VideoCodecProfile profile,
                                      const Options& options,
+                                     EncoderInfoCB info_cb,
                                      OutputCB output_cb,
                                      EncoderStatusCB done_cb);
   void InitializeInternalOnAcceleratorThread();
@@ -183,6 +185,7 @@
   VideoEncodeAccelerator::SupportedRateControlMode supported_rc_modes_ =
       VideoEncodeAccelerator::kNoMode;
   Options options_;
+  EncoderInfoCB info_cb_;
   OutputCB output_cb_;
 
   gfx::Size input_coded_size_;
diff --git a/media/video/video_encode_accelerator_adapter_test.cc b/media/video/video_encode_accelerator_adapter_test.cc
index 15611b32..4921715 100644
--- a/media/video/video_encode_accelerator_adapter_test.cc
+++ b/media/video/video_encode_accelerator_adapter_test.cc
@@ -27,6 +27,7 @@
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "media/video/mock_gpu_video_accelerator_factories.h"
 #include "media/video/mock_video_encode_accelerator.h"
+#include "media/video/video_encoder_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libyuv/include/libyuv.h"
 #include "ui/gfx/color_space.h"
@@ -224,22 +225,24 @@
 TEST_F(VideoEncodeAcceleratorAdapterTest, PreInitialize) {
   VideoEncoder::Options options;
   options.frame_size = gfx::Size(640, 480);
-  VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
-      [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
-      });
 
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        /*output_cb=*/base::DoNothing(), ValidatingStatusCB());
   RunUntilIdle();
 }
 
 TEST_F(VideoEncodeAcceleratorAdapterTest, InitializeAfterFirstFrame) {
   VideoEncoder::Options options;
   options.frame_size = gfx::Size(640, 480);
-  int outputs_count = 0;
   auto pixel_format = PIXEL_FORMAT_I420;
   const gfx::ColorSpace expected_color_space =
       ExpectedColorSpace(pixel_format, pixel_format);
+
+  bool info_cb_called = false;
+  VideoEncoder::EncoderInfoCB info_cb = base::BindLambdaForTesting(
+      [&](const VideoEncoderInfo& info) { info_cb_called = true; });
+
+  int outputs_count = 0;
   VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
       [&](VideoEncoderOutput output,
           absl::optional<VideoEncoder::CodecDescription>) {
@@ -254,14 +257,17 @@
         EXPECT_EQ(frame->coded_size(), options.frame_size);
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, std::move(info_cb),
+                        std::move(output_cb), ValidatingStatusCB());
 
   auto frame =
       CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
 
   adapter()->Encode(frame, true, ValidatingStatusCB());
   RunUntilIdle();
+  vea()->NotifyEncoderInfoChange(VideoEncoderInfo());
+  RunUntilIdle();
+  EXPECT_TRUE(info_cb_called);
   EXPECT_EQ(outputs_count, 1);
 }
 
@@ -312,8 +318,8 @@
         }
         return result;
       }));
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   auto frame1 =
       CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
@@ -359,8 +365,8 @@
         EXPECT_EQ(frame->coded_size(), options.frame_size);
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   auto frame =
       CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
@@ -392,8 +398,8 @@
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
   adapter()->Initialize(
-      VIDEO_CODEC_PROFILE_UNKNOWN, options, std::move(output_cb),
-      base::BindLambdaForTesting([](EncoderStatus s) {
+      VIDEO_CODEC_PROFILE_UNKNOWN, options, /*info_cb=*/base::DoNothing(),
+      std::move(output_cb), base::BindLambdaForTesting([](EncoderStatus s) {
         EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderInitializationError);
       }));
 
@@ -418,8 +424,8 @@
       base::BindLambdaForTesting(
           [&](EncoderStatus s) { EXPECT_FALSE(s.is_ok()); });
 
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   vea()->SetWillEncodingSucceed(false);
 
@@ -462,8 +468,8 @@
         EXPECT_EQ(frame->coded_size(), options.frame_size);
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   adapter()->Encode(small_frame, true, ValidatingStatusCB());
   adapter()->Encode(large_frame, false, ValidatingStatusCB());
@@ -492,8 +498,8 @@
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
   vea()->SupportResize();
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   auto frame1 =
       CreateGreenFrame(small_size, pixel_format, base::Milliseconds(1));
@@ -552,8 +558,8 @@
         EXPECT_EQ(frame->coded_size(), options.frame_size);
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   for (int frame_index = 0; frame_index < frames_to_encode; frame_index++) {
     gfx::Size size;
@@ -594,8 +600,8 @@
         size_t size = keyframe ? 1 : 0;  // Drop non-key frame
         return BitstreamBufferMetadata(size, keyframe, frame->timestamp());
       }));
-  adapter()->Initialize(profile_, options, std::move(output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(output_cb), ValidatingStatusCB());
 
   auto frame1 =
       CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
@@ -642,8 +648,8 @@
         EXPECT_EQ(frame->coded_size(), options.frame_size);
         return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
       }));
-  adapter()->Initialize(profile_, options, std::move(first_output_cb),
-                        ValidatingStatusCB());
+  adapter()->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
+                        std::move(first_output_cb), ValidatingStatusCB());
   // We must encode one frame before we can change options.
   auto first_frame =
       CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
diff --git a/media/video/video_encoder_fallback.cc b/media/video/video_encoder_fallback.cc
index 91cbcad..a9bc66e 100644
--- a/media/video/video_encoder_fallback.cc
+++ b/media/video/video_encoder_fallback.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/sequence_checker.h"
 #include "media/base/video_frame.h"
+#include "media/video/video_encoder_info.h"
 
 namespace media {
 
@@ -24,11 +25,13 @@
 
 void VideoEncoderFallback::Initialize(VideoCodecProfile profile,
                                       const Options& options,
+                                      EncoderInfoCB info_cb,
                                       OutputCB output_cb,
                                       EncoderStatusCB done_cb) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   init_done_cb_ = std::move(done_cb);
+  info_cb_ = std::move(info_cb);
   output_cb_ = std::move(output_cb);
   profile_ = profile;
   options_ = options;
@@ -45,6 +48,8 @@
 
   encoder_->Initialize(
       profile, options,
+      base::BindRepeating(&VideoEncoderFallback::CallInfo,
+                          weak_factory_.GetWeakPtr()),
       base::BindRepeating(&VideoEncoderFallback::CallOutput,
                           weak_factory_.GetWeakPtr()),
       base::BindOnce(done_callback, weak_factory_.GetWeakPtr()));
@@ -142,6 +147,8 @@
 
   encoder_->Initialize(
       profile_, options_,
+      base::BindRepeating(&VideoEncoderFallback::CallInfo,
+                          weak_factory_.GetWeakPtr()),
       base::BindRepeating(&VideoEncoderFallback::CallOutput,
                           weak_factory_.GetWeakPtr()),
       base::BindOnce(&VideoEncoderFallback::FallbackInitCompleted,
@@ -161,6 +168,8 @@
 
     encoder_->Initialize(
         profile_, options_,
+        base::BindRepeating(&VideoEncoderFallback::CallInfo,
+                            weak_factory_.GetWeakPtr()),
         base::BindRepeating(&VideoEncoderFallback::CallOutput,
                             weak_factory_.GetWeakPtr()),
         base::BindOnce(&VideoEncoderFallback::FallbackInitCompleted,
@@ -176,6 +185,10 @@
   }
 }
 
+void VideoEncoderFallback::CallInfo(const VideoEncoderInfo& encoder_info) {
+  info_cb_.Run(encoder_info);
+}
+
 void VideoEncoderFallback::CallOutput(VideoEncoderOutput output,
                                       absl::optional<CodecDescription> desc) {
   output_cb_.Run(std::move(output), std::move(desc));
diff --git a/media/video/video_encoder_fallback.h b/media/video/video_encoder_fallback.h
index 32dd682c..116cd87 100644
--- a/media/video/video_encoder_fallback.h
+++ b/media/video/video_encoder_fallback.h
@@ -32,6 +32,7 @@
   // VideoEncoder implementation.
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override;
   void Encode(scoped_refptr<VideoFrame> frame,
@@ -49,6 +50,7 @@
   PendingEncode MakePendingEncode(scoped_refptr<VideoFrame> frame,
                                   bool key_frame,
                                   EncoderStatusCB done_cb);
+  void CallInfo(const VideoEncoderInfo& info);
   void CallOutput(VideoEncoderOutput output,
                   absl::optional<CodecDescription> desc);
 
@@ -67,6 +69,7 @@
 
   CreateFallbackCB create_fallback_cb_;
   EncoderStatusCB init_done_cb_;
+  EncoderInfoCB info_cb_;
   OutputCB output_cb_;
   VideoCodecProfile profile_;
   Options options_;
diff --git a/media/video/video_encoder_fallback_test.cc b/media/video/video_encoder_fallback_test.cc
index c9dbb051..e2a748c 100644
--- a/media/video/video_encoder_fallback_test.cc
+++ b/media/video/video_encoder_fallback_test.cc
@@ -16,6 +16,7 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/mock_filters.h"
 #include "media/base/video_frame.h"
+#include "media/video/video_encoder_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -88,20 +89,28 @@
 };
 
 TEST_F(VideoEncoderFallbackTest, NoFallbackEncoding) {
-  int outputs = 0;
   VideoEncoder::Options options;
   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
+
+  int info_cb_count = 0;
+  VideoEncoder::EncoderInfoCB info_cb =
+      BindToCurrentLoop(base::BindLambdaForTesting(
+          [&](const VideoEncoderInfo& info) { info_cb_count++; }));
+
+  int outputs = 0;
   VideoEncoder::OutputCB output_cb =
       BindToCurrentLoop(base::BindLambdaForTesting(
           [&](VideoEncoderOutput,
               absl::optional<VideoEncoder::CodecDescription>) { outputs++; }));
   VideoEncoder::OutputCB saved_output_cb;
 
-  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
+        info_cb.Run(VideoEncoderInfo());
         saved_output_cb = std::move(output_cb);
         RunStatusCallbackAync(std::move(done_cb));
       }));
@@ -116,8 +125,8 @@
             RunStatusCallbackAync(std::move(done_cb));
           }));
 
-  fallback_encoder_->Initialize(profile, options, std::move(output_cb),
-                                ValidatingStatusCB());
+  fallback_encoder_->Initialize(profile, options, std::move(info_cb),
+                                std::move(output_cb), ValidatingStatusCB());
 
   RunLoop();
   for (int i = 0; i < kFrameCount; i++) {
@@ -128,15 +137,22 @@
   }
   RunLoop();
   EXPECT_FALSE(FallbackHappened());
+  EXPECT_EQ(info_cb_count, 1);
   EXPECT_EQ(outputs, kFrameCount);
 }
 
 // Test that VideoEncoderFallback can switch to a secondary encoder if
 // the main encoder fails to initialize.
 TEST_F(VideoEncoderFallbackTest, FallbackOnInitialize) {
-  int outputs = 0;
   VideoEncoder::Options options;
   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
+
+  int info_cb_count = 0;
+  VideoEncoder::EncoderInfoCB info_cb =
+      BindToCurrentLoop(base::BindLambdaForTesting(
+          [&](const VideoEncoderInfo& info) { info_cb_count++; }));
+
+  int outputs = 0;
   VideoEncoder::OutputCB output_cb =
       BindToCurrentLoop(base::BindLambdaForTesting(
           [&](VideoEncoderOutput,
@@ -144,9 +160,10 @@
   VideoEncoder::OutputCB saved_output_cb;
 
   // Initialize() on the main encoder should fail
-  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
         RunStatusCallbackAync(
@@ -155,11 +172,13 @@
       }));
 
   // Initialize() on the second encoder should succeed
-  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
+        info_cb.Run(VideoEncoderInfo());
         saved_output_cb = std::move(output_cb);
         RunStatusCallbackAync(std::move(done_cb));
       }));
@@ -175,8 +194,8 @@
             RunStatusCallbackAync(std::move(done_cb));
           }));
 
-  fallback_encoder_->Initialize(profile, options, std::move(output_cb),
-                                ValidatingStatusCB());
+  fallback_encoder_->Initialize(profile, options, std::move(info_cb),
+                                std::move(output_cb), ValidatingStatusCB());
 
   RunLoop();
   for (int i = 0; i < kFrameCount; i++) {
@@ -187,15 +206,23 @@
   }
   RunLoop();
   EXPECT_TRUE(FallbackHappened());
+  EXPECT_EQ(info_cb_count, 1);
   EXPECT_EQ(outputs, kFrameCount);
 }
 
 // Test that VideoEncoderFallback can switch to a secondary encoder if
 // the main encoder fails on encode.
 TEST_F(VideoEncoderFallbackTest, FallbackOnEncode) {
-  int outputs = 0;
   VideoEncoder::Options options;
   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
+
+  int info_cb_count = 0;
+  VideoEncoder::EncoderInfoCB info_cb =
+      BindToCurrentLoop(base::BindLambdaForTesting(
+          [&](const VideoEncoderInfo& info) { info_cb_count++; }));
+  VideoEncoder::EncoderInfoCB saved_info_cb;
+
+  int outputs = 0;
   VideoEncoder::OutputCB output_cb =
       BindToCurrentLoop(base::BindLambdaForTesting(
           [&](VideoEncoderOutput,
@@ -204,21 +231,26 @@
   VideoEncoder::OutputCB secondary_output_cb;
 
   // Initialize() on the main encoder should succeed
-  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
+        info_cb.Run(VideoEncoderInfo());
+        saved_info_cb = std::move(info_cb);
         primary_output_cb = std::move(output_cb);
         RunStatusCallbackAync(std::move(done_cb));
       }));
 
   // Initialize() on the second encoder should succeed as well
-  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
+        info_cb.Run(VideoEncoderInfo());
         secondary_output_cb = std::move(output_cb);
         RunStatusCallbackAync(std::move(done_cb));
       }));
@@ -257,8 +289,8 @@
             RunStatusCallbackAync(std::move(done_cb));
           }));
 
-  fallback_encoder_->Initialize(profile, options, std::move(output_cb),
-                                ValidatingStatusCB());
+  fallback_encoder_->Initialize(profile, options, std::move(info_cb),
+                                std::move(output_cb), ValidatingStatusCB());
 
   RunLoop();
   for (int i = 0; i < kFrameCount; i++) {
@@ -269,6 +301,7 @@
   }
   RunLoop();
   EXPECT_TRUE(FallbackHappened());
+  EXPECT_EQ(info_cb_count, 2);
   EXPECT_EQ(outputs, kFrameCount);
 }
 
@@ -277,14 +310,12 @@
 TEST_F(VideoEncoderFallbackTest, SecondaryFailureOnInitialize) {
   VideoEncoder::Options options;
   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
-  auto output_cb = BindToCurrentLoop(base::BindLambdaForTesting(
-      [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
-      }));
 
   // Initialize() on the main encoder should fail
-  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
         RunStatusCallbackAync(std::move(done_cb),
@@ -292,9 +323,10 @@
       }));
 
   // Initialize() on the second encoder should also fail
-  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
         RunStatusCallbackAync(std::move(done_cb),
@@ -302,7 +334,8 @@
       }));
 
   fallback_encoder_->Initialize(
-      profile, options, std::move(output_cb),
+      profile, options, /*info_cb=*/base::DoNothing(),
+      /*output_cb=*/base::DoNothing(),
       ValidatingStatusCB(EncoderStatus::Codes::kEncoderUnsupportedCodec));
   RunLoop();
 
@@ -345,9 +378,10 @@
   VideoEncoder::OutputCB secondary_output_cb;
 
   // Initialize() on the main encoder should succeed
-  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*main_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
         primary_output_cb = std::move(output_cb);
@@ -355,9 +389,10 @@
       }));
 
   // Initialize() on the second encoder should succeed as well
-  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _))
+  EXPECT_CALL(*secondary_video_encoder_, Initialize(_, _, _, _, _))
       .WillOnce(Invoke([&, this](VideoCodecProfile profile,
                                  const VideoEncoder::Options& options,
+                                 VideoEncoder::EncoderInfoCB info_cb,
                                  VideoEncoder::OutputCB output_cb,
                                  VideoEncoder::EncoderStatusCB done_cb) {
         secondary_output_cb = std::move(output_cb);
@@ -404,8 +439,8 @@
         RunStatusCallbackAync(std::move(done_cb));
       }));
 
-  fallback_encoder_->Initialize(profile, options, std::move(output_cb),
-                                ValidatingStatusCB());
+  fallback_encoder_->Initialize(profile, options, /*info_cb=*/base::DoNothing(),
+                                std::move(output_cb), ValidatingStatusCB());
   RunLoop();
 
   for (int i = 1; i <= kFrameCount; i++) {
diff --git a/media/video/video_encoder_info.cc b/media/video/video_encoder_info.cc
index e74ed0c5..8d2fcb8 100644
--- a/media/video/video_encoder_info.cc
+++ b/media/video/video_encoder_info.cc
@@ -38,6 +38,8 @@
   }
 
   return l.implementation_name == r.implementation_name &&
+         l.frame_delay == r.frame_delay &&
+         l.input_capacity == r.input_capacity &&
          l.supports_native_handle == r.supports_native_handle &&
          l.has_trusted_rate_controller == r.has_trusted_rate_controller &&
          l.is_hardware_accelerated == r.is_hardware_accelerated &&
diff --git a/media/video/video_encoder_info.h b/media/video/video_encoder_info.h
index f364e8a..e71d32b 100644
--- a/media/video/video_encoder_info.h
+++ b/media/video/video_encoder_info.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "media/base/media_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
@@ -41,6 +42,19 @@
 
   std::string implementation_name;
 
+  // The number of additional input frames that must be enqueued before the
+  // encoder starts producing output for the first frame, i.e., the size of the
+  // compression window. Equal to 0 if the encoder can produce a chunk of
+  // output just from the frame submitted last.
+  // If absent, the encoder client will assume some default value.
+  absl::optional<int> frame_delay;
+
+  // The number of input frames the encoder can queue internally. Once this
+  // number is reached, further encode requests can block until some output has
+  // been produced.
+  // If absent, the encoder client will assume some default value.
+  absl::optional<int> input_capacity;
+
   bool supports_native_handle = true;
   bool has_trusted_rate_controller = false;
   bool is_hardware_accelerated = true;
diff --git a/media/video/vpx_video_encoder.cc b/media/video/vpx_video_encoder.cc
index 6df0eb7..22d8db9 100644
--- a/media/video/vpx_video_encoder.cc
+++ b/media/video/vpx_video_encoder.cc
@@ -15,6 +15,7 @@
 #include "media/base/timestamp_constants.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
+#include "media/video/video_encoder_info.h"
 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
 
@@ -245,6 +246,7 @@
 
 void VpxVideoEncoder::Initialize(VideoCodecProfile profile,
                                  const Options& options,
+                                 EncoderInfoCB info_cb,
                                  OutputCB output_cb,
                                  EncoderStatusCB done_cb) {
   done_cb = BindCallbackToCurrentLoopIfNeeded(std::move(done_cb));
@@ -385,6 +387,12 @@
   originally_configured_size_ = options.frame_size;
   output_cb_ = BindCallbackToCurrentLoopIfNeeded(std::move(output_cb));
   codec_ = std::move(codec);
+
+  VideoEncoderInfo info;
+  info.implementation_name = "VpxVideoEncoder";
+  info.is_hardware_accelerated = false;
+  BindCallbackToCurrentLoopIfNeeded(std::move(info_cb)).Run(info);
+
   std::move(done_cb).Run(EncoderStatus::Codes::kOk);
 }
 
diff --git a/media/video/vpx_video_encoder.h b/media/video/vpx_video_encoder.h
index 9ca5438..2a8d9da3 100644
--- a/media/video/vpx_video_encoder.h
+++ b/media/video/vpx_video_encoder.h
@@ -26,6 +26,7 @@
   // VideoDecoder implementation.
   void Initialize(VideoCodecProfile profile,
                   const Options& options,
+                  EncoderInfoCB info_cb,
                   OutputCB output_cb,
                   EncoderStatusCB done_cb) override;
   void Encode(scoped_refptr<VideoFrame> frame,
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
index 191a96b..464b7d7d 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -24,7 +24,6 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/limits.h"
 #include "media/base/mime_util.h"
-#include "media/base/offloading_video_encoder.h"
 #include "media/base/svc_scalability_mode.h"
 #include "media/base/timestamp_constants.h"
 #include "media/base/video_codecs.h"
@@ -34,6 +33,7 @@
 #include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "media/video/h264_level_limits.h"
+#include "media/video/offloading_video_encoder.h"
 #include "media/video/video_encode_accelerator_adapter.h"
 #include "media/video/video_encoder_fallback.h"
 #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-blink.h"
@@ -109,7 +109,23 @@
 namespace {
 
 constexpr const char kCategory[] = "media";
-constexpr int kMaxActiveEncodes = 5;
+
+int ComputeMaxActiveEncodes(
+    absl::optional<int> frame_delay = absl::nullopt,
+    absl::optional<int> input_capacity = absl::nullopt) {
+  constexpr int kDefaultEncoderFrameDelay = 0;
+
+  // The maximum number of input frames above the encoder frame delay that we
+  // want to be able to enqueue in |media_encoder_|.
+  constexpr int kDefaultEncoderExtraInputCapacity = 5;
+
+  const int preferred_capacity =
+      frame_delay.value_or(kDefaultEncoderFrameDelay) +
+      kDefaultEncoderExtraInputCapacity;
+  return input_capacity.has_value()
+             ? std::min(preferred_capacity, input_capacity.value())
+             : preferred_capacity;
+}
 
 bool IsAcceleratedConfigurationSupported(
     media::VideoCodecProfile profile,
@@ -540,6 +556,7 @@
                            const VideoEncoderInit* init,
                            ExceptionState& exception_state)
     : Base(script_state, init, exception_state),
+      max_active_encodes_(ComputeMaxActiveEncodes()),
       frame_metadata_(128) {
   UseCounter::Count(ExecutionContext::From(script_state),
                     WebFeature::kWebCodecs);
@@ -558,21 +575,6 @@
   return VerifyCodecSupportStatic(config, &exception_state);
 }
 
-void VideoEncoder::OnMediaEncoderCreated(std::string encoder_name,
-                                         bool is_hw_accelerated) {
-  if (is_hw_accelerated)
-    ApplyCodecPressure();
-  else
-    ReleaseCodecPressure();
-
-  // TODO(https://crbug.com/1139089) : Add encoder properties.
-  media::MediaLog* log = logger_->log();
-
-  log->SetProperty<media::MediaLogProperty::kVideoEncoderName>(encoder_name);
-  log->SetProperty<media::MediaLogProperty::kIsPlatformVideoEncoder>(
-      is_hw_accelerated);
-}
-
 std::unique_ptr<media::VideoEncoder>
 VideoEncoder::CreateAcceleratedVideoEncoder(
     media::VideoCodecProfile profile,
@@ -627,16 +629,13 @@
   switch (codec) {
     case media::VideoCodec::kAV1:
       result = CreateAv1VideoEncoder();
-      self->OnMediaEncoderCreated("Av1VideoEncoder", false);
       break;
     case media::VideoCodec::kVP8:
     case media::VideoCodec::kVP9:
       result = CreateVpxVideoEncoder();
-      self->OnMediaEncoderCreated("VpxVideoEncoder", false);
       break;
     case media::VideoCodec::kH264:
       result = CreateOpenH264VideoEncoder();
-      self->OnMediaEncoderCreated("OpenH264VideoEncoder", false);
       break;
     default:
       break;
@@ -654,8 +653,6 @@
       MayHaveOSSoftwareEncoder(config.profile)) {
     auto result = CreateAcceleratedVideoEncoder(config.profile, config.options,
                                                 gpu_factories, config.hw_pref);
-    if (result)
-      OnMediaEncoderCreated("AcceleratedVideoEncoder", true);
 
     if (config.hw_pref == HardwarePreference::kPreferHardware) {
       return result;
@@ -691,6 +688,10 @@
     return;
   }
 
+  auto info_cb = ConvertToBaseRepeatingCallback(
+      CrossThreadBindRepeating(&VideoEncoder::OnMediaEncoderInfoChanged,
+                               MakeUnwrappingCrossThreadWeakHandle(this)));
+
   auto output_cb = ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
       &VideoEncoder::CallOutputCallback,
       MakeUnwrappingCrossThreadWeakHandle(this),
@@ -722,7 +723,8 @@
   };
 
   media_encoder_->Initialize(
-      active_config_->profile, active_config_->options, std::move(output_cb),
+      active_config_->profile, active_config_->options, std::move(info_cb),
+      std::move(output_cb),
       ConvertToBaseOnceCallback(CrossThreadBindOnce(
           done_callback, MakeUnwrappingCrossThreadWeakHandle(this),
           MakeUnwrappingCrossThreadHandle(request), active_config_->codec)));
@@ -752,7 +754,7 @@
 }
 
 bool VideoEncoder::ReadyToProcessNextRequest() {
-  if (active_encodes_ >= kMaxActiveEncodes)
+  if (active_encodes_ >= max_active_encodes_)
     return false;
 
   return Base::ReadyToProcessNextRequest();
@@ -1052,6 +1054,25 @@
                                       std::move(reconf_done_callback)));
 }
 
+void VideoEncoder::OnMediaEncoderInfoChanged(
+    const media::VideoEncoderInfo& encoder_info) {
+  if (encoder_info.is_hardware_accelerated)
+    ApplyCodecPressure();
+  else
+    ReleaseCodecPressure();
+
+  media::MediaLog* log = logger_->log();
+  log->SetProperty<media::MediaLogProperty::kVideoEncoderName>(
+      encoder_info.implementation_name);
+  log->SetProperty<media::MediaLogProperty::kIsPlatformVideoEncoder>(
+      encoder_info.is_hardware_accelerated);
+
+  max_active_encodes_ = ComputeMaxActiveEncodes(encoder_info.frame_delay,
+                                                encoder_info.input_capacity);
+  // We may have increased our capacity for active encodes.
+  ProcessRequests();
+}
+
 void VideoEncoder::CallOutputCallback(
     ParsedConfig* active_config,
     uint32_t reset_count,
@@ -1193,7 +1214,8 @@
   auto runner = context->GetTaskRunner(TaskType::kInternalDefault);
   auto* software_encoder_raw = software_encoder.get();
   software_encoder_raw->Initialize(
-      config->profile, config->options, base::DoNothing(),
+      config->profile, config->options, /*info_cb=*/base::DoNothing(),
+      /*output_cb=*/base::DoNothing(),
       ConvertToBaseOnceCallback(CrossThreadBindOnce(
           done_callback, std::move(software_encoder),
           MakeUnwrappingCrossThreadHandle(resolver), std::move(runner),
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.h b/third_party/blink/renderer/modules/webcodecs/video_encoder.h
index 7049fbc..3f54a1ad 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder.h
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.h
@@ -90,6 +90,7 @@
   using Base = EncoderBase<VideoEncoderTraits>;
   using ParsedConfig = VideoEncoderTraits::ParsedConfig;
 
+  void OnMediaEncoderInfoChanged(const media::VideoEncoderInfo& encoder_info);
   void CallOutputCallback(
       ParsedConfig* active_config,
       uint32_t reset_count,
@@ -108,7 +109,6 @@
                       scoped_refptr<media::VideoFrame> txt_frame,
                       media::VideoEncoder::EncoderStatusCB done_callback,
                       scoped_refptr<media::VideoFrame> result_frame);
-  void OnMediaEncoderCreated(std::string encoder_name, bool is_hw_accelerated);
   static std::unique_ptr<media::VideoEncoder> CreateSoftwareVideoEncoder(
       VideoEncoder* self,
       media::VideoCodec codec);
@@ -145,9 +145,12 @@
   bool disable_accelerated_frame_pool_ = false;
 
   // The number of encoding requests currently handled by |media_encoder_|
-  // Should not exceed |kMaxActiveEncodes|.
+  // Should not exceed |max_active_encodes_|.
   int active_encodes_ = 0;
 
+  // The current upper limit on |active_encodes_|.
+  int max_active_encodes_;
+
   // Per-frame metadata to be applied to outputs, linked by timestamp.
   struct FrameMetadata {
     base::TimeDelta duration;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc
index 6bfcb03..f1b3fa6 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_test.cc
@@ -6,6 +6,7 @@
 
 #include "base/run_loop.h"
 #include "media/base/mock_filters.h"
+#include "media/video/video_encoder_info.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -52,8 +53,8 @@
 
  private:
   void SetupExpectations(base::RepeatingClosure quit_closure) {
-    EXPECT_CALL(*next_mock_encoder_, Initialize(_, _, _, _))
-        .WillOnce([quit_closure](Unused, Unused, Unused,
+    EXPECT_CALL(*next_mock_encoder_, Initialize(_, _, _, _, _))
+        .WillOnce([quit_closure](Unused, Unused, Unused, Unused,
                                  media::VideoEncoder::EncoderStatusCB done_cb) {
           scheduler::GetSequencedTaskRunnerForTesting()->PostTask(
               FROM_HERE, WTF::BindOnce(std::move(done_cb),
@@ -67,7 +68,12 @@
       const ParsedConfig& config,
       media::GpuVideoAcceleratorFactories* gpu_factories) override {
     EXPECT_TRUE(next_mock_encoder_);
-    OnMediaEncoderCreated("MockEncoderName", mock_encoder_is_hw_);
+
+    media::VideoEncoderInfo info;
+    info.implementation_name = "MockEncoderName";
+    info.is_hardware_accelerated = mock_encoder_is_hw_;
+    OnMediaEncoderInfoChanged(info);
+
     return std::move(next_mock_encoder_);
   }