summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgarykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-06 22:50:00 +0000
committergarykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-06 22:50:00 +0000
commit88552a9c89b99b93211ac5e679a0c13420e294db (patch)
treebe326ad62f7c9c9b3dfdea155a306005af00356a
parentce3b22e8da4fa9ca838423bacd54e45c3030d518 (diff)
downloadchromium_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
-rw-r--r--gfx/point.h10
-rw-r--r--gfx/rect.cc12
-rw-r--r--gfx/rect.h8
-rw-r--r--remoting/base/capture_data.h10
-rw-r--r--remoting/base/codec_test.cc10
-rw-r--r--remoting/base/encoder_verbatim.cc13
-rw-r--r--remoting/base/encoder_zlib.cc43
-rw-r--r--remoting/base/encoder_zlib.h11
-rw-r--r--remoting/base/types.h21
-rw-r--r--remoting/host/capturer.cc43
-rw-r--r--remoting/host/capturer.h99
-rw-r--r--remoting/host/capturer_fake.cc34
-rw-r--r--remoting/host/capturer_fake.h6
-rw-r--r--remoting/host/capturer_fake_ascii.cc33
-rw-r--r--remoting/host/capturer_fake_ascii.h6
-rw-r--r--remoting/host/capturer_gdi.cc42
-rw-r--r--remoting/host/capturer_gdi.h14
-rw-r--r--remoting/host/capturer_linux.cc5
-rw-r--r--remoting/host/capturer_linux.h6
-rw-r--r--remoting/host/capturer_mac.cc25
-rw-r--r--remoting/host/capturer_mac.h7
-rw-r--r--remoting/host/capturer_mac_unittest.cc16
-rw-r--r--remoting/host/chromoting_host.cc2
-rw-r--r--remoting/host/chromoting_host.h3
-rw-r--r--remoting/host/client_connection.h2
-rw-r--r--remoting/host/differ.cc10
-rw-r--r--remoting/host/differ.h11
-rw-r--r--remoting/host/differ_unittest.cc67
-rw-r--r--remoting/host/mock_objects.h9
-rw-r--r--remoting/host/session_manager.cc7
-rw-r--r--remoting/host/session_manager_unittest.cc14
-rw-r--r--remoting/host/simple_host_process.cc4
-rw-r--r--remoting/remoting.gyp1
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;
diff --git a/gfx/rect.h b/gfx/rect.h
index 9736331..a07fffa 100644
--- a/gfx/rect.h
+++ b/gfx/rect.h
@@ -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'