diff options
author | kxing@chromium.org <kxing@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-23 01:36:10 +0000 |
---|---|---|
committer | kxing@chromium.org <kxing@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-23 01:36:10 +0000 |
commit | 386098336aa778f82d5a079b9371a1c63bd46d94 (patch) | |
tree | 3f238db944ed2ac50f2224b62feb5a36193123fd /remoting/base | |
parent | e7e5bc86181faa3076671af080f809944594b60d (diff) | |
download | chromium_src-386098336aa778f82d5a079b9371a1c63bd46d94.zip chromium_src-386098336aa778f82d5a079b9371a1c63bd46d94.tar.gz chromium_src-386098336aa778f82d5a079b9371a1c63bd46d94.tar.bz2 |
Moved the video encoders/decoders to the codec directory.
Review URL: https://chromiumcodereview.appspot.com/10877014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152912 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/base')
-rw-r--r-- | remoting/base/base_mock_objects.cc | 13 | ||||
-rw-r--r-- | remoting/base/base_mock_objects.h | 31 | ||||
-rw-r--r-- | remoting/base/codec_test.cc | 497 | ||||
-rw-r--r-- | remoting/base/codec_test.h | 40 | ||||
-rw-r--r-- | remoting/base/decoder.h | 75 | ||||
-rw-r--r-- | remoting/base/decoder_row_based.cc | 225 | ||||
-rw-r--r-- | remoting/base/decoder_row_based.h | 84 | ||||
-rw-r--r-- | remoting/base/decoder_vp8.cc | 211 | ||||
-rw-r--r-- | remoting/base/decoder_vp8.h | 60 | ||||
-rw-r--r-- | remoting/base/decoder_vp8_unittest.cc | 74 | ||||
-rw-r--r-- | remoting/base/encode_decode_unittest.cc | 31 | ||||
-rw-r--r-- | remoting/base/encoder.h | 48 | ||||
-rw-r--r-- | remoting/base/encoder_row_based.cc | 177 | ||||
-rw-r--r-- | remoting/base/encoder_row_based.h | 71 | ||||
-rw-r--r-- | remoting/base/encoder_row_based_unittest.cc | 21 | ||||
-rw-r--r-- | remoting/base/encoder_vp8.cc | 307 | ||||
-rw-r--r-- | remoting/base/encoder_vp8.h | 64 | ||||
-rw-r--r-- | remoting/base/encoder_vp8_unittest.cc | 96 |
18 files changed, 0 insertions, 2125 deletions
diff --git a/remoting/base/base_mock_objects.cc b/remoting/base/base_mock_objects.cc deleted file mode 100644 index d76a965..0000000 --- a/remoting/base/base_mock_objects.cc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2011 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/base_mock_objects.h" - -namespace remoting { - -MockEncoder::MockEncoder() {} - -MockEncoder::~MockEncoder() {} - -} // namespace remoting diff --git a/remoting/base/base_mock_objects.h b/remoting/base/base_mock_objects.h deleted file mode 100644 index e90530d..0000000 --- a/remoting/base/base_mock_objects.h +++ /dev/null @@ -1,31 +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_BASE_BASE_MOCK_OBJECTS_H_ -#define REMOTING_BASE_BASE_MOCK_OBJECTS_H_ - -#include "remoting/base/capture_data.h" -#include "remoting/base/decoder.h" -#include "remoting/base/encoder.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace remoting { - -class MockEncoder : public Encoder { - public: - MockEncoder(); - virtual ~MockEncoder(); - - MOCK_METHOD3(Encode, void( - scoped_refptr<CaptureData> capture_data, - bool key_frame, - const DataAvailableCallback& data_available_callback)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockEncoder); -}; - -} // namespace remoting - -#endif // REMOTING_BASE_BASE_MOCK_OBJECTS_H_ diff --git a/remoting/base/codec_test.cc b/remoting/base/codec_test.cc deleted file mode 100644 index 6813c66..0000000 --- a/remoting/base/codec_test.cc +++ /dev/null @@ -1,497 +0,0 @@ -// Copyright (c) 2012 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 <deque> -#include <stdlib.h> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "media/base/video_frame.h" -#include "remoting/base/base_mock_objects.h" -#include "remoting/base/codec_test.h" -#include "remoting/base/decoder.h" -#include "remoting/base/encoder.h" -#include "remoting/base/util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const int kBytesPerPixel = 4; - -// Some sample rects for testing. -std::vector<std::vector<SkIRect> > MakeTestRectLists(const SkISize& size) { - std::vector<std::vector<SkIRect> > rect_lists; - std::vector<SkIRect> rects; - rects.push_back(SkIRect::MakeXYWH(0, 0, size.width(), size.height())); - rect_lists.push_back(rects); - rects.clear(); - rects.push_back(SkIRect::MakeXYWH(0, 0, size.width() / 2, size.height() / 2)); - rect_lists.push_back(rects); - rects.clear(); - rects.push_back(SkIRect::MakeXYWH(size.width() / 2, size.height() / 2, - size.width() / 2, size.height() / 2)); - rect_lists.push_back(rects); - rects.clear(); - rects.push_back(SkIRect::MakeXYWH(16, 16, 16, 16)); - rects.push_back(SkIRect::MakeXYWH(128, 64, 32, 32)); - rect_lists.push_back(rects); - return rect_lists; -} - -} // namespace - -namespace remoting { - -// A class to test the message output of the encoder. -class EncoderMessageTester { - public: - EncoderMessageTester() - : begin_rect_(0), - rect_data_(0), - end_rect_(0), - added_rects_(0), - state_(kWaitingForBeginRect), - strict_(false) { - } - - ~EncoderMessageTester() { - EXPECT_EQ(begin_rect_, end_rect_); - EXPECT_GT(begin_rect_, 0); - EXPECT_EQ(kWaitingForBeginRect, state_); - if (strict_) { - EXPECT_EQ(added_rects_, begin_rect_); - } - } - - // Test that we received the correct packet. - void ReceivedPacket(VideoPacket* packet) { - if (state_ == kWaitingForBeginRect) { - EXPECT_TRUE((packet->flags() & VideoPacket::FIRST_PACKET) != 0); - state_ = kWaitingForRectData; - ++begin_rect_; - - if (strict_) { - SkIRect rect = rects_.front(); - rects_.pop_front(); - EXPECT_EQ(rect.fLeft, packet->format().x()); - EXPECT_EQ(rect.fTop, packet->format().y()); - EXPECT_EQ(rect.width(), packet->format().width()); - EXPECT_EQ(rect.height(), packet->format().height()); - } - } else { - EXPECT_FALSE((packet->flags() & VideoPacket::FIRST_PACKET) != 0); - } - - if (state_ == kWaitingForRectData) { - if (packet->has_data()) { - ++rect_data_; - } - - if ((packet->flags() & VideoPacket::LAST_PACKET) != 0) { - // Expect that we have received some data. - EXPECT_GT(rect_data_, 0); - rect_data_ = 0; - state_ = kWaitingForBeginRect; - ++end_rect_; - } - - if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) { - // LAST_PARTITION must always be marked with LAST_PACKET. - EXPECT_TRUE((packet->flags() & VideoPacket::LAST_PACKET) != 0); - } - } - } - - void set_strict(bool strict) { - strict_ = strict; - } - - void AddRects(const SkIRect* rects, int count) { - rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); - added_rects_ += count; - } - - private: - enum State { - kWaitingForBeginRect, - kWaitingForRectData, - }; - - int begin_rect_; - int rect_data_; - int end_rect_; - int added_rects_; - State state_; - bool strict_; - - std::deque<SkIRect> rects_; - - DISALLOW_COPY_AND_ASSIGN(EncoderMessageTester); -}; - -class DecoderTester { - public: - DecoderTester(Decoder* decoder, const SkISize& screen_size, - const SkISize& view_size) - : screen_size_(screen_size), - view_size_(view_size), - strict_(false), - decoder_(decoder) { - image_data_.reset(new uint8[ - view_size_.width() * view_size_.height() * kBytesPerPixel]); - EXPECT_TRUE(image_data_.get()); - decoder_->Initialize(screen_size_); - } - - void Reset() { - expected_region_.setEmpty(); - update_region_.setEmpty(); - } - - void ResetRenderedData() { - memset(image_data_.get(), 0, - view_size_.width() * view_size_.height() * kBytesPerPixel); - } - - void ReceivedPacket(VideoPacket* packet) { - Decoder::DecodeResult result = decoder_->DecodePacket(packet); - - ASSERT_NE(Decoder::DECODE_ERROR, result); - - if (result == Decoder::DECODE_DONE) { - RenderFrame(); - } - } - - void RenderFrame() { - decoder_->RenderFrame(view_size_, - SkIRect::MakeSize(view_size_), - image_data_.get(), - view_size_.width() * kBytesPerPixel, - &update_region_); - } - - void ReceivedScopedPacket(scoped_ptr<VideoPacket> packet) { - ReceivedPacket(packet.get()); - } - - void set_strict(bool strict) { - strict_ = strict; - } - - void set_capture_data(scoped_refptr<CaptureData> data) { - capture_data_ = data; - } - - void AddRects(const SkIRect* rects, int count) { - SkRegion new_rects; - new_rects.setRects(rects, count); - AddRegion(new_rects); - } - - void AddRegion(const SkRegion& region) { - expected_region_.op(region, SkRegion::kUnion_Op); - } - - void VerifyResults() { - if (!strict_) - return; - - ASSERT_TRUE(capture_data_.get()); - - // Test the content of the update region. - EXPECT_EQ(expected_region_, update_region_); - for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) { - const int stride = view_size_.width() * kBytesPerPixel; - EXPECT_EQ(stride, capture_data_->data_planes().strides[0]); - const int offset = stride * i.rect().top() + - kBytesPerPixel * i.rect().left(); - const uint8* original = capture_data_->data_planes().data[0] + offset; - const uint8* decoded = image_data_.get() + offset; - const int row_size = kBytesPerPixel * i.rect().width(); - for (int y = 0; y < i.rect().height(); ++y) { - EXPECT_EQ(0, memcmp(original, decoded, row_size)) - << "Row " << y << " is different"; - original += stride; - decoded += stride; - } - } - } - - // The error at each pixel is the root mean square of the errors in - // the R, G, and B components, each normalized to [0, 1]. This routine - // checks that the maximum and mean pixel errors do not exceed given limits. -void VerifyResultsApprox(const uint8* expected_view_data, - double max_error_limit, double mean_error_limit) { - double max_error = 0.0; - double sum_error = 0.0; - int error_num = 0; - for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) { - const int stride = view_size_.width() * kBytesPerPixel; - const int offset = stride * i.rect().top() + - kBytesPerPixel * i.rect().left(); - const uint8* expected = expected_view_data + offset; - const uint8* actual = image_data_.get() + offset; - for (int y = 0; y < i.rect().height(); ++y) { - for (int x = 0; x < i.rect().width(); ++x) { - double error = CalculateError(expected, actual); - max_error = std::max(max_error, error); - sum_error += error; - ++error_num; - expected += 4; - actual += 4; - } - } - } - EXPECT_LE(max_error, max_error_limit); - double mean_error = sum_error / error_num; - EXPECT_LE(mean_error, mean_error_limit); - LOG(INFO) << "Max error: " << max_error; - LOG(INFO) << "Mean error: " << mean_error; - } - - double CalculateError(const uint8* original, const uint8* decoded) { - double error_sum_squares = 0.0; - for (int i = 0; i < 3; i++) { - double error = static_cast<double>(*original++) - - static_cast<double>(*decoded++); - error /= 255.0; - error_sum_squares += error * error; - } - original++; - decoded++; - return sqrt(error_sum_squares / 3.0); - } - - private: - SkISize screen_size_; - SkISize view_size_; - bool strict_; - SkRegion expected_region_; - SkRegion update_region_; - Decoder* decoder_; - scoped_array<uint8> image_data_; - scoped_refptr<CaptureData> capture_data_; - - DISALLOW_COPY_AND_ASSIGN(DecoderTester); -}; - -// The EncoderTester provides a hook for retrieving the data, and passing the -// message to other subprograms for validaton. -class EncoderTester { - public: - EncoderTester(EncoderMessageTester* message_tester) - : message_tester_(message_tester), - decoder_tester_(NULL), - data_available_(0) { - } - - ~EncoderTester() { - EXPECT_GT(data_available_, 0); - } - - void DataAvailable(scoped_ptr<VideoPacket> packet) { - ++data_available_; - message_tester_->ReceivedPacket(packet.get()); - - // Send the message to the DecoderTester. - if (decoder_tester_) { - decoder_tester_->ReceivedPacket(packet.get()); - } - } - - void AddRects(const SkIRect* rects, int count) { - message_tester_->AddRects(rects, count); - } - - void set_decoder_tester(DecoderTester* decoder_tester) { - decoder_tester_ = decoder_tester; - } - - private: - EncoderMessageTester* message_tester_; - DecoderTester* decoder_tester_; - int data_available_; - - DISALLOW_COPY_AND_ASSIGN(EncoderTester); -}; - -scoped_refptr<CaptureData> PrepareEncodeData(const SkISize& size, - media::VideoFrame::Format format, - uint8** memory) { - // TODO(hclam): Support also YUV format. - CHECK_EQ(format, media::VideoFrame::RGB32); - int memory_size = size.width() * size.height() * kBytesPerPixel; - - *memory = new uint8[memory_size]; - srand(0); - for (int i = 0; i < memory_size; ++i) { - (*memory)[i] = rand() % 256; - } - - DataPlanes planes; - memset(planes.data, 0, sizeof(planes.data)); - memset(planes.strides, 0, sizeof(planes.strides)); - planes.data[0] = *memory; - planes.strides[0] = size.width() * kBytesPerPixel; - - scoped_refptr<CaptureData> data = - new CaptureData(planes, size, format); - return data; -} - -static void TestEncodingRects(Encoder* encoder, - EncoderTester* tester, - scoped_refptr<CaptureData> data, - const SkIRect* rects, int count) { - data->mutable_dirty_region().setEmpty(); - for (int i = 0; i < count; ++i) { - data->mutable_dirty_region().op(rects[i], SkRegion::kUnion_Op); - } - tester->AddRects(rects, count); - - encoder->Encode(data, true, base::Bind( - &EncoderTester::DataAvailable, base::Unretained(tester))); -} - -void TestEncoder(Encoder* encoder, bool strict) { - SkISize kSize = SkISize::Make(320, 240); - - EncoderMessageTester message_tester; - message_tester.set_strict(strict); - - EncoderTester tester(&message_tester); - - uint8* memory; - scoped_refptr<CaptureData> data = - PrepareEncodeData(kSize, media::VideoFrame::RGB32, &memory); - scoped_array<uint8> memory_wrapper(memory); - - std::vector<std::vector<SkIRect> > test_rect_lists = MakeTestRectLists(kSize); - for (size_t i = 0; i < test_rect_lists.size(); ++i) { - const std::vector<SkIRect>& test_rects = test_rect_lists[i]; - TestEncodingRects(encoder, &tester, data, - &test_rects[0], test_rects.size()); - } -} - -static void TestEncodeDecodeRects(Encoder* encoder, - EncoderTester* encoder_tester, - DecoderTester* decoder_tester, - scoped_refptr<CaptureData> data, - const SkIRect* rects, int count) { - data->mutable_dirty_region().setRects(rects, count); - encoder_tester->AddRects(rects, count); - decoder_tester->AddRects(rects, count); - - // Generate random data for the updated region. - srand(0); - for (int i = 0; i < count; ++i) { - CHECK_EQ(data->pixel_format(), media::VideoFrame::RGB32); - const int bytes_per_pixel = 4; // Because of RGB32 on previous line. - const int row_size = bytes_per_pixel * rects[i].width(); - uint8* memory = data->data_planes().data[0] + - data->data_planes().strides[0] * rects[i].top() + - bytes_per_pixel * rects[i].left(); - for (int y = 0; y < rects[i].height(); ++y) { - for (int x = 0; x < row_size; ++x) - memory[x] = rand() % 256; - memory += data->data_planes().strides[0]; - } - } - - encoder->Encode(data, true, base::Bind(&EncoderTester::DataAvailable, - base::Unretained(encoder_tester))); - decoder_tester->VerifyResults(); - decoder_tester->Reset(); -} - -void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) { - SkISize kSize = SkISize::Make(320, 240); - - EncoderMessageTester message_tester; - message_tester.set_strict(strict); - - EncoderTester encoder_tester(&message_tester); - - uint8* memory; - scoped_refptr<CaptureData> data = - PrepareEncodeData(kSize, media::VideoFrame::RGB32, &memory); - scoped_array<uint8> memory_wrapper(memory); - - DecoderTester decoder_tester(decoder, kSize, kSize); - decoder_tester.set_strict(strict); - decoder_tester.set_capture_data(data); - encoder_tester.set_decoder_tester(&decoder_tester); - - std::vector<std::vector<SkIRect> > test_rect_lists = MakeTestRectLists(kSize); - for (size_t i = 0; i < test_rect_lists.size(); ++i) { - const std::vector<SkIRect> test_rects = test_rect_lists[i]; - TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, - &test_rects[0], test_rects.size()); - } -} - -static void FillWithGradient(uint8* memory, const SkISize& frame_size, - const SkIRect& rect) { - for (int j = rect.top(); j < rect.bottom(); ++j) { - uint8* p = memory + ((j * frame_size.width()) + rect.left()) * 4; - for (int i = rect.left(); i < rect.right(); ++i) { - *p++ = static_cast<uint8>((255.0 * i) / frame_size.width()); - *p++ = static_cast<uint8>((164.0 * j) / frame_size.height()); - *p++ = static_cast<uint8>((82.0 * (i + j)) / - (frame_size.width() + frame_size.height())); - *p++ = 0; - } - } -} - -void TestEncoderDecoderGradient(Encoder* encoder, - Decoder* decoder, - const SkISize& screen_size, - const SkISize& view_size, - double max_error_limit, - double mean_error_limit) { - SkIRect screen_rect = SkIRect::MakeSize(screen_size); - scoped_array<uint8> screen_data(new uint8[ - screen_size.width() * screen_size.height() * kBytesPerPixel]); - FillWithGradient(screen_data.get(), screen_size, screen_rect); - - SkIRect view_rect = SkIRect::MakeSize(view_size); - scoped_array<uint8> expected_view_data(new uint8[ - view_size.width() * view_size.height() * kBytesPerPixel]); - FillWithGradient(expected_view_data.get(), view_size, view_rect); - - DataPlanes planes; - memset(planes.data, 0, sizeof(planes.data)); - memset(planes.strides, 0, sizeof(planes.strides)); - planes.data[0] = screen_data.get(); - planes.strides[0] = screen_size.width() * kBytesPerPixel; - - scoped_refptr<CaptureData> capture_data = - new CaptureData(planes, screen_size, media::VideoFrame::RGB32); - capture_data->mutable_dirty_region().op(screen_rect, SkRegion::kUnion_Op); - - DecoderTester decoder_tester(decoder, screen_size, view_size); - decoder_tester.set_capture_data(capture_data); - decoder_tester.AddRegion(capture_data->dirty_region()); - - encoder->Encode(capture_data, true, - base::Bind(&DecoderTester::ReceivedScopedPacket, - base::Unretained(&decoder_tester))); - - decoder_tester.VerifyResultsApprox(expected_view_data.get(), - max_error_limit, mean_error_limit); - - // Check that the decoder correctly re-renders the frame if its client - // invalidates the frame. - decoder_tester.ResetRenderedData(); - decoder->Invalidate(view_size, SkRegion(view_rect)); - decoder_tester.RenderFrame(); - decoder_tester.VerifyResultsApprox(expected_view_data.get(), - max_error_limit, mean_error_limit); -} - -} // namespace remoting diff --git a/remoting/base/codec_test.h b/remoting/base/codec_test.h deleted file mode 100644 index ba71dad..0000000 --- a/remoting/base/codec_test.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2012 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_CODEC_TEST_H_ -#define REMOTING_BASE_CODEC_TEST_H_ - -#include "base/memory/ref_counted.h" -#include "media/base/video_frame.h" -#include "remoting/base/capture_data.h" - -namespace remoting { - -class Decoder; -class Encoder; - -// Generate test data and test the encoder for a regular encoding sequence. -// This will test encoder test and the sequence of messages sent. -// -// If |strict| is set to true then this routine will make sure the updated -// rects match dirty rects. -void TestEncoder(Encoder* encoder, bool strict); - -// Generate test data and test the encoder and decoder pair. -// -// If |strict| is set to true, this routine will make sure the updated rects -// are correct. -void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict); - -// Generate a frame containing a gradient, and test the encoder and decoder -// pair. -void TestEncoderDecoderGradient(Encoder* encoder, Decoder* decoder, - const SkISize& screen_size, - const SkISize& view_size, - double max_error_limit, - double mean_error_limit); - -} // namespace remoting - -#endif // REMOTING_BASE_CODEC_TEST_H_ diff --git a/remoting/base/decoder.h b/remoting/base/decoder.h deleted file mode 100644 index 9286ab5..0000000 --- a/remoting/base/decoder.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2012 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 "base/basictypes.h" -#include "remoting/proto/video.pb.h" -#include "third_party/skia/include/core/SkRect.h" -#include "third_party/skia/include/core/SkRegion.h" -#include "third_party/skia/include/core/SkSize.h" - -namespace remoting { - -// Interface for a decoder that takes a stream of bytes from the network and -// outputs frames of data. -// -// TODO(ajwong): Beef up this documentation once the API stablizes. -class Decoder { - public: - // DecodeResult is returned from DecodePacket() and indicates current state - // of the decoder. DECODE_DONE means that last packet for the frame was - // processed, and the frame can be displayed now. DECODE_IN_PROGRESS - // indicates that the decoder must receive more data before the frame can be - // displayed. DECODE_ERROR is returned if there was an error in the stream. - enum DecodeResult { - DECODE_ERROR = -1, - DECODE_IN_PROGRESS, - DECODE_DONE, - }; - - Decoder() {} - virtual ~Decoder() {} - - // Initializes the decoder and sets the output dimensions. - // |screen size| must not be empty. - virtual void Initialize(const SkISize& screen_size) = 0; - - // Feeds more data into the decoder. - virtual DecodeResult DecodePacket(const VideoPacket* packet) = 0; - - // Returns true if decoder is ready to accept data via DecodePacket. - virtual bool IsReadyForData() = 0; - - virtual VideoPacketFormat::Encoding Encoding() = 0; - - // Marks the specified |region| of the view for update the next time - // RenderFrame() is called. |region| is expressed in |view_size| coordinates. - // |view_size| must not be empty. - virtual void Invalidate(const SkISize& view_size, - const SkRegion& region) = 0; - - // Copies invalidated pixels within |clip_area| to |image_buffer|. Pixels are - // invalidated either by new data received in DecodePacket(), or by explicit - // calls to Invalidate(). |clip_area| is specified in |view_size| coordinates. - // If |view_size| differs from the source size then the copied pixels will be - // scaled accordingly. |view_size| cannot be empty. - // - // |image_buffer|'s origin must correspond to the top-left of |clip_area|, - // and the buffer must be large enough to hold |clip_area| RGBA32 pixels. - // |image_stride| gives the output buffer's stride in pixels. - // - // On return, |output_region| contains the updated area, in |view_size| - // coordinates. - virtual void RenderFrame(const SkISize& view_size, - const SkIRect& clip_area, - uint8* image_buffer, - int image_stride, - SkRegion* output_region) = 0; -}; - -} // namespace remoting - -#endif // REMOTING_BASE_DECODER_H_ diff --git a/remoting/base/decoder_row_based.cc b/remoting/base/decoder_row_based.cc deleted file mode 100644 index d98a5ca..0000000 --- a/remoting/base/decoder_row_based.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2012 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_row_based.h" - -#include "base/logging.h" -#include "remoting/base/decompressor.h" -#include "remoting/base/decompressor_zlib.h" -#include "remoting/base/decompressor_verbatim.h" -#include "remoting/base/util.h" - -namespace remoting { - -namespace { -// Both input and output data are assumed to be RGBA32. -const int kBytesPerPixel = 4; -} - -DecoderRowBased* DecoderRowBased::CreateZlibDecoder() { - return new DecoderRowBased(new DecompressorZlib(), - VideoPacketFormat::ENCODING_ZLIB); -} - -DecoderRowBased* DecoderRowBased::CreateVerbatimDecoder() { - return new DecoderRowBased(new DecompressorVerbatim(), - VideoPacketFormat::ENCODING_VERBATIM); -} - -DecoderRowBased::DecoderRowBased(Decompressor* decompressor, - VideoPacketFormat::Encoding encoding) - : state_(kUninitialized), - clip_(SkIRect::MakeEmpty()), - decompressor_(decompressor), - encoding_(encoding), - row_pos_(0), - row_y_(0), - screen_size_(SkISize::Make(0, 0)) { -} - -DecoderRowBased::~DecoderRowBased() { -} - -bool DecoderRowBased::IsReadyForData() { - switch (state_) { - case kUninitialized: - case kError: - return false; - case kReady: - case kProcessing: - case kPartitionDone: - case kDone: - return true; - } - NOTREACHED(); - return false; -} - -void DecoderRowBased::Initialize(const SkISize& screen_size) { - decompressor_->Reset(); - updated_region_.setEmpty(); - screen_buffer_.reset(NULL); - - screen_size_ = screen_size; - // Allocate the screen buffer, if necessary. - if (!screen_size_.isEmpty()) { - screen_buffer_.reset(new uint8[ - screen_size_.width() * screen_size_.height() * kBytesPerPixel]); - } - - state_ = kReady; -} - -Decoder::DecodeResult DecoderRowBased::DecodePacket(const VideoPacket* packet) { - UpdateStateForPacket(packet); - - if (state_ == kError) { - return DECODE_ERROR; - } - - const uint8* in = reinterpret_cast<const uint8*>(packet->data().data()); - const int in_size = packet->data().size(); - const int row_size = clip_.width() * kBytesPerPixel; - - int out_stride = screen_size_.width() * kBytesPerPixel; - uint8* out = screen_buffer_.get() + out_stride * (clip_.top() + row_y_) + - kBytesPerPixel * clip_.left(); - - // Consume all the data in the message. - bool decompress_again = true; - int used = 0; - while (decompress_again && used < in_size) { - if (row_y_ >= clip_.height()) { - state_ = kError; - LOG(WARNING) << "Too much data is received for the given rectangle."; - return DECODE_ERROR; - } - - 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 += out_stride; - } - } - - if (state_ == kPartitionDone || state_ == kDone) { - if (row_y_ < clip_.height()) { - state_ = kError; - LOG(WARNING) << "Received LAST_PACKET, but didn't get enough data."; - return DECODE_ERROR; - } - - updated_region_.op(clip_, SkRegion::kUnion_Op); - decompressor_->Reset(); - } - - if (state_ == kDone) { - return DECODE_DONE; - } else { - return DECODE_IN_PROGRESS; - } -} - -void DecoderRowBased::UpdateStateForPacket(const VideoPacket* packet) { - if (state_ == kError) { - return; - } - - if (packet->flags() & VideoPacket::FIRST_PACKET) { - if (state_ != kReady && state_ != kDone && state_ != kPartitionDone) { - state_ = kError; - LOG(WARNING) << "Received unexpected FIRST_PACKET."; - return; - } - - // Reset the buffer location status variables on the first packet. - clip_.setXYWH(packet->format().x(), packet->format().y(), - packet->format().width(), packet->format().height()); - if (!SkIRect::MakeSize(screen_size_).contains(clip_)) { - state_ = kError; - LOG(WARNING) << "Invalid clipping area received."; - return; - } - - state_ = kProcessing; - row_pos_ = 0; - row_y_ = 0; - } - - if (state_ != kProcessing) { - state_ = kError; - LOG(WARNING) << "Received unexpected packet."; - return; - } - - if (packet->flags() & VideoPacket::LAST_PACKET) { - if (state_ != kProcessing) { - state_ = kError; - LOG(WARNING) << "Received unexpected LAST_PACKET."; - return; - } - state_ = kPartitionDone; - } - - if (packet->flags() & VideoPacket::LAST_PARTITION) { - if (state_ != kPartitionDone) { - state_ = kError; - LOG(WARNING) << "Received unexpected LAST_PARTITION."; - return; - } - state_ = kDone; - } - - return; -} - -VideoPacketFormat::Encoding DecoderRowBased::Encoding() { - return encoding_; -} - -void DecoderRowBased::Invalidate(const SkISize& view_size, - const SkRegion& region) { - updated_region_.op(region, SkRegion::kUnion_Op); -} - -void DecoderRowBased::RenderFrame(const SkISize& view_size, - const SkIRect& clip_area, - uint8* image_buffer, - int image_stride, - SkRegion* output_region) { - output_region->setEmpty(); - - // TODO(alexeypa): scaling is not implemented. - SkIRect clip_rect = SkIRect::MakeSize(screen_size_); - if (!clip_rect.intersect(clip_area)) - return; - - int screen_stride = screen_size_.width() * kBytesPerPixel; - - for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) { - SkIRect rect(i.rect()); - if (!rect.intersect(clip_rect)) - continue; - - CopyRGB32Rect(screen_buffer_.get(), screen_stride, - clip_rect, - image_buffer, image_stride, - clip_area, - rect); - output_region->op(rect, SkRegion::kUnion_Op); - } - - updated_region_.setEmpty(); -} - -} // namespace remoting diff --git a/remoting/base/decoder_row_based.h b/remoting/base/decoder_row_based.h deleted file mode 100644 index fc76837..0000000 --- a/remoting/base/decoder_row_based.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2012 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_ROW_BASED_H_ -#define REMOTING_BASE_DECODER_ROW_BASED_H_ - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "remoting/base/decoder.h" - -namespace remoting { - -class Decompressor; - -class DecoderRowBased : public Decoder { - public: - virtual ~DecoderRowBased(); - - static DecoderRowBased* CreateZlibDecoder(); - static DecoderRowBased* CreateVerbatimDecoder(); - - // Decoder implementation. - virtual bool IsReadyForData() OVERRIDE; - virtual void Initialize(const SkISize& screen_size) OVERRIDE; - virtual DecodeResult DecodePacket(const VideoPacket* packet) OVERRIDE; - virtual VideoPacketFormat::Encoding Encoding() OVERRIDE; - virtual void Invalidate(const SkISize& view_size, - const SkRegion& region) OVERRIDE; - virtual void RenderFrame(const SkISize& view_size, - const SkIRect& clip_area, - uint8* image_buffer, - int image_stride, - SkRegion* output_region) OVERRIDE; - - private: - enum State { - kUninitialized, - kReady, - kProcessing, - kPartitionDone, - kDone, - kError, - }; - - DecoderRowBased(Decompressor* decompressor, - VideoPacketFormat::Encoding encoding); - - // Helper method. Called from DecodePacket to updated state of the decoder. - void UpdateStateForPacket(const VideoPacket* packet); - - // The internal state of the decoder. - State state_; - - // Keeps track of the updating rect. - SkIRect clip_; - - // The compression for the input byte stream. - scoped_ptr<Decompressor> decompressor_; - - // The encoding of the incoming stream. - VideoPacketFormat::Encoding encoding_; - - // The position in the row that we are updating. - int row_pos_; - - // The current row in the rect that we are updaing. - int row_y_; - - // The region updated that hasn't been copied to the screen yet. - SkRegion updated_region_; - - // Size of the remote screen. - SkISize screen_size_; - - // The bitmap holding the remote screen bits. - scoped_array<uint8> screen_buffer_; - - DISALLOW_COPY_AND_ASSIGN(DecoderRowBased); -}; - -} // namespace remoting - -#endif // REMOTING_BASE_DECODER_ROW_BASED_H_ diff --git a/remoting/base/decoder_vp8.cc b/remoting/base/decoder_vp8.cc deleted file mode 100644 index 74fd8a8..0000000 --- a/remoting/base/decoder_vp8.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2012 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_vp8.h" - -#include <math.h> - -#include "base/logging.h" -#include "media/base/media.h" -#include "media/base/yuv_convert.h" -#include "remoting/base/util.h" - -extern "C" { -#define VPX_CODEC_DISABLE_COMPAT 1 -#include "third_party/libvpx/libvpx.h" -} - -namespace remoting { - -DecoderVp8::DecoderVp8() - : state_(kUninitialized), - codec_(NULL), - last_image_(NULL), - screen_size_(SkISize::Make(0, 0)) { -} - -DecoderVp8::~DecoderVp8() { - if (codec_) { - vpx_codec_err_t ret = vpx_codec_destroy(codec_); - CHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; - } - delete codec_; -} - -void DecoderVp8::Initialize(const SkISize& screen_size) { - DCHECK(!screen_size.isEmpty()); - - screen_size_ = screen_size; - state_ = kReady; -} - -Decoder::DecodeResult DecoderVp8::DecodePacket(const VideoPacket* packet) { - DCHECK_EQ(kReady, state_); - - // Initialize the codec as needed. - if (!codec_) { - codec_ = new vpx_codec_ctx_t(); - - // TODO(hclam): Scale the number of threads with number of cores of the - // machine. - vpx_codec_dec_cfg config; - config.w = 0; - config.h = 0; - config.threads = 2; - vpx_codec_err_t ret = - vpx_codec_dec_init( - codec_, vpx_codec_vp8_dx(), &config, 0); - if (ret != VPX_CODEC_OK) { - LOG(INFO) << "Cannot initialize codec."; - delete codec_; - codec_ = NULL; - state_ = kError; - return DECODE_ERROR; - } - } - - // Do the actual decoding. - vpx_codec_err_t ret = vpx_codec_decode( - codec_, reinterpret_cast<const uint8*>(packet->data().data()), - packet->data().size(), NULL, 0); - if (ret != VPX_CODEC_OK) { - LOG(INFO) << "Decoding failed:" << vpx_codec_err_to_string(ret) << "\n" - << "Details: " << vpx_codec_error(codec_) << "\n" - << vpx_codec_error_detail(codec_); - return DECODE_ERROR; - } - - // Gets the decoded data. - vpx_codec_iter_t iter = NULL; - vpx_image_t* image = vpx_codec_get_frame(codec_, &iter); - if (!image) { - LOG(INFO) << "No video frame decoded"; - return DECODE_ERROR; - } - last_image_ = image; - - SkRegion region; - for (int i = 0; i < packet->dirty_rects_size(); ++i) { - Rect remoting_rect = packet->dirty_rects(i); - SkIRect rect = SkIRect::MakeXYWH(remoting_rect.x(), - remoting_rect.y(), - remoting_rect.width(), - remoting_rect.height()); - region.op(rect, SkRegion::kUnion_Op); - } - - updated_region_.op(region, SkRegion::kUnion_Op); - return DECODE_DONE; -} - -bool DecoderVp8::IsReadyForData() { - return state_ == kReady; -} - -VideoPacketFormat::Encoding DecoderVp8::Encoding() { - return VideoPacketFormat::ENCODING_VP8; -} - -void DecoderVp8::Invalidate(const SkISize& view_size, - const SkRegion& region) { - DCHECK_EQ(kReady, state_); - DCHECK(!view_size.isEmpty()); - - for (SkRegion::Iterator i(region); !i.done(); i.next()) { - SkIRect rect = i.rect(); - rect = ScaleRect(rect, view_size, screen_size_); - updated_region_.op(rect, SkRegion::kUnion_Op); - } -} - -void DecoderVp8::RenderFrame(const SkISize& view_size, - const SkIRect& clip_area, - uint8* image_buffer, - int image_stride, - SkRegion* output_region) { - DCHECK_EQ(kReady, state_); - DCHECK(!view_size.isEmpty()); - - // Early-return and do nothing if we haven't yet decoded any frames. - if (!last_image_) - return; - - SkIRect source_clip = SkIRect::MakeWH(last_image_->d_w, last_image_->d_h); - - // ScaleYUVToRGB32WithRect does not currently support up-scaling. We won't - // be asked to up-scale except during resizes or if page zoom is >100%, so - // we work-around the limitation by using the slower ScaleYUVToRGB32. - // TODO(wez): Remove this hack if/when ScaleYUVToRGB32WithRect can up-scale. - if (!updated_region_.isEmpty() && - (source_clip.width() < view_size.width() || - source_clip.height() < view_size.height())) { - // We're scaling only |clip_area| into the |image_buffer|, so we need to - // work out which source rectangle that corresponds to. - SkIRect source_rect = ScaleRect(clip_area, view_size, screen_size_); - source_rect = SkIRect::MakeLTRB(RoundToTwosMultiple(source_rect.left()), - RoundToTwosMultiple(source_rect.top()), - source_rect.right(), - source_rect.bottom()); - - // If there were no changes within the clip source area then don't render. - if (!updated_region_.intersects(source_rect)) - return; - - // Scale & convert the entire clip area. - int y_offset = CalculateYOffset(source_rect.x(), - source_rect.y(), - last_image_->stride[0]); - int uv_offset = CalculateUVOffset(source_rect.x(), - source_rect.y(), - last_image_->stride[1]); - ScaleYUVToRGB32(last_image_->planes[0] + y_offset, - last_image_->planes[1] + uv_offset, - last_image_->planes[2] + uv_offset, - image_buffer, - source_rect.width(), - source_rect.height(), - clip_area.width(), - clip_area.height(), - last_image_->stride[0], - last_image_->stride[1], - image_stride, - media::YV12, - media::ROTATE_0, - media::FILTER_BILINEAR); - - output_region->op(clip_area, SkRegion::kUnion_Op); - updated_region_.op(source_rect, SkRegion::kDifference_Op); - return; - } - - for (SkRegion::Iterator i(updated_region_); !i.done(); i.next()) { - // Determine the scaled area affected by this rectangle changing. - SkIRect rect = i.rect(); - if (!rect.intersect(source_clip)) - continue; - rect = ScaleRect(rect, screen_size_, view_size); - if (!rect.intersect(clip_area)) - continue; - - ConvertAndScaleYUVToRGB32Rect(last_image_->planes[0], - last_image_->planes[1], - last_image_->planes[2], - last_image_->stride[0], - last_image_->stride[1], - screen_size_, - source_clip, - image_buffer, - image_stride, - view_size, - clip_area, - rect); - - output_region->op(rect, SkRegion::kUnion_Op); - } - - updated_region_.op(ScaleRect(clip_area, view_size, screen_size_), - SkRegion::kDifference_Op); -} - -} // namespace remoting diff --git a/remoting/base/decoder_vp8.h b/remoting/base/decoder_vp8.h deleted file mode 100644 index 53029e2..0000000 --- a/remoting/base/decoder_vp8.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 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_VP8_H_ -#define REMOTING_BASE_DECODER_VP8_H_ - -#include "base/compiler_specific.h" -#include "remoting/base/decoder.h" - -typedef struct vpx_codec_ctx vpx_codec_ctx_t; -typedef struct vpx_image vpx_image_t; - -namespace remoting { - -class DecoderVp8 : public Decoder { - public: - DecoderVp8(); - virtual ~DecoderVp8(); - - // Decoder implementations. - virtual void Initialize(const SkISize& screen_size) OVERRIDE; - virtual DecodeResult DecodePacket(const VideoPacket* packet) OVERRIDE; - virtual bool IsReadyForData() OVERRIDE; - virtual VideoPacketFormat::Encoding Encoding() OVERRIDE; - virtual void Invalidate(const SkISize& view_size, - const SkRegion& region) OVERRIDE; - virtual void RenderFrame(const SkISize& view_size, - const SkIRect& clip_area, - uint8* image_buffer, - int image_stride, - SkRegion* output_region) OVERRIDE; - - private: - enum State { - kUninitialized, - kReady, - kError, - }; - - // The internal state of the decoder. - State state_; - - vpx_codec_ctx_t* codec_; - - // Pointer to the last decoded image. - vpx_image_t* last_image_; - - // The region updated that hasn't been copied to the screen yet. - SkRegion updated_region_; - - // Output dimensions. - SkISize screen_size_; - - DISALLOW_COPY_AND_ASSIGN(DecoderVp8); -}; - -} // namespace remoting - -#endif // REMOTING_BASE_DECODER_VP8_H_ diff --git a/remoting/base/decoder_vp8_unittest.cc b/remoting/base/decoder_vp8_unittest.cc deleted file mode 100644 index 553d27c..0000000 --- a/remoting/base/decoder_vp8_unittest.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2012 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/codec_test.h" -#include "remoting/base/decoder_vp8.h" -#include "remoting/base/encoder_vp8.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -class DecoderVp8Test : public testing::Test { - protected: - EncoderVp8 encoder_; - DecoderVp8 decoder_; - - void TestGradient(int screen_width, int screen_height, - int view_width, int view_height, - double max_error_limit, double mean_error_limit) { - TestEncoderDecoderGradient(&encoder_, &decoder_, - SkISize::Make(screen_width, screen_height), - SkISize::Make(view_width, view_height), - max_error_limit, mean_error_limit); - } -}; - -TEST_F(DecoderVp8Test, EncodeAndDecode) { - TestEncoderDecoder(&encoder_, &decoder_, false); -} - -// Check that encoding and decoding a particular frame doesn't change the -// frame too much. The frame used is a gradient, which does not contain sharp -// transitions, so encoding lossiness should not be too high. -TEST_F(DecoderVp8Test, Gradient) { - TestGradient(320, 240, 320, 240, 0.03, 0.01); -} - -TEST_F(DecoderVp8Test, GradientScaleUpEvenToEven) { - TestGradient(320, 240, 640, 480, 0.04, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleUpEvenToOdd) { - TestGradient(320, 240, 641, 481, 0.04, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleUpOddToEven) { - TestGradient(321, 241, 640, 480, 0.04, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleUpOddToOdd) { - TestGradient(321, 241, 641, 481, 0.04, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleDownEvenToEven) { - TestGradient(320, 240, 160, 120, 0.04, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleDownEvenToOdd) { - // The maximum error is non-deterministic. The mean error is not too high, - // which suggests that the problem is restricted to a small area of the output - // image. See crbug.com/139437 and crbug.com/139633. - TestGradient(320, 240, 161, 121, 1.0, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleDownOddToEven) { - TestGradient(321, 241, 160, 120, 0.04, 0.02); -} - -TEST_F(DecoderVp8Test, GradientScaleDownOddToOdd) { - TestGradient(321, 241, 161, 121, 0.04, 0.02); -} - -} // namespace remoting diff --git a/remoting/base/encode_decode_unittest.cc b/remoting/base/encode_decode_unittest.cc deleted file mode 100644 index 10baf7c..0000000 --- a/remoting/base/encode_decode_unittest.cc +++ /dev/null @@ -1,31 +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/base/codec_test.h" -#include "remoting/base/decoder_row_based.h" -#include "remoting/base/encoder_row_based.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -TEST(EncodeDecodeTest, EncodeAndDecodeZlib) { - scoped_ptr<EncoderRowBased> encoder(EncoderRowBased::CreateZlibEncoder()); - scoped_ptr<DecoderRowBased> decoder(DecoderRowBased::CreateZlibDecoder()); - TestEncoderDecoder(encoder.get(), decoder.get(), true); -} - -TEST(EncodeDecodeTest, EncodeAndDecodeSmallOutputBufferZlib) { - scoped_ptr<EncoderRowBased> encoder(EncoderRowBased::CreateZlibEncoder(64)); - scoped_ptr<DecoderRowBased> decoder(DecoderRowBased::CreateZlibDecoder()); - TestEncoderDecoder(encoder.get(), decoder.get(), true); -} - -TEST(EncodeDecodeTest, EncodeAndDecodeNoneStrictZlib) { - scoped_ptr<EncoderRowBased> encoder(EncoderRowBased::CreateZlibEncoder()); - scoped_ptr<DecoderRowBased> decoder(DecoderRowBased::CreateZlibDecoder()); - TestEncoderDecoder(encoder.get(), decoder.get(), false); -} - -} // namespace remoting diff --git a/remoting/base/encoder.h b/remoting/base/encoder.h deleted file mode 100644 index ae6fadc..0000000 --- a/remoting/base/encoder.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 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" - -namespace media { - class DataBuffer; -} - -namespace remoting { - -class CaptureData; -class VideoPacket; - -// A class to perform the task of encoding a continous stream of -// images. -// This class operates asynchronously to enable maximum throughput. -class Encoder { - public: - - // 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. - typedef base::Callback<void(scoped_ptr<VideoPacket>)> 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<CaptureData> capture_data, - bool key_frame, - const DataAvailableCallback& data_available_callback) = 0; -}; - -} // namespace remoting - -#endif // REMOTING_BASE_ENCODER_H_ diff --git a/remoting/base/encoder_row_based.cc b/remoting/base/encoder_row_based.cc deleted file mode 100644 index c28c06c..0000000 --- a/remoting/base/encoder_row_based.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2012 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_row_based.h" - -#include "base/logging.h" -#include "remoting/base/capture_data.h" -#include "remoting/base/compressor_verbatim.h" -#include "remoting/base/compressor_zlib.h" -#include "remoting/base/util.h" -#include "remoting/proto/video.pb.h" - -namespace remoting { - -static const int kPacketSize = 1024 * 1024; - -EncoderRowBased* EncoderRowBased::CreateZlibEncoder() { - return new EncoderRowBased(new CompressorZlib(), - VideoPacketFormat::ENCODING_ZLIB); -} - -EncoderRowBased* EncoderRowBased::CreateZlibEncoder(int packet_size) { - return new EncoderRowBased(new CompressorZlib(), - VideoPacketFormat::ENCODING_ZLIB, - packet_size); -} - -EncoderRowBased* EncoderRowBased::CreateVerbatimEncoder() { - return new EncoderRowBased(new CompressorVerbatim(), - VideoPacketFormat::ENCODING_VERBATIM); -} - -EncoderRowBased* EncoderRowBased::CreateVerbatimEncoder(int packet_size) { - return new EncoderRowBased(new CompressorVerbatim(), - VideoPacketFormat::ENCODING_VERBATIM, - packet_size); -} - -EncoderRowBased::EncoderRowBased(Compressor* compressor, - VideoPacketFormat::Encoding encoding) - : encoding_(encoding), - compressor_(compressor), - screen_size_(SkISize::Make(0,0)), - packet_size_(kPacketSize) { -} - -EncoderRowBased::EncoderRowBased(Compressor* compressor, - VideoPacketFormat::Encoding encoding, - int packet_size) - : encoding_(encoding), - compressor_(compressor), - screen_size_(SkISize::Make(0,0)), - packet_size_(packet_size) { -} - -EncoderRowBased::~EncoderRowBased() {} - -void EncoderRowBased::Encode( - scoped_refptr<CaptureData> capture_data, - bool key_frame, - const DataAvailableCallback& data_available_callback) { - CHECK(capture_data->pixel_format() == media::VideoFrame::RGB32) - << "RowBased Encoder only works with RGB32. Got " - << capture_data->pixel_format(); - capture_data_ = capture_data; - callback_ = data_available_callback; - - const SkRegion& region = capture_data->dirty_region(); - SkRegion::Iterator iter(region); - while (!iter.done()) { - SkIRect rect = iter.rect(); - iter.next(); - EncodeRect(rect, iter.done()); - } - - capture_data_ = NULL; - callback_.Reset(); -} - -void EncoderRowBased::EncodeRect(const SkIRect& rect, bool last) { - CHECK(capture_data_->data_planes().data[0]); - CHECK_EQ(capture_data_->pixel_format(), media::VideoFrame::RGB32); - const int strides = capture_data_->data_planes().strides[0]; - const int bytes_per_pixel = 4; - const int row_size = bytes_per_pixel * rect.width(); - - compressor_->Reset(); - - scoped_ptr<VideoPacket> packet(new VideoPacket()); - PrepareUpdateStart(rect, packet.get()); - const uint8* in = capture_data_->data_planes().data[0] + - rect.fTop * strides + rect.fLeft * bytes_per_pixel; - // TODO(hclam): Fill in the sequence number. - uint8* out = GetOutputBuffer(packet.get(), packet_size_); - int filled = 0; - int row_pos = 0; // Position in the current row in bytes. - int row_y = 0; // Current row. - bool compress_again = true; - while (compress_again) { - // Prepare a message for sending out. - if (!packet.get()) { - packet.reset(new VideoPacket()); - out = GetOutputBuffer(packet.get(), packet_size_); - filled = 0; - } - - Compressor::CompressorFlush flush = Compressor::CompressorNoFlush; - if (row_y == rect.height() - 1) { - flush = Compressor::CompressorFinish; - } - - int consumed = 0; - int written = 0; - compress_again = compressor_->Process(in + row_pos, row_size - row_pos, - out + filled, packet_size_ - filled, - flush, &consumed, &written); - row_pos += consumed; - filled += written; - - // We have reached the end of stream. - if (!compress_again) { - packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET); - packet->set_capture_time_ms(capture_data_->capture_time_ms()); - packet->set_client_sequence_number( - capture_data_->client_sequence_number()); - SkIPoint dpi(capture_data_->dpi()); - if (dpi.x()) - packet->mutable_format()->set_x_dpi(dpi.x()); - if (dpi.y()) - packet->mutable_format()->set_y_dpi(dpi.y()); - if (last) - packet->set_flags(packet->flags() | VideoPacket::LAST_PARTITION); - DCHECK(row_pos == row_size); - DCHECK(row_y == rect.height() - 1); - } - - // If we have filled the message or we have reached the end of stream. - if (filled == packet_size_ || !compress_again) { - packet->mutable_data()->resize(filled); - callback_.Run(packet.Pass()); - } - - // Reached the end of input row and we're not at the last row. - if (row_pos == row_size && row_y < rect.height() - 1) { - row_pos = 0; - in += strides; - ++row_y; - } - } -} - -void EncoderRowBased::PrepareUpdateStart(const SkIRect& rect, - VideoPacket* packet) { - packet->set_flags(packet->flags() | VideoPacket::FIRST_PACKET); - - VideoPacketFormat* format = packet->mutable_format(); - format->set_x(rect.fLeft); - format->set_y(rect.fTop); - format->set_width(rect.width()); - format->set_height(rect.height()); - format->set_encoding(encoding_); - if (capture_data_->size() != screen_size_) { - screen_size_ = capture_data_->size(); - format->set_screen_width(screen_size_.width()); - format->set_screen_height(screen_size_.height()); - } -} - -uint8* EncoderRowBased::GetOutputBuffer(VideoPacket* packet, size_t size) { - packet->mutable_data()->resize(size); - // TODO(ajwong): Is there a better way to do this at all??? - return const_cast<uint8*>(reinterpret_cast<const uint8*>( - packet->mutable_data()->data())); -} - -} // namespace remoting diff --git a/remoting/base/encoder_row_based.h b/remoting/base/encoder_row_based.h deleted file mode 100644 index 5d8a877..0000000 --- a/remoting/base/encoder_row_based.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2011 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_ROW_BASED_H_ -#define REMOTING_BASE_ENCODER_ROW_BASED_H_ - -#include "remoting/base/encoder.h" -#include "remoting/proto/video.pb.h" -#include "third_party/skia/include/core/SkRect.h" - -namespace remoting { - -class Compressor; - -// EncoderRowBased implements an Encoder using zlib or verbatim -// compression. Zlib-based encoder must be created using -// CreateZlibEncoder(), verbatim encoder is created with -// CreateVerbatimEncoder(). -// -// Compressor is reset before encoding each rectangle, so that each -// rectangle can be decoded independently. -class EncoderRowBased : public Encoder { - public: - static EncoderRowBased* CreateZlibEncoder(); - static EncoderRowBased* CreateZlibEncoder(int packet_size); - static EncoderRowBased* CreateVerbatimEncoder(); - static EncoderRowBased* CreateVerbatimEncoder(int packet_size); - - virtual ~EncoderRowBased(); - - virtual void Encode( - scoped_refptr<CaptureData> capture_data, - bool key_frame, - const DataAvailableCallback& data_available_callback) OVERRIDE; - - private: - EncoderRowBased(Compressor* compressor, VideoPacketFormat::Encoding encoding); - EncoderRowBased(Compressor* compressor, VideoPacketFormat::Encoding encoding, - int packet_size); - - // Encode a single dirty rect using compressor. - void EncodeRect(const SkIRect& rect, bool last); - - // Marks a packet as the first in a series of rectangle updates. - void PrepareUpdateStart(const SkIRect& rect, VideoPacket* packet); - - // Retrieves a pointer to the output buffer in |update| used for storing the - // encoded rectangle data. Will resize the buffer to |size|. - uint8* GetOutputBuffer(VideoPacket* packet, size_t size); - - // Submit |message| to |callback_|. - void SubmitMessage(VideoPacket* packet, size_t rect_index); - - // The encoding of the incoming stream. - VideoPacketFormat::Encoding encoding_; - - scoped_ptr<Compressor> compressor_; - - scoped_refptr<CaptureData> capture_data_; - DataAvailableCallback callback_; - - // The most recent screen size. - SkISize screen_size_; - - int packet_size_; -}; - -} // namespace remoting - -#endif // REMOTING_BASE_ENCODER_ROW_BASED_H_ diff --git a/remoting/base/encoder_row_based_unittest.cc b/remoting/base/encoder_row_based_unittest.cc deleted file mode 100644 index 735e806..0000000 --- a/remoting/base/encoder_row_based_unittest.cc +++ /dev/null @@ -1,21 +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/base/codec_test.h" -#include "remoting/base/encoder_row_based.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -TEST(EncoderZlibTest, TestEncoder) { - scoped_ptr<EncoderRowBased> encoder(EncoderRowBased::CreateZlibEncoder()); - TestEncoder(encoder.get(), true); -} - -TEST(EncoderZlibTest, TestEncoderSmallOutputBuffer) { - scoped_ptr<EncoderRowBased> encoder(EncoderRowBased::CreateZlibEncoder(16)); - TestEncoder(encoder.get(), true); -} - -} // namespace remoting diff --git a/remoting/base/encoder_vp8.cc b/remoting/base/encoder_vp8.cc deleted file mode 100644 index f329948..0000000 --- a/remoting/base/encoder_vp8.cc +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright (c) 2012 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_vp8.h" - -#include "base/logging.h" -#include "base/sys_info.h" -#include "media/base/yuv_convert.h" -#include "remoting/base/capture_data.h" -#include "remoting/base/util.h" -#include "remoting/proto/video.pb.h" - -extern "C" { -#define VPX_CODEC_DISABLE_COMPAT 1 -#include "third_party/libvpx/libvpx.h" -} - -namespace { - -// Defines the dimension of a macro block. This is used to compute the active -// map for the encoder. -const int kMacroBlockSize = 16; - -} // namespace remoting - -namespace remoting { - -EncoderVp8::EncoderVp8() - : initialized_(false), - codec_(NULL), - image_(NULL), - active_map_width_(0), - active_map_height_(0), - last_timestamp_(0) { -} - -EncoderVp8::~EncoderVp8() { - Destroy(); -} - -void EncoderVp8::Destroy() { - if (initialized_) { - vpx_codec_err_t ret = vpx_codec_destroy(codec_.get()); - DCHECK(ret == VPX_CODEC_OK) << "Failed to destroy codec"; - initialized_ = false; - } -} - -bool EncoderVp8::Init(const SkISize& size) { - Destroy(); - codec_.reset(new vpx_codec_ctx_t()); - image_.reset(new vpx_image_t()); - memset(image_.get(), 0, sizeof(vpx_image_t)); - - image_->fmt = VPX_IMG_FMT_YV12; - - // libvpx seems to require both to be assigned. - image_->d_w = size.width(); - image_->w = size.width(); - image_->d_h = size.height(); - image_->h = size.height(); - - // Initialize active map. - active_map_width_ = (image_->w + kMacroBlockSize - 1) / kMacroBlockSize; - active_map_height_ = (image_->h + kMacroBlockSize - 1) / kMacroBlockSize; - active_map_.reset(new uint8[active_map_width_ * active_map_height_]); - - // YUV image size is 1.5 times of a plane. Multiplication is performed first - // to avoid rounding error. - const int y_plane_size = image_->w * image_->h; - const int uv_width = (image_->w + 1) / 2; - const int uv_height = (image_->w + 1) / 2; - const int uv_plane_size = uv_width * uv_height; - const int yuv_image_size = y_plane_size + uv_plane_size * 2; - - // libvpx may try to access memory after the buffer (it still - // doesn't use it) - it copies the data in 16x16 blocks: - // crbug.com/119633 . Here we workaround that problem by adding - // padding at the end of the buffer. Overreading to U and V buffers - // is safe so the padding is necessary only at the end. - // - // TODO(sergeyu): Remove this padding when the bug is fixed in libvpx. - const int active_map_area = active_map_width_ * kMacroBlockSize * - active_map_height_ * kMacroBlockSize; - const int padding_size = active_map_area - y_plane_size; - const int buffer_size = yuv_image_size + padding_size; - - yuv_image_.reset(new uint8[buffer_size]); - - // Reset image value to 128 so we just need to fill in the y plane. - memset(yuv_image_.get(), 128, yuv_image_size); - - // Fill in the information for |image_|. - unsigned char* image = reinterpret_cast<unsigned char*>(yuv_image_.get()); - image_->planes[0] = image; - image_->planes[1] = image + y_plane_size; - image_->planes[2] = image + y_plane_size + uv_plane_size; - image_->stride[0] = image_->w; - image_->stride[1] = uv_width; - image_->stride[2] = uv_width; - - // Configure the encoder. - vpx_codec_enc_cfg_t config; - const vpx_codec_iface_t* algo = vpx_codec_vp8_cx(); - CHECK(algo); - vpx_codec_err_t ret = vpx_codec_enc_config_default(algo, &config, 0); - if (ret != VPX_CODEC_OK) - return false; - - config.rc_target_bitrate = image_->w * image_->h * - config.rc_target_bitrate / config.g_w / config.g_h; - config.g_w = image_->w; - config.g_h = image_->h; - config.g_pass = VPX_RC_ONE_PASS; - - // Value of 2 means using the real time profile. This is basically a - // redundant option since we explicitly select real time mode when doing - // encoding. - config.g_profile = 2; - - // Using 2 threads gives a great boost in performance for most systems with - // adequate processing power. NB: Going to multiple threads on low end - // windows systems can really hurt performance. - // http://crbug.com/99179 - config.g_threads = (base::SysInfo::NumberOfProcessors() > 2) ? 2 : 1; - config.rc_min_quantizer = 20; - config.rc_max_quantizer = 30; - config.g_timebase.num = 1; - config.g_timebase.den = 20; - - if (vpx_codec_enc_init(codec_.get(), algo, &config, 0)) - return false; - - // Value of 16 will have the smallest CPU load. This turns off subpixel - // motion search. - if (vpx_codec_control(codec_.get(), VP8E_SET_CPUUSED, 16)) - return false; - - // Use the lowest level of noise sensitivity so as to spend less time - // on motion estimation and inter-prediction mode. - if (vpx_codec_control(codec_.get(), VP8E_SET_NOISE_SENSITIVITY, 0)) - return false; - return true; -} - -void EncoderVp8::PrepareImage(scoped_refptr<CaptureData> capture_data, - SkRegion* updated_region) { - // Perform RGB->YUV conversion. - CHECK_EQ(capture_data->pixel_format(), media::VideoFrame::RGB32) - << "Only RGB32 is supported"; - - const SkRegion& region = capture_data->dirty_region(); - if (region.isEmpty()) { - updated_region->setEmpty(); - return; - } - - // Align the region to macroblocks, to avoid encoding artefacts. - // This also ensures that all rectangles have even-aligned top-left, which - // is required for ConvertRGBToYUVWithRect() to work. - std::vector<SkIRect> aligned_rects; - for (SkRegion::Iterator r(region); !r.done(); r.next()) { - aligned_rects.push_back(AlignRect(r.rect())); - } - DCHECK(!aligned_rects.empty()); - updated_region->setRects(&aligned_rects[0], aligned_rects.size()); - - // Clip back to the screen dimensions, in case they're not macroblock aligned. - // The conversion routines don't require even width & height, so this is safe - // even if the source dimensions are not even. - updated_region->op(SkIRect::MakeWH(image_->w, image_->h), - SkRegion::kIntersect_Op); - - // Convert the updated region to YUV ready for encoding. - const uint8* rgb_data = capture_data->data_planes().data[0]; - const int rgb_stride = capture_data->data_planes().strides[0]; - const int y_stride = image_->stride[0]; - DCHECK(image_->stride[1] == image_->stride[2]); - const int uv_stride = image_->stride[1]; - uint8* y_data = image_->planes[0]; - uint8* u_data = image_->planes[1]; - uint8* v_data = image_->planes[2]; - for (SkRegion::Iterator r(*updated_region); !r.done(); r.next()) { - const SkIRect& rect = r.rect(); - ConvertRGB32ToYUVWithRect( - rgb_data, y_data, u_data, v_data, - rect.x(), rect.y(), rect.width(), rect.height(), - rgb_stride, y_stride, uv_stride); - } -} - -void EncoderVp8::PrepareActiveMap(const SkRegion& updated_region) { - // Clear active map first. - memset(active_map_.get(), 0, active_map_width_ * active_map_height_); - - // Mark updated areas active. - for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) { - const SkIRect& rect = r.rect(); - int left = rect.left() / kMacroBlockSize; - int right = (rect.right() - 1) / kMacroBlockSize; - int top = rect.top() / kMacroBlockSize; - int bottom = (rect.bottom() - 1) / kMacroBlockSize; - CHECK(right < active_map_width_); - CHECK(bottom < active_map_height_); - - uint8* map = active_map_.get() + top * active_map_width_; - for (int y = top; y <= bottom; ++y) { - for (int x = left; x <= right; ++x) - map[x] = 1; - map += active_map_width_; - } - } -} - -void EncoderVp8::Encode(scoped_refptr<CaptureData> capture_data, - bool key_frame, - const DataAvailableCallback& data_available_callback) { - DCHECK_LE(32, capture_data->size().width()); - DCHECK_LE(32, capture_data->size().height()); - - if (!initialized_ || - (capture_data->size() != SkISize::Make(image_->w, image_->h))) { - bool ret = Init(capture_data->size()); - // TODO(hclam): Handle error better. - CHECK(ret) << "Initialization of encoder failed"; - initialized_ = ret; - } - - // Convert the updated capture data ready for encode. - SkRegion updated_region; - PrepareImage(capture_data, &updated_region); - - // Update active map based on updated region. - PrepareActiveMap(updated_region); - - // Apply active map to the encoder. - vpx_active_map_t act_map; - act_map.rows = active_map_height_; - act_map.cols = active_map_width_; - act_map.active_map = active_map_.get(); - if (vpx_codec_control(codec_.get(), VP8E_SET_ACTIVEMAP, &act_map)) { - LOG(ERROR) << "Unable to apply active map"; - } - - // Do the actual encoding. - vpx_codec_err_t ret = vpx_codec_encode(codec_.get(), image_.get(), - last_timestamp_, - 1, 0, VPX_DL_REALTIME); - DCHECK_EQ(ret, VPX_CODEC_OK) - << "Encoding error: " << vpx_codec_err_to_string(ret) << "\n" - << "Details: " << vpx_codec_error(codec_.get()) << "\n" - << vpx_codec_error_detail(codec_.get()); - - // TODO(hclam): Apply the proper timestamp here. - last_timestamp_ += 50; - - // Read the encoded data. - vpx_codec_iter_t iter = NULL; - bool got_data = false; - - // TODO(hclam): Make sure we get exactly one frame from the packet. - // TODO(hclam): We should provide the output buffer to avoid one copy. - scoped_ptr<VideoPacket> packet(new VideoPacket()); - - while (!got_data) { - const vpx_codec_cx_pkt_t* vpx_packet = vpx_codec_get_cx_data(codec_.get(), - &iter); - if (!vpx_packet) - continue; - - switch (vpx_packet->kind) { - case VPX_CODEC_CX_FRAME_PKT: - got_data = true; - // TODO(sergeyu): Split each frame into multiple partitions. - packet->set_data(vpx_packet->data.frame.buf, vpx_packet->data.frame.sz); - break; - default: - break; - } - } - - // Construct the VideoPacket message. - packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VP8); - packet->set_flags(VideoPacket::FIRST_PACKET | VideoPacket::LAST_PACKET | - VideoPacket::LAST_PARTITION); - packet->mutable_format()->set_screen_width(capture_data->size().width()); - packet->mutable_format()->set_screen_height(capture_data->size().height()); - packet->set_capture_time_ms(capture_data->capture_time_ms()); - packet->set_client_sequence_number(capture_data->client_sequence_number()); - SkIPoint dpi(capture_data->dpi()); - if (dpi.x()) - packet->mutable_format()->set_x_dpi(dpi.x()); - if (dpi.y()) - packet->mutable_format()->set_y_dpi(dpi.y()); - for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) { - Rect* rect = packet->add_dirty_rects(); - rect->set_x(r.rect().x()); - rect->set_y(r.rect().y()); - rect->set_width(r.rect().width()); - rect->set_height(r.rect().height()); - } - - data_available_callback.Run(packet.Pass()); -} - -} // namespace remoting diff --git a/remoting/base/encoder_vp8.h b/remoting/base/encoder_vp8.h deleted file mode 100644 index b9883a5..0000000 --- a/remoting/base/encoder_vp8.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2012 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 "base/gtest_prod_util.h" -#include "remoting/base/encoder.h" -#include "third_party/skia/include/core/SkRegion.h" - -typedef struct vpx_codec_ctx vpx_codec_ctx_t; -typedef struct vpx_image vpx_image_t; - -namespace remoting { - -// A class that uses VP8 to perform encoding. -class EncoderVp8 : public Encoder { - public: - EncoderVp8(); - virtual ~EncoderVp8(); - - virtual void Encode( - scoped_refptr<CaptureData> capture_data, - bool key_frame, - const DataAvailableCallback& data_available_callback) OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(EncoderVp8Test, AlignAndClipRect); - - // Initialize the encoder. Returns true if successful. - bool Init(const SkISize& size); - - // Destroy the encoder. - void Destroy(); - - // Prepare |image_| for encoding. Write updated rectangles into - // |updated_region|. - void PrepareImage(scoped_refptr<CaptureData> capture_data, - SkRegion* updated_region); - - // Update the active map according to |updated_region|. Active map is then - // given to the encoder to speed up encoding. - void PrepareActiveMap(const SkRegion& updated_region); - - // True if the encoder is initialized. - bool initialized_; - - scoped_ptr<vpx_codec_ctx_t> codec_; - scoped_ptr<vpx_image_t> image_; - scoped_array<uint8> active_map_; - int active_map_width_; - int active_map_height_; - int last_timestamp_; - - // Buffer for storing the yuv image. - scoped_array<uint8> yuv_image_; - - 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 deleted file mode 100644 index 635284b..0000000 --- a/remoting/base/encoder_vp8_unittest.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 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 <limits> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "remoting/base/capture_data.h" -#include "remoting/base/codec_test.h" -#include "remoting/base/encoder_vp8.h" -#include "remoting/proto/video.pb.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const int kIntMax = std::numeric_limits<int>::max(); - -} // namespace - -namespace remoting { - -TEST(EncoderVp8Test, TestEncoder) { - EncoderVp8 encoder; - TestEncoder(&encoder, false); -} - -class EncoderCallback { - public: - void DataAvailable(scoped_ptr<VideoPacket> packet) { - } -}; - -// Test that calling Encode with a differently-sized CaptureData does not -// leak memory. -TEST(EncoderVp8Test, TestSizeChangeNoLeak) { - int height = 1000; - int width = 1000; - const int kBytesPerPixel = 4; - - EncoderVp8 encoder; - EncoderCallback callback; - - std::vector<uint8> buffer(width * height * kBytesPerPixel); - DataPlanes planes; - planes.data[0] = &buffer.front(); - planes.strides[0] = width; - - scoped_refptr<CaptureData> capture_data(new CaptureData( - planes, SkISize::Make(width, height), media::VideoFrame::RGB32)); - encoder.Encode(capture_data, false, - base::Bind(&EncoderCallback::DataAvailable, - base::Unretained(&callback))); - - height /= 2; - capture_data = new CaptureData(planes, SkISize::Make(width, height), - media::VideoFrame::RGB32); - encoder.Encode(capture_data, false, - base::Bind(&EncoderCallback::DataAvailable, - base::Unretained(&callback))); -} - -class EncoderDpiCallback { - public: - void DataAvailable(scoped_ptr<VideoPacket> packet) { - EXPECT_EQ(packet->format().x_dpi(), 96); - EXPECT_EQ(packet->format().y_dpi(), 97); - } -}; - -// Test that the DPI information is correctly propagated from the CaptureData -// to the VideoPacket. -TEST(EncoderVp8Test, TestDpiPropagation) { - int height = 32; - int width = 32; - const int kBytesPerPixel = 4; - - EncoderVp8 encoder; - EncoderDpiCallback callback; - - std::vector<uint8> buffer(width * height * kBytesPerPixel); - DataPlanes planes; - planes.data[0] = &buffer.front(); - planes.strides[0] = width; - - scoped_refptr<CaptureData> capture_data(new CaptureData( - planes, SkISize::Make(width, height), media::VideoFrame::RGB32)); - capture_data->set_dpi(SkIPoint::Make(96, 97)); - encoder.Encode(capture_data, false, - base::Bind(&EncoderDpiCallback::DataAvailable, - base::Unretained(&callback))); -} - -} // namespace remoting |