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 ||