diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 10:45:24 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 10:45:24 +0000 |
commit | b9ed58f046141b4610c1bdc966d962d5fb95ac6b (patch) | |
tree | b7dc10e49ea765b6ebc99985d3538a2e1363942e /remoting/codec | |
parent | c1c88cf23606dd1ca2bfd9f57496aeec847e713f (diff) | |
download | chromium_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/DEPS | 1 | ||||
-rw-r--r-- | remoting/codec/codec_test.cc | 237 | ||||
-rw-r--r-- | remoting/codec/codec_test.h | 10 | ||||
-rw-r--r-- | remoting/codec/video_decoder_vp8_unittest.cc | 10 | ||||
-rw-r--r-- | remoting/codec/video_encoder.h | 27 | ||||
-rw-r--r-- | remoting/codec/video_encoder_verbatim.cc | 65 | ||||
-rw-r--r-- | remoting/codec/video_encoder_verbatim.h | 16 | ||||
-rw-r--r-- | remoting/codec/video_encoder_vp8.cc | 53 | ||||
-rw-r--r-- | remoting/codec/video_encoder_vp8.h | 14 | ||||
-rw-r--r-- | remoting/codec/video_encoder_vp8_unittest.cc | 35 |
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))); } |