diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc index 0000000..0000000 100644 --- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc +++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc @@ -2390,9 +2390,18 @@ HRESULT MediaFoundationVideoEncodeAccelerator::PopulateInputSampleBufferGpu( hr = texture_buffer.As(&dxgi_buffer); RETURN_ON_HR_FAILURE(hr, "Failed to get dxgi buffer", hr); hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&input_texture)); } - if (frame->visible_rect().size() != input_visible_size_) { + // Mirror the texture-size check in CopyInputSampleBufferFromGpu(). The + // SharedImage zero-copy path (mf_helpers.cc CreateSampleFromTexture / + // GenerateResourceOnSyncTokenReleased) allocates a coded_size texture with + // pInitialData=nullptr and copies only |visible_rect| into it; without this + // check, the uninitialised tail (stale GPU VRAM) is handed to the encoder MFT + // and can leak into the output bitstream. + D3D11_TEXTURE2D_DESC input_desc = {}; + input_texture->GetDesc(&input_desc); + gfx::Size texture_size(input_desc.Width, input_desc.Height); + if (texture_size != input_visible_size_ || + frame->visible_rect().size() != input_visible_size_) { hr = PerformD3DScaling(input_texture.Get(), frame->visible_rect()); RETURN_ON_HR_FAILURE(hr, "Failed to perform D3D video processing", hr); sample_texture = scaled_d3d11_texture_; } else if (input.generate_sample_on_wait_sync_token) { diff --git a/media/base/win/mf_helpers.cc b/media/base/win/mf_helpers.cc index 0000000..0000000 100644 --- a/media/base/win/mf_helpers.cc +++ b/media/base/win/mf_helpers.cc @@ -907,14 +907,13 @@ Microsoft::WRL::ComPtr CreateSampleFromTexture( << logging::SystemErrorCodeToString(hr); return nullptr; } Microsoft::WRL::ComPtr device_context; device->GetImmediateContext(&device_context); - D3D11_BOX src_box = {static_cast(frame->visible_rect().x()), - static_cast(frame->visible_rect().y()), - 0, - static_cast(frame->visible_rect().right()), - static_cast(frame->visible_rect().bottom()), - 1}; + // Copy the entire source texture so the destination (allocated with + // pInitialData=nullptr, i.e. uninitialised default-heap GPU memory) has no + // unwritten tail that could leak stale VRAM into the encoder bitstream. + // The destination was created with the source's GetDesc(), so a full copy + // is always in-bounds. device_context->CopySubresourceRegion(copied_texture.Get(), 0, 0, 0, 0, - input_texture.Get(), 0, &src_box); + input_texture.Get(), 0, nullptr); input_texture = copied_texture; } @@ -1176,15 +1175,12 @@ void GenerateResourceOnSyncTokenReleased( Microsoft::WRL::ComPtr device_context; shared_d3d11_device->GetImmediateContext(&device_context); - D3D11_BOX src_box = {static_cast(frame->visible_rect().x()), - static_cast(frame->visible_rect().y()), - 0, - static_cast(frame->visible_rect().right()), - static_cast(frame->visible_rect().bottom()), - 1}; + // Copy the full subresource so the freshly-allocated (uninitialised) + // |shared_texture| has no unwritten tail. See CreateSampleFromTexture() + // for rationale. device_context->CopySubresourceRegion(shared_texture.Get(), 0, 0, 0, 0, input_texture.texture.Get(), - input_texture.array_index, &src_box); + input_texture.array_index, nullptr); Microsoft::WRL::ComPtr shared_dxgi_resource; hr = shared_texture.As(&shared_dxgi_resource); CHECK_EQ(hr, S_OK);