summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgarykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 23:31:38 +0000
committergarykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 23:31:38 +0000
commit299369a5c7d94021316f8d769b54f5555e7c0416 (patch)
treec4987a52ed131ddf6e86b350e84f92acdea45fcc
parent757f2e2ba0c1fa7100461745bfac865e3da1d976 (diff)
downloadchromium_src-299369a5c7d94021316f8d769b54f5555e7c0416.zip
chromium_src-299369a5c7d94021316f8d769b54f5555e7c0416.tar.gz
chromium_src-299369a5c7d94021316f8d769b54f5555e7c0416.tar.bz2
Fix Chromoting's verbatim decoder to work with the new protocol.
BUG=none TEST=verify chromoting works when host uses --verbatim flag Review URL: http://codereview.chromium.org/4152007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64179 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/base/encoder_verbatim.cc147
-rw-r--r--remoting/base/encoder_verbatim.h29
2 files changed, 107 insertions, 69 deletions
diff --git a/remoting/base/encoder_verbatim.cc b/remoting/base/encoder_verbatim.cc
index 17a2da4..8c59a7d 100644
--- a/remoting/base/encoder_verbatim.cc
+++ b/remoting/base/encoder_verbatim.cc
@@ -12,84 +12,107 @@
namespace remoting {
+// TODO(garykac): Move up into shared location. Share value with encoder_zlib.
+// TODO(garykac): 10* is added to ensure that rects fit in a single packet.
+// Add support for splitting across packets and remove the 10*.
+static const int kPacketSize = 10 * 1024 * 1024;
+
using media::DataBuffer;
+EncoderVerbatim::EncoderVerbatim()
+ : packet_size_(kPacketSize) {
+}
+
+EncoderVerbatim::EncoderVerbatim(int packet_size)
+ : packet_size_(packet_size) {
+}
+
void EncoderVerbatim::Encode(scoped_refptr<CaptureData> capture_data,
bool key_frame,
DataAvailableCallback* data_available_callback) {
+ capture_data_ = capture_data;
+ callback_.reset(data_available_callback);
+
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;
- ChromotingHostMessage* msg = new ChromotingHostMessage();
- UpdateStreamPacketMessage* packet = msg->mutable_update_stream_packet();
-
- if (EncodeRect(dirty_rect.x(), dirty_rect.y(), dirty_rect.width(),
- dirty_rect.height(), capture_data, packet)) {
- // Prepare the end rect content.
- packet->mutable_end_rect();
-
- EncodingState state = EncodingInProgress;
- if (index == 0) {
- state |= EncodingStarting;
- }
- if (index == num_rects - 1) {
- state |= EncodingEnded;
- }
- data_available_callback->Run(msg, state);
- }
+ EncodeRect(*r, index);
}
- delete data_available_callback;
+ capture_data_ = NULL;
+ callback_.reset();
}
-bool EncoderVerbatim::EncodeRect(
- int x, int y, int width, int height,
- const scoped_refptr<CaptureData>& capture_data,
- UpdateStreamPacketMessage* packet) {
- // Prepare the begin rect content.
- packet->mutable_begin_rect()->set_x(x);
- packet->mutable_begin_rect()->set_y(y);
- packet->mutable_begin_rect()->set_width(width);
- packet->mutable_begin_rect()->set_height(height);
- packet->mutable_begin_rect()->set_encoding(EncodingNone);
- packet->mutable_begin_rect()->set_pixel_format(capture_data->pixel_format());
-
- // Calculate the size of output.
- int bytes_per_pixel = GetBytesPerPixel(capture_data->pixel_format());
- int row_size = bytes_per_pixel * width;
- int output_size = 0;
- for (int i = 0; i < DataPlanes::kPlaneCount; ++i) {
- // TODO(hclam): Handle YUV since the height would be different.
- const uint8* in = capture_data->data_planes().data[i];
- if (!in) continue;
- output_size += row_size * height;
+// TODO(garykac): This assumes that the rect fits into a single packet.
+// Fix this by modeling after code in encoder_zlib.cc
+void EncoderVerbatim::EncodeRect(const gfx::Rect& rect, size_t rect_index) {
+ CHECK(capture_data_->data_planes().data[0]);
+ const int stride = 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();
+
+ ChromotingHostMessage* message = new ChromotingHostMessage();
+ RectangleUpdatePacket* update = message->mutable_rectangle_update();
+ PrepareUpdateStart(rect, update);
+
+ const uint8* in = capture_data_->data_planes().data[0] +
+ rect.y() * stride +
+ rect.x() * bytes_per_pixel;
+ // TODO(hclam): Fill in the sequence number.
+ uint8* out = GetOutputBuffer(update, packet_size_);
+ int total_bytes = 0;
+ for (int y = 0; y < rect.height(); y++) {
+ memcpy(out, in, row_size);
+ out += row_size;
+ in += stride;
+ total_bytes += row_size;
}
- // Resize the output data buffer.
- packet->mutable_rect_data()->mutable_data()->resize(output_size);
- uint8* out = (uint8*)packet->mutable_rect_data()->mutable_data()->data();
-
- for (int i = 0; i < DataPlanes::kPlaneCount; ++i) {
- // Skip over planes that don't have data.
- if (!capture_data->data_planes().data[i])
- continue;
-
- const uint8* in = capture_data->data_planes().data[i] +
- y * capture_data->data_planes().strides[i] +
- x * bytes_per_pixel;
-
- // TODO(hclam): Handle YUV since the height would be different.
- for (int j = 0; j < height; ++j) {
- DCHECK_LE(row_size, capture_data->data_planes().strides[i]);
- memcpy(out, in, width * bytes_per_pixel);
- in += capture_data->data_planes().strides[i];
- out += row_size;
- }
+ // We have reached the end of stream.
+ update->set_flags(update->flags() | RectangleUpdatePacket::LAST_PACKET);
+
+ // If we have filled the message or we have reached the end of stream.
+ message->mutable_rectangle_update()->mutable_encoded_rect()->
+ resize(total_bytes);
+ SubmitMessage(message, rect_index);
+}
+
+void EncoderVerbatim::PrepareUpdateStart(const gfx::Rect& rect,
+ RectangleUpdatePacket* update) {
+
+ update->set_flags(update->flags() | RectangleUpdatePacket::FIRST_PACKET);
+ RectangleFormat* format = update->mutable_format();
+
+ format->set_x(rect.x());
+ format->set_y(rect.y());
+ format->set_width(rect.width());
+ format->set_height(rect.height());
+ format->set_encoding(EncodingNone);
+ format->set_pixel_format(capture_data_->pixel_format());
+}
+
+uint8* EncoderVerbatim::GetOutputBuffer(RectangleUpdatePacket* update,
+ size_t size) {
+ update->mutable_encoded_rect()->resize(size);
+ // TODO(ajwong): Is there a better way to do this at all???
+ return const_cast<uint8*>(reinterpret_cast<const uint8*>(
+ update->mutable_encoded_rect()->data()));
+}
+
+void EncoderVerbatim::SubmitMessage(ChromotingHostMessage* message,
+ size_t rect_index) {
+ EncodingState state = EncodingInProgress;
+ const RectangleUpdatePacket& update = message->rectangle_update();
+ if (rect_index == 0 &&
+ (update.flags() | RectangleUpdatePacket::FIRST_PACKET)) {
+ state |= EncodingStarting;
+ }
+ if (rect_index == capture_data_->dirty_rects().size() - 1 &&
+ (update.flags() | RectangleUpdatePacket::LAST_PACKET)) {
+ state |= EncodingEnded;
}
- return true;
+ callback_->Run(message, state);
}
} // namespace remoting
diff --git a/remoting/base/encoder_verbatim.h b/remoting/base/encoder_verbatim.h
index dd019fc..10fa7ac 100644
--- a/remoting/base/encoder_verbatim.h
+++ b/remoting/base/encoder_verbatim.h
@@ -7,6 +7,8 @@
#include "remoting/base/encoder.h"
+#include "gfx/rect.h"
+
namespace remoting {
class UpdateStreamPacket;
@@ -15,7 +17,9 @@ class UpdateStreamPacket;
// buffer verbatim.
class EncoderVerbatim : public Encoder {
public:
- EncoderVerbatim() {}
+ EncoderVerbatim();
+ EncoderVerbatim(int packet_size);
+
virtual ~EncoderVerbatim() {}
virtual void Encode(scoped_refptr<CaptureData> capture_data,
@@ -23,12 +27,23 @@ class EncoderVerbatim : public Encoder {
DataAvailableCallback* data_available_callback);
private:
- // Encode a single dirty rect. Called by Encode(). Output is written
- // to |msg|.
- // Returns false if there is an error.
- bool EncodeRect(int x, int y, int width, int height,
- const scoped_refptr<CaptureData>& capture_data,
- UpdateStreamPacketMessage* msg);
+ // Encode a single dirty rect.
+ void EncodeRect(const gfx::Rect& rect, size_t rect_index);
+
+ // Marks a packets as the first in a series of rectangle updates.
+ void PrepareUpdateStart(const gfx::Rect& rect,
+ RectangleUpdatePacket* update);
+
+ // Retrieves a pointer to the output buffer in |update| used for storing the
+ // encoded rectangle data. Will resize the buffer to |size|.
+ uint8* GetOutputBuffer(RectangleUpdatePacket* update, size_t size);
+
+ // Submit |message| to |callback_|.
+ void SubmitMessage(ChromotingHostMessage* message, size_t rect_index);
+
+ scoped_refptr<CaptureData> capture_data_;
+ scoped_ptr<DataAvailableCallback> callback_;
+ int packet_size_;
};
} // namespace remoting