diff --git a/media/gpu/windows/d3d12_video_encode_h264_delegate.cc b/media/gpu/windows/d3d12_video_encode_h264_delegate.cc index f6365db802d73..04997a08228a6 100644 --- a/media/gpu/windows/d3d12_video_encode_h264_delegate.cc +++ b/media/gpu/windows/d3d12_video_encode_h264_delegate.cc @@ -648,7 +648,13 @@ EncoderStatus D3D12VideoEncodeH264Delegate::InitializeVideoEncoder( "support manual reference control, got %u", picture_control_support_h264.MaxDPBCapacity)}; } - max_num_ref_frames_ = picture_control_support_h264.MaxDPBCapacity; + // Manual reference buffers map directly onto long-term reference indices, + // so the number of DPB slots used must not exceed what the driver can + // track as long-term references plus the slot reserved for frame_num gap + // handling. + max_num_ref_frames_ = + std::min(picture_control_support_h264.MaxDPBCapacity, + picture_control_support_h264.MaxLongTermReferences + 1); } if ((config.bitrate.mode() == Bitrate::Mode::kConstant || diff --git a/media/gpu/windows/d3d12_video_encode_h264_delegate_unittest.cc b/media/gpu/windows/d3d12_video_encode_h264_delegate_unittest.cc index 457d49b68f2fb..8613f758f5632 100644 --- a/media/gpu/windows/d3d12_video_encode_h264_delegate_unittest.cc +++ b/media/gpu/windows/d3d12_video_encode_h264_delegate_unittest.cc @@ -72,8 +72,9 @@ class D3D12VideoEncodeH264DelegateTest return E_INVALIDARG; } picture_control->PictureSupport.pH264Support->MaxLongTermReferences = - 1; - picture_control->PictureSupport.pH264Support->MaxDPBCapacity = 16; + kMaxLongTermReferences; + picture_control->PictureSupport.pH264Support->MaxDPBCapacity = + kMaxDPBCapacity; return S_OK; }); ON_CALL(*video_device3_.Get(), @@ -195,6 +196,8 @@ class D3D12VideoEncodeH264DelegateTest static constexpr D3D12_VIDEO_ENCODER_LEVELS_H264 kMaxLevel = D3D12_VIDEO_ENCODER_LEVELS_H264_31; + static constexpr UINT kMaxLongTermReferences = 4; + static constexpr UINT kMaxDPBCapacity = 16; Microsoft::WRL::ComPtr device_; Microsoft::WRL::ComPtr video_device3_; }; @@ -471,6 +474,21 @@ TEST_F(D3D12VideoEncodeH264DelegateTest, } } +TEST_F(D3D12VideoEncodeH264DelegateTest, + ManualReferenceBuffersLimitedByLongTermReferences) { + static_assert(kMaxLongTermReferences < kMaxDPBCapacity); + VideoEncodeAccelerator::Config config = GetDefaultH264Config(); + config.manual_reference_buffer_control = true; + ASSERT_TRUE(encoder_delegate_->Initialize(config).is_ok()); + // Manual reference buffers are implemented as long-term references, so the + // number of DPB slots used must respect the driver's long-term reference + // limit rather than its full DPB capacity. + EXPECT_EQ(encoder_delegate_->GetMaxNumOfRefFrames(), + kMaxLongTermReferences + 1u); + EXPECT_LE(encoder_delegate_->GetMaxNumOfManualRefBuffers(), + static_cast(kMaxLongTermReferences)); +} + TEST_F(D3D12VideoEncodeH264DelegateTest, EncodeWithManualReferenceControl) { VideoEncodeAccelerator::Config config = GetDefaultH264Config(); config.manual_reference_buffer_control = true;