Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Unified Diff: webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc

Issue 2796673002: Fix crash in XServerPixelBuffer. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc
diff --git a/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc b/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc
index ce23847cd6e7119e18789c06ba09fd04631abdc0..388f64cda638cbcffd1fa214c16f21de4f645515 100644
--- a/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc
+++ b/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc
@@ -18,6 +18,8 @@
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
#include "webrtc/system_wrappers/include/logging.h"
+namespace webrtc {
+
namespace {
// Returns the number of bits |mask| has to be shifted left so its last
@@ -55,9 +57,78 @@ bool IsXImageRGBFormat(XImage* image) {
image->blue_mask == 0xff;
}
-} // namespace
+// We expose two forms of blitting to handle variations in the pixel format.
+// In FastBlit(), the operation is effectively a memcpy.
GeorgeZ 2017/04/03 18:59:58 Please explain a little of SlowBlit().
+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();
-namespace webrtc {
+ 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() {}
@@ -70,6 +141,10 @@ void XServerPixelBuffer::Release() {
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;
@@ -131,18 +206,18 @@ void XServerPixelBuffer::InitShm(const XWindowAttributes& attributes) {
shm_segment_info_->shmid = -1;
shm_segment_info_->shmaddr = nullptr;
shm_segment_info_->readOnly = False;
- x_image_ = XShmCreateImage(display_, default_visual, default_depth, ZPixmap,
- 0, shm_segment_info_, window_size_.width(),
- window_size_.height());
- if (x_image_) {
+ x_shm_image_ = XShmCreateImage(display_, default_visual, default_depth,
+ ZPixmap, 0, shm_segment_info_,
+ window_size_.width(), window_size_.height());
+ if (x_shm_image_) {
shm_segment_info_->shmid =
- shmget(IPC_PRIVATE, x_image_->bytes_per_line * x_image_->height,
+ 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_image_->data = shm_segment_info_->shmaddr;
+ x_shm_image_->data = shm_segment_info_->shmaddr;
XErrorTrap error_trap(display_);
using_shm = XShmAttach(display_, shm_segment_info_);
@@ -235,7 +310,7 @@ void XServerPixelBuffer::Synchronize() {
XErrorTrap error_trap(display_);
// XShmGetImage fails if the window is partially out of screen.
xshm_get_image_succeeded_ =
- XShmGetImage(display_, window_, x_image_, 0, 0, AllPlanes);
+ XShmGetImage(display_, window_, x_shm_image_, 0, 0, AllPlanes);
}
}
@@ -244,6 +319,7 @@ bool XServerPixelBuffer::CaptureRect(const DesktopRect& rect,
assert(rect.right() <= window_size_.width());
assert(rect.bottom() <= window_size_.height());
+ XImage* image;
uint8_t* data;
if (shm_segment_info_ && (shm_pixmap_ || xshm_get_image_succeeded_)) {
@@ -253,9 +329,12 @@ bool XServerPixelBuffer::CaptureRect(const DesktopRect& rect,
rect.left(), rect.top());
XSync(display_, False);
}
- data = reinterpret_cast<uint8_t*>(x_image_->data) +
- rect.top() * x_image_->bytes_per_line +
- rect.left() * x_image_->bits_per_pixel / 8;
+
+ 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_);
@@ -264,85 +343,17 @@ bool XServerPixelBuffer::CaptureRect(const DesktopRect& rect,
if (!x_image_)
return false;
- data = reinterpret_cast<uint8_t*>(x_image_->data);
+ image = x_image_;
+ data = reinterpret_cast<uint8_t*>(image->data);
}
- if (IsXImageRGBFormat(x_image_)) {
- FastBlit(data, rect, frame);
+ if (IsXImageRGBFormat(image)) {
+ FastBlit(image, data, rect, frame);
} else {
- SlowBlit(data, rect, frame);
+ SlowBlit(image, data, rect, frame);
}
return true;
}
-void XServerPixelBuffer::FastBlit(uint8_t* image,
- const DesktopRect& rect,
- DesktopFrame* frame) {
- uint8_t* src_pos = image;
- 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 XServerPixelBuffer::SlowBlit(uint8_t* image,
- 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;
- uint8_t* src_pos = image;
- 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 webrtc
« no previous file with comments | « webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698