Revert "Add support for screen sharing with PipeWire on Wayland"
This reverts commit dd20c9c1e3f681f6c33d1879c76f588bd4b095bd. Reason for revert: Speculative revert; looks like it causes crashes on official builders. See crbug.com/901319. Original change's description: > Add support for screen sharing with PipeWire on Wayland > > Currently, when users want to use the screen sharing and are using the > Wayland display server (the default on Fedora distribution), then it > doesn't work, because the WebRTC only includes the X11 implementation. > This change adds the support by using the PipeWire multimedia server. > > The PipeWire implementation in WebRTC stays in > screen-capturer-pipewire.c and is guarded by the rtc_use_pipewire build > flag that is automatically enabled on Linux. > > More information are included in the relevant commit messages. > > Tested on the current Chromium master and Firefox. > > The sysroot changes are requested in: > https://chromium-review.googlesource.com/c/chromium/src/+/1258174 > > Co-authored-by: Jan Grulich <grulja@gmail.com> > Co-authored-by: Eike Rathke <erathke@redhat.com> > Change-Id: I212074a4bc437b99a77bf383266026c5bfae7c4a > > BUG=chromium:682122 > > Change-Id: I212074a4bc437b99a77bf383266026c5bfae7c4a > Reviewed-on: https://webrtc-review.googlesource.com/c/103504 > Commit-Queue: Patrik Höglund <phoglund@webrtc.org> > Reviewed-by: Patrik Höglund <phoglund@webrtc.org> > Reviewed-by: Brave Yao <braveyao@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#25461} TBR=phoglund@webrtc.org,jamiewalch@chromium.org,niklas.enbom@webrtc.org,braveyao@webrtc.org,tomas.popela@gmail.com # Not skipping CQ checks because original CL landed > 1 day ago. NOPRESUBMIT=true Bug: chromium:682122, chromium:901319 Change-Id: I4ca5da77daea73cae1232953a0d633900a85a93d Reviewed-on: https://webrtc-review.googlesource.com/c/109584 Commit-Queue: Patrik Höglund <phoglund@webrtc.org> Reviewed-by: Patrik Höglund <phoglund@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25522}
This commit is contained in:

committed by
Commit Bot

parent
82c07ea1da
commit
3ddaf3c408
@ -1,351 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/desktop_capture/linux/x_server_pixel_buffer.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#include "modules/desktop_capture/desktop_frame.h"
|
||||
#include "modules/desktop_capture/linux/window_list_utils.h"
|
||||
#include "modules/desktop_capture/linux/x_error_trap.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns the number of bits |mask| has to be shifted left so its last
|
||||
// (most-significant) bit set becomes the most-significant bit of the word.
|
||||
// When |mask| is 0 the function returns 31.
|
||||
uint32_t MaskToShift(uint32_t mask) {
|
||||
int shift = 0;
|
||||
if ((mask & 0xffff0000u) == 0) {
|
||||
mask <<= 16;
|
||||
shift += 16;
|
||||
}
|
||||
if ((mask & 0xff000000u) == 0) {
|
||||
mask <<= 8;
|
||||
shift += 8;
|
||||
}
|
||||
if ((mask & 0xf0000000u) == 0) {
|
||||
mask <<= 4;
|
||||
shift += 4;
|
||||
}
|
||||
if ((mask & 0xc0000000u) == 0) {
|
||||
mask <<= 2;
|
||||
shift += 2;
|
||||
}
|
||||
if ((mask & 0x80000000u) == 0)
|
||||
shift += 1;
|
||||
|
||||
return shift;
|
||||
}
|
||||
|
||||
// Returns true if |image| is in RGB format.
|
||||
bool IsXImageRGBFormat(XImage* image) {
|
||||
return image->bits_per_pixel == 32 && image->red_mask == 0xff0000 &&
|
||||
image->green_mask == 0xff00 && image->blue_mask == 0xff;
|
||||
}
|
||||
|
||||
// We expose two forms of blitting to handle variations in the pixel format.
|
||||
// In FastBlit(), the operation is effectively a memcpy.
|
||||
void FastBlit(XImage* x_image,
|
||||
uint8_t* src_pos,
|
||||
const DesktopRect& rect,
|
||||
DesktopFrame* frame) {
|
||||
int src_stride = x_image->bytes_per_line;
|
||||
int dst_x = rect.left(), dst_y = rect.top();
|
||||
|
||||
uint8_t* dst_pos = frame->data() + frame->stride() * dst_y;
|
||||
dst_pos += dst_x * DesktopFrame::kBytesPerPixel;
|
||||
|
||||
int height = rect.height();
|
||||
int row_bytes = rect.width() * DesktopFrame::kBytesPerPixel;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
memcpy(dst_pos, src_pos, row_bytes);
|
||||
src_pos += src_stride;
|
||||
dst_pos += frame->stride();
|
||||
}
|
||||
}
|
||||
|
||||
void SlowBlit(XImage* x_image,
|
||||
uint8_t* src_pos,
|
||||
const DesktopRect& rect,
|
||||
DesktopFrame* frame) {
|
||||
int src_stride = x_image->bytes_per_line;
|
||||
int dst_x = rect.left(), dst_y = rect.top();
|
||||
int width = rect.width(), height = rect.height();
|
||||
|
||||
uint32_t red_mask = x_image->red_mask;
|
||||
uint32_t green_mask = x_image->red_mask;
|
||||
uint32_t blue_mask = x_image->blue_mask;
|
||||
|
||||
uint32_t red_shift = MaskToShift(red_mask);
|
||||
uint32_t green_shift = MaskToShift(green_mask);
|
||||
uint32_t blue_shift = MaskToShift(blue_mask);
|
||||
|
||||
int bits_per_pixel = x_image->bits_per_pixel;
|
||||
|
||||
uint8_t* dst_pos = frame->data() + frame->stride() * dst_y;
|
||||
dst_pos += dst_x * DesktopFrame::kBytesPerPixel;
|
||||
// TODO(hclam): Optimize, perhaps using MMX code or by converting to
|
||||
// YUV directly.
|
||||
// TODO(sergeyu): This code doesn't handle XImage byte order properly and
|
||||
// won't work with 24bpp images. Fix it.
|
||||
for (int y = 0; y < height; y++) {
|
||||
uint32_t* dst_pos_32 = reinterpret_cast<uint32_t*>(dst_pos);
|
||||
uint32_t* src_pos_32 = reinterpret_cast<uint32_t*>(src_pos);
|
||||
uint16_t* src_pos_16 = reinterpret_cast<uint16_t*>(src_pos);
|
||||
for (int x = 0; x < width; x++) {
|
||||
// Dereference through an appropriately-aligned pointer.
|
||||
uint32_t pixel;
|
||||
if (bits_per_pixel == 32) {
|
||||
pixel = src_pos_32[x];
|
||||
} else if (bits_per_pixel == 16) {
|
||||
pixel = src_pos_16[x];
|
||||
} else {
|
||||
pixel = src_pos[x];
|
||||
}
|
||||
uint32_t r = (pixel & red_mask) << red_shift;
|
||||
uint32_t g = (pixel & green_mask) << green_shift;
|
||||
uint32_t b = (pixel & blue_mask) << blue_shift;
|
||||
// Write as 32-bit RGB.
|
||||
dst_pos_32[x] =
|
||||
((r >> 8) & 0xff0000) | ((g >> 16) & 0xff00) | ((b >> 24) & 0xff);
|
||||
}
|
||||
dst_pos += frame->stride();
|
||||
src_pos += src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
XServerPixelBuffer::XServerPixelBuffer() {}
|
||||
|
||||
XServerPixelBuffer::~XServerPixelBuffer() {
|
||||
Release();
|
||||
}
|
||||
|
||||
void XServerPixelBuffer::Release() {
|
||||
if (x_image_) {
|
||||
XDestroyImage(x_image_);
|
||||
x_image_ = nullptr;
|
||||
}
|
||||
if (x_shm_image_) {
|
||||
XDestroyImage(x_shm_image_);
|
||||
x_shm_image_ = nullptr;
|
||||
}
|
||||
if (shm_pixmap_) {
|
||||
XFreePixmap(display_, shm_pixmap_);
|
||||
shm_pixmap_ = 0;
|
||||
}
|
||||
if (shm_gc_) {
|
||||
XFreeGC(display_, shm_gc_);
|
||||
shm_gc_ = nullptr;
|
||||
}
|
||||
|
||||
ReleaseSharedMemorySegment();
|
||||
|
||||
window_ = 0;
|
||||
}
|
||||
|
||||
void XServerPixelBuffer::ReleaseSharedMemorySegment() {
|
||||
if (!shm_segment_info_)
|
||||
return;
|
||||
if (shm_segment_info_->shmaddr != nullptr)
|
||||
shmdt(shm_segment_info_->shmaddr);
|
||||
if (shm_segment_info_->shmid != -1)
|
||||
shmctl(shm_segment_info_->shmid, IPC_RMID, 0);
|
||||
delete shm_segment_info_;
|
||||
shm_segment_info_ = nullptr;
|
||||
}
|
||||
|
||||
bool XServerPixelBuffer::Init(Display* display, Window window) {
|
||||
Release();
|
||||
display_ = display;
|
||||
|
||||
XWindowAttributes attributes;
|
||||
if (!GetWindowRect(display_, window, &window_rect_, &attributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
window_ = window;
|
||||
InitShm(attributes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XServerPixelBuffer::InitShm(const XWindowAttributes& attributes) {
|
||||
Visual* default_visual = attributes.visual;
|
||||
int default_depth = attributes.depth;
|
||||
|
||||
int major, minor;
|
||||
Bool have_pixmaps;
|
||||
if (!XShmQueryVersion(display_, &major, &minor, &have_pixmaps)) {
|
||||
// Shared memory not supported. CaptureRect will use the XImage API instead.
|
||||
return;
|
||||
}
|
||||
|
||||
bool using_shm = false;
|
||||
shm_segment_info_ = new XShmSegmentInfo;
|
||||
shm_segment_info_->shmid = -1;
|
||||
shm_segment_info_->shmaddr = nullptr;
|
||||
shm_segment_info_->readOnly = False;
|
||||
x_shm_image_ = XShmCreateImage(display_, default_visual, default_depth,
|
||||
ZPixmap, 0, shm_segment_info_,
|
||||
window_rect_.width(), window_rect_.height());
|
||||
if (x_shm_image_) {
|
||||
shm_segment_info_->shmid =
|
||||
shmget(IPC_PRIVATE, x_shm_image_->bytes_per_line * x_shm_image_->height,
|
||||
IPC_CREAT | 0600);
|
||||
if (shm_segment_info_->shmid != -1) {
|
||||
void* shmat_result = shmat(shm_segment_info_->shmid, 0, 0);
|
||||
if (shmat_result != reinterpret_cast<void*>(-1)) {
|
||||
shm_segment_info_->shmaddr = reinterpret_cast<char*>(shmat_result);
|
||||
x_shm_image_->data = shm_segment_info_->shmaddr;
|
||||
|
||||
XErrorTrap error_trap(display_);
|
||||
using_shm = XShmAttach(display_, shm_segment_info_);
|
||||
XSync(display_, False);
|
||||
if (error_trap.GetLastErrorAndDisable() != 0)
|
||||
using_shm = false;
|
||||
if (using_shm) {
|
||||
RTC_LOG(LS_VERBOSE)
|
||||
<< "Using X shared memory segment " << shm_segment_info_->shmid;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RTC_LOG(LS_WARNING) << "Failed to get shared memory segment. "
|
||||
"Performance may be degraded.";
|
||||
}
|
||||
}
|
||||
|
||||
if (!using_shm) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Not using shared memory. Performance may be degraded.";
|
||||
ReleaseSharedMemorySegment();
|
||||
return;
|
||||
}
|
||||
|
||||
if (have_pixmaps)
|
||||
have_pixmaps = InitPixmaps(default_depth);
|
||||
|
||||
shmctl(shm_segment_info_->shmid, IPC_RMID, 0);
|
||||
shm_segment_info_->shmid = -1;
|
||||
|
||||
RTC_LOG(LS_VERBOSE) << "Using X shared memory extension v" << major << "."
|
||||
<< minor << " with" << (have_pixmaps ? "" : "out")
|
||||
<< " pixmaps.";
|
||||
}
|
||||
|
||||
bool XServerPixelBuffer::InitPixmaps(int depth) {
|
||||
if (XShmPixmapFormat(display_) != ZPixmap)
|
||||
return false;
|
||||
|
||||
{
|
||||
XErrorTrap error_trap(display_);
|
||||
shm_pixmap_ = XShmCreatePixmap(
|
||||
display_, window_, shm_segment_info_->shmaddr, shm_segment_info_,
|
||||
window_rect_.width(), window_rect_.height(), depth);
|
||||
XSync(display_, False);
|
||||
if (error_trap.GetLastErrorAndDisable() != 0) {
|
||||
// |shm_pixmap_| is not not valid because the request was not processed
|
||||
// by the X Server, so zero it.
|
||||
shm_pixmap_ = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
XErrorTrap error_trap(display_);
|
||||
XGCValues shm_gc_values;
|
||||
shm_gc_values.subwindow_mode = IncludeInferiors;
|
||||
shm_gc_values.graphics_exposures = False;
|
||||
shm_gc_ = XCreateGC(display_, window_,
|
||||
GCSubwindowMode | GCGraphicsExposures, &shm_gc_values);
|
||||
XSync(display_, False);
|
||||
if (error_trap.GetLastErrorAndDisable() != 0) {
|
||||
XFreePixmap(display_, shm_pixmap_);
|
||||
shm_pixmap_ = 0;
|
||||
shm_gc_ = 0; // See shm_pixmap_ comment above.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XServerPixelBuffer::IsWindowValid() const {
|
||||
XWindowAttributes attributes;
|
||||
{
|
||||
XErrorTrap error_trap(display_);
|
||||
if (!XGetWindowAttributes(display_, window_, &attributes) ||
|
||||
error_trap.GetLastErrorAndDisable() != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XServerPixelBuffer::Synchronize() {
|
||||
if (shm_segment_info_ && !shm_pixmap_) {
|
||||
// XShmGetImage can fail if the display is being reconfigured.
|
||||
XErrorTrap error_trap(display_);
|
||||
// XShmGetImage fails if the window is partially out of screen.
|
||||
xshm_get_image_succeeded_ =
|
||||
XShmGetImage(display_, window_, x_shm_image_, 0, 0, AllPlanes);
|
||||
}
|
||||
}
|
||||
|
||||
bool XServerPixelBuffer::CaptureRect(const DesktopRect& rect,
|
||||
DesktopFrame* frame) {
|
||||
RTC_DCHECK_LE(rect.right(), window_rect_.width());
|
||||
RTC_DCHECK_LE(rect.bottom(), window_rect_.height());
|
||||
|
||||
XImage* image;
|
||||
uint8_t* data;
|
||||
|
||||
if (shm_segment_info_ && (shm_pixmap_ || xshm_get_image_succeeded_)) {
|
||||
if (shm_pixmap_) {
|
||||
XCopyArea(display_, window_, shm_pixmap_, shm_gc_, rect.left(),
|
||||
rect.top(), rect.width(), rect.height(), rect.left(),
|
||||
rect.top());
|
||||
XSync(display_, False);
|
||||
}
|
||||
|
||||
image = x_shm_image_;
|
||||
data = reinterpret_cast<uint8_t*>(image->data) +
|
||||
rect.top() * image->bytes_per_line +
|
||||
rect.left() * image->bits_per_pixel / 8;
|
||||
|
||||
} else {
|
||||
if (x_image_)
|
||||
XDestroyImage(x_image_);
|
||||
x_image_ = XGetImage(display_, window_, rect.left(), rect.top(),
|
||||
rect.width(), rect.height(), AllPlanes, ZPixmap);
|
||||
if (!x_image_)
|
||||
return false;
|
||||
|
||||
image = x_image_;
|
||||
data = reinterpret_cast<uint8_t*>(image->data);
|
||||
}
|
||||
|
||||
if (IsXImageRGBFormat(image)) {
|
||||
FastBlit(image, data, rect, frame);
|
||||
} else {
|
||||
SlowBlit(image, data, rect, frame);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
Reference in New Issue
Block a user