diff options
author | garykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-06 22:50:00 +0000 |
---|---|---|
committer | garykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-06 22:50:00 +0000 |
commit | 88552a9c89b99b93211ac5e679a0c13420e294db (patch) | |
tree | be326ad62f7c9c9b3dfdea155a306005af00356a | |
parent | ce3b22e8da4fa9ca838423bacd54e45c3030d518 (diff) | |
download | chromium_src-88552a9c89b99b93211ac5e679a0c13420e294db.zip chromium_src-88552a9c89b99b93211ac5e679a0c13420e294db.tar.gz chromium_src-88552a9c89b99b93211ac5e679a0c13420e294db.tar.bz2 |
Initial pass at integrating Differ into the chromoting host code.
BUG=none
TEST=run Win host; x11 client
Review URL: http://codereview.chromium.org/3013015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55297 0039d316-1c4b-4281-b951-d872f2087c98
33 files changed, 387 insertions, 217 deletions
diff --git a/gfx/point.h b/gfx/point.h index e93dc0c..5c6cb72 100644 --- a/gfx/point.h +++ b/gfx/point.h @@ -73,6 +73,16 @@ class Point { return !(*this == rhs); } + // A point is less than another point if its y-value is closer + // to the origin. If the y-values are the same, then point with + // the x-value closer to the origin is considered less than the + // other. + // This comparison is required to use Points in sets, or sorted + // vectors. + bool operator<(const Point& rhs) const { + return (y_ == rhs.y_) ? (x_ < rhs.x_) : (y_ < rhs.y_); + } + #if defined(OS_WIN) POINT ToPOINT() const; #elif defined(OS_MACOSX) diff --git a/gfx/rect.cc b/gfx/rect.cc index 6053b9e..c081dea 100644 --- a/gfx/rect.cc +++ b/gfx/rect.cc @@ -117,6 +117,18 @@ bool Rect::operator==(const Rect& other) const { return origin_ == other.origin_ && size_ == other.size_; } +bool Rect::operator<(const Rect& other) const { + if (origin_ == other.origin_) { + if (width() == other.width()) { + return height() < other.height(); + } else { + return width() < other.width(); + } + } else { + return origin_ < other.origin_; + } +} + #if defined(OS_WIN) RECT Rect::ToRECT() const { RECT r; @@ -102,6 +102,14 @@ class Rect { return !(*this == other); } + // A rect is less than another rect if its origin is less than + // the other rect's origin. If the origins are equal, then the + // shortest rect is less than the other. If the origin and the + // height are equal, then the narrowest rect is less than. + // This comparison is required to use Rects in sets, or sorted + // vectors. + bool operator<(const Rect& other) const; + #if defined(OS_WIN) // Construct an equivalent Win32 RECT object. RECT ToRECT() const; diff --git a/remoting/base/capture_data.h b/remoting/base/capture_data.h index 2ac8a12..b06dfa4 100644 --- a/remoting/base/capture_data.h +++ b/remoting/base/capture_data.h @@ -9,13 +9,11 @@ #include "base/basictypes.h" #include "base/ref_counted.h" -#include "gfx/rect.h" #include "remoting/base/protocol/chromotocol.pb.h" +#include "remoting/base/types.h" namespace remoting { -typedef std::vector<gfx::Rect> RectVector; - struct DataPlanes { static const int kPlaneCount = 3; uint8* data[kPlaneCount]; @@ -45,7 +43,7 @@ class CaptureData : public base::RefCountedThreadSafe<CaptureData> { // Get the list of updated rectangles in the last capture. The result is // written into |rects|. - const RectVector& dirty_rects() const { return dirty_rects_; } + const InvalidRects& dirty_rects() const { return dirty_rects_; } // Get the width of the image captured. int width() const { return width_; } @@ -57,11 +55,11 @@ class CaptureData : public base::RefCountedThreadSafe<CaptureData> { PixelFormat pixel_format() const { return pixel_format_; } // Mutating methods. - RectVector& mutable_dirty_rects() { return dirty_rects_; } + InvalidRects& mutable_dirty_rects() { return dirty_rects_; } private: const DataPlanes data_planes_; - RectVector dirty_rects_; + InvalidRects dirty_rects_; int width_; int height_; PixelFormat pixel_format_; diff --git a/remoting/base/codec_test.cc b/remoting/base/codec_test.cc index 4085b28..b0628fb 100644 --- a/remoting/base/codec_test.cc +++ b/remoting/base/codec_test.cc @@ -339,8 +339,9 @@ static void TestEncodingRects(Encoder* encoder, scoped_refptr<CaptureData> data, const gfx::Rect* rects, int count) { data->mutable_dirty_rects().clear(); - data->mutable_dirty_rects().insert( - data->mutable_dirty_rects().begin(), rects, rects + count); + for (int i = 0; i < count; ++i) { + data->mutable_dirty_rects().insert(rects[i]); + } tester->AddRects(rects, count); encoder->Encode(data, true, @@ -371,8 +372,9 @@ static void TestEncodingRects(Encoder* encoder, scoped_refptr<CaptureData> data, const gfx::Rect* rects, int count) { data->mutable_dirty_rects().clear(); - data->mutable_dirty_rects().insert( - data->mutable_dirty_rects().begin(), rects, rects + count); + for (int i = 0; i < count; ++i) { + data->mutable_dirty_rects().insert(rects[i]); + } encoder_tester->AddRects(rects, count); decoder_tester->AddRects(rects, count); decoder_tester->reset_decode_done(); diff --git a/remoting/base/encoder_verbatim.cc b/remoting/base/encoder_verbatim.cc index 7f39f27..6a5a7d6 100644 --- a/remoting/base/encoder_verbatim.cc +++ b/remoting/base/encoder_verbatim.cc @@ -17,9 +17,12 @@ using media::DataBuffer; void EncoderVerbatim::Encode(scoped_refptr<CaptureData> capture_data, bool key_frame, DataAvailableCallback* data_available_callback) { - int num_rects = capture_data->dirty_rects().size(); - for (int i = 0; i < num_rects; i++) { - const gfx::Rect& dirty_rect = capture_data->dirty_rects()[i]; + const InvalidRects& rects = capture_data->dirty_rects(); + int num_rects = rects.size(); + int index = 0; + for (InvalidRects::const_iterator r = rects.begin(); + r != rects.end(); ++r, ++index) { + const gfx::Rect& dirty_rect = *r; HostMessage* msg = new HostMessage(); UpdateStreamPacketMessage* packet = msg->mutable_update_stream_packet(); @@ -29,10 +32,10 @@ void EncoderVerbatim::Encode(scoped_refptr<CaptureData> capture_data, packet->mutable_end_rect(); EncodingState state = EncodingInProgress; - if (i == 0) { + if (index == 0) { state |= EncodingStarting; } - if (i == num_rects - 1) { + if (index == num_rects - 1) { state |= EncodingEnded; } data_available_callback->Run(msg, state); diff --git a/remoting/base/encoder_zlib.cc b/remoting/base/encoder_zlib.cc index 848804a..84842ac 100644 --- a/remoting/base/encoder_zlib.cc +++ b/remoting/base/encoder_zlib.cc @@ -30,24 +30,25 @@ void EncoderZlib::Encode(scoped_refptr<CaptureData> capture_data, callback_.reset(data_available_callback); CompressorZlib compressor; - for (current_rect_ = 0; current_rect_ < capture_data->dirty_rects().size(); - ++current_rect_) { - EncodeRect(&compressor); + const InvalidRects& rects = capture_data->dirty_rects(); + int index = 0; + for (InvalidRects::const_iterator r = rects.begin(); + r != rects.end(); ++r, ++index) { + EncodeRect(&compressor, *r, index); } capture_data_ = NULL; callback_.reset(); - current_rect_ = 0; } -void EncoderZlib::EncodeRect(CompressorZlib* compressor) { +void EncoderZlib::EncodeRect(CompressorZlib* compressor, + const gfx::Rect& rect, size_t rect_index) { CHECK(capture_data_->data_planes().data[0]); - const gfx::Rect rect = capture_data_->dirty_rects()[current_rect_]; const int strides = capture_data_->data_planes().strides[0]; const int bytes_per_pixel = GetBytesPerPixel(capture_data_->pixel_format()); const int row_size = bytes_per_pixel * rect.width(); - HostMessage* message = PrepareMessage(true); + HostMessage* message = PrepareMessage(&rect); const uint8 * in = capture_data_->data_planes().data[0] + rect.y() * strides + rect.x() * bytes_per_pixel; @@ -61,7 +62,7 @@ void EncoderZlib::EncodeRect(CompressorZlib* compressor) { while (compress_again) { // Prepare a message for sending out. if (!message) { - message = PrepareMessage(false); + message = PrepareMessage(NULL); out = (uint8*)(message->mutable_update_stream_packet()-> mutable_rect_data()->mutable_data()->data()); filled = 0; @@ -69,10 +70,11 @@ void EncoderZlib::EncodeRect(CompressorZlib* compressor) { Compressor::CompressorFlush flush = Compressor::CompressorNoFlush; if (row_y == rect.height() - 1) { - if (current_rect_ == capture_data_->dirty_rects().size() - 1) + if (rect_index == capture_data_->dirty_rects().size() - 1) { flush = Compressor::CompressorFinish; - else + } else { flush = Compressor::CompressorSyncFlush; + } } int consumed = 0; @@ -92,7 +94,7 @@ void EncoderZlib::EncodeRect(CompressorZlib* compressor) { if (filled == packet_size_ || !compress_again) { message->mutable_update_stream_packet()->mutable_rect_data()-> mutable_data()->resize(filled); - SubmitMessage(message); + SubmitMessage(message, rect_index); message = NULL; } @@ -105,17 +107,16 @@ void EncoderZlib::EncodeRect(CompressorZlib* compressor) { } } -HostMessage* EncoderZlib::PrepareMessage(bool new_rect) { +HostMessage* EncoderZlib::PrepareMessage(const gfx::Rect* rect) { HostMessage* message = new HostMessage(); UpdateStreamPacketMessage* packet = message->mutable_update_stream_packet(); // Prepare the begin rect content. - if (new_rect) { - gfx::Rect rect = capture_data_->dirty_rects()[current_rect_]; - packet->mutable_begin_rect()->set_x(rect.x()); - packet->mutable_begin_rect()->set_y(rect.y()); - packet->mutable_begin_rect()->set_width(rect.width()); - packet->mutable_begin_rect()->set_height(rect.height()); + if (rect != NULL) { + packet->mutable_begin_rect()->set_x(rect->x()); + packet->mutable_begin_rect()->set_y(rect->y()); + packet->mutable_begin_rect()->set_width(rect->width()); + packet->mutable_begin_rect()->set_height(rect->height()); packet->mutable_begin_rect()->set_encoding(EncodingZlib); packet->mutable_begin_rect()->set_pixel_format( capture_data_->pixel_format()); @@ -125,11 +126,11 @@ HostMessage* EncoderZlib::PrepareMessage(bool new_rect) { return message; } -void EncoderZlib::SubmitMessage(HostMessage* message) { +void EncoderZlib::SubmitMessage(HostMessage* message, size_t rect_index) { EncodingState state = EncodingInProgress; - if (current_rect_ == 0 && message->update_stream_packet().has_begin_rect()) + if (rect_index == 0 && message->update_stream_packet().has_begin_rect()) state |= EncodingStarting; - if (current_rect_ == capture_data_->dirty_rects().size() - 1 && + if (rect_index == capture_data_->dirty_rects().size() - 1 && message->update_stream_packet().has_end_rect()) state |= EncodingEnded; callback_->Run(message, state); diff --git a/remoting/base/encoder_zlib.h b/remoting/base/encoder_zlib.h index 9266e2b1..476135b 100644 --- a/remoting/base/encoder_zlib.h +++ b/remoting/base/encoder_zlib.h @@ -7,6 +7,8 @@ #include "remoting/base/encoder.h" +#include "gfx/rect.h" + namespace remoting { class CompressorZlib; @@ -26,18 +28,19 @@ class EncoderZlib : public Encoder { private: // Encode a single dirty rect using compressor. - void EncodeRect(CompressorZlib* compressor); + void EncodeRect(CompressorZlib* compressor, const gfx::Rect& rect, + size_t rect_index); // Create a new HostMessage with the right flag and attributes. The message // can be used immediately for output of encoding. - HostMessage* PrepareMessage(bool new_rect); + HostMessage* PrepareMessage(const gfx::Rect* rect); // Submit |message| to |callback_|. - void SubmitMessage(HostMessage* message); + void SubmitMessage(HostMessage* message, size_t rect_index); scoped_refptr<CaptureData> capture_data_; scoped_ptr<DataAvailableCallback> callback_; - size_t current_rect_; + //size_t current_rect_; int packet_size_; }; diff --git a/remoting/base/types.h b/remoting/base/types.h new file mode 100644 index 0000000..321bb0a --- /dev/null +++ b/remoting/base/types.h @@ -0,0 +1,21 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_BASE_TYPES_H_ +#define REMOTING_BASE_TYPES_H_ + +#include <set> + +#include "gfx/rect.h" + +namespace remoting { + +// The collection of 'invalid' screen rectangles. +// This is used to keep track of regions of the screen that require +// updating. +typedef std::set<gfx::Rect> InvalidRects; + +} // namespace remoting + +#endif // REMOTING_BASE_TYPES_H_ diff --git a/remoting/host/capturer.cc b/remoting/host/capturer.cc index 917a960..b61132b 100644 --- a/remoting/host/capturer.cc +++ b/remoting/host/capturer.cc @@ -4,6 +4,8 @@ #include "remoting/host/capturer.h" +#include <algorithm> + namespace remoting { Capturer::Capturer() @@ -17,30 +19,41 @@ Capturer::Capturer() Capturer::~Capturer() { } -void Capturer::CaptureInvalidRects(CaptureCompletedCallback* callback) { - // Braced to scope the lock. - RectVector local_rects; +void Capturer::ClearInvalidRects() { + AutoLock auto_inval_rects_lock(inval_rects_lock_); + inval_rects_.clear(); +} + +void Capturer::InvalidateRects(const InvalidRects& inval_rects) { + InvalidRects temp_rects; + std::set_union(inval_rects_.begin(), inval_rects_.end(), + inval_rects.begin(), inval_rects.end(), + std::inserter(temp_rects, temp_rects.begin())); { AutoLock auto_inval_rects_lock(inval_rects_lock_); - local_rects = inval_rects_; - inval_rects_.clear(); + inval_rects_.swap(temp_rects); } - - CaptureRects(local_rects, callback); } -void Capturer::InvalidateRects(const RectVector& inval_rects) { +void Capturer::InvalidateFullScreen() { AutoLock auto_inval_rects_lock(inval_rects_lock_); - inval_rects_.insert(inval_rects_.end(), - inval_rects.begin(), - inval_rects.end()); + inval_rects_.clear(); + inval_rects_.insert(gfx::Rect(0, 0, width_, height_)); } -void Capturer::InvalidateFullScreen() { - RectVector rects; - rects.push_back(gfx::Rect(0, 0, width_, height_)); +void Capturer::CaptureInvalidRects(CaptureCompletedCallback* callback) { + // Calculate which rects need to be captured. + CalculateInvalidRects(); + + // Braced to scope the lock. + InvalidRects local_rects; + { + AutoLock auto_inval_rects_lock(inval_rects_lock_); + local_rects = inval_rects_; + inval_rects_.clear(); + } - InvalidateRects(rects); + CaptureRects(local_rects, callback); } void Capturer::FinishCapture(scoped_refptr<CaptureData> data, diff --git a/remoting/host/capturer.h b/remoting/host/capturer.h index 30d6737..8a11ed5 100644 --- a/remoting/host/capturer.h +++ b/remoting/host/capturer.h @@ -10,16 +10,33 @@ #include "base/lock.h" #include "base/task.h" #include "remoting/base/capture_data.h" +#include "remoting/base/types.h" namespace remoting { // A class to perform the task of capturing the image of a window. // The capture action is asynchronous to allow maximum throughput. // -// Implementation has to ensure the following gurantees: +// The full capture process is as follows: +// +// (1) InvalidateRects +// This is an optional step where regions of the screen are marked as +// invalid. Some platforms (Windows, for now) won't use this and will +// instead calculate the diff-regions later (in step (2). Other +// platforms (Mac) will use this to mark all the changed regions of the +// screen. Some limited rect-merging (e.g., to eliminate exact +// duplicates) may be done here. +// +// (2) CaptureInvalidRects +// This is where the bits for the invalid rects are packaged up and sent +// to the encoder. +// A screen capture is performed if needed. For example, Windows requires +// a capture to calculate the diff from the previous screen, whereas the +// Mac version does not. +// +// Implementation has to ensure the following guarantees: // 1. Double buffering -// Since data can be read while another capture action is -// happening. +// Since data can be read while another capture action is happening. class Capturer { public: // CaptureCompletedCallback is called when the capturer has completed. @@ -28,11 +45,35 @@ class Capturer { Capturer(); virtual ~Capturer(); + // Called when the screen configuration is changed. + virtual void ScreenConfigurationChanged() = 0; - // Capture the updated regions since last capture. If the last - // capture doesn't exist, the full window is captured. + // Return the width of the screen. + virtual int width() const { return width_; } + + // Return the height of the screen. + virtual int height() const { return height_; } + + // Return the pixel format of the screen. + virtual PixelFormat pixel_format() const { return pixel_format_; } + + // Clear out the list of invalid rects. + void ClearInvalidRects(); + + // Invalidate the specified screen rects. + void InvalidateRects(const InvalidRects& inval_rects); + + // Invalidate the entire screen. + virtual void InvalidateFullScreen(); + + // Capture the screen data associated with each of the accumulated + // rects in |inval_rects|. + // This routine will first call CalculateInvalidRects to update the + // list of |inval_rects|. + // When the capture is complete, |callback| is called. // - // When complete |callback| is called. + // If |inval_rects_| is empty, then this does nothing except + // call the |callback| routine. // // It is OK to call this method while another thread is reading // data of the last capture. @@ -40,45 +81,32 @@ class Capturer { // method is called. virtual void CaptureInvalidRects(CaptureCompletedCallback* callback); + protected: + // Update the list of |invalid_rects| to prepare for capturing the + // screen data. + // Depending on the platform implementation, this routine might: + // (a) Analyze screen and calculate the list of rects that have changed + // since the last capture. + // (b) Merge already-acculumated rects into a more optimal list (for + // example, by combining or removing rects). + virtual void CalculateInvalidRects() = 0; + // Capture the specified screen rects and call |callback| when complete. // Dirty or invalid regions are ignored and only the given |rects| areas are // captured. - // - // It is OK to call this method while another thread is reading - // data of the last capture. - // There can be at most one concurrent read going on when this - // method is called. - virtual void CaptureRects(const RectVector& rects, + // This routine is used internally by CaptureInvalidRects(). + virtual void CaptureRects(const InvalidRects& rects, CaptureCompletedCallback* callback) = 0; - // Invalidate the specified screen rects. - virtual void InvalidateRects(const RectVector& inval_rects); - - // Invalidate the entire screen. - virtual void InvalidateFullScreen(); - - // Called when the screen configuration is changed. - virtual void ScreenConfigurationChanged() = 0; - - // Return the width of the screen. - virtual int width() const { return width_; } - - // Return the height of the screen - virtual int height() const { return height_; } - - // Return the pixel format of the screen - virtual PixelFormat pixel_format() const { return pixel_format_; } - - protected: // Finish/cleanup capture task. - // This should be called at the end of each of the CaptureXxx() routines. + // This should be called by CaptureRects() when it finishes. // This routine should (at least): // (1) Call the |callback| routine. // (2) Select the next screen buffer. // Note that capturers are required to be double-buffered so that we can // read from one which capturing into another. - virtual void FinishCapture(scoped_refptr<CaptureData> data, - CaptureCompletedCallback* callback); + void FinishCapture(scoped_refptr<CaptureData> data, + CaptureCompletedCallback* callback); // Number of screen buffers. static const int kNumBuffers = 2; @@ -95,11 +123,10 @@ class Capturer { int current_buffer_; private: - // Rects that have been manually invalidated (through InvalidateRect). // These will be returned as dirty_rects in the capture data during the next // capture. - RectVector inval_rects_; + InvalidRects inval_rects_; // A lock protecting |inval_rects_| across threads. Lock inval_rects_lock_; diff --git a/remoting/host/capturer_fake.cc b/remoting/host/capturer_fake.cc index eee2d5a..e546788 100644 --- a/remoting/host/capturer_fake.cc +++ b/remoting/host/capturer_fake.cc @@ -20,21 +20,6 @@ CapturerFake::CapturerFake() CapturerFake::~CapturerFake() { } -void CapturerFake::CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback) { - GenerateImage(); - DataPlanes planes; - planes.data[0] = buffers_[current_buffer_].get(); - planes.strides[0] = bytes_per_row_; - - scoped_refptr<CaptureData> capture_data(new CaptureData(planes, - width_, - height_, - pixel_format_)); - capture_data->mutable_dirty_rects() = rects; - FinishCapture(capture_data, callback); -} - void CapturerFake::ScreenConfigurationChanged() { width_ = kWidth; height_ = kHeight; @@ -48,6 +33,25 @@ void CapturerFake::ScreenConfigurationChanged() { } } +void CapturerFake::CalculateInvalidRects() { + GenerateImage(); + InvalidateFullScreen(); +} + +void CapturerFake::CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback) { + DataPlanes planes; + planes.data[0] = buffers_[current_buffer_].get(); + planes.strides[0] = bytes_per_row_; + + scoped_refptr<CaptureData> capture_data(new CaptureData(planes, + width_, + height_, + pixel_format_)); + capture_data->mutable_dirty_rects() = rects; + FinishCapture(capture_data, callback); +} + void CapturerFake::GenerateImage() { uint8* row = buffers_[current_buffer_].get(); for (int y = 0; y < height_; ++y) { diff --git a/remoting/host/capturer_fake.h b/remoting/host/capturer_fake.h index 79de376..84cc7ba 100644 --- a/remoting/host/capturer_fake.h +++ b/remoting/host/capturer_fake.h @@ -20,11 +20,13 @@ class CapturerFake : public Capturer { CapturerFake(); virtual ~CapturerFake(); - virtual void CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback); virtual void ScreenConfigurationChanged(); private: + virtual void CalculateInvalidRects(); + virtual void CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback); + // Generates an image in the front buffer. void GenerateImage(); diff --git a/remoting/host/capturer_fake_ascii.cc b/remoting/host/capturer_fake_ascii.cc index ccdbfcf..1bb9d44 100644 --- a/remoting/host/capturer_fake_ascii.cc +++ b/remoting/host/capturer_fake_ascii.cc @@ -18,19 +18,6 @@ CapturerFakeAscii::CapturerFakeAscii() { CapturerFakeAscii::~CapturerFakeAscii() { } -void CapturerFakeAscii::CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback) { - GenerateImage(); - DataPlanes planes; - planes.data[0] = buffers_[current_buffer_].get(); - planes.strides[0] = bytes_per_row_; - scoped_refptr<CaptureData> capture_data(new CaptureData(planes, - width_, - height_, - pixel_format_)); - FinishCapture(capture_data, callback); -} - void CapturerFakeAscii::ScreenConfigurationChanged() { width_ = kWidth; height_ = kHeight; @@ -44,6 +31,26 @@ void CapturerFakeAscii::ScreenConfigurationChanged() { } } +void CapturerFakeAscii::CalculateInvalidRects() { + // Capture and invalidate the entire screen. + // Performing the capture here is modelled on the Windows + // GDI capturer. + GenerateImage(); + InvalidateFullScreen(); +} + +void CapturerFakeAscii::CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback) { + DataPlanes planes; + planes.data[0] = buffers_[current_buffer_].get(); + planes.strides[0] = bytes_per_row_; + scoped_refptr<CaptureData> capture_data(new CaptureData(planes, + width_, + height_, + pixel_format_)); + FinishCapture(capture_data, callback); +} + void CapturerFakeAscii::GenerateImage() { for (int y = 0; y < height_; ++y) { uint8* row = buffers_[current_buffer_].get() + bytes_per_row_ * y; diff --git a/remoting/host/capturer_fake_ascii.h b/remoting/host/capturer_fake_ascii.h index 5457c41..fc03856 100644 --- a/remoting/host/capturer_fake_ascii.h +++ b/remoting/host/capturer_fake_ascii.h @@ -20,11 +20,13 @@ class CapturerFakeAscii : public Capturer { CapturerFakeAscii(); virtual ~CapturerFakeAscii(); - virtual void CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback); virtual void ScreenConfigurationChanged(); private: + virtual void CalculateInvalidRects(); + virtual void CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback); + // Generates an image in the front buffer. void GenerateImage(); diff --git a/remoting/host/capturer_gdi.cc b/remoting/host/capturer_gdi.cc index 6190819..209eea4 100644 --- a/remoting/host/capturer_gdi.cc +++ b/remoting/host/capturer_gdi.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "remoting/host/capturer_gdi.h" +#include "remoting/host/differ.h" #include "gfx/rect.h" @@ -13,8 +14,10 @@ static const int kPixelsPerMeter = 3780; // 32 bit RGBA is 4 bytes per pixel. static const int kBytesPerPixel = 4; -CapturerGdi::CapturerGdi() : desktop_dc_(NULL), - memory_dc_(NULL) { +CapturerGdi::CapturerGdi() + : desktop_dc_(NULL), + memory_dc_(NULL), + capture_fullscreen_(true) { memset(target_bitmap_, 0, sizeof(target_bitmap_)); memset(buffers_, 0, sizeof(buffers_)); } @@ -57,6 +60,9 @@ void CapturerGdi::ScreenConfigurationChanged() { pixel_format_ = PixelFormatRgb32; bytes_per_row_ = rounded_width * kBytesPerPixel; + // Create a differ for this screen size. + differ_.reset(new Differ(width_, height_, 4, bytes_per_row_)); + // Create a device independant bitmap (DIB) that is the same size. BITMAPINFO bmi; memset(&bmi, 0, sizeof(bmi)); @@ -75,15 +81,41 @@ void CapturerGdi::ScreenConfigurationChanged() { static_cast<void**>(&buffers_[i]), NULL, 0); } + + capture_fullscreen_ = true; } -void CapturerGdi::CaptureRects(const RectVector& rects, +void CapturerGdi::CalculateInvalidRects() { + ClearInvalidRects(); + CaptureImage(); + + if (capture_fullscreen_) { + InvalidateFullScreen(); + } else { + // Calculate the difference between the previous and current screen. + int prev_buffer_id = current_buffer_ - 1; + if (prev_buffer_id < 0) { + prev_buffer_id = kNumBuffers - 1; + } + + void* prev_buffer = buffers_[prev_buffer_id]; + void* curr_buffer = buffers_[current_buffer_]; + + InvalidRects rects; + differ_->CalcDirtyRects(prev_buffer, curr_buffer, &rects); + + InvalidateRects(rects); + } + + capture_fullscreen_ = false; +} + +void CapturerGdi::CaptureRects(const InvalidRects& rects, CaptureCompletedCallback* callback) { DataPlanes planes; planes.data[0] = static_cast<uint8*>(buffers_[current_buffer_]); planes.strides[0] = bytes_per_row_; - CaptureImage(); scoped_refptr<CaptureData> data(new CaptureData(planes, width(), height(), @@ -94,7 +126,7 @@ void CapturerGdi::CaptureRects(const RectVector& rects, } void CapturerGdi::CaptureImage() { - // Selection the target bitmap into the memory dc. + // Select the target bitmap into the memory dc. SelectObject(memory_dc_, target_bitmap_[current_buffer_]); // And then copy the rect from desktop to memory. diff --git a/remoting/host/capturer_gdi.h b/remoting/host/capturer_gdi.h index 4a1949e..989f491 100644 --- a/remoting/host/capturer_gdi.h +++ b/remoting/host/capturer_gdi.h @@ -12,6 +12,8 @@ typedef HBITMAP BitmapRef; namespace remoting { +class Differ; + // CapturerGdi captures 32bit RGB using GDI. // // CapturerGdi is doubled buffered as required by Capturer. See @@ -21,11 +23,13 @@ class CapturerGdi : public Capturer { CapturerGdi(); virtual ~CapturerGdi(); - virtual void CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback); virtual void ScreenConfigurationChanged(); private: + virtual void CalculateInvalidRects(); + virtual void CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback); + void ReleaseBuffers(); // Generates an image in the current buffer. void CaptureImage(); @@ -38,6 +42,12 @@ class CapturerGdi : public Capturer { // We have two buffers for the screen images as required by Capturer. void* buffers_[kNumBuffers]; + // Class to calculate the difference between two screen bitmaps. + scoped_ptr<Differ> differ_; + + // True if we should force a fullscreen capture. + bool capture_fullscreen_; + DISALLOW_COPY_AND_ASSIGN(CapturerGdi); }; diff --git a/remoting/host/capturer_linux.cc b/remoting/host/capturer_linux.cc index e61d530..e53c597 100644 --- a/remoting/host/capturer_linux.cc +++ b/remoting/host/capturer_linux.cc @@ -16,7 +16,10 @@ CapturerLinux::~CapturerLinux() { void CapturerLinux::ScreenConfigurationChanged() { } -void CapturerLinux::CaptureRects(const RectVector& rects, +void CapturerLinux::CalculateInvalidRects() { +} + +void CapturerLinux::CaptureRects(const InvalidRects& rects, CaptureCompletedCallback* callback) { } diff --git a/remoting/host/capturer_linux.h b/remoting/host/capturer_linux.h index db47679..b7c2d93 100644 --- a/remoting/host/capturer_linux.h +++ b/remoting/host/capturer_linux.h @@ -15,12 +15,12 @@ class CapturerLinux : public Capturer { CapturerLinux(); virtual ~CapturerLinux(); - virtual void CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback); - virtual void ScreenConfigurationChanged(); private: + virtual void CalculateInvalidRects(); + virtual void CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback); DISALLOW_COPY_AND_ASSIGN(CapturerLinux); }; diff --git a/remoting/host/capturer_mac.cc b/remoting/host/capturer_mac.cc index bfb031a..6d6b6cc 100644 --- a/remoting/host/capturer_mac.cc +++ b/remoting/host/capturer_mac.cc @@ -71,11 +71,17 @@ void CapturerMac::ScreenConfigurationChanged() { CGLSetCurrentContext(cgl_context_); } -void CapturerMac::CaptureRects(const RectVector& rects, +void CapturerMac::CalculateInvalidRects() { + // Since the Mac gets its list of invalid rects via calls to InvalidateRect(), + // this step only needs to perform post-processing optimizations on the rect + // list (if needed). +} + +void CapturerMac::CaptureRects(const InvalidRects& rects, CaptureCompletedCallback* callback) { // TODO(dmaclach): something smarter here in the future. gfx::Rect dirtyRect; - for (RectVector::const_iterator i = rects.begin(); i < rects.end(); ++i) { + for (InvalidRects::const_iterator i = rects.begin(); i != rects.end(); ++i) { dirtyRect = dirtyRect.Union(*i); } @@ -101,32 +107,31 @@ void CapturerMac::CaptureRects(const RectVector& rects, width(), height(), pixel_format())); - data->mutable_dirty_rects().assign(1, dirtyRect); + data->mutable_dirty_rects().clear(); + data->mutable_dirty_rects().insert(dirtyRect); FinishCapture(data, callback); } - void CapturerMac::ScreenRefresh(CGRectCount count, const CGRect *rect_array) { - RectVector rects; + InvalidRects rects; for (CGRectCount i = 0; i < count; ++i) { CGRect rect = rect_array[i]; rect.origin.y = height() - rect.size.height; - rects.push_back(gfx::Rect(rect)); + rects.insert(gfx::Rect(rect)); } InvalidateRects(rects); - } void CapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta, size_t count, const CGRect *rect_array) { - RectVector rects; + InvalidRects rects; for (CGRectCount i = 0; i < count; ++i) { CGRect rect = rect_array[i]; rect.origin.y = height() - rect.size.height; - rects.push_back(gfx::Rect(rect)); + rects.insert(gfx::Rect(rect)); rect = CGRectOffset(rect, delta.dX, delta.dY); - rects.push_back(gfx::Rect(rect)); + rects.insert(gfx::Rect(rect)); } InvalidateRects(rects); } diff --git a/remoting/host/capturer_mac.h b/remoting/host/capturer_mac.h index 1ca88ae1..b679d8e 100644 --- a/remoting/host/capturer_mac.h +++ b/remoting/host/capturer_mac.h @@ -18,12 +18,13 @@ class CapturerMac : public Capturer { CapturerMac(); virtual ~CapturerMac(); - virtual void CaptureRects(const RectVector& rects, - CaptureCompletedCallback* callback); - virtual void ScreenConfigurationChanged(); private: + virtual void CalculateInvalidRects(); + virtual void CaptureRects(const InvalidRects& rects, + CaptureCompletedCallback* callback); + void ScreenRefresh(CGRectCount count, const CGRect *rect_array); void ScreenUpdateMove(CGScreenUpdateMoveDelta delta, size_t count, diff --git a/remoting/host/capturer_mac_unittest.cc b/remoting/host/capturer_mac_unittest.cc index a172b15..937d2bd 100644 --- a/remoting/host/capturer_mac_unittest.cc +++ b/remoting/host/capturer_mac_unittest.cc @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/scoped_ptr.h" +#include "remoting/base/types.h" #include "remoting/host/capturer_mac.h" #include "testing/gmock/include/gmock/gmock.h" @@ -18,20 +19,20 @@ class CapturerMacTest : public testing::Test { virtual void SetUp() { capturer_.reset(new CapturerMac()); capturer_->ScreenConfigurationChanged(); - rects_.push_back(gfx::Rect(0, 0, 10, 10)); + rects_.insert(gfx::Rect(0, 0, 10, 10)); } scoped_ptr<CapturerMac> capturer_; - RectVector rects_; + InvalidRects rects_; }; class CapturerCallback { public: - explicit CapturerCallback(const RectVector& rects) : rects_(rects) { } + explicit CapturerCallback(const InvalidRects& rects) : rects_(rects) { } void CaptureDoneCallback(scoped_refptr<CaptureData> capture_data); protected: - RectVector rects_; + InvalidRects rects_; private: DISALLOW_COPY_AND_ASSIGN(CapturerCallback); @@ -66,9 +67,10 @@ TEST_F(CapturerMacTest, Capture) { } // namespace remoting -std::ostream& operator<<(std::ostream& out, const remoting::RectVector& rects) { - for (remoting::RectVector::const_iterator i = rects.begin(); - i < rects.end(); +std::ostream& operator<<(std::ostream& out, + const remoting::InvalidRects& rects) { + for (remoting::InvalidRects::const_iterator i = rects.begin(); + i != rects.end(); ++i) { out << *i << std::endl; } diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 063ee83..3e47f54 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -96,7 +96,7 @@ void ChromotingHost::OnClientDisconnected(ClientConnection* client) { //////////////////////////////////////////////////////////////////////////// // ClientConnection::EventHandler implementations void ChromotingHost::HandleMessages(ClientConnection* client, - ClientMessageList* messages) { + ClientMessageList* messages) { DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); // Delegate the messages to EventExecutor and delete the unhandled diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index d281b97..c45fe08 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h @@ -8,7 +8,10 @@ #include <string> #include "base/thread.h" +#include "remoting/base/encoder.h" +#include "remoting/host/capturer.h" #include "remoting/host/client_connection.h" +#include "remoting/host/event_executor.h" #include "remoting/host/heartbeat_sender.h" #include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" diff --git a/remoting/host/client_connection.h b/remoting/host/client_connection.h index c647eb6..c03a9bb 100644 --- a/remoting/host/client_connection.h +++ b/remoting/host/client_connection.h @@ -125,7 +125,7 @@ class ClientConnection : public base::RefCountedThreadSafe<ClientConnection>, // Process a data buffer received from libjingle. void PacketReceivedTask(scoped_refptr<media::DataBuffer> data); - // The libjingle channel used to send and receive data from the remote viewer. + // The libjingle channel used to send and receive data from the remote client. scoped_refptr<JingleChannel> channel_; // The message loop that this object runs on. diff --git a/remoting/host/differ.cc b/remoting/host/differ.cc index e0a8125..3409e0f 100644 --- a/remoting/host/differ.cc +++ b/remoting/host/differ.cc @@ -8,12 +8,12 @@ namespace remoting { -Differ::Differ(int width, int height, int bpp) { +Differ::Differ(int width, int height, int bpp, int stride) { // Dimensions of screen. width_ = width; height_ = height; bytes_per_pixel_ = bpp; - bytes_per_row_ = width_ * bytes_per_pixel_; + bytes_per_row_ = stride; // Calc number of blocks (full and partial) required to cover entire image. // One additional row/column is added as a boundary on the right & bottom. @@ -24,7 +24,7 @@ Differ::Differ(int width, int height, int bpp) { } void Differ::CalcDirtyRects(const void* prev_buffer, const void* curr_buffer, - DirtyRects* rects) { + InvalidRects* rects) { if (!rects) { return; } @@ -147,7 +147,7 @@ DiffInfo Differ::DiffPartialBlock(const uint8* prev_buffer, return 0; } -void Differ::MergeBlocks(DirtyRects* rects) { +void Differ::MergeBlocks(InvalidRects* rects) { DCHECK(rects); rects->clear(); @@ -211,7 +211,7 @@ void Differ::MergeBlocks(DirtyRects* rects) { if (top + height > height_) { height = height_ - top; } - rects->push_back(gfx::Rect(left, top, width, height)); + rects->insert(gfx::Rect(left, top, width, height)); } // Increment to next block in this row. diff --git a/remoting/host/differ.h b/remoting/host/differ.h index 2ad48b9..1476cdb 100644 --- a/remoting/host/differ.h +++ b/remoting/host/differ.h @@ -10,10 +10,10 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "gfx/rect.h" +#include "remoting/base/types.h" namespace remoting { -typedef std::vector<gfx::Rect> DirtyRects; typedef uint8 DiffInfo; // Size (in pixels) of each square block used for diffing. @@ -24,12 +24,12 @@ class Differ { public: // Create a differ that operates on bitmaps with the specified width, height // and bytes_per_pixel. - Differ(int width, int height, int bytes_per_pixel); + Differ(int width, int height, int bytes_per_pixel, int stride); // Given the previous and current screen buffer, calculate the set of // rectangles that enclose all the changed pixels in the new screen. void CalcDirtyRects(const void* prev_buffer, const void* curr_buffer, - DirtyRects* rects); + InvalidRects* rects); // Identify all of the blocks that contain changed pixels. void MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer); @@ -54,7 +54,7 @@ class Differ { // blocks into larger rectangular units. // The goal is to minimize the number of rects that cover the dirty blocks, // although it is not required to calc the absolute minimum of rects. - void MergeBlocks(DirtyRects* rects); + void MergeBlocks(InvalidRects* rects); // Allow tests to access our private parts. friend class DifferTest; @@ -65,9 +65,10 @@ class Differ { int height_; // Number of bytes for each pixel in source and dest bitmap. + // (Yes, they must match.) int bytes_per_pixel_; - // Number of bytes in each row of the image. + // Number of bytes in each row of the image (AKA: stride). int bytes_per_row_; // Diff information for each block in the image. diff --git a/remoting/host/differ_unittest.cc b/remoting/host/differ_unittest.cc index 171d11d..f6156f3 100644 --- a/remoting/host/differ_unittest.cc +++ b/remoting/host/differ_unittest.cc @@ -9,9 +9,10 @@ namespace remoting { // 96x96 screen gives a 3x3 grid of blocks. -const int kScreenWidth = 96; +const int kScreenWidth= 96; const int kScreenHeight = 96; const int kBytesPerPixel = 3; +const int kBytesPerRow = (kBytesPerPixel * kScreenWidth); class DifferTest : public testing::Test { public: @@ -20,18 +21,17 @@ class DifferTest : public testing::Test { protected: virtual void SetUp() { - InitDiffer(kScreenWidth, kScreenHeight, kBytesPerPixel); + InitDiffer(kScreenWidth, kScreenHeight, kBytesPerPixel, kBytesPerRow); } - void InitDiffer(int width, int height, int bpp) { + void InitDiffer(int width, int height, int bpp, int stride) { width_ = width; height_ = height; bytes_per_pixel_ = bpp; - - stride_ = width_ * bytes_per_pixel_; + stride_ = stride; buffer_size_ = width_ * height_ * bytes_per_pixel_; - differ_.reset(new Differ(width_, height_, bytes_per_pixel_)); + differ_.reset(new Differ(width_, height_, bytes_per_pixel_, stride_)); prev_.reset(new uint8[buffer_size_]); memset(prev_.get(), 0, buffer_size_); @@ -126,12 +126,11 @@ class DifferTest : public testing::Test { // Verify that the given dirty rect matches the expected |x|, |y|, |width| // and |height|. // |x|, |y|, |width| and |height| are specified in block (not pixel) units. - void CheckDirtyRect(const gfx::Rect& rect, int x, int y, + void CheckDirtyRect(const InvalidRects& rects, int x, int y, int width, int height) { - EXPECT_EQ(x * kBlockSize, rect.x()); - EXPECT_EQ(y * kBlockSize, rect.y()); - EXPECT_EQ(width * kBlockSize, rect.width()); - EXPECT_EQ(height * kBlockSize, rect.height()); + gfx::Rect r(x * kBlockSize, y * kBlockSize, + width * kBlockSize, height * kBlockSize); + EXPECT_TRUE(rects.find(r) != rects.end()); } // Mark the range of blocks specified and then verify that they are @@ -142,11 +141,11 @@ class DifferTest : public testing::Test { ClearDiffInfo(); MarkBlocks(x_origin, y_origin, width, height); - scoped_ptr<DirtyRects> dirty(new DirtyRects()); + scoped_ptr<InvalidRects> dirty(new InvalidRects()); differ_->MergeBlocks(dirty.get()); ASSERT_EQ(1UL, dirty->size()); - CheckDirtyRect(dirty->at(0), x_origin, y_origin, width, height); + CheckDirtyRect(*dirty.get(), x_origin, y_origin, width, height); } // The differ class we're testing. @@ -269,7 +268,7 @@ TEST_F(DifferTest, MergeBlocks_Empty) { // +---+---+---+---+ ClearDiffInfo(); - scoped_ptr<DirtyRects> dirty(new DirtyRects()); + scoped_ptr<InvalidRects> dirty(new InvalidRects()); differ_->MergeBlocks(dirty.get()); EXPECT_EQ(0UL, dirty->size()); @@ -416,7 +415,7 @@ TEST_F(DifferTest, MergeBlocks_BlockRect) { // The exact rects returned depend on the current implementation, so these // may need to be updated if we modify how we merge blocks. TEST_F(DifferTest, MergeBlocks_MultiRect) { - scoped_ptr<DirtyRects> dirty; + scoped_ptr<InvalidRects> dirty; // +---+---+---+---+ +---+---+---+ // | | X | | _ | | | 0 | | @@ -432,13 +431,13 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(0, 1, 1, 1); MarkBlocks(2, 2, 1, 1); - dirty.reset(new DirtyRects()); + dirty.reset(new InvalidRects()); differ_->MergeBlocks(dirty.get()); ASSERT_EQ(3UL, dirty->size()); - CheckDirtyRect(dirty->at(0), 1, 0, 1, 1); - CheckDirtyRect(dirty->at(1), 0, 1, 1, 1); - CheckDirtyRect(dirty->at(2), 2, 2, 1, 1); + CheckDirtyRect(*dirty.get(), 1, 0, 1, 1); + CheckDirtyRect(*dirty.get(), 0, 1, 1, 1); + CheckDirtyRect(*dirty.get(), 2, 2, 1, 1); // +---+---+---+---+ +---+---+---+ // | | | X | _ | | | | 0 | @@ -453,12 +452,12 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 0, 1, 3); MarkBlocks(0, 1, 2, 2); - dirty.reset(new DirtyRects()); + dirty.reset(new InvalidRects()); differ_->MergeBlocks(dirty.get()); ASSERT_EQ(2UL, dirty->size()); - CheckDirtyRect(dirty->at(0), 2, 0, 1, 3); - CheckDirtyRect(dirty->at(1), 0, 1, 2, 2); + CheckDirtyRect(*dirty.get(), 2, 0, 1, 3); + CheckDirtyRect(*dirty.get(), 0, 1, 2, 2); // +---+---+---+---+ +---+---+---+ // | | | | _ | | | | | @@ -474,13 +473,13 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 1, 1, 1); MarkBlocks(0, 2, 3, 1); - dirty.reset(new DirtyRects()); + dirty.reset(new InvalidRects()); differ_->MergeBlocks(dirty.get()); ASSERT_EQ(3UL, dirty->size()); - CheckDirtyRect(dirty->at(0), 0, 1, 1, 2); - CheckDirtyRect(dirty->at(1), 2, 1, 1, 2); - CheckDirtyRect(dirty->at(2), 1, 2, 1, 1); + CheckDirtyRect(*dirty.get(), 0, 1, 1, 2); + CheckDirtyRect(*dirty.get(), 2, 1, 1, 2); + CheckDirtyRect(*dirty.get(), 1, 2, 1, 1); // +---+---+---+---+ +---+---+---+ // | X | X | X | _ | | 0 0 0 | @@ -497,14 +496,14 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(2, 1, 1, 1); MarkBlocks(0, 2, 3, 1); - dirty.reset(new DirtyRects()); + dirty.reset(new InvalidRects()); differ_->MergeBlocks(dirty.get()); ASSERT_EQ(4UL, dirty->size()); - CheckDirtyRect(dirty->at(0), 0, 0, 3, 1); - CheckDirtyRect(dirty->at(1), 0, 1, 1, 2); - CheckDirtyRect(dirty->at(2), 2, 1, 1, 2); - CheckDirtyRect(dirty->at(3), 1, 2, 1, 1); + CheckDirtyRect(*dirty.get(), 0, 0, 3, 1); + CheckDirtyRect(*dirty.get(), 0, 1, 1, 2); + CheckDirtyRect(*dirty.get(), 2, 1, 1, 2); + CheckDirtyRect(*dirty.get(), 1, 2, 1, 1); // +---+---+---+---+ +---+---+---+ // | X | X | | _ | | 0 0 | | @@ -519,12 +518,12 @@ TEST_F(DifferTest, MergeBlocks_MultiRect) { MarkBlocks(0, 0, 2, 2); MarkBlocks(1, 2, 1, 1); - dirty.reset(new DirtyRects()); + dirty.reset(new InvalidRects()); differ_->MergeBlocks(dirty.get()); ASSERT_EQ(2UL, dirty->size()); - CheckDirtyRect(dirty->at(0), 0, 0, 2, 2); - CheckDirtyRect(dirty->at(1), 1, 2, 1, 1); + CheckDirtyRect(*dirty.get(), 0, 0, 2, 2); + CheckDirtyRect(*dirty.get(), 1, 2, 1, 1); } } // namespace remoting diff --git a/remoting/host/mock_objects.h b/remoting/host/mock_objects.h index f58ac3b..f7d142c 100644 --- a/remoting/host/mock_objects.h +++ b/remoting/host/mock_objects.h @@ -18,12 +18,13 @@ class MockCapturer : public Capturer { public: MockCapturer() {} + MOCK_METHOD0(ScreenConfigurationChanged, void()); + MOCK_METHOD1(InvalidateRects, void(const InvalidRects& inval_rects)); + MOCK_METHOD0(InvalidateFullScreen, void()); + MOCK_METHOD0(CalculateInvalidRects, void()); MOCK_METHOD1(CaptureInvalidRects, void(CaptureCompletedCallback* callback)); - MOCK_METHOD2(CaptureRects, void(const RectVector& rects, + MOCK_METHOD2(CaptureRects, void(const InvalidRects& rects, CaptureCompletedCallback* callback)); - MOCK_METHOD1(InvalidateRects, void(const RectVector& inval_rects)); - MOCK_METHOD0(InvalidateFullScreen, void()); - MOCK_METHOD0(ScreenConfigurationChanged, void()); MOCK_CONST_METHOD0(width, int()); MOCK_CONST_METHOD0(height, int()); diff --git a/remoting/host/session_manager.cc b/remoting/host/session_manager.cc index ebfafeba..9d4f83e 100644 --- a/remoting/host/session_manager.cc +++ b/remoting/host/session_manager.cc @@ -210,17 +210,14 @@ void SessionManager::DoCapture() { // And finally perform one capture. DCHECK(capturer_.get()); - // TODO(dmaclach): make this not required on the Mac eventually. - // Will require getting the X11client to work properly. Right now X11 expects - // full screens each pass. - capturer_->InvalidateFullScreen(); capturer_->CaptureInvalidRects( NewCallback(this, &SessionManager::CaptureDoneCallback)); } void SessionManager::CaptureDoneCallback( scoped_refptr<CaptureData> capture_data) { - // TODO(hclam): There is a bug if the capturer doesn't produce any dirty rects. + // TODO(hclam): There is a bug if the capturer doesn't produce any dirty + // rects. DCHECK_EQ(capture_loop_, MessageLoop::current()); encode_loop_->PostTask( FROM_HERE, diff --git a/remoting/host/session_manager_unittest.cc b/remoting/host/session_manager_unittest.cc index 239eb97..29fa0f8 100644 --- a/remoting/host/session_manager_unittest.cc +++ b/remoting/host/session_manager_unittest.cc @@ -53,8 +53,12 @@ TEST_F(SessionManagerTest, Init) { } ACTION_P2(RunCallback, rects, data) { - RectVector& dirty_rects = data->mutable_dirty_rects(); - dirty_rects.insert(dirty_rects.end(), rects.begin(), rects.end()); + InvalidRects& dirty_rects = data->mutable_dirty_rects(); + InvalidRects temp_rects; + std::set_union(dirty_rects.begin(), dirty_rects.end(), + rects.begin(), rects.end(), + std::inserter(temp_rects, temp_rects.begin())); + dirty_rects.swap(temp_rects); arg0->Run(data); delete arg0; } @@ -79,8 +83,8 @@ ACTION_P(AssignDirtyRect, rects) { TEST_F(SessionManagerTest, OneRecordCycle) { Init(); - RectVector update_rects; - update_rects.push_back(gfx::Rect(0, 0, 10, 10)); + InvalidRects update_rects; + update_rects.insert(gfx::Rect(0, 0, 10, 10)); DataPlanes planes; for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { planes.data[i] = reinterpret_cast<uint8*>(i); @@ -98,7 +102,6 @@ TEST_F(SessionManagerTest, OneRecordCycle) { record_->AddClient(client_); // First the capturer is called. - EXPECT_CALL(*capturer_, InvalidateFullScreen()); EXPECT_CALL(*capturer_, CaptureInvalidRects(NotNull())) .WillOnce(RunCallback(update_rects, data)); @@ -115,7 +118,6 @@ TEST_F(SessionManagerTest, OneRecordCycle) { .Times(AtLeast(0)) .WillRepeatedly(Return(0)); - // Start the recording. record_->Start(); diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc index 4620f8f..88c6234 100644 --- a/remoting/host/simple_host_process.cc +++ b/remoting/host/simple_host_process.cc @@ -103,7 +103,7 @@ int main(int argc, char** argv) { if (fake) { // Inject a fake capturer. - LOG(INFO) << "Usage a fake capturer."; + LOG(INFO) << "Using a fake capturer."; capturer.reset(new remoting::CapturerFake()); } @@ -131,7 +131,7 @@ int main(int argc, char** argv) { encoder.release(), executor.release()); - // Let the chromoting host runs until the shutdown task is executed. + // Let the chromoting host run until the shutdown task is executed. MessageLoop message_loop(MessageLoop::TYPE_UI); host->Start(NewRunnableFunction(&ShutdownTask, &message_loop)); message_loop.Run(); diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 3e3283f..5168970 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -158,6 +158,7 @@ 'base/protocol_decoder.h', 'base/protocol_util.cc', 'base/protocol_util.h', + 'base/types.h', ], }, # end of target 'chromoting_base' |