summaryrefslogtreecommitdiffstats
path: root/remoting/codec
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-16 10:45:24 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-16 10:45:24 +0000
commitb9ed58f046141b4610c1bdc966d962d5fb95ac6b (patch)
treeb7dc10e49ea765b6ebc99985d3538a2e1363942e /remoting/codec
parentc1c88cf23606dd1ca2bfd9f57496aeec847e713f (diff)
downloadchromium_src-b9ed58f046141b4610c1bdc966d962d5fb95ac6b.zip
chromium_src-b9ed58f046141b4610c1bdc966d962d5fb95ac6b.tar.gz
chromium_src-b9ed58f046141b4610c1bdc966d962d5fb95ac6b.tar.bz2
Use webrtc::DesktopCapturer for screen capturer implementation.
Screen capturers are being moved from media/video/capture/screen to third_party/webrtc. This CL is an intermediate step in that process. Depends on https://webrtc-codereview.appspot.com/1322007/ TBR=brettw@chromium.org (third_party/webrtc dependency) Review URL: https://chromiumcodereview.appspot.com/13983010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200504 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/codec')
-rw-r--r--remoting/codec/DEPS1
-rw-r--r--remoting/codec/codec_test.cc237
-rw-r--r--remoting/codec/codec_test.h10
-rw-r--r--remoting/codec/video_decoder_vp8_unittest.cc10
-rw-r--r--remoting/codec/video_encoder.h27
-rw-r--r--remoting/codec/video_encoder_verbatim.cc65
-rw-r--r--remoting/codec/video_encoder_verbatim.h16
-rw-r--r--remoting/codec/video_encoder_vp8.cc53
-rw-r--r--remoting/codec/video_encoder_vp8.h14
-rw-r--r--remoting/codec/video_encoder_vp8_unittest.cc35
10 files changed, 237 insertions, 231 deletions
diff --git a/remoting/codec/DEPS b/remoting/codec/DEPS
index 61e5c26..913ea7d 100644
--- a/remoting/codec/DEPS
+++ b/remoting/codec/DEPS
@@ -5,4 +5,5 @@ include_rules = [
"+google/protobuf",
"+third_party/opus",
"+third_party/speex",
+ "+third_party/webrtc",
]
diff --git a/remoting/codec/codec_test.cc b/remoting/codec/codec_test.cc
index af8b11b..efcc872 100644
--- a/remoting/codec/codec_test.cc
+++ b/remoting/codec/codec_test.cc
@@ -14,27 +14,33 @@
#include "remoting/codec/video_encoder.h"
#include "remoting/base/util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+
+using webrtc::DesktopRect;
+using webrtc::DesktopSize;
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()));
+std::vector<std::vector<DesktopRect> > MakeTestRectLists(DesktopSize size) {
+ std::vector<std::vector<DesktopRect> > rect_lists;
+ std::vector<DesktopRect> rects;
+ rects.push_back(DesktopRect::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));
+ rects.push_back(DesktopRect::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));
+ rects.push_back(DesktopRect::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));
+ rects.push_back(DesktopRect::MakeXYWH(16, 16, 16, 16));
+ rects.push_back(DesktopRect::MakeXYWH(128, 64, 32, 32));
rect_lists.push_back(rects);
return rect_lists;
}
@@ -72,10 +78,10 @@ class VideoEncoderMessageTester {
++begin_rect_;
if (strict_) {
- SkIRect rect = rects_.front();
+ DesktopRect rect = rects_.front();
rects_.pop_front();
- EXPECT_EQ(rect.fLeft, packet->format().x());
- EXPECT_EQ(rect.fTop, packet->format().y());
+ EXPECT_EQ(rect.left(), packet->format().x());
+ EXPECT_EQ(rect.top(), packet->format().y());
EXPECT_EQ(rect.width(), packet->format().width());
EXPECT_EQ(rect.height(), packet->format().height());
}
@@ -107,7 +113,7 @@ class VideoEncoderMessageTester {
strict_ = strict;
}
- void AddRects(const SkIRect* rects, int count) {
+ void AddRects(const DesktopRect* rects, int count) {
rects_.insert(rects_.begin() + rects_.size(), rects, rects + count);
added_rects_ += count;
}
@@ -125,15 +131,16 @@ class VideoEncoderMessageTester {
State state_;
bool strict_;
- std::deque<SkIRect> rects_;
+ std::deque<DesktopRect> rects_;
DISALLOW_COPY_AND_ASSIGN(VideoEncoderMessageTester);
};
class VideoDecoderTester {
public:
- VideoDecoderTester(VideoDecoder* decoder, const SkISize& screen_size,
- const SkISize& view_size)
+ VideoDecoderTester(VideoDecoder* decoder,
+ const DesktopSize& screen_size,
+ const DesktopSize& view_size)
: screen_size_(screen_size),
view_size_(view_size),
strict_(false),
@@ -141,11 +148,12 @@ class VideoDecoderTester {
image_data_.reset(new uint8[
view_size_.width() * view_size_.height() * kBytesPerPixel]);
EXPECT_TRUE(image_data_.get());
- decoder_->Initialize(screen_size_);
+ decoder_->Initialize(
+ SkISize::Make(screen_size_.width(), screen_size_.height()));
}
void Reset() {
- expected_region_.setEmpty();
+ expected_region_.Clear();
update_region_.setEmpty();
}
@@ -165,11 +173,12 @@ class VideoDecoderTester {
}
void RenderFrame() {
- decoder_->RenderFrame(view_size_,
- SkIRect::MakeSize(view_size_),
- image_data_.get(),
- view_size_.width() * kBytesPerPixel,
- &update_region_);
+ decoder_->RenderFrame(
+ SkISize::Make(view_size_.width(), view_size_.height()),
+ SkIRect::MakeWH(view_size_.width(), view_size_.height()),
+ image_data_.get(),
+ view_size_.width() * kBytesPerPixel,
+ &update_region_);
}
void ReceivedScopedPacket(scoped_ptr<VideoPacket> packet) {
@@ -180,34 +189,46 @@ class VideoDecoderTester {
strict_ = strict;
}
- void set_capture_data(scoped_refptr<media::ScreenCaptureData> data) {
- capture_data_ = data;
+ void set_frame(webrtc::DesktopFrame* frame) {
+ frame_ = frame;
}
- void AddRects(const SkIRect* rects, int count) {
- SkRegion new_rects;
- new_rects.setRects(rects, count);
- AddRegion(new_rects);
+ void AddRects(const DesktopRect* rects, int count) {
+ for (int i = 0; i < count; ++i) {
+ expected_region_.AddRect(rects[i]);
+ }
}
- void AddRegion(const SkRegion& region) {
- expected_region_.op(region, SkRegion::kUnion_Op);
+ void AddRegion(const webrtc::DesktopRegion& region) {
+ expected_region_.AddRegion(region);
}
void VerifyResults() {
if (!strict_)
return;
- ASSERT_TRUE(capture_data_.get());
+ ASSERT_TRUE(frame_);
// Test the content of the update region.
- EXPECT_EQ(expected_region_, update_region_);
+ //
+ // TODO(sergeyu): Change this to use DesktopRegion when it's capable of
+ // merging the rectangles.
+ SkRegion expected_region;
+ for (webrtc::DesktopRegion::Iterator it(expected_region_);
+ !it.IsAtEnd(); it.Advance()) {
+ expected_region.op(
+ SkIRect::MakeXYWH(it.rect().top(), it.rect().left(),
+ it.rect().width(), it.rect().height()),
+ SkRegion::kUnion_Op);
+ }
+ 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_->stride());
+ EXPECT_EQ(stride, frame_->stride());
const int offset = stride * i.rect().top() +
kBytesPerPixel * i.rect().left();
- const uint8* original = capture_data_->data() + offset;
+ const uint8* original = frame_->data() + 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) {
@@ -265,14 +286,14 @@ class VideoDecoderTester {
}
private:
- SkISize screen_size_;
- SkISize view_size_;
+ DesktopSize screen_size_;
+ DesktopSize view_size_;
bool strict_;
- SkRegion expected_region_;
+ webrtc::DesktopRegion expected_region_;
SkRegion update_region_;
VideoDecoder* decoder_;
scoped_ptr<uint8[]> image_data_;
- scoped_refptr<media::ScreenCaptureData> capture_data_;
+ webrtc::DesktopFrame* frame_;
DISALLOW_COPY_AND_ASSIGN(VideoDecoderTester);
};
@@ -301,7 +322,7 @@ class VideoEncoderTester {
}
}
- void AddRects(const SkIRect* rects, int count) {
+ void AddRects(const DesktopRect* rects, int count) {
message_tester_->AddRects(rects, count);
}
@@ -317,34 +338,30 @@ class VideoEncoderTester {
DISALLOW_COPY_AND_ASSIGN(VideoEncoderTester);
};
-scoped_refptr<media::ScreenCaptureData> PrepareEncodeData(
- const SkISize& size,
- scoped_ptr<uint8[]>* memory) {
- int memory_size = size.width() * size.height() * kBytesPerPixel;
-
- memory->reset(new uint8[memory_size]);
+scoped_ptr<webrtc::DesktopFrame> PrepareFrame(const DesktopSize& size) {
+ scoped_ptr<webrtc::DesktopFrame> frame(new webrtc::BasicDesktopFrame(size));
srand(0);
+ int memory_size = size.width() * size.height() * kBytesPerPixel;
for (int i = 0; i < memory_size; ++i) {
- (*memory)[i] = rand() % 256;
+ frame->data()[i] = rand() % 256;
}
- scoped_refptr<media::ScreenCaptureData> data = new media::ScreenCaptureData(
- memory->get(), size.width() * kBytesPerPixel, size);
- return data;
+ return frame.Pass();
}
static void TestEncodingRects(VideoEncoder* encoder,
VideoEncoderTester* tester,
- scoped_refptr<media::ScreenCaptureData> data,
- const SkIRect* rects, int count) {
- data->mutable_dirty_region().setEmpty();
+ webrtc::DesktopFrame* frame,
+ const DesktopRect* rects,
+ int count) {
+ frame->mutable_updated_region()->Clear();
for (int i = 0; i < count; ++i) {
- data->mutable_dirty_region().op(rects[i], SkRegion::kUnion_Op);
+ frame->mutable_updated_region()->AddRect(rects[i]);
}
tester->AddRects(rects, count);
- encoder->Encode(data, true, base::Bind(
+ encoder->Encode(frame, base::Bind(
&VideoEncoderTester::DataAvailable, base::Unretained(tester)));
}
@@ -356,18 +373,15 @@ void TestVideoEncoder(VideoEncoder* encoder, bool strict) {
VideoEncoderTester tester(&message_tester);
- scoped_ptr<uint8[]> memory;
-
for (size_t xi = 0; xi < arraysize(kSizes); ++xi) {
for (size_t yi = 0; yi < arraysize(kSizes); ++yi) {
- SkISize size = SkISize::Make(kSizes[xi], kSizes[yi]);
- scoped_refptr<media::ScreenCaptureData> data =
- PrepareEncodeData(size, &memory);
- std::vector<std::vector<SkIRect> > test_rect_lists =
+ DesktopSize size = DesktopSize(kSizes[xi], kSizes[yi]);
+ scoped_ptr<webrtc::DesktopFrame> frame = PrepareFrame(size);
+ std::vector<std::vector<DesktopRect> > test_rect_lists =
MakeTestRectLists(size);
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,
+ const std::vector<DesktopRect>& test_rects = test_rect_lists[i];
+ TestEncodingRects(encoder, &tester, frame.get(),
&test_rects[0], test_rects.size());
}
}
@@ -377,68 +391,69 @@ void TestVideoEncoder(VideoEncoder* encoder, bool strict) {
static void TestEncodeDecodeRects(VideoEncoder* encoder,
VideoEncoderTester* encoder_tester,
VideoDecoderTester* decoder_tester,
- scoped_refptr<media::ScreenCaptureData> data,
- const SkIRect* rects, int count) {
- data->mutable_dirty_region().setRects(rects, count);
+ webrtc::DesktopFrame* frame,
+ const DesktopRect* rects, int count) {
+ frame->mutable_updated_region()->Clear();
+ for (int i = 0; i < count; ++i) {
+ frame->mutable_updated_region()->AddRect(rects[i]);
+ }
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) {
- 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() +
- data->stride() * rects[i].top() +
- bytes_per_pixel * rects[i].left();
+ const int row_size =
+ webrtc::DesktopFrame::kBytesPerPixel * rects[i].width();
+ uint8* memory = frame->data() +
+ frame->stride() * rects[i].top() +
+ webrtc::DesktopFrame::kBytesPerPixel * 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->stride();
+ memory += frame->stride();
}
}
- encoder->Encode(data, true, base::Bind(&VideoEncoderTester::DataAvailable,
- base::Unretained(encoder_tester)));
+ encoder->Encode(frame, base::Bind(&VideoEncoderTester::DataAvailable,
+ base::Unretained(encoder_tester)));
decoder_tester->VerifyResults();
decoder_tester->Reset();
}
void TestVideoEncoderDecoder(
VideoEncoder* encoder, VideoDecoder* decoder, bool strict) {
- SkISize kSize = SkISize::Make(320, 240);
+ DesktopSize kSize = DesktopSize(320, 240);
VideoEncoderMessageTester message_tester;
message_tester.set_strict(strict);
VideoEncoderTester encoder_tester(&message_tester);
- scoped_ptr<uint8[]> memory;
- scoped_refptr<media::ScreenCaptureData> data =
- PrepareEncodeData(kSize, &memory);
+ scoped_ptr<webrtc::DesktopFrame> frame = PrepareFrame(kSize);
VideoDecoderTester decoder_tester(decoder, kSize, kSize);
decoder_tester.set_strict(strict);
- decoder_tester.set_capture_data(data);
+ decoder_tester.set_frame(frame.get());
encoder_tester.set_decoder_tester(&decoder_tester);
- std::vector<std::vector<SkIRect> > test_rect_lists = MakeTestRectLists(kSize);
+ std::vector<std::vector<DesktopRect> > 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());
+ const std::vector<DesktopRect> test_rects = test_rect_lists[i];
+ TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester,
+ frame.get(), &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()));
+static void FillWithGradient(webrtc::DesktopFrame* frame) {
+ for (int j = 0; j < frame->size().height(); ++j) {
+ uint8* p = frame->data() + j * frame->stride();
+ for (int i = 0; i < frame->size().width(); ++i) {
+ *p++ = (255.0 * i) / frame->size().width();
+ *p++ = (164.0 * j) / frame->size().height();
+ *p++ = (82.0 * (i + j)) /
+ (frame->size().width() + frame->size().height());
*p++ = 0;
}
}
@@ -446,42 +461,38 @@ static void FillWithGradient(uint8* memory, const SkISize& frame_size,
void TestVideoEncoderDecoderGradient(VideoEncoder* encoder,
VideoDecoder* decoder,
- const SkISize& screen_size,
- const SkISize& view_size,
+ const DesktopSize& screen_size,
+ const DesktopSize& view_size,
double max_error_limit,
double mean_error_limit) {
- SkIRect screen_rect = SkIRect::MakeSize(screen_size);
- scoped_ptr<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_ptr<uint8[]> expected_view_data(new uint8[
- view_size.width() * view_size.height() * kBytesPerPixel]);
- FillWithGradient(expected_view_data.get(), view_size, view_rect);
+ scoped_ptr<webrtc::BasicDesktopFrame> frame(
+ new webrtc::BasicDesktopFrame(screen_size));
+ FillWithGradient(frame.get());
+ frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(screen_size));
- scoped_refptr<media::ScreenCaptureData> capture_data =
- new media::ScreenCaptureData(
- screen_data.get(), screen_size.width() * kBytesPerPixel, screen_size);
- capture_data->mutable_dirty_region().op(screen_rect, SkRegion::kUnion_Op);
+ scoped_ptr<webrtc::BasicDesktopFrame> expected_result(
+ new webrtc::BasicDesktopFrame(view_size));
+ FillWithGradient(expected_result.get());
VideoDecoderTester decoder_tester(decoder, screen_size, view_size);
- decoder_tester.set_capture_data(capture_data);
- decoder_tester.AddRegion(capture_data->dirty_region());
+ decoder_tester.set_frame(frame.get());
+ decoder_tester.AddRegion(frame->updated_region());
- encoder->Encode(capture_data, true,
+ encoder->Encode(frame.get(),
base::Bind(&VideoDecoderTester::ReceivedScopedPacket,
base::Unretained(&decoder_tester)));
- decoder_tester.VerifyResultsApprox(expected_view_data.get(),
+ decoder_tester.VerifyResultsApprox(expected_result->data(),
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->Invalidate(
+ SkISize::Make(view_size.width(), view_size.height()),
+ SkRegion(SkIRect::MakeWH(view_size.width(), view_size.height())));
decoder_tester.RenderFrame();
- decoder_tester.VerifyResultsApprox(expected_view_data.get(),
+ decoder_tester.VerifyResultsApprox(expected_result->data(),
max_error_limit, mean_error_limit);
}
diff --git a/remoting/codec/codec_test.h b/remoting/codec/codec_test.h
index d2bda83..e7e055f 100644
--- a/remoting/codec/codec_test.h
+++ b/remoting/codec/codec_test.h
@@ -6,8 +6,10 @@
#define REMOTING_CODEC_CODEC_TEST_H_
#include "base/memory/ref_counted.h"
-#include "media/base/video_frame.h"
-#include "media/video/capture/screen/screen_capture_data.h"
+
+namespace webrtc {
+class DesktopSize;
+}
namespace remoting {
@@ -33,8 +35,8 @@ void TestVideoEncoderDecoder(VideoEncoder* encoder,
// pair.
void TestVideoEncoderDecoderGradient(VideoEncoder* encoder,
VideoDecoder* decoder,
- const SkISize& screen_size,
- const SkISize& view_size,
+ const webrtc::DesktopSize& screen_size,
+ const webrtc::DesktopSize& view_size,
double max_error_limit,
double mean_error_limit);
diff --git a/remoting/codec/video_decoder_vp8_unittest.cc b/remoting/codec/video_decoder_vp8_unittest.cc
index d8d36f0..64d30df 100644
--- a/remoting/codec/video_decoder_vp8_unittest.cc
+++ b/remoting/codec/video_decoder_vp8_unittest.cc
@@ -8,6 +8,7 @@
#include "remoting/codec/codec_test.h"
#include "remoting/codec/video_encoder_vp8.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
namespace remoting {
@@ -19,10 +20,11 @@ class VideoDecoderVp8Test : public testing::Test {
void TestGradient(int screen_width, int screen_height,
int view_width, int view_height,
double max_error_limit, double mean_error_limit) {
- TestVideoEncoderDecoderGradient(&encoder_, &decoder_,
- SkISize::Make(screen_width, screen_height),
- SkISize::Make(view_width, view_height),
- max_error_limit, mean_error_limit);
+ TestVideoEncoderDecoderGradient(
+ &encoder_, &decoder_,
+ webrtc::DesktopSize(screen_width, screen_height),
+ webrtc::DesktopSize(view_width, view_height),
+ max_error_limit, mean_error_limit);
}
};
diff --git a/remoting/codec/video_encoder.h b/remoting/codec/video_encoder.h
index 81179c4..a89e1e7 100644
--- a/remoting/codec/video_encoder.h
+++ b/remoting/codec/video_encoder.h
@@ -7,19 +7,19 @@
#include "base/basictypes.h"
#include "base/callback.h"
-#include "media/base/data_buffer.h"
-namespace media {
-class ScreenCaptureData;
-} // namespace media
+class SkRegion;
+
+namespace webrtc {
+class DesktopFrame;
+} // namespace webrtc
namespace remoting {
class VideoPacket;
-// A class to perform the task of encoding a continous stream of
-// images.
-// This class operates asynchronously to enable maximum throughput.
+// A class to perform the task of encoding a continuous stream of images. The
+// interface is asynchronous to enable maximum throughput.
class VideoEncoder {
public:
@@ -29,15 +29,10 @@ class VideoEncoder {
virtual ~VideoEncoder() {}
- // 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<media::ScreenCaptureData> capture_data,
- bool key_frame,
+ // Encode an image stored in |frame|. Doesn't take ownership of |frame|. When
+ // encoded data is available, partial or full |data_available_callback| is
+ // called.
+ virtual void Encode(const webrtc::DesktopFrame* frame,
const DataAvailableCallback& data_available_callback) = 0;
};
diff --git a/remoting/codec/video_encoder_verbatim.cc b/remoting/codec/video_encoder_verbatim.cc
index 2e7f6d0..4680362 100644
--- a/remoting/codec/video_encoder_verbatim.cc
+++ b/remoting/codec/video_encoder_verbatim.cc
@@ -5,17 +5,17 @@
#include "remoting/codec/video_encoder_verbatim.h"
#include "base/logging.h"
-#include "media/video/capture/screen/screen_capture_data.h"
+#include "base/stl_util.h"
#include "remoting/base/util.h"
#include "remoting/proto/video.pb.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
namespace remoting {
static const int kPacketSize = 1024 * 1024;
VideoEncoderVerbatim::VideoEncoderVerbatim()
- : screen_size_(SkISize::Make(0,0)),
- max_packet_size_(kPacketSize) {
+ : max_packet_size_(kPacketSize) {
}
void VideoEncoderVerbatim::SetMaxPacketSize(int size) {
@@ -26,35 +26,33 @@ VideoEncoderVerbatim::~VideoEncoderVerbatim() {
}
void VideoEncoderVerbatim::Encode(
- scoped_refptr<media::ScreenCaptureData> capture_data,
- bool key_frame,
+ const webrtc::DesktopFrame* frame,
const DataAvailableCallback& data_available_callback) {
- capture_data_ = capture_data;
callback_ = data_available_callback;
encode_start_time_ = base::Time::Now();
- const SkRegion& region = capture_data->dirty_region();
- SkRegion::Iterator iter(region);
- while (!iter.done()) {
- SkIRect rect = iter.rect();
- iter.next();
- EncodeRect(rect, iter.done());
+ webrtc::DesktopRegion::Iterator iter(frame->updated_region());
+ while (!iter.IsAtEnd()) {
+ const webrtc::DesktopRect& rect = iter.rect();
+ iter.Advance();
+ EncodeRect(frame, rect, iter.IsAtEnd());
}
- capture_data_ = NULL;
callback_.Reset();
}
-void VideoEncoderVerbatim::EncodeRect(const SkIRect& rect, bool last) {
- CHECK(capture_data_->data());
- const int stride = capture_data_->stride();
+void VideoEncoderVerbatim::EncodeRect(const webrtc::DesktopFrame* frame,
+ const webrtc::DesktopRect& rect,
+ bool last) {
+ CHECK(frame->data());
+ const int stride = frame->stride();
const int bytes_per_pixel = 4;
const int row_size = bytes_per_pixel * rect.width();
scoped_ptr<VideoPacket> packet(new VideoPacket());
- PrepareUpdateStart(rect, packet.get());
- const uint8* in = capture_data_->data() +
- rect.fTop * stride + rect.fLeft * bytes_per_pixel;
+ PrepareUpdateStart(frame, rect, packet.get());
+ const uint8* in = frame->data() +
+ rect.top() * stride + rect.left() * bytes_per_pixel;
// TODO(hclam): Fill in the sequence number.
uint8* out = GetOutputBuffer(packet.get(), max_packet_size_);
int filled = 0;
@@ -88,16 +86,14 @@ void VideoEncoderVerbatim::EncodeRect(const SkIRect& rect, bool last) {
packet->mutable_data()->resize(filled);
packet->set_flags(packet->flags() | VideoPacket::LAST_PACKET);
- packet->set_capture_time_ms(capture_data_->capture_time_ms());
+
+ packet->set_capture_time_ms(frame->capture_time_ms());
packet->set_encode_time_ms(
(base::Time::Now() - encode_start_time_).InMillisecondsRoundedUp());
- 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 (!frame->dpi().is_zero()) {
+ packet->mutable_format()->set_x_dpi(frame->dpi().x());
+ packet->mutable_format()->set_y_dpi(frame->dpi().y());
+ }
if (last)
packet->set_flags(packet->flags() | VideoPacket::LAST_PARTITION);
}
@@ -110,18 +106,19 @@ void VideoEncoderVerbatim::EncodeRect(const SkIRect& rect, bool last) {
}
}
-void VideoEncoderVerbatim::PrepareUpdateStart(const SkIRect& rect,
+void VideoEncoderVerbatim::PrepareUpdateStart(const webrtc::DesktopFrame* frame,
+ const webrtc::DesktopRect& 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_x(rect.left());
+ format->set_y(rect.top());
format->set_width(rect.width());
format->set_height(rect.height());
format->set_encoding(VideoPacketFormat::ENCODING_VERBATIM);
- if (capture_data_->size() != screen_size_) {
- screen_size_ = capture_data_->size();
+ if (frame->size().equals(screen_size_)) {
+ screen_size_ = frame->size();
format->set_screen_width(screen_size_.width());
format->set_screen_height(screen_size_.height());
}
@@ -129,9 +126,7 @@ void VideoEncoderVerbatim::PrepareUpdateStart(const SkIRect& rect,
uint8* VideoEncoderVerbatim::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()));
+ return reinterpret_cast<uint8*>(string_as_array(packet->mutable_data()));
}
} // namespace remoting
diff --git a/remoting/codec/video_encoder_verbatim.h b/remoting/codec/video_encoder_verbatim.h
index 2b6250b..bf8e901 100644
--- a/remoting/codec/video_encoder_verbatim.h
+++ b/remoting/codec/video_encoder_verbatim.h
@@ -8,7 +8,7 @@
#include "base/time.h"
#include "remoting/codec/video_encoder.h"
#include "remoting/proto/video.pb.h"
-#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
namespace remoting {
@@ -24,17 +24,20 @@ class VideoEncoderVerbatim : public VideoEncoder {
// VideoEncoder interface.
virtual void Encode(
- scoped_refptr<media::ScreenCaptureData> capture_data,
- bool key_frame,
+ const webrtc::DesktopFrame* frame,
const DataAvailableCallback& data_available_callback) OVERRIDE;
private:
// Encode a single dirty |rect|.
- void EncodeRect(const SkIRect& rect, bool last);
+ void EncodeRect(const webrtc::DesktopFrame* frame,
+ const webrtc::DesktopRect& rect,
+ bool last);
// Initializes first packet in a sequence of video packets to update screen
// rectangle |rect|.
- void PrepareUpdateStart(const SkIRect& rect, VideoPacket* packet);
+ void PrepareUpdateStart(const webrtc::DesktopFrame* frame,
+ const webrtc::DesktopRect& rect,
+ VideoPacket* packet);
// Allocates a buffer of the specified |size| inside |packet| and returns the
// pointer to it.
@@ -43,12 +46,11 @@ class VideoEncoderVerbatim : public VideoEncoder {
// Submit |packet| to |callback_|.
void SubmitMessage(VideoPacket* packet, size_t rect_index);
- scoped_refptr<media::ScreenCaptureData> capture_data_;
DataAvailableCallback callback_;
base::Time encode_start_time_;
// The most recent screen size.
- SkISize screen_size_;
+ webrtc::DesktopSize screen_size_;
int max_packet_size_;
};
diff --git a/remoting/codec/video_encoder_vp8.cc b/remoting/codec/video_encoder_vp8.cc
index a4e4d1a..7824065 100644
--- a/remoting/codec/video_encoder_vp8.cc
+++ b/remoting/codec/video_encoder_vp8.cc
@@ -8,9 +8,10 @@
#include "base/sys_info.h"
#include "base/time.h"
#include "media/base/yuv_convert.h"
-#include "media/video/capture/screen/screen_capture_data.h"
#include "remoting/base/util.h"
#include "remoting/proto/video.pb.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
extern "C" {
#define VPX_CODEC_DISABLE_COMPAT 1
@@ -49,7 +50,7 @@ void VideoEncoderVp8::Destroy() {
}
}
-bool VideoEncoderVp8::Init(const SkISize& size) {
+bool VideoEncoderVp8::Init(const webrtc::DesktopSize& size) {
Destroy();
codec_.reset(new vpx_codec_ctx_t());
image_.reset(new vpx_image_t());
@@ -146,11 +147,9 @@ bool VideoEncoderVp8::Init(const SkISize& size) {
return true;
}
-void VideoEncoderVp8::PrepareImage(
- scoped_refptr<media::ScreenCaptureData> capture_data,
- SkRegion* updated_region) {
- const SkRegion& region = capture_data->dirty_region();
- if (region.isEmpty()) {
+void VideoEncoderVp8::PrepareImage(const webrtc::DesktopFrame* frame,
+ SkRegion* updated_region) {
+ if (frame->updated_region().is_empty()) {
updated_region->setEmpty();
return;
}
@@ -159,8 +158,11 @@ void VideoEncoderVp8::PrepareImage(
// 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()));
+ for (webrtc::DesktopRegion::Iterator r(frame->updated_region());
+ !r.IsAtEnd(); r.Advance()) {
+ const webrtc::DesktopRect& rect = r.rect();
+ aligned_rects.push_back(AlignRect(
+ SkIRect::MakeLTRB(rect.left(), rect.top(), rect.right(), rect.bottom())));
}
DCHECK(!aligned_rects.empty());
updated_region->setRects(&aligned_rects[0], aligned_rects.size());
@@ -172,8 +174,8 @@ void VideoEncoderVp8::PrepareImage(
SkRegion::kIntersect_Op);
// Convert the updated region to YUV ready for encoding.
- const uint8* rgb_data = capture_data->data();
- const int rgb_stride = capture_data->stride();
+ const uint8* rgb_data = frame->data();
+ const int rgb_stride = frame->stride();
const int y_stride = image_->stride[0];
DCHECK_EQ(image_->stride[1], image_->stride[2]);
const int uv_stride = image_->stride[1];
@@ -213,17 +215,16 @@ void VideoEncoderVp8::PrepareActiveMap(const SkRegion& updated_region) {
}
void VideoEncoderVp8::Encode(
- scoped_refptr<media::ScreenCaptureData> capture_data,
- bool key_frame,
+ const webrtc::DesktopFrame* frame,
const DataAvailableCallback& data_available_callback) {
- DCHECK_LE(32, capture_data->size().width());
- DCHECK_LE(32, capture_data->size().height());
+ DCHECK_LE(32, frame->size().width());
+ DCHECK_LE(32, frame->size().height());
base::Time encode_start_time = base::Time::Now();
if (!initialized_ ||
- (capture_data->size() != SkISize::Make(image_->w, image_->h))) {
- bool ret = Init(capture_data->size());
+ !frame->size().equals(webrtc::DesktopSize(image_->w, image_->h))) {
+ bool ret = Init(frame->size());
// TODO(hclam): Handle error better.
CHECK(ret) << "Initialization of encoder failed";
initialized_ = ret;
@@ -231,7 +232,7 @@ void VideoEncoderVp8::Encode(
// Convert the updated capture data ready for encode.
SkRegion updated_region;
- PrepareImage(capture_data, &updated_region);
+ PrepareImage(frame, &updated_region);
// Update active map based on updated region.
PrepareActiveMap(updated_region);
@@ -286,17 +287,15 @@ void VideoEncoderVp8::Encode(
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->mutable_format()->set_screen_width(frame->size().width());
+ packet->mutable_format()->set_screen_height(frame->size().height());
+ packet->set_capture_time_ms(frame->capture_time_ms());
packet->set_encode_time_ms(
(base::Time::Now() - encode_start_time).InMillisecondsRoundedUp());
- 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 (!frame->dpi().is_zero()) {
+ packet->mutable_format()->set_x_dpi(frame->dpi().x());
+ packet->mutable_format()->set_y_dpi(frame->dpi().y());
+ }
for (SkRegion::Iterator r(updated_region); !r.done(); r.next()) {
Rect* rect = packet->add_dirty_rects();
rect->set_x(r.rect().x());
diff --git a/remoting/codec/video_encoder_vp8.h b/remoting/codec/video_encoder_vp8.h
index f26fad3..912c845 100644
--- a/remoting/codec/video_encoder_vp8.h
+++ b/remoting/codec/video_encoder_vp8.h
@@ -12,6 +12,10 @@
typedef struct vpx_codec_ctx vpx_codec_ctx_t;
typedef struct vpx_image vpx_image_t;
+namespace webrtc {
+class DesktopSize;
+} // namespace webrtc
+
namespace remoting {
// A class that uses VP8 to perform encoding.
@@ -20,23 +24,25 @@ class VideoEncoderVp8 : public VideoEncoder {
VideoEncoderVp8();
virtual ~VideoEncoderVp8();
+ // VideoEncoder interface.
virtual void Encode(
- scoped_refptr<media::ScreenCaptureData> capture_data,
- bool key_frame,
+ const webrtc::DesktopFrame* frame,
const DataAvailableCallback& data_available_callback) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(VideoEncoderVp8Test, AlignAndClipRect);
// Initialize the encoder. Returns true if successful.
- bool Init(const SkISize& size);
+ bool Init(const webrtc::DesktopSize& size);
// Destroy the encoder.
void Destroy();
// Prepare |image_| for encoding. Write updated rectangles into
// |updated_region|.
- void PrepareImage(scoped_refptr<media::ScreenCaptureData> capture_data,
+ //
+ // TODO(sergeyu): Update this code to use webrtc::DesktopRegion.
+ void PrepareImage(const webrtc::DesktopFrame* frame,
SkRegion* updated_region);
// Update the active map according to |updated_region|. Active map is then
diff --git a/remoting/codec/video_encoder_vp8_unittest.cc b/remoting/codec/video_encoder_vp8_unittest.cc
index 9a32fe2..684910d 100644
--- a/remoting/codec/video_encoder_vp8_unittest.cc
+++ b/remoting/codec/video_encoder_vp8_unittest.cc
@@ -10,10 +10,10 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
-#include "media/video/capture/screen/screen_capture_data.h"
#include "remoting/codec/codec_test.h"
#include "remoting/proto/video.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
namespace {
@@ -39,25 +39,21 @@ class VideoEncoderCallback {
TEST(VideoEncoderVp8Test, TestSizeChangeNoLeak) {
int height = 1000;
int width = 1000;
- const int kBytesPerPixel = 4;
VideoEncoderVp8 encoder;
VideoEncoderCallback callback;
- std::vector<uint8> buffer(width * height * kBytesPerPixel);
- scoped_refptr<media::ScreenCaptureData> capture_data(
- new media::ScreenCaptureData(&buffer.front(), width * kBytesPerPixel,
- SkISize::Make(width, height)));
- encoder.Encode(capture_data, false,
- base::Bind(&VideoEncoderCallback::DataAvailable,
- base::Unretained(&callback)));
+ scoped_ptr<webrtc::DesktopFrame> frame(new webrtc::BasicDesktopFrame(
+ webrtc::DesktopSize(width, height)));
+
+ encoder.Encode(frame.get(), base::Bind(&VideoEncoderCallback::DataAvailable,
+ base::Unretained(&callback)));
height /= 2;
- capture_data = new media::ScreenCaptureData(
- &buffer.front(), width * kBytesPerPixel, SkISize::Make(width, height));
- encoder.Encode(capture_data, false,
- base::Bind(&VideoEncoderCallback::DataAvailable,
- base::Unretained(&callback)));
+ frame.reset(new webrtc::BasicDesktopFrame(
+ webrtc::DesktopSize(width, height)));
+ encoder.Encode(frame.get(), base::Bind(&VideoEncoderCallback::DataAvailable,
+ base::Unretained(&callback)));
}
class VideoEncoderDpiCallback {
@@ -73,17 +69,14 @@ class VideoEncoderDpiCallback {
TEST(VideoEncoderVp8Test, TestDpiPropagation) {
int height = 32;
int width = 32;
- const int kBytesPerPixel = 4;
VideoEncoderVp8 encoder;
VideoEncoderDpiCallback callback;
- std::vector<uint8> buffer(width * height * kBytesPerPixel);
- scoped_refptr<media::ScreenCaptureData> capture_data(
- new media::ScreenCaptureData(&buffer.front(), width * kBytesPerPixel,
- SkISize::Make(width, height)));
- capture_data->set_dpi(SkIPoint::Make(96, 97));
- encoder.Encode(capture_data, false,
+ scoped_ptr<webrtc::DesktopFrame> frame(new webrtc::BasicDesktopFrame(
+ webrtc::DesktopSize(width, height)));
+ frame->set_dpi(webrtc::DesktopVector(96, 97));
+ encoder.Encode(frame.get(),
base::Bind(&VideoEncoderDpiCallback::DataAvailable,
base::Unretained(&callback)));
}