diff options
author | garykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-27 23:31:38 +0000 |
---|---|---|
committer | garykac@google.com <garykac@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-27 23:31:38 +0000 |
commit | 299369a5c7d94021316f8d769b54f5555e7c0416 (patch) | |
tree | c4987a52ed131ddf6e86b350e84f92acdea45fcc | |
parent | 757f2e2ba0c1fa7100461745bfac865e3da1d976 (diff) | |
download | chromium_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.cc | 147 | ||||
-rw-r--r-- | remoting/base/encoder_verbatim.h | 29 |
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 |