From a6ed749b12c63d252c6d893d5b5b62fcf35773d9 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Fri, 10 Jun 2022 09:21:48 +0200 Subject: [PATCH] Wayland screencast: update stride when we import DMA-BUFs When DMA-BUFs are used, sometimes stride we get from PipeWire might contain additional padding, but after we import the buffer, the stride we used is no longer relevant and we should just calculate it based on width. Bug: chromium:1333304 Change-Id: Id4300550f0b3c539ddd749e9285f525d4f816b80 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265384 Reviewed-by: Alexander Cooper Commit-Queue: Jan Grulich Reviewed-by: Mark Foltz Cr-Commit-Position: refs/heads/main@{#37195} --- .../linux/wayland/shared_screencast_stream.cc | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc index 56469235be..74bf29d19c 100644 --- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc +++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc @@ -647,6 +647,16 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { plane_datas.push_back(data); } + // When importing DMA-BUFs, we use the stride (number of bytes from one row + // of pixels in the buffer) provided by PipeWire. The stride from PipeWire + // is given by the graphics driver and some drivers might add some + // additional padding for memory layout optimizations so not everytime the + // stride is equal to BYTES_PER_PIXEL x WIDTH. This is fine, because during + // the import we will use OpenGL and same graphics driver so it will be able + // to work with the stride it provided, but later on when we work with + // images we get from DMA-BUFs we will need to update the stride to be equal + // to BYTES_PER_PIXEL x WIDTH as that's the size of the DesktopFrame we + // allocate for each captured frame. src_unique_ptr = egl_dmabuf_->ImageFromDmaBuf( desktop_size_, spa_video_format_.format, plane_datas, modifier_); if (src_unique_ptr) { @@ -722,8 +732,19 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { ? video_metadata->region.position.x : 0; - uint8_t* updated_src = src + (spa_buffer->datas[0].chunk->stride * y_offset) + - (kBytesPerPixel * x_offset); + const uint32_t frame_stride = kBytesPerPixel * video_size_.width(); + uint32_t stride = spa_buffer->datas[0].chunk->stride; + + if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf && stride > frame_stride) { + // When DMA-BUFs are used, sometimes spa_buffer->stride we get might + // contain additional padding, but after we import the buffer, the stride + // we used is no longer relevant and we should just calculate it based on + // width. For more context see https://crbug.com/1333304. + stride = frame_stride; + } + + uint8_t* updated_src = + src + (stride * y_offset) + (kBytesPerPixel * x_offset); webrtc::MutexLock lock(&queue_lock_); @@ -745,8 +766,7 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { } queue_.current_frame()->CopyPixelsFrom( - updated_src, - (spa_buffer->datas[0].chunk->stride - (kBytesPerPixel * x_offset)), + updated_src, (stride - (kBytesPerPixel * x_offset)), DesktopRect::MakeWH(video_size_.width(), video_size_.height())); if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx ||