diff options
-rw-r--r-- | remoting/host/video_frame_capturer_linux.cc | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/remoting/host/video_frame_capturer_linux.cc b/remoting/host/video_frame_capturer_linux.cc index 06a3ef5..c472f49 100644 --- a/remoting/host/video_frame_capturer_linux.cc +++ b/remoting/host/video_frame_capturer_linux.cc @@ -63,6 +63,7 @@ class VideoFrameBuffer { uint8* ptr() const { return ptr_.get(); } void set_needs_update() { needs_update_ = true; } + bool needs_update() const { return needs_update_; } private: SkISize size_; @@ -174,7 +175,7 @@ class VideoFrameCapturerLinux : public VideoFrameCapturer { SkRegion last_invalid_region_; // Last capture buffer used. - uint8* last_buffer_; + int last_buffer_; // |Differ| for use when polling for changes. scoped_ptr<Differ> differ_; @@ -196,7 +197,7 @@ VideoFrameCapturerLinux::VideoFrameCapturerLinux() damage_region_(0), current_buffer_(0), pixel_format_(media::VideoFrame::RGB32), - last_buffer_(NULL) { + last_buffer_(kNumBuffers - 1) { helper_.SetLogGridSize(4); } @@ -317,14 +318,23 @@ void VideoFrameCapturerLinux::CaptureInvalidRegion( // screen-resolution. VideoFrameBuffer ¤t = buffers_[current_buffer_]; current.Update(display_, root_window_); - // Also refresh the Differ helper used by CaptureFrame(), if needed. - if (!use_damage_ && !last_buffer_) { - differ_.reset(new Differ(current.size().width(), current.size().height(), - kBytesPerPixel, current.bytes_per_row())); + + // Mark the previous frame for update if its dimensions no longer match. + if (buffers_[last_buffer_].size() != current.size()) { + buffers_[last_buffer_].set_needs_update(); + + // Also refresh the Differ helper used by CaptureFrame(), if needed. + if (!use_damage_) { + differ_.reset(new Differ(current.size().width(), current.size().height(), + kBytesPerPixel, current.bytes_per_row())); + } } scoped_refptr<CaptureData> capture_data(CaptureFrame()); + // Swap the current & previous buffers ready for the next capture. + last_invalid_region_ = capture_data->dirty_region(); + last_buffer_ = current_buffer_; current_buffer_ = (current_buffer_ + 1) % kNumBuffers; callback.Run(capture_data); @@ -410,13 +420,13 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() { // if any. If there isn't a previous frame, that means a screen-resolution // change occurred, and |invalid_rects| will be updated to include the whole // screen. - if (use_damage_ && last_buffer_) + if (use_damage_ && !buffers_[last_buffer_].needs_update()) SynchronizeFrame(); SkRegion invalid_region; x_server_pixel_buffer_.Synchronize(); - if (use_damage_ && last_buffer_) { + if (use_damage_ && !buffers_[last_buffer_].needs_update()) { // Atomically fetch and clear the damage region. XDamageSubtract(display_, damage_handle_, None, damage_region_); int nRects = 0; @@ -443,11 +453,13 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() { buffer.size().height()); CaptureRect(screen_rect, capture_data); - if (last_buffer_) { + if (!buffers_[last_buffer_].needs_update()) { // Full-screen polling, so calculate the invalid rects here, based on the // changed pixels between current and previous buffers. DCHECK(differ_ != NULL); - differ_->CalcDirtyRegion(last_buffer_, buffer.ptr(), &invalid_region); + VideoFrameBuffer& last_buffer = buffers_[last_buffer_]; + differ_->CalcDirtyRegion( + last_buffer.ptr(), buffer.ptr(), &invalid_region); } else { // No previous buffer, so always invalidate the whole screen, whether // or not DAMAGE is being used. DAMAGE doesn't necessarily send a @@ -458,13 +470,10 @@ CaptureData* VideoFrameCapturerLinux::CaptureFrame() { } capture_data->mutable_dirty_region() = invalid_region; - last_invalid_region_ = invalid_region; - last_buffer_ = buffer.ptr(); return capture_data; } void VideoFrameCapturerLinux::ScreenConfigurationChanged() { - last_buffer_ = NULL; for (int i = 0; i < kNumBuffers; ++i) { buffers_[i].set_needs_update(); } @@ -481,13 +490,15 @@ void VideoFrameCapturerLinux::SynchronizeFrame() { // TODO(hclam): We can reduce the amount of copying here by subtracting // |capturer_helper_|s region from |last_invalid_region_|. // http://crbug.com/92354 - DCHECK(last_buffer_); + DCHECK(!buffers_[last_buffer_].needs_update()); + DCHECK_NE(last_buffer_, current_buffer_); VideoFrameBuffer& buffer = buffers_[current_buffer_]; + VideoFrameBuffer& last_buffer = buffers_[last_buffer_]; for (SkRegion::Iterator it(last_invalid_region_); !it.done(); it.next()) { const SkIRect& r = it.rect(); int offset = r.fTop * buffer.bytes_per_row() + r.fLeft * kBytesPerPixel; for (int i = 0; i < r.height(); ++i) { - memcpy(buffer.ptr() + offset, last_buffer_ + offset, + memcpy(buffer.ptr() + offset, last_buffer.ptr() + offset, r.width() * kBytesPerPixel); offset += buffer.size().width() * kBytesPerPixel; } |