From be2da4de5227f4f1cbb8455a58045c5e51076474 Mon Sep 17 00:00:00 2001 From: "hclam@chromium.org" Date: Fri, 23 Jul 2010 00:54:47 +0000 Subject: Moving Encoder and Decoder to remoting/base Putting Encder and Decoder together so we can have test that tests both of them. TEST=remoting_unittests Review URL: http://codereview.chromium.org/2840036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53427 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/service/DEPS | 1 + chrome/service/service_process.cc | 3 +- remoting/base/capture_data.h | 75 +++++++++++++++ remoting/base/decoder.h | 114 +++++++++++++++++++++++ remoting/base/decoder_verbatim.cc | 127 +++++++++++++++++++++++++ remoting/base/decoder_verbatim.h | 56 +++++++++++ remoting/base/decoder_verbatim_unittest.cc | 72 +++++++++++++++ remoting/base/encoder.h | 61 ++++++++++++ remoting/base/encoder_verbatim.cc | 89 ++++++++++++++++++ remoting/base/encoder_verbatim.h | 36 ++++++++ remoting/base/encoder_vp8.cc | 133 +++++++++++++++++++++++++++ remoting/base/encoder_vp8.h | 61 ++++++++++++ remoting/base/encoder_vp8_unittest.cc | 68 ++++++++++++++ remoting/base/mock_objects.h | 16 ++++ remoting/client/decoder.h | 114 ----------------------- remoting/client/decoder_verbatim.cc | 127 ------------------------- remoting/client/decoder_verbatim.h | 56 ----------- remoting/client/decoder_verbatim_unittest.cc | 72 --------------- remoting/client/mock_objects.h | 1 - remoting/client/plugin/pepper_view.cc | 2 +- remoting/client/plugin/pepper_view.h | 2 +- remoting/client/x11_view.cc | 2 +- remoting/client/x11_view.h | 2 +- remoting/host/capturer.h | 62 +------------ remoting/host/capturer_fake.cc | 2 +- remoting/host/capturer_fake_ascii.cc | 2 +- remoting/host/capturer_gdi.cc | 2 +- remoting/host/capturer_mac.cc | 2 +- remoting/host/capturer_mac_unittest.cc | 6 +- remoting/host/chromoting_host.cc | 3 + remoting/host/chromoting_host.h | 8 +- remoting/host/encoder.h | 61 ------------ remoting/host/encoder_verbatim.cc | 87 ------------------ remoting/host/encoder_verbatim.h | 36 -------- remoting/host/encoder_vp8.cc | 133 --------------------------- remoting/host/encoder_vp8.h | 61 ------------ remoting/host/encoder_vp8_unittest.cc | 68 -------------- remoting/host/mock_objects.h | 14 --- remoting/host/session_manager.cc | 6 +- remoting/host/session_manager.h | 8 +- remoting/host/session_manager_unittest.cc | 11 +-- remoting/host/simple_host_process.cc | 2 +- remoting/remoting.gyp | 25 ++--- 43 files changed, 955 insertions(+), 934 deletions(-) create mode 100644 remoting/base/capture_data.h create mode 100644 remoting/base/decoder.h create mode 100644 remoting/base/decoder_verbatim.cc create mode 100644 remoting/base/decoder_verbatim.h create mode 100644 remoting/base/decoder_verbatim_unittest.cc create mode 100644 remoting/base/encoder.h create mode 100644 remoting/base/encoder_verbatim.cc create mode 100644 remoting/base/encoder_verbatim.h create mode 100644 remoting/base/encoder_vp8.cc create mode 100644 remoting/base/encoder_vp8.h create mode 100644 remoting/base/encoder_vp8_unittest.cc delete mode 100644 remoting/client/decoder.h delete mode 100644 remoting/client/decoder_verbatim.cc delete mode 100644 remoting/client/decoder_verbatim.h delete mode 100644 remoting/client/decoder_verbatim_unittest.cc delete mode 100644 remoting/host/encoder.h delete mode 100644 remoting/host/encoder_verbatim.cc delete mode 100644 remoting/host/encoder_verbatim.h delete mode 100644 remoting/host/encoder_vp8.cc delete mode 100644 remoting/host/encoder_vp8.h delete mode 100644 remoting/host/encoder_vp8_unittest.cc diff --git a/chrome/service/DEPS b/chrome/service/DEPS index 804d3c2..6563aaa 100644 --- a/chrome/service/DEPS +++ b/chrome/service/DEPS @@ -1,4 +1,5 @@ include_rules = [ # For Chromoting Host Process + "+remoting/base", "+remoting/host", ] diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc index 408be65..4d757ae 100644 --- a/chrome/service/service_process.cc +++ b/chrome/service/service_process.cc @@ -9,9 +9,9 @@ #include "net/base/network_change_notifier.h" #if defined(ENABLE_REMOTING) +#include "remoting/base/encoder_verbatim.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" -#include "remoting/host/encoder_verbatim.h" #include "remoting/host/host_config.h" #if defined(OS_WIN) @@ -97,4 +97,3 @@ ServiceProcess::~ServiceProcess() { DCHECK(cloud_print_proxy_list_.size() == 0); g_service_process = NULL; } - diff --git a/remoting/base/capture_data.h b/remoting/base/capture_data.h new file mode 100644 index 0000000..2ac8a12 --- /dev/null +++ b/remoting/base/capture_data.h @@ -0,0 +1,75 @@ +// 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_CAPTURE_DATA_H_ +#define REMOTING_BASE_CAPTURE_DATA_H_ + +#include + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "gfx/rect.h" +#include "remoting/base/protocol/chromotocol.pb.h" + +namespace remoting { + +typedef std::vector RectVector; + +struct DataPlanes { + static const int kPlaneCount = 3; + uint8* data[kPlaneCount]; + int strides[kPlaneCount]; + + DataPlanes() { + for (int i = 0; i < kPlaneCount; ++i) { + data[i] = NULL; + strides[i] = 0; + } + } +}; + +// Stores the data and information of a capture to pass off to the +// encoding thread. +class CaptureData : public base::RefCountedThreadSafe { + public: + CaptureData(const DataPlanes &data_planes, + int width, + int height, + PixelFormat format) : + data_planes_(data_planes), dirty_rects_(), + width_(width), height_(height), pixel_format_(format) { } + + // Get the data_planes data of the last capture. + const DataPlanes& data_planes() const { return data_planes_; } + + // Get the list of updated rectangles in the last capture. The result is + // written into |rects|. + const RectVector& dirty_rects() const { return dirty_rects_; } + + // Get the width of the image captured. + int width() const { return width_; } + + // Get the height of the image captured. + int height() const { return height_; } + + // Get the pixel format of the image captured. + PixelFormat pixel_format() const { return pixel_format_; } + + // Mutating methods. + RectVector& mutable_dirty_rects() { return dirty_rects_; } + + private: + const DataPlanes data_planes_; + RectVector dirty_rects_; + int width_; + int height_; + PixelFormat pixel_format_; + + friend class base::RefCountedThreadSafe; + ~CaptureData() {} +}; + +} // namespace remoting + +#endif // REMOTING_BASE_CAPTURE_DATA_H_ diff --git a/remoting/base/decoder.h b/remoting/base/decoder.h new file mode 100644 index 0000000..1df477d --- /dev/null +++ b/remoting/base/decoder.h @@ -0,0 +1,114 @@ +// 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_DECODER_H_ +#define REMOTING_BASE_DECODER_H_ + +#include + +#include "base/task.h" +#include "base/scoped_ptr.h" +#include "gfx/rect.h" +#include "media/base/video_frame.h" +#include "remoting/base/protocol/chromotocol.pb.h" + +namespace remoting { + +// TODO(hclam): Merge this with the one in remoting/host/encoder.h. +typedef std::vector UpdatedRects; + +// Defines the behavior of a decoder for decoding images received from the +// host. +// +// Sequence of actions with a decoder is as follows: +// +// 1. BeginDecode(PartialDecodeDone, DecodeDone, VideoFrame) +// 2. PartialDecode(HostMessage) +// ... +// 3. EndDecode() +// +// The decoder will reply with: +// 1. PartialDecodeDone(VideoFrame, UpdatedRects) +// ... +// 2. DecodeDone(VideoFrame) +// +// The format of VideoFrame is a contract between the object that creates the +// decoder (most likely the renderer) and the decoder. +class Decoder { + public: + + virtual ~Decoder() { + } + + // Tell the decoder to use |frame| as a target to write the decoded image + // for the coming update stream. + // If decode is partially done and |frame| can be read, |partial_decode_done| + // is called and |update_rects| contains the updated regions. + // If decode is completed |decode_done| is called. + // Return true if the decoder can writes output to |frame| and accept + // the codec format. + // TODO(hclam): Provide more information when calling this function. + virtual bool BeginDecode(scoped_refptr frame, + UpdatedRects* updated_rects, + Task* partial_decode_done, + Task* decode_done) = 0; + + // Give a HostMessage that contains the update stream packet that contains + // the encoded data to the decoder. + // The decoder will own |message| and is responsible for deleting it. + // + // If the decoder has written something into |frame|, + // |partial_decode_done_| is called with |frame| and updated regions. + // Return true if the decoder can accept |message| and decode it. + // + // HostMessage returned by this method will contain a + // UpdateStreamPacketMessage. + // This message will contain either: + // 1. UpdateStreamBeginRect + // 2. UpdateStreamRectData + // 3. UpdateStreamEndRect + // + // See remoting/base/protocol/chromotocol.proto for more information about + // these messages. + virtual bool PartialDecode(HostMessage* message) = 0; + + // Notify the decoder that we have received the last update stream packet. + // If the decoding of the update stream has completed |decode_done_| is + // called with |frame|. + // If the update stream is not received fully and this method is called the + // decoder should also call |decode_done_| as soon as possible. + virtual void EndDecode() = 0; + + protected: + // Every decoder will have two internal states because there are three + // kinds of messages send to PartialDecode(). + // + // Here's a state diagram: + // + // UpdateStreamBeginRect UpdateStreamRectData + // .............. ............ + // . . . . + // . v . . + // kWaitingForBeginRect kWaitingForRectData . + // ^ . ^ . + // . . . . + // .............. ............ + // UpdateStreaEndRect + enum State { + // In this state the decoder is waiting for UpdateStreamBeginRect. + // After receiving UpdateStreaBeginRect, the encoder will transit to + // to kWaitingForRectData state. + kWaitingForBeginRect, + + // In this state the decoder is waiting for UpdateStreamRectData. + // The decode remains in this state if UpdateStreamRectData is received. + // The decoder will transit to kWaitingForBeginRect if UpdateStreamEndRect + // is received. + kWaitingForRectData, + }; +}; + +} // namespace remoting + +#endif // REMOTING_BASE_DECODER_H_ diff --git a/remoting/base/decoder_verbatim.cc b/remoting/base/decoder_verbatim.cc new file mode 100644 index 0000000..e17310d --- /dev/null +++ b/remoting/base/decoder_verbatim.cc @@ -0,0 +1,127 @@ +// 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_verbatim.h" + +#include "remoting/base/protocol_util.h" + +namespace remoting { + +DecoderVerbatim::DecoderVerbatim() + : state_(kWaitingForBeginRect), + rect_x_(0), + rect_y_(0), + rect_width_(0), + rect_height_(0), + bytes_per_pixel_(0), + updated_rects_(NULL), + reverse_rows_(true) { +} + +bool DecoderVerbatim::BeginDecode(scoped_refptr 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_); + + partial_decode_done_.reset(partial_decode_done); + decode_done_.reset(decode_done); + updated_rects_ = updated_rects; + + // TODO(hclam): Check if we can accept the color format of the video frame + // and the codec. + frame_ = frame; + return true; +} + +bool DecoderVerbatim::PartialDecode(HostMessage* message) { + scoped_ptr 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 DecoderVerbatim::EndDecode() { + DCHECK_EQ(kWaitingForBeginRect, state_); + decode_done_->Run(); + + partial_decode_done_.reset(); + decode_done_.reset(); + frame_ = NULL; + updated_rects_ = NULL; +} + +bool DecoderVerbatim::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(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); + return true; +} + +bool DecoderVerbatim::HandleRectData(HostMessage* message) { + DCHECK_EQ(kWaitingForRectData, state_); + DCHECK_EQ(0, + message->update_stream_packet().rect_data().sequence_number()); + + // Copy the data line by line. + const int src_stride = bytes_per_pixel_ * rect_width_; + const char* src = + message->update_stream_packet().rect_data().data().c_str(); + int src_stride_dir = src_stride; + if (reverse_rows_) { + // Copy rows from bottom to top to flip the image vertically. + src += (rect_height_ - 1) * src_stride; + // Change the direction of the stride to work bottom to top. + src_stride_dir *= -1; + } + const int dest_stride = frame_->stride(media::VideoFrame::kRGBPlane); + uint8* dest = frame_->data(media::VideoFrame::kRGBPlane) + + dest_stride * rect_y_ + bytes_per_pixel_ * rect_x_; + for (int i = 0; i < rect_height_; ++i) { + memcpy(dest, src, src_stride); + dest += dest_stride; + src += src_stride_dir; + } + + updated_rects_->clear(); + updated_rects_->push_back(gfx::Rect(rect_x_, rect_y_, + rect_width_, rect_height_)); + partial_decode_done_->Run(); + return true; +} + +bool DecoderVerbatim::HandleEndRect(HostMessage* message) { + DCHECK_EQ(kWaitingForRectData, state_); + state_ = kWaitingForBeginRect; + return true; +} + +} // namespace remoting diff --git a/remoting/base/decoder_verbatim.h b/remoting/base/decoder_verbatim.h new file mode 100644 index 0000000..ba97b5e --- /dev/null +++ b/remoting/base/decoder_verbatim.h @@ -0,0 +1,56 @@ +// 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_DECODER_VERBATIM_H_ +#define REMOTING_BASE_DECODER_VERBATIM_H_ + +#include "remoting/base/decoder.h" + +namespace remoting { + +class DecoderVerbatim : public Decoder { + public: + DecoderVerbatim(); + + // Decoder implementations. + virtual bool BeginDecode(scoped_refptr frame, + UpdatedRects* update_rects, + Task* partial_decode_done, + Task* decode_done); + virtual bool PartialDecode(HostMessage* message); + virtual void EndDecode(); + + private: + bool HandleBeginRect(HostMessage* message); + bool HandleRectData(HostMessage* message); + bool HandleEndRect(HostMessage* message); + + // The internal state of the decoder. + State state_; + + // Keeps track of the updating rect. + int rect_x_; + int rect_y_; + int rect_width_; + int rect_height_; + int bytes_per_pixel_; + + // Tasks to call when decode is done. + scoped_ptr partial_decode_done_; + scoped_ptr decode_done_; + + // The video frame to write to. + scoped_refptr frame_; + UpdatedRects* updated_rects_; + + // True if we should reverse the rows when copying data into the target + // frame buffer. + bool reverse_rows_; + + DISALLOW_COPY_AND_ASSIGN(DecoderVerbatim); +}; + +} // namespace remoting + +#endif // REMOTING_BASE_DECODER_VERBATIM_H_ diff --git a/remoting/base/decoder_verbatim_unittest.cc b/remoting/base/decoder_verbatim_unittest.cc new file mode 100644 index 0000000..f32b08c --- /dev/null +++ b/remoting/base/decoder_verbatim_unittest.cc @@ -0,0 +1,72 @@ +// 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 "media/base/video_frame.h" +#include "remoting/base/decoder_verbatim.h" +#include "remoting/client/mock_objects.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::InSequence; + +namespace remoting { + +TEST(DecoderVerbatimTest, SimpleDecode) { + DecoderVerbatim decoder; + scoped_refptr handler = new MockDecodeDoneHandler(); + + const size_t kWidth = 10; + const size_t kHeight = 1; + const char kData[] = "ABCDEFGHIJ"; + scoped_ptr msg(new HostMessage()); + + // Prepare the begin rect message. + UpdateStreamBeginRect* begin_rect = + msg->mutable_update_stream_packet()->mutable_begin_rect(); + begin_rect->set_width(kWidth); + begin_rect->set_height(kHeight); + begin_rect->set_x(0); + begin_rect->set_y(0); + begin_rect->set_pixel_format(PixelFormatAscii); + + // Prepare the rect data. + msg->mutable_update_stream_packet()->mutable_rect_data()->set_data( + kData, sizeof(kData)); + + // Prepare the end rect. + msg->mutable_update_stream_packet()->mutable_end_rect(); + + scoped_refptr frame; + media::VideoFrame::CreateFrame(media::VideoFrame::ASCII, kWidth, kHeight, + base::TimeDelta(), base::TimeDelta(), &frame); + ASSERT_TRUE(frame); + + InSequence s; + EXPECT_CALL(*handler, PartialDecodeDone()); + EXPECT_CALL(*handler, DecodeDone()); + + UpdatedRects rects; + decoder.BeginDecode( + frame, &rects, + NewRunnableMethod(handler.get(), + &MockDecodeDoneHandler::PartialDecodeDone), + NewRunnableMethod(handler.get(), &MockDecodeDoneHandler::DecodeDone)); + decoder.PartialDecode(msg.release()); + decoder.EndDecode(); + + // Make sure we get the same data back. + EXPECT_EQ(kWidth, frame->width()); + EXPECT_EQ(kHeight, frame->height()); + EXPECT_EQ(media::VideoFrame::ASCII, frame->format()); + // TODO(hclam): Enable this line. + // EXPECT_EQ(0, memcmp(kData, frame->data(media::VideoFrame::kRGBPlane), + // sizeof(kData))); + + // Check the updated rects. + ASSERT_TRUE(rects.size() == 1); + EXPECT_EQ(kWidth, static_cast(rects[0].width())); + EXPECT_EQ(kHeight, static_cast(rects[0].height())); +} + +} // namespace remoting diff --git a/remoting/base/encoder.h b/remoting/base/encoder.h new file mode 100644 index 0000000..0c1fd50f --- /dev/null +++ b/remoting/base/encoder.h @@ -0,0 +1,61 @@ +// 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_ENCODER_H_ +#define REMOTING_BASE_ENCODER_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "media/base/data_buffer.h" +#include "remoting/base/protocol/chromotocol.pb.h" + +namespace media { + class DataBuffer; +} + +namespace remoting { + +class CaptureData; +class HostMessage; + +// A class to perform the task of encoding a continous stream of +// images. +// This class operates asynchronously to enable maximum throughput. +class Encoder { + public: + + // EncodingState is a bitfield that tracks the state of the encoding. + // An encoding that consists of a single block could concievably be starting + // inprogress and ended at the same time. + enum { + EncodingStarting = 1 << 0, + EncodingInProgress = 1 << 1, + EncodingEnded = 1 << 2 + }; + typedef int EncodingState; + + // DataAvailableCallback is called as blocks of data are made available + // from the encoder. Data made available by the encoder is in the form + // of HostMessage to reduce the amount of memory copies. + // The callback takes ownership of the HostMessage and is responsible for + // deleting it. + typedef Callback2::Type DataAvailableCallback; + + virtual ~Encoder() {} + + // Encode an image stored in |capture_data|. + // + // If |key_frame| is true, the encoder should not reference + // previous encode and encode the full frame. + // + // When encoded data is available, partial or full |data_available_callback| + // is called. + virtual void Encode(scoped_refptr capture_data, + bool key_frame, + DataAvailableCallback* data_available_callback) = 0; +}; + +} // namespace remoting + +#endif // REMOTING_BASE_ENCODER_H_ diff --git a/remoting/base/encoder_verbatim.cc b/remoting/base/encoder_verbatim.cc new file mode 100644 index 0000000..f6cc2ca --- /dev/null +++ b/remoting/base/encoder_verbatim.cc @@ -0,0 +1,89 @@ +// 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/encoder_verbatim.h" + +#include "gfx/rect.h" +#include "media/base/data_buffer.h" +#include "remoting/base/capture_data.h" +#include "remoting/base/protocol_util.h" +#include "remoting/base/protocol/chromotocol.pb.h" + +namespace remoting { + +using media::DataBuffer; + +void EncoderVerbatim::Encode(scoped_refptr 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]; + HostMessage* msg = new HostMessage(); + 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 (i == 0) { + state |= EncodingStarting; + } + if (i == num_rects - 1) { + state |= EncodingEnded; + } + data_available_callback->Run(msg, state); + } + } + + delete data_available_callback; +} + +bool EncoderVerbatim::EncodeRect( + int x, int y, int width, int height, + const scoped_refptr& 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; + } + + // Resize the output data buffer. + packet->mutable_rect_data()->mutable_data()->resize(output_size); + uint8* out = reinterpret_cast( + &((*packet->mutable_rect_data()->mutable_data())[0])); + + for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { + const uint8* in = capture_data->data_planes().data[i]; + // Skip over planes that don't have data. + if (!in) continue; + + // 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, row_size); + in += capture_data->data_planes().strides[i]; + out += row_size; + } + } + return true; +} + +} // namespace remoting diff --git a/remoting/base/encoder_verbatim.h b/remoting/base/encoder_verbatim.h new file mode 100644 index 0000000..dd019fc --- /dev/null +++ b/remoting/base/encoder_verbatim.h @@ -0,0 +1,36 @@ +// 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_ENCODER_VERBATIM_H_ +#define REMOTING_BASE_ENCODER_VERBATIM_H_ + +#include "remoting/base/encoder.h" + +namespace remoting { + +class UpdateStreamPacket; + +// EncoderVerbatim implements Encoder and simply copies input to the output +// buffer verbatim. +class EncoderVerbatim : public Encoder { + public: + EncoderVerbatim() {} + virtual ~EncoderVerbatim() {} + + virtual void Encode(scoped_refptr capture_data, + bool key_frame, + 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& capture_data, + UpdateStreamPacketMessage* msg); +}; + +} // namespace remoting + +#endif // REMOTING_BASE_ENCODER_VERBATIM_H_ diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc new file mode 100644 index 0000000..231acd5 --- /dev/null +++ b/remoting/base/encoder_vp8.cc @@ -0,0 +1,133 @@ +// 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 "base/logging.h" +#include "media/base/callback.h" +#include "media/base/data_buffer.h" +#include "remoting/host/encoder_vp8.h" + +extern "C" { +// TODO(garykac): Rix with correct path to vp8 header. +#include "remoting/third_party/on2/include/vp8cx.h" +} + +namespace remoting { + +EncoderVp8::EncoderVp8() + : initialized_(false), + last_timestamp_(0) { +} + +EncoderVp8::~EncoderVp8() { +} + +bool EncoderVp8::Init() { + // TODO(hclam): Now always assume we receive YV12. May need to extend this + // so we can do color space conversion manually. + image_.fmt = IMG_FMT_YV12; + image_.w = width_; + image_.h = height_; + + on2_codec_enc_cfg_t config; + on2_codec_err_t result = on2_codec_enc_config_default(&on2_codec_vp8_cx_algo, + &config, 0); + + // TODO(hclam): Adjust the parameters. + config.g_w = width_; + config.g_h = height_; + config.g_pass = ON2_RC_ONE_PASS; + config.g_profile = 1; + config.g_threads = 2; + config.rc_target_bitrate = 1000000; + config.rc_min_quantizer = 0; + config.rc_max_quantizer = 15; + config.g_timebase.num = 1; + config.g_timebase.den = 30; + + if (on2_codec_enc_init(&codec_, &on2_codec_vp8_cx_algo, &config, 0)) + return false; + + on2_codec_control_(&codec_, VP8E_SET_CPUUSED, -15); + return true; +} + +void EncoderVp8::Encode(const DirtyRects& dirty_rects, + const uint8** input_data, + const int* strides, + bool key_frame, + UpdateStreamPacketHeader* header, + scoped_refptr* output_data, + bool* encode_done, + Task* data_available_task) { + // This will allow the task be called when this method exits. + media::AutoTaskRunner task(data_available_task); + *encode_done = false; + + // TODO(hclam): We only initialize the encoder once. We may have to + // allow encoder be initialized with difference sizes. + if (!initialized_) { + if (!Init()) { + LOG(ERROR) << "Can't initialize VP8 encoder"; + return; + } + initialized_ = true; + } + + // Assume the capturer has done the color space conversion. + if (!input_data || !strides) + return; + + image_.planes[0] = (unsigned char*)input_data[0]; + image_.planes[1] = (unsigned char*)input_data[1]; + image_.planes[2] = (unsigned char*)input_data[2]; + image_.stride[0] = strides[0]; + image_.stride[1] = strides[1]; + image_.stride[2] = strides[2]; + + // Do the actual encoding. + if (on2_codec_encode(&codec_, &image_, + last_timestamp_, 1, 0, ON2_DL_REALTIME)) { + return; + } + + // TODO(hclam): fix this. + last_timestamp_ += 100; + + // Read the encoded data. + on2_codec_iter_t iter = NULL; + bool got_data = false; + + // TODO(hclam: We assume one frame of input will get exactly one frame of + // output. This assumption may not be valid. + while (!got_data) { + on2_codec_cx_pkt_t* packet = on2_codec_get_cx_data(&codec_, &iter); + if (!packet) + continue; + + switch (packet->kind) { + case ON2_CODEC_CX_FRAME_PKT: + got_data = true; + *encode_done = true; + *output_data = new media::DataBuffer(packet->data.frame.sz); + memcpy((*output_data)->GetWritableData(), + packet->data.frame.buf, + packet->data.frame.sz); + break; + default: + break; + } + } + return; +} + +void EncoderVp8::SetSize(int width, int height) { + width_ = width; + height_ = height; +} + +void EncoderVp8::SetPixelFormat(PixelFormat pixel_format) { + pixel_format_ = pixel_format; +} + +} // namespace remoting diff --git a/remoting/base/encoder_vp8.h b/remoting/base/encoder_vp8.h new file mode 100644 index 0000000..4b8b539 --- /dev/null +++ b/remoting/base/encoder_vp8.h @@ -0,0 +1,61 @@ +// 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_ENCODER_VP8_H_ +#define REMOTING_BASE_ENCODER_VP8_H_ + +#include "remoting/host/encoder.h" + +#include "remoting/base/protocol/chromotocol.pb.h" + +extern "C" { +// TODO(garykac): fix this link with the correct path to on2 +#include "remoting/third_party/on2/include/on2_encoder.h" +} // extern "C" + +namespace media { + +class DataBuffer; + +} // namespace media + +namespace remoting { + +// A class that uses VP8 to perform encoding. +class EncoderVp8 : public Encoder { + public: + EncoderVp8(); + virtual ~EncoderVp8(); + + virtual void Encode(const DirtyRects& dirty_rects, + const uint8** input_data, + const int* strides, + bool key_frame, + UpdateStreamPacketHeader* header, + scoped_refptr* output_data, + bool* encode_done, + Task* data_available_task); + virtual void SetSize(int width, int height); + virtual void SetPixelFormat(PixelFormat pixel_format); + + private: + // Setup the VP8 encoder. + bool Init(); + + // True if the encoder is initialized. + bool initialized_; + + int width_; + int height_; + PixelFormat pixel_format_; + on2_codec_ctx_t codec_; + on2_image_t image_; + int last_timestamp_; + + DISALLOW_COPY_AND_ASSIGN(EncoderVp8); +}; + +} // namespace remoting + +#endif // REMOTING_BASE_ENCODER_VP8_H_ diff --git a/remoting/base/encoder_vp8_unittest.cc b/remoting/base/encoder_vp8_unittest.cc new file mode 100644 index 0000000..0b29830 --- /dev/null +++ b/remoting/base/encoder_vp8_unittest.cc @@ -0,0 +1,68 @@ +// 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 "media/base/data_buffer.h" +#include "remoting/base/pixel_format.h" +#include "remoting/host/encoder_vp8.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace remoting { + +static const int kWidth = 1024; +static const int kHeight = 768; +static const PixelFormat kPixelFormat = kPixelFormat_YV12; + +static void GenerateData(uint8* data, int size) { + for (int i = 0; i < size; ++i) { + data[i] = i; + } +} + +class EncodeDoneHandler + : public base::RefCountedThreadSafe { + public: + MOCK_METHOD0(EncodeDone, void()); +}; + +TEST(EncoderVp8Test, SimpleEncode) { + EncoderVp8 encoder; + encoder.SetSize(kWidth, kHeight); + encoder.SetPixelFormat(kPixelFormat); + + DirtyRects rects; + rects.push_back(gfx::Rect(kWidth, kHeight)); + + // Prepare memory for encoding. + int strides[3]; + strides[0] = kWidth; + strides[1] = strides[2] = kWidth / 2; + + uint8* planes[3]; + planes[0] = new uint8[kWidth * kHeight]; + planes[1] = new uint8[kWidth * kHeight / 4]; + planes[2] = new uint8[kWidth * kHeight / 4]; + GenerateData(planes[0], kWidth * kHeight); + GenerateData(planes[1], kWidth * kHeight / 4); + GenerateData(planes[2], kWidth * kHeight / 4); + + scoped_refptr handler = new EncodeDoneHandler(); + UpdateStreamPacketHeader* header = new UpdateStreamPacketHeader(); + scoped_refptr encoded_data; + bool encode_done = false; + EXPECT_CALL(*handler, EncodeDone()); + encoder.Encode(rects, const_cast(planes), + strides, true, header, &encoded_data, &encode_done, + NewRunnableMethod(handler.get(), + &EncodeDoneHandler::EncodeDone)); + + EXPECT_TRUE(encode_done); + ASSERT_TRUE(encoded_data.get()); + EXPECT_NE(0u, encoded_data->GetBufferSize()); + + delete [] planes[0]; + delete [] planes[1]; + delete [] planes[2]; +} + +} // namespace remoting diff --git a/remoting/base/mock_objects.h b/remoting/base/mock_objects.h index a61830e..7565f22 100644 --- a/remoting/base/mock_objects.h +++ b/remoting/base/mock_objects.h @@ -5,6 +5,9 @@ #ifndef REMOTING_BASE_MOCK_OBJECTS_H_ #define REMOTING_BASE_MOCK_OBJECTS_H_ +#include "remoting/base/capture_data.h" +#include "remoting/base/decoder.h" +#include "remoting/base/encoder.h" #include "remoting/base/protocol_decoder.h" #include "testing/gmock/include/gmock/gmock.h" @@ -25,6 +28,19 @@ class MockProtocolDecoder : public ProtocolDecoder { DISALLOW_COPY_AND_ASSIGN(MockProtocolDecoder); }; +class MockEncoder : public Encoder { + public: + MockEncoder() {} + + MOCK_METHOD3(Encode, void( + scoped_refptr capture_data, + bool key_frame, + DataAvailableCallback* data_available_callback)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockEncoder); +}; + } // namespace remoting #endif // REMOTING_BASE_MOCK_OBJECTS_H_ diff --git a/remoting/client/decoder.h b/remoting/client/decoder.h deleted file mode 100644 index 4d083bd..0000000 --- a/remoting/client/decoder.h +++ /dev/null @@ -1,114 +0,0 @@ -// 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_CLIENT_DECODER_H_ -#define REMOTING_CLIENT_DECODER_H_ - -#include - -#include "base/task.h" -#include "base/scoped_ptr.h" -#include "gfx/rect.h" -#include "media/base/video_frame.h" -#include "remoting/base/protocol/chromotocol.pb.h" - -namespace remoting { - -// TODO(hclam): Merge this with the one in remoting/host/encoder.h. -typedef std::vector UpdatedRects; - -// Defines the behavior of a decoder for decoding images received from the -// host. -// -// Sequence of actions with a decoder is as follows: -// -// 1. BeginDecode(PartialDecodeDone, DecodeDone, VideoFrame) -// 2. PartialDecode(HostMessage) -// ... -// 3. EndDecode() -// -// The decoder will reply with: -// 1. PartialDecodeDone(VideoFrame, UpdatedRects) -// ... -// 2. DecodeDone(VideoFrame) -// -// The format of VideoFrame is a contract between the object that creates the -// decoder (most likely the renderer) and the decoder. -class Decoder { - public: - - virtual ~Decoder() { - } - - // Tell the decoder to use |frame| as a target to write the decoded image - // for the coming update stream. - // If decode is partially done and |frame| can be read, |partial_decode_done| - // is called and |update_rects| contains the updated regions. - // If decode is completed |decode_done| is called. - // Return true if the decoder can writes output to |frame| and accept - // the codec format. - // TODO(hclam): Provide more information when calling this function. - virtual bool BeginDecode(scoped_refptr frame, - UpdatedRects* updated_rects, - Task* partial_decode_done, - Task* decode_done) = 0; - - // Give a HostMessage that contains the update stream packet that contains - // the encoded data to the decoder. - // The decoder will own |message| and is responsible for deleting it. - // - // If the decoder has written something into |frame|, - // |partial_decode_done_| is called with |frame| and updated regions. - // Return true if the decoder can accept |message| and decode it. - // - // HostMessage returned by this method will contain a - // UpdateStreamPacketMessage. - // This message will contain either: - // 1. UpdateStreamBeginRect - // 2. UpdateStreamRectData - // 3. UpdateStreamEndRect - // - // See remoting/base/protocol/chromotocol.proto for more information about - // these messages. - virtual bool PartialDecode(HostMessage* message) = 0; - - // Notify the decoder that we have received the last update stream packet. - // If the decoding of the update stream has completed |decode_done_| is - // called with |frame|. - // If the update stream is not received fully and this method is called the - // decoder should also call |decode_done_| as soon as possible. - virtual void EndDecode() = 0; - - protected: - // Every decoder will have two internal states because there are three - // kinds of messages send to PartialDecode(). - // - // Here's a state diagram: - // - // UpdateStreamBeginRect UpdateStreamRectData - // .............. ............ - // . . . . - // . v . . - // kWaitingForBeginRect kWaitingForRectData . - // ^ . ^ . - // . . . . - // .............. ............ - // UpdateStreaEndRect - enum State { - // In this state the decoder is waiting for UpdateStreamBeginRect. - // After receiving UpdateStreaBeginRect, the encoder will transit to - // to kWaitingForRectData state. - kWaitingForBeginRect, - - // In this state the decoder is waiting for UpdateStreamRectData. - // The decode remains in this state if UpdateStreamRectData is received. - // The decoder will transit to kWaitingForBeginRect if UpdateStreamEndRect - // is received. - kWaitingForRectData, - }; -}; - -} // namespace remoting - -#endif // REMOTING_CLIENT_DECODER_H_ diff --git a/remoting/client/decoder_verbatim.cc b/remoting/client/decoder_verbatim.cc deleted file mode 100644 index d27d265..0000000 --- a/remoting/client/decoder_verbatim.cc +++ /dev/null @@ -1,127 +0,0 @@ -// 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/client/decoder_verbatim.h" - -#include "remoting/base/protocol_util.h" - -namespace remoting { - -DecoderVerbatim::DecoderVerbatim() - : state_(kWaitingForBeginRect), - rect_x_(0), - rect_y_(0), - rect_width_(0), - rect_height_(0), - bytes_per_pixel_(0), - updated_rects_(NULL), - reverse_rows_(true) { -} - -bool DecoderVerbatim::BeginDecode(scoped_refptr 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_); - - partial_decode_done_.reset(partial_decode_done); - decode_done_.reset(decode_done); - updated_rects_ = updated_rects; - - // TODO(hclam): Check if we can accept the color format of the video frame - // and the codec. - frame_ = frame; - return true; -} - -bool DecoderVerbatim::PartialDecode(HostMessage* message) { - scoped_ptr 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 DecoderVerbatim::EndDecode() { - DCHECK_EQ(kWaitingForBeginRect, state_); - decode_done_->Run(); - - partial_decode_done_.reset(); - decode_done_.reset(); - frame_ = NULL; - updated_rects_ = NULL; -} - -bool DecoderVerbatim::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(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); - return true; -} - -bool DecoderVerbatim::HandleRectData(HostMessage* message) { - DCHECK_EQ(kWaitingForRectData, state_); - DCHECK_EQ(0, - message->update_stream_packet().rect_data().sequence_number()); - - // Copy the data line by line. - const int src_stride = bytes_per_pixel_ * rect_width_; - const char* src = - message->update_stream_packet().rect_data().data().c_str(); - int src_stride_dir = src_stride; - if (reverse_rows_) { - // Copy rows from bottom to top to flip the image vertically. - src += (rect_height_ - 1) * src_stride; - // Change the direction of the stride to work bottom to top. - src_stride_dir *= -1; - } - const int dest_stride = frame_->stride(media::VideoFrame::kRGBPlane); - uint8* dest = frame_->data(media::VideoFrame::kRGBPlane) + - dest_stride * rect_y_ + bytes_per_pixel_ * rect_x_; - for (int i = 0; i < rect_height_; ++i) { - memcpy(dest, src, src_stride); - dest += dest_stride; - src += src_stride_dir; - } - - updated_rects_->clear(); - updated_rects_->push_back(gfx::Rect(rect_x_, rect_y_, - rect_width_, rect_height_)); - partial_decode_done_->Run(); - return true; -} - -bool DecoderVerbatim::HandleEndRect(HostMessage* message) { - DCHECK_EQ(kWaitingForRectData, state_); - state_ = kWaitingForBeginRect; - return true; -} - -} // namespace remoting diff --git a/remoting/client/decoder_verbatim.h b/remoting/client/decoder_verbatim.h deleted file mode 100644 index 6efc732..0000000 --- a/remoting/client/decoder_verbatim.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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_CLIENT_DECODER_VERBATIM_H_ -#define REMOTING_CLIENT_DECODER_VERBATIM_H_ - -#include "remoting/client/decoder.h" - -namespace remoting { - -class DecoderVerbatim : public Decoder { - public: - DecoderVerbatim(); - - // Decoder implementations. - virtual bool BeginDecode(scoped_refptr frame, - UpdatedRects* update_rects, - Task* partial_decode_done, - Task* decode_done); - virtual bool PartialDecode(HostMessage* message); - virtual void EndDecode(); - - private: - bool HandleBeginRect(HostMessage* message); - bool HandleRectData(HostMessage* message); - bool HandleEndRect(HostMessage* message); - - // The internal state of the decoder. - State state_; - - // Keeps track of the updating rect. - int rect_x_; - int rect_y_; - int rect_width_; - int rect_height_; - int bytes_per_pixel_; - - // Tasks to call when decode is done. - scoped_ptr partial_decode_done_; - scoped_ptr decode_done_; - - // The video frame to write to. - scoped_refptr frame_; - UpdatedRects* updated_rects_; - - // True if we should reverse the rows when copying data into the target - // frame buffer. - bool reverse_rows_; - - DISALLOW_COPY_AND_ASSIGN(DecoderVerbatim); -}; - -} // namespace remoting - -#endif // REMOTING_CLIENT_DECODER_VERBATIM_H_ diff --git a/remoting/client/decoder_verbatim_unittest.cc b/remoting/client/decoder_verbatim_unittest.cc deleted file mode 100644 index d541d22..0000000 --- a/remoting/client/decoder_verbatim_unittest.cc +++ /dev/null @@ -1,72 +0,0 @@ -// 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 "media/base/video_frame.h" -#include "remoting/client/decoder_verbatim.h" -#include "remoting/client/mock_objects.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::InSequence; - -namespace remoting { - -TEST(DecoderVerbatimTest, SimpleDecode) { - DecoderVerbatim decoder; - scoped_refptr handler = new MockDecodeDoneHandler(); - - const size_t kWidth = 10; - const size_t kHeight = 1; - const char kData[] = "ABCDEFGHIJ"; - scoped_ptr msg(new HostMessage()); - - // Prepare the begin rect message. - UpdateStreamBeginRect* begin_rect = - msg->mutable_update_stream_packet()->mutable_begin_rect(); - begin_rect->set_width(kWidth); - begin_rect->set_height(kHeight); - begin_rect->set_x(0); - begin_rect->set_y(0); - begin_rect->set_pixel_format(PixelFormatAscii); - - // Prepare the rect data. - msg->mutable_update_stream_packet()->mutable_rect_data()->set_data( - kData, sizeof(kData)); - - // Prepare the end rect. - msg->mutable_update_stream_packet()->mutable_end_rect(); - - scoped_refptr frame; - media::VideoFrame::CreateFrame(media::VideoFrame::ASCII, kWidth, kHeight, - base::TimeDelta(), base::TimeDelta(), &frame); - ASSERT_TRUE(frame); - - InSequence s; - EXPECT_CALL(*handler, PartialDecodeDone()); - EXPECT_CALL(*handler, DecodeDone()); - - UpdatedRects rects; - decoder.BeginDecode( - frame, &rects, - NewRunnableMethod(handler.get(), - &MockDecodeDoneHandler::PartialDecodeDone), - NewRunnableMethod(handler.get(), &MockDecodeDoneHandler::DecodeDone)); - decoder.PartialDecode(msg.release()); - decoder.EndDecode(); - - // Make sure we get the same data back. - EXPECT_EQ(kWidth, frame->width()); - EXPECT_EQ(kHeight, frame->height()); - EXPECT_EQ(media::VideoFrame::ASCII, frame->format()); - // TODO(hclam): Enable this line. - // EXPECT_EQ(0, memcmp(kData, frame->data(media::VideoFrame::kRGBPlane), - // sizeof(kData))); - - // Check the updated rects. - ASSERT_TRUE(rects.size() == 1); - EXPECT_EQ(kWidth, static_cast(rects[0].width())); - EXPECT_EQ(kHeight, static_cast(rects[0].height())); -} - -} // namespace remoting diff --git a/remoting/client/mock_objects.h b/remoting/client/mock_objects.h index 06ed801..bee3581 100644 --- a/remoting/client/mock_objects.h +++ b/remoting/client/mock_objects.h @@ -6,7 +6,6 @@ #define REMOTING_CLIENT_MOCK_OBJECTS_H_ #include "base/ref_counted.h" -#include "remoting/client/decoder.h" #include "testing/gmock/include/gmock/gmock.h" namespace remoting { diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc index ce38289..5b96226 100644 --- a/remoting/client/plugin/pepper_view.cc +++ b/remoting/client/plugin/pepper_view.cc @@ -5,7 +5,7 @@ #include "remoting/client/plugin/pepper_view.h" #include "base/message_loop.h" -#include "remoting/client/decoder_verbatim.h" +#include "remoting/base/decoder_verbatim.h" #include "remoting/client/plugin/chromoting_plugin.h" #include "remoting/client/plugin/pepper_util.h" #include "third_party/ppapi/cpp/device_context_2d.h" diff --git a/remoting/client/plugin/pepper_view.h b/remoting/client/plugin/pepper_view.h index 3622ab3..0a3147e 100644 --- a/remoting/client/plugin/pepper_view.h +++ b/remoting/client/plugin/pepper_view.h @@ -17,8 +17,8 @@ #include "base/scoped_ptr.h" #include "base/task.h" #include "media/base/video_frame.h" +#include "remoting/base/decoder.h" #include "remoting/client/chromoting_view.h" -#include "remoting/client/decoder.h" #include "third_party/ppapi/cpp/device_context_2d.h" namespace remoting { diff --git a/remoting/client/x11_view.cc b/remoting/client/x11_view.cc index e4b59ae..fe30291 100644 --- a/remoting/client/x11_view.cc +++ b/remoting/client/x11_view.cc @@ -10,7 +10,7 @@ #include #include "base/logging.h" -#include "remoting/client/decoder_verbatim.h" +#include "remoting/base/decoder_verbatim.h" namespace remoting { diff --git a/remoting/client/x11_view.h b/remoting/client/x11_view.h index 73e63c7..2825575 100644 --- a/remoting/client/x11_view.h +++ b/remoting/client/x11_view.h @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "media/base/video_frame.h" -#include "remoting/client/decoder.h" +#include "remoting/base/decoder.h" #include "remoting/client/chromoting_view.h" typedef unsigned long XID; diff --git a/remoting/host/capturer.h b/remoting/host/capturer.h index 6e16098..30d6737 100644 --- a/remoting/host/capturer.h +++ b/remoting/host/capturer.h @@ -5,19 +5,14 @@ #ifndef REMOTING_HOST_CAPTURER_H_ #define REMOTING_HOST_CAPTURER_H_ -#include - #include "base/basictypes.h" #include "base/callback.h" #include "base/lock.h" #include "base/task.h" -#include "gfx/rect.h" -#include "remoting/base/protocol/chromotocol.pb.h" +#include "remoting/base/capture_data.h" namespace remoting { -typedef std::vector RectVector; - // A class to perform the task of capturing the image of a window. // The capture action is asynchronous to allow maximum throughput. // @@ -27,61 +22,6 @@ typedef std::vector RectVector; // happening. class Capturer { public: - - struct DataPlanes { - static const int kPlaneCount = 3; - uint8* data[kPlaneCount]; - int strides[kPlaneCount]; - - DataPlanes() { - for (int i = 0; i < kPlaneCount; ++i) { - data[i] = NULL; - strides[i] = 0; - } - } - }; - - // Stores the data and information of a capture to pass off to the - // encoding thread. - class CaptureData : public base::RefCountedThreadSafe { - public: - CaptureData(const DataPlanes &data_planes, - int width, - int height, - PixelFormat format) : - data_planes_(data_planes), dirty_rects_(), - width_(width), height_(height), pixel_format_(format) { } - - // Get the data_planes data of the last capture. - const DataPlanes& data_planes() const { return data_planes_; } - - // Get the list of updated rectangles in the last capture. The result is - // written into |rects|. - const RectVector& dirty_rects() const { return dirty_rects_; } - - // Get the width of the image captured. - int width() const { return width_; } - - // Get the height of the image captured. - int height() const { return height_; } - - // Get the pixel format of the image captured. - PixelFormat pixel_format() const { return pixel_format_; } - - // Mutating methods. - RectVector& mutable_dirty_rects() { return dirty_rects_; } - - private: - const DataPlanes data_planes_; - RectVector dirty_rects_; - int width_; - int height_; - PixelFormat pixel_format_; - - friend class base::RefCountedThreadSafe; - ~CaptureData() {} - }; - // CaptureCompletedCallback is called when the capturer has completed. typedef Callback1 >::Type CaptureCompletedCallback; diff --git a/remoting/host/capturer_fake.cc b/remoting/host/capturer_fake.cc index 9ffe5bf..eee2d5a 100644 --- a/remoting/host/capturer_fake.cc +++ b/remoting/host/capturer_fake.cc @@ -23,7 +23,7 @@ CapturerFake::~CapturerFake() { void CapturerFake::CaptureRects(const RectVector& rects, CaptureCompletedCallback* callback) { GenerateImage(); - Capturer::DataPlanes planes; + DataPlanes planes; planes.data[0] = buffers_[current_buffer_].get(); planes.strides[0] = bytes_per_row_; diff --git a/remoting/host/capturer_fake_ascii.cc b/remoting/host/capturer_fake_ascii.cc index d0d7479..ccdbfcf 100644 --- a/remoting/host/capturer_fake_ascii.cc +++ b/remoting/host/capturer_fake_ascii.cc @@ -21,7 +21,7 @@ CapturerFakeAscii::~CapturerFakeAscii() { void CapturerFakeAscii::CaptureRects(const RectVector& rects, CaptureCompletedCallback* callback) { GenerateImage(); - Capturer::DataPlanes planes; + DataPlanes planes; planes.data[0] = buffers_[current_buffer_].get(); planes.strides[0] = bytes_per_row_; scoped_refptr capture_data(new CaptureData(planes, diff --git a/remoting/host/capturer_gdi.cc b/remoting/host/capturer_gdi.cc index 7f54aa9..6190819 100644 --- a/remoting/host/capturer_gdi.cc +++ b/remoting/host/capturer_gdi.cc @@ -79,7 +79,7 @@ void CapturerGdi::ScreenConfigurationChanged() { void CapturerGdi::CaptureRects(const RectVector& rects, CaptureCompletedCallback* callback) { - Capturer::DataPlanes planes; + DataPlanes planes; planes.data[0] = static_cast(buffers_[current_buffer_]); planes.strides[0] = bytes_per_row_; diff --git a/remoting/host/capturer_mac.cc b/remoting/host/capturer_mac.cc index 52d58c3..bfb031a 100644 --- a/remoting/host/capturer_mac.cc +++ b/remoting/host/capturer_mac.cc @@ -93,7 +93,7 @@ void CapturerMac::CaptureRects(const RectVector& rects, buffers_[current_buffer_].get()); glPopClientAttrib(); - Capturer::DataPlanes planes; + DataPlanes planes; planes.data[0] = buffers_[current_buffer_].get(); planes.strides[0] = bytes_per_row_; diff --git a/remoting/host/capturer_mac_unittest.cc b/remoting/host/capturer_mac_unittest.cc index e59a0bb..a172b15 100644 --- a/remoting/host/capturer_mac_unittest.cc +++ b/remoting/host/capturer_mac_unittest.cc @@ -28,7 +28,7 @@ class CapturerMacTest : public testing::Test { class CapturerCallback { public: explicit CapturerCallback(const RectVector& rects) : rects_(rects) { } - void CaptureDoneCallback(scoped_refptr capture_data); + void CaptureDoneCallback(scoped_refptr capture_data); protected: RectVector rects_; @@ -38,7 +38,7 @@ class CapturerCallback { }; void CapturerCallback::CaptureDoneCallback( - scoped_refptr capture_data) { + scoped_refptr capture_data) { CGDirectDisplayID mainDevice = CGMainDisplayID(); int width = CGDisplayPixelsWide(mainDevice); int height = CGDisplayPixelsHigh(mainDevice); @@ -46,7 +46,7 @@ void CapturerCallback::CaptureDoneCallback( EXPECT_EQ(rects_, capture_data->dirty_rects()); EXPECT_EQ(width, capture_data->width()); EXPECT_EQ(height, capture_data->height()); - const Capturer::DataPlanes &planes = capture_data->data_planes(); + const DataPlanes &planes = capture_data->data_planes(); EXPECT_TRUE(planes.data[0] != NULL); EXPECT_TRUE(planes.data[1] == NULL); EXPECT_TRUE(planes.data[2] == NULL); diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 3c349fa..7795de1 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -8,8 +8,11 @@ #include "base/task.h" #include "build/build_config.h" #include "remoting/base/constants.h" +#include "remoting/base/encoder.h" #include "remoting/base/protocol_decoder.h" #include "remoting/host/chromoting_host_context.h" +#include "remoting/host/capturer.h" +#include "remoting/host/event_executor.h" #include "remoting/host/host_config.h" #include "remoting/host/session_manager.h" #include "remoting/jingle_glue/jingle_channel.h" diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index ee15b47a..d281b97 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h @@ -8,12 +8,8 @@ #include #include "base/thread.h" -#include "remoting/host/capturer.h" #include "remoting/host/client_connection.h" -#include "remoting/host/encoder.h" -#include "remoting/host/event_executor.h" #include "remoting/host/heartbeat_sender.h" -#include "remoting/host/session_manager.h" #include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" @@ -21,8 +17,12 @@ class Task; namespace remoting { +class Capturer; class ChromotingHostContext; +class Encoder; +class EventExecutor; class MutableHostConfig; +class SessionManager; // A class to implement the functionality of a host process. // diff --git a/remoting/host/encoder.h b/remoting/host/encoder.h deleted file mode 100644 index ee43c94..0000000 --- a/remoting/host/encoder.h +++ /dev/null @@ -1,61 +0,0 @@ -// 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_HOST_ENCODER_H_ -#define REMOTING_HOST_ENCODER_H_ - -#include "base/basictypes.h" -#include "base/callback.h" -#include "media/base/data_buffer.h" -#include "remoting/base/protocol/chromotocol.pb.h" -#include "remoting/host/capturer.h" - -namespace media { - class DataBuffer; -} - -namespace remoting { - -class HostMessage; - -// A class to perform the task of encoding a continous stream of -// images. -// This class operates asynchronously to enable maximum throughput. -class Encoder { - public: - - // EncodingState is a bitfield that tracks the state of the encoding. - // An encoding that consists of a single block could concievably be starting - // inprogress and ended at the same time. - enum { - EncodingStarting = 1 << 0, - EncodingInProgress = 1 << 1, - EncodingEnded = 1 << 2 - }; - typedef int EncodingState; - - // DataAvailableCallback is called as blocks of data are made available - // from the encoder. Data made available by the encoder is in the form - // of HostMessage to reduce the amount of memory copies. - // The callback takes ownership of the HostMessage and is responsible for - // deleting it. - typedef Callback2::Type DataAvailableCallback; - - virtual ~Encoder() {} - - // Encode an image stored in |capture_data|. - // - // If |key_frame| is true, the encoder should not reference - // previous encode and encode the full frame. - // - // When encoded data is available, partial or full |data_available_callback| - // is called. - virtual void Encode(scoped_refptr capture_data, - bool key_frame, - DataAvailableCallback* data_available_callback) = 0; -}; - -} // namespace remoting - -#endif // REMOTING_HOST_ENCODER_H_ diff --git a/remoting/host/encoder_verbatim.cc b/remoting/host/encoder_verbatim.cc deleted file mode 100644 index fd9dadf..0000000 --- a/remoting/host/encoder_verbatim.cc +++ /dev/null @@ -1,87 +0,0 @@ -// 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/host/encoder_verbatim.h" - -#include "gfx/rect.h" -#include "media/base/data_buffer.h" -#include "remoting/base/protocol_util.h" -#include "remoting/base/protocol/chromotocol.pb.h" - -namespace remoting { - -using media::DataBuffer; - -void EncoderVerbatim::Encode(scoped_refptr 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]; - HostMessage* msg = new HostMessage(); - UpdateStreamPacketMessage* packet = msg->mutable_update_stream_packet(); - - if (EncodeRect(dirty_rect, capture_data, packet)) { - // Prepare the end rect content. - packet->mutable_end_rect(); - - EncodingState state = EncodingInProgress; - if (i == 0) { - state |= EncodingStarting; - } - if (i == num_rects - 1) { - state |= EncodingEnded; - } - data_available_callback->Run(msg, state); - } - } - - delete data_available_callback; -} - -bool EncoderVerbatim::EncodeRect( - const gfx::Rect& dirty, - const scoped_refptr& capture_data, - UpdateStreamPacketMessage* packet) { - // Prepare the begin rect content. - packet->mutable_begin_rect()->set_x(dirty.x()); - packet->mutable_begin_rect()->set_y(dirty.y()); - packet->mutable_begin_rect()->set_width(dirty.width()); - packet->mutable_begin_rect()->set_height(dirty.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 * dirty.width(); - int output_size = 0; - for (int i = 0; i < Capturer::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 * dirty.height(); - } - - // Resize the output data buffer. - packet->mutable_rect_data()->mutable_data()->resize(output_size); - uint8* out = reinterpret_cast( - &((*packet->mutable_rect_data()->mutable_data())[0])); - - for (int i = 0; i < Capturer::DataPlanes::kPlaneCount; ++i) { - const uint8* in = capture_data->data_planes().data[i]; - // Skip over planes that don't have data. - if (!in) continue; - - // TODO(hclam): Handle YUV since the height would be different. - for (int j = 0; j < dirty.height(); ++j) { - DCHECK_LE(row_size, capture_data->data_planes().strides[i]); - memcpy(out, in, row_size); - in += capture_data->data_planes().strides[i]; - out += row_size; - } - } - return true; -} - -} // namespace remoting diff --git a/remoting/host/encoder_verbatim.h b/remoting/host/encoder_verbatim.h deleted file mode 100644 index 175b954..0000000 --- a/remoting/host/encoder_verbatim.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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_HOST_ENCODER_VERBATIM_H_ -#define REMOTING_HOST_ENCODER_VERBATIM_H_ - -#include "remoting/host/encoder.h" - -namespace remoting { - -class UpdateStreamPacket; - -// EncoderVerbatim implements Encoder and simply copies input to the output -// buffer verbatim. -class EncoderVerbatim : public Encoder { - public: - EncoderVerbatim() {} - virtual ~EncoderVerbatim() {} - - virtual void Encode(scoped_refptr capture_data, - bool key_frame, - 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(const gfx::Rect& dirty, - const scoped_refptr& capture_data, - UpdateStreamPacketMessage* msg); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_ENCODER_VERBATIM_H_ diff --git a/remoting/host/encoder_vp8.cc b/remoting/host/encoder_vp8.cc deleted file mode 100644 index 231acd5..0000000 --- a/remoting/host/encoder_vp8.cc +++ /dev/null @@ -1,133 +0,0 @@ -// 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 "base/logging.h" -#include "media/base/callback.h" -#include "media/base/data_buffer.h" -#include "remoting/host/encoder_vp8.h" - -extern "C" { -// TODO(garykac): Rix with correct path to vp8 header. -#include "remoting/third_party/on2/include/vp8cx.h" -} - -namespace remoting { - -EncoderVp8::EncoderVp8() - : initialized_(false), - last_timestamp_(0) { -} - -EncoderVp8::~EncoderVp8() { -} - -bool EncoderVp8::Init() { - // TODO(hclam): Now always assume we receive YV12. May need to extend this - // so we can do color space conversion manually. - image_.fmt = IMG_FMT_YV12; - image_.w = width_; - image_.h = height_; - - on2_codec_enc_cfg_t config; - on2_codec_err_t result = on2_codec_enc_config_default(&on2_codec_vp8_cx_algo, - &config, 0); - - // TODO(hclam): Adjust the parameters. - config.g_w = width_; - config.g_h = height_; - config.g_pass = ON2_RC_ONE_PASS; - config.g_profile = 1; - config.g_threads = 2; - config.rc_target_bitrate = 1000000; - config.rc_min_quantizer = 0; - config.rc_max_quantizer = 15; - config.g_timebase.num = 1; - config.g_timebase.den = 30; - - if (on2_codec_enc_init(&codec_, &on2_codec_vp8_cx_algo, &config, 0)) - return false; - - on2_codec_control_(&codec_, VP8E_SET_CPUUSED, -15); - return true; -} - -void EncoderVp8::Encode(const DirtyRects& dirty_rects, - const uint8** input_data, - const int* strides, - bool key_frame, - UpdateStreamPacketHeader* header, - scoped_refptr* output_data, - bool* encode_done, - Task* data_available_task) { - // This will allow the task be called when this method exits. - media::AutoTaskRunner task(data_available_task); - *encode_done = false; - - // TODO(hclam): We only initialize the encoder once. We may have to - // allow encoder be initialized with difference sizes. - if (!initialized_) { - if (!Init()) { - LOG(ERROR) << "Can't initialize VP8 encoder"; - return; - } - initialized_ = true; - } - - // Assume the capturer has done the color space conversion. - if (!input_data || !strides) - return; - - image_.planes[0] = (unsigned char*)input_data[0]; - image_.planes[1] = (unsigned char*)input_data[1]; - image_.planes[2] = (unsigned char*)input_data[2]; - image_.stride[0] = strides[0]; - image_.stride[1] = strides[1]; - image_.stride[2] = strides[2]; - - // Do the actual encoding. - if (on2_codec_encode(&codec_, &image_, - last_timestamp_, 1, 0, ON2_DL_REALTIME)) { - return; - } - - // TODO(hclam): fix this. - last_timestamp_ += 100; - - // Read the encoded data. - on2_codec_iter_t iter = NULL; - bool got_data = false; - - // TODO(hclam: We assume one frame of input will get exactly one frame of - // output. This assumption may not be valid. - while (!got_data) { - on2_codec_cx_pkt_t* packet = on2_codec_get_cx_data(&codec_, &iter); - if (!packet) - continue; - - switch (packet->kind) { - case ON2_CODEC_CX_FRAME_PKT: - got_data = true; - *encode_done = true; - *output_data = new media::DataBuffer(packet->data.frame.sz); - memcpy((*output_data)->GetWritableData(), - packet->data.frame.buf, - packet->data.frame.sz); - break; - default: - break; - } - } - return; -} - -void EncoderVp8::SetSize(int width, int height) { - width_ = width; - height_ = height; -} - -void EncoderVp8::SetPixelFormat(PixelFormat pixel_format) { - pixel_format_ = pixel_format; -} - -} // namespace remoting diff --git a/remoting/host/encoder_vp8.h b/remoting/host/encoder_vp8.h deleted file mode 100644 index 1cd16ac..0000000 --- a/remoting/host/encoder_vp8.h +++ /dev/null @@ -1,61 +0,0 @@ -// 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_HOST_ENCODER_VP8_H_ -#define REMOTING_HOST_ENCODER_VP8_H_ - -#include "remoting/host/encoder.h" - -#include "remoting/base/protocol/chromotocol.pb.h" - -extern "C" { -// TODO(garykac): fix this link with the correct path to on2 -#include "remoting/third_party/on2/include/on2_encoder.h" -} // extern "C" - -namespace media { - -class DataBuffer; - -} // namespace media - -namespace remoting { - -// A class that uses VP8 to perform encoding. -class EncoderVp8 : public Encoder { - public: - EncoderVp8(); - virtual ~EncoderVp8(); - - virtual void Encode(const DirtyRects& dirty_rects, - const uint8** input_data, - const int* strides, - bool key_frame, - UpdateStreamPacketHeader* header, - scoped_refptr* output_data, - bool* encode_done, - Task* data_available_task); - virtual void SetSize(int width, int height); - virtual void SetPixelFormat(PixelFormat pixel_format); - - private: - // Setup the VP8 encoder. - bool Init(); - - // True if the encoder is initialized. - bool initialized_; - - int width_; - int height_; - PixelFormat pixel_format_; - on2_codec_ctx_t codec_; - on2_image_t image_; - int last_timestamp_; - - DISALLOW_COPY_AND_ASSIGN(EncoderVp8); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_ENCODER_VP8_H_ diff --git a/remoting/host/encoder_vp8_unittest.cc b/remoting/host/encoder_vp8_unittest.cc deleted file mode 100644 index 0b29830..0000000 --- a/remoting/host/encoder_vp8_unittest.cc +++ /dev/null @@ -1,68 +0,0 @@ -// 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 "media/base/data_buffer.h" -#include "remoting/base/pixel_format.h" -#include "remoting/host/encoder_vp8.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace remoting { - -static const int kWidth = 1024; -static const int kHeight = 768; -static const PixelFormat kPixelFormat = kPixelFormat_YV12; - -static void GenerateData(uint8* data, int size) { - for (int i = 0; i < size; ++i) { - data[i] = i; - } -} - -class EncodeDoneHandler - : public base::RefCountedThreadSafe { - public: - MOCK_METHOD0(EncodeDone, void()); -}; - -TEST(EncoderVp8Test, SimpleEncode) { - EncoderVp8 encoder; - encoder.SetSize(kWidth, kHeight); - encoder.SetPixelFormat(kPixelFormat); - - DirtyRects rects; - rects.push_back(gfx::Rect(kWidth, kHeight)); - - // Prepare memory for encoding. - int strides[3]; - strides[0] = kWidth; - strides[1] = strides[2] = kWidth / 2; - - uint8* planes[3]; - planes[0] = new uint8[kWidth * kHeight]; - planes[1] = new uint8[kWidth * kHeight / 4]; - planes[2] = new uint8[kWidth * kHeight / 4]; - GenerateData(planes[0], kWidth * kHeight); - GenerateData(planes[1], kWidth * kHeight / 4); - GenerateData(planes[2], kWidth * kHeight / 4); - - scoped_refptr handler = new EncodeDoneHandler(); - UpdateStreamPacketHeader* header = new UpdateStreamPacketHeader(); - scoped_refptr encoded_data; - bool encode_done = false; - EXPECT_CALL(*handler, EncodeDone()); - encoder.Encode(rects, const_cast(planes), - strides, true, header, &encoded_data, &encode_done, - NewRunnableMethod(handler.get(), - &EncodeDoneHandler::EncodeDone)); - - EXPECT_TRUE(encode_done); - ASSERT_TRUE(encoded_data.get()); - EXPECT_NE(0u, encoded_data->GetBufferSize()); - - delete [] planes[0]; - delete [] planes[1]; - delete [] planes[2]; -} - -} // namespace remoting diff --git a/remoting/host/mock_objects.h b/remoting/host/mock_objects.h index f4135f2..f58ac3b 100644 --- a/remoting/host/mock_objects.h +++ b/remoting/host/mock_objects.h @@ -9,7 +9,6 @@ #include "remoting/base/protocol_decoder.h" #include "remoting/host/capturer.h" #include "remoting/host/client_connection.h" -#include "remoting/host/encoder.h" #include "remoting/host/event_executor.h" #include "testing/gmock/include/gmock/gmock.h" @@ -32,19 +31,6 @@ class MockCapturer : public Capturer { DISALLOW_COPY_AND_ASSIGN(MockCapturer); }; -class MockEncoder : public Encoder { - public: - MockEncoder() {} - - MOCK_METHOD3(Encode, void( - scoped_refptr capture_data, - bool key_frame, - DataAvailableCallback* data_available_callback)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockEncoder); -}; - class MockEventExecutor : public EventExecutor { public: MockEventExecutor() {} diff --git a/remoting/host/session_manager.cc b/remoting/host/session_manager.cc index 5be8b56d..ebfafeba 100644 --- a/remoting/host/session_manager.cc +++ b/remoting/host/session_manager.cc @@ -10,9 +10,9 @@ #include "base/scoped_ptr.h" #include "base/stl_util-inl.h" #include "media/base/data_buffer.h" +#include "remoting/base/capture_data.h" #include "remoting/base/protocol_decoder.h" #include "remoting/host/client_connection.h" -#include "remoting/host/encoder.h" namespace remoting { @@ -219,7 +219,7 @@ void SessionManager::DoCapture() { } void SessionManager::CaptureDoneCallback( - scoped_refptr capture_data) { + scoped_refptr capture_data) { // TODO(hclam): There is a bug if the capturer doesn't produce any dirty rects. DCHECK_EQ(capture_loop_, MessageLoop::current()); encode_loop_->PostTask( @@ -381,7 +381,7 @@ void SessionManager::DoRemoveAllClients() { // Encoder thread -------------------------------------------------------------- void SessionManager::DoEncode( - scoped_refptr capture_data) { + scoped_refptr capture_data) { DCHECK_EQ(encode_loop_, MessageLoop::current()); // TODO(hclam): Enable |force_refresh| if a new client was diff --git a/remoting/host/session_manager.h b/remoting/host/session_manager.h index c2a2149..83c437a 100644 --- a/remoting/host/session_manager.h +++ b/remoting/host/session_manager.h @@ -12,9 +12,9 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/time.h" +#include "remoting/base/encoder.h" #include "remoting/base/protocol/chromotocol.pb.h" #include "remoting/host/capturer.h" -#include "remoting/host/encoder.h" namespace media { @@ -24,7 +24,7 @@ class DataBuffer; namespace remoting { -class Encoder; +class CaptureData; class ClientConnection; // A class for controlling and coordinate Capturer, Encoder @@ -115,7 +115,7 @@ class SessionManager : public base::RefCountedThreadSafe { void ScheduleNextCapture(); void DoCapture(); - void CaptureDoneCallback(scoped_refptr capture_data); + void CaptureDoneCallback(scoped_refptr capture_data); void DoFinishEncode(); void DoGetInitInfo(scoped_refptr client); @@ -142,7 +142,7 @@ class SessionManager : public base::RefCountedThreadSafe { // Encoder thread ----------------------------------------------------------- - void DoEncode(scoped_refptr capture_data); + void DoEncode(scoped_refptr capture_data); // EncodeDataAvailableTask takes ownership of header and is responsible for // deleting it. diff --git a/remoting/host/session_manager_unittest.cc b/remoting/host/session_manager_unittest.cc index e6d8114..239eb97 100644 --- a/remoting/host/session_manager_unittest.cc +++ b/remoting/host/session_manager_unittest.cc @@ -4,6 +4,7 @@ #include "base/message_loop.h" #include "base/task.h" +#include "remoting/base/mock_objects.h" #include "remoting/host/mock_objects.h" #include "remoting/host/session_manager.h" #include "testing/gmock/include/gmock/gmock.h" @@ -80,15 +81,13 @@ TEST_F(SessionManagerTest, OneRecordCycle) { RectVector update_rects; update_rects.push_back(gfx::Rect(0, 0, 10, 10)); - Capturer::DataPlanes planes; - for (int i = 0; i < Capturer::DataPlanes::kPlaneCount; ++i) { + DataPlanes planes; + for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { planes.data[i] = reinterpret_cast(i); planes.strides[i] = kWidth * 4; } - scoped_refptr data(new Capturer::CaptureData(planes, - kWidth, - kHeight, - kFormat)); + scoped_refptr data(new CaptureData(planes, kWidth, + kHeight, kFormat)); // Set the recording rate to very low to avoid capture twice. record_->SetMaxRate(0.01); diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc index a83dfc8..1c89fa3 100644 --- a/remoting/host/simple_host_process.cc +++ b/remoting/host/simple_host_process.cc @@ -26,10 +26,10 @@ #include "base/nss_util.h" #include "base/scoped_nsautorelease_pool.h" #include "base/thread.h" +#include "remoting/base/encoder_verbatim.h" #include "remoting/host/capturer_fake.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" -#include "remoting/host/encoder_verbatim.h" #include "remoting/host/json_host_config.h" #if defined(OS_WIN) diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 85718e3..3c601d3 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -129,14 +129,24 @@ # depend on chromotocol_proto_lib for headers. 'hard_dependency': 1, 'sources': [ + 'base/capture_data.h', 'base/compressor.h', 'base/compressor_zlib.cc', 'base/compressor_zlib.h', 'base/constants.cc', 'base/constants.h', + 'base/decoder.h', + 'base/decoder_verbatim.cc', + 'base/decoder_verbatim.h', 'base/decompressor.h', 'base/decompressor_zlib.cc', 'base/decompressor_zlib.h', + 'base/encoder.h', + 'base/encoder_verbatim.cc', + 'base/encoder_verbatim.h', + # TODO(hclam): Enable VP8 in the build. + #'base/encoder_vp8.cc', + #'base/encoder_vp8.h', 'base/multiple_array_input_stream.cc', 'base/multiple_array_input_stream.h', 'base/protocol_decoder.cc', @@ -166,12 +176,6 @@ 'host/differ.cc', 'host/differ_block.h', 'host/differ_block.cc', - 'host/encoder.h', - 'host/encoder_verbatim.cc', - 'host/encoder_verbatim.h', - # TODO(hclam): Enable VP8 in the build. - #'host/encoder_vp8.cc', - #'host/encoder_vp8.h', 'host/event_executor.h', 'host/session_manager.cc', 'host/session_manager.h', @@ -231,9 +235,6 @@ 'client/client_context.h', 'client/client_util.cc', 'client/client_util.h', - 'client/decoder.h', - 'client/decoder_verbatim.cc', - 'client/decoder_verbatim.h', 'client/host_connection.h', 'client/input_handler.h', 'client/jingle_host_connection.cc', @@ -342,12 +343,14 @@ ], 'sources': [ 'base/compressor_zlib_unittest.cc', + 'base/decoder_verbatim_unittest.cc', 'base/decompressor_zlib_unittest.cc', + # TODO(hclam): Enable VP8 in the build. + #'base/encoder_vp8_unittest.cc', 'base/mock_objects.h', 'base/multiple_array_input_stream_unittest.cc', 'base/protocol_decoder_unittest.cc', 'client/mock_objects.h', - 'client/decoder_verbatim_unittest.cc', 'host/chromoting_host_context_unittest.cc', 'host/client_connection_unittest.cc', 'host/differ_unittest.cc', @@ -355,8 +358,6 @@ 'host/json_host_config_unittest.cc', 'host/mock_objects.h', 'host/session_manager_unittest.cc', - # TODO(hclam): Enable VP8 in the build. - #'host/encoder_vp8_unittest.cc', 'jingle_glue/jingle_thread_unittest.cc', 'jingle_glue/jingle_channel_unittest.cc', 'jingle_glue/iq_request_unittest.cc', -- cgit v1.1