summaryrefslogtreecommitdiffstats
path: root/remoting/base/decoder_zlib.cc
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-27 01:42:46 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-27 01:42:46 +0000
commit66db1af9f23041dd22f821cdee8f470e20bd2650 (patch)
treeb284e9776df8cafc55629c5c75f5d7df4846f5eb /remoting/base/decoder_zlib.cc
parent60b7dda9b3a35d038b7ac0f04ca8f242266eb2c6 (diff)
downloadchromium_src-66db1af9f23041dd22f821cdee8f470e20bd2650.zip
chromium_src-66db1af9f23041dd22f821cdee8f470e20bd2650.tar.gz
chromium_src-66db1af9f23041dd22f821cdee8f470e20bd2650.tar.bz2
EncoderZlib/DecoderZlib for chromoting
Encoder and decoder using zlib for chromoting. This implementation has zero copy out of the decoder and encoder. The consequence is that we have to break out the zlib stream into rect boundaries which requires the synchronication flush feature in zlib. This feature will hurt compression ratio but the effect still need to be measured. This patch also provides tests for testing the Encoder and Decoder pair with zlib. TEST=remoting_unittests Review URL: http://codereview.chromium.org/2868062 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53738 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/base/decoder_zlib.cc')
-rw-r--r--remoting/base/decoder_zlib.cc143
1 files changed, 143 insertions, 0 deletions
diff --git a/remoting/base/decoder_zlib.cc b/remoting/base/decoder_zlib.cc
new file mode 100644
index 0000000..59f9852
--- /dev/null
+++ b/remoting/base/decoder_zlib.cc
@@ -0,0 +1,143 @@
+// 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.
+
+#include "remoting/base/decoder_zlib.h"
+
+#include "remoting/base/decompressor_zlib.h"
+#include "remoting/base/protocol_util.h"
+
+namespace remoting {
+
+DecoderZlib::DecoderZlib()
+ : state_(kWaitingForBeginRect),
+ rect_x_(0),
+ rect_y_(0),
+ rect_width_(0),
+ rect_height_(0),
+ bytes_per_pixel_(0),
+ updated_rects_(NULL),
+ row_pos_(0),
+ row_y_(0) {
+}
+
+bool DecoderZlib::BeginDecode(scoped_refptr<media::VideoFrame> frame,
+ UpdatedRects* updated_rects,
+ Task* partial_decode_done,
+ Task* decode_done) {
+ DCHECK(!partial_decode_done_.get());
+ DCHECK(!decode_done_.get());
+ DCHECK(!updated_rects_);
+ DCHECK_EQ(kWaitingForBeginRect, state_);
+ CHECK(static_cast<PixelFormat>(frame->format()) == PixelFormatRgb32)
+ << "Only RGB32 is supported";
+
+ partial_decode_done_.reset(partial_decode_done);
+ decode_done_.reset(decode_done);
+ updated_rects_ = updated_rects;
+ frame_ = frame;
+
+ // Create the decompressor.
+ decompressor_.reset(new DecompressorZlib());
+ return true;
+}
+
+bool DecoderZlib::PartialDecode(HostMessage* message) {
+ scoped_ptr<HostMessage> msg_deleter(message);
+ DCHECK(message->has_update_stream_packet());
+
+ bool ret = true;
+ if (message->update_stream_packet().has_begin_rect())
+ ret = HandleBeginRect(message);
+ if (ret && message->update_stream_packet().has_rect_data())
+ ret = HandleRectData(message);
+ if (ret && message->update_stream_packet().has_end_rect())
+ ret = HandleEndRect(message);
+ return ret;
+}
+
+void DecoderZlib::EndDecode() {
+ DCHECK_EQ(kWaitingForBeginRect, state_);
+ decode_done_->Run();
+
+ partial_decode_done_.reset();
+ decode_done_.reset();
+ updated_rects_ = NULL;
+ frame_ = NULL;
+ decompressor_.reset();
+}
+
+bool DecoderZlib::HandleBeginRect(HostMessage* message) {
+ DCHECK_EQ(kWaitingForBeginRect, state_);
+ state_ = kWaitingForRectData;
+
+ rect_width_ = message->update_stream_packet().begin_rect().width();
+ rect_height_ = message->update_stream_packet().begin_rect().height();
+ rect_x_ = message->update_stream_packet().begin_rect().x();
+ rect_y_ = message->update_stream_packet().begin_rect().y();
+
+ PixelFormat pixel_format =
+ message->update_stream_packet().begin_rect().pixel_format();
+
+ if (static_cast<PixelFormat>(frame_->format()) != pixel_format) {
+ NOTREACHED() << "Pixel format of message doesn't match the video frame. "
+ "Expected vs received = "
+ << frame_->format() << " vs " << pixel_format
+ << " Color space conversion required.";
+ return false;
+ }
+
+ bytes_per_pixel_ = GetBytesPerPixel(pixel_format);
+ row_pos_ = 0;
+ row_y_ = 0;
+ return true;
+}
+
+bool DecoderZlib::HandleRectData(HostMessage* message) {
+ DCHECK_EQ(kWaitingForRectData, state_);
+ DCHECK_EQ(0,
+ message->update_stream_packet().rect_data().sequence_number());
+
+ const uint8* in =
+ (const uint8*)message->update_stream_packet().rect_data().data().data();
+ const int in_size =
+ message->update_stream_packet().rect_data().data().size();
+ const int row_size = rect_width_ * bytes_per_pixel_;
+ const int stride = frame_->stride(media::VideoFrame::kRGBPlane);
+ uint8* out = frame_->data(media::VideoFrame::kRGBPlane) +
+ stride * (rect_y_ + row_y_) + bytes_per_pixel_ * rect_x_;
+
+ // Consume all the data in the message.
+ bool decompress_again = true;
+ int used = 0;
+ while (decompress_again && used < in_size) {
+ int written = 0;
+ int consumed = 0;
+ decompress_again = decompressor_->Process(
+ in + used, in_size - used, out + row_pos_, row_size - row_pos_,
+ &consumed, &written);
+ used += consumed;
+ row_pos_ += written;
+
+ // If this row is completely filled then move onto the next row.
+ if (row_pos_ == row_size) {
+ ++row_y_;
+ row_pos_ = 0;
+ out += stride;
+ }
+ }
+ return true;
+}
+
+bool DecoderZlib::HandleEndRect(HostMessage* message) {
+ DCHECK_EQ(kWaitingForRectData, state_);
+ state_ = kWaitingForBeginRect;
+
+ updated_rects_->clear();
+ updated_rects_->push_back(gfx::Rect(rect_x_, rect_y_,
+ rect_width_, rect_height_));
+ partial_decode_done_->Run();
+ return true;
+}
+
+} // namespace remoting