[WGC] Fix frame size synchronization Fixes a scenario where the mapped_texture_ and frame_pool_ sizes of the WGC capturer could get out of sync and potentially bypass their reconciliation on the following frame. Fixed: chromium:517727318 Change-Id: Ie4e951bbdf41491200b7ba1289f85e4c02bc22d1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/476860 Commit-Queue: Mark Foltz <mfoltz@chromium.org> Auto-Submit: Alexander Cooper <alcooper@chromium.org> Reviewed-by: Mark Foltz <mfoltz@chromium.org> Cr-Commit-Position: refs/heads/main@{#47898}
diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc index c7eaf54..9a887d7 100644 --- a/modules/desktop_capture/win/wgc_capture_session.cc +++ b/modules/desktop_capture/win/wgc_capture_session.cc
@@ -564,14 +564,6 @@ return hr; } - if (!mapped_texture_) { - hr = CreateMappedTexture(texture_2D); - if (FAILED(hr)) { - RecordGetFrameResult(GetFrameResult::kCreateMappedTextureFailed); - return hr; - } - } - // We need to copy `texture_2D` into `mapped_texture_` as the latter has the // D3D11_CPU_ACCESS_READ flag set, which lets us access the image data. // Otherwise it would only be readable by the GPU. @@ -588,17 +580,28 @@ // If the size changed, we must resize `mapped_texture_` and `frame_pool_` to // fit the new size. This must be done before `CopySubresourceRegion` so that // the textures are the same size. - if (SizeHasChanged(new_size, size_)) { + const bool needs_resize = SizeHasChanged(new_size, size_); + + if (!mapped_texture_ || needs_resize) { hr = CreateMappedTexture(texture_2D, new_size.Width, new_size.Height); if (FAILED(hr)) { - RecordGetFrameResult(GetFrameResult::kResizeMappedTextureFailed); + RecordGetFrameResult(GetFrameResult::kCreateMappedTextureFailed); return hr; } + } + if (needs_resize) { hr = frame_pool_->Recreate(direct3d_device_.Get(), kPixelFormat, num_buffers(), new_size); if (FAILED(hr)) { RecordGetFrameResult(GetFrameResult::kRecreateFramePoolFailed); + // On failure, `frame_pool_` remains at `size_`. Reset `mapped_texture_` + // because `mapped_texture_` and `frame_pool_` are now at inconsistent + // sizes. Clearing it forces a consistent recreation on the next frame. + // Note that it's not sufficient to simply leave `mapped_texture_` at it's + // current size, because if the window were to be resized back to `size_`, + // then we would erroneously think we don't need to re-create the texture. + mapped_texture_.Reset(); return hr; } } @@ -713,7 +716,7 @@ const int width_in_bytes = current_frame->size().width() * DesktopFrame::kBytesPerPixel; RTC_DCHECK_GE(current_frame->stride(), width_in_bytes); - RTC_DCHECK_GE(map_info.RowPitch, width_in_bytes); + RTC_CHECK_GE(map_info.RowPitch, width_in_bytes); const int middle_pixel_offset = (image_width / 2) * DesktopFrame::kBytesPerPixel; for (int i = 0; i < image_height; i++) {