16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/host/fake_desktop_capturer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind.h" 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/ref_counted.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace remoting { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// FakeDesktopCapturer generates a white picture of size kWidth x kHeight 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with a rectangle of size kBoxWidth x kBoxHeight. The rectangle moves kSpeed 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pixels per frame along both axes, and bounces off the sides of the screen. 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static const int kWidth = FakeDesktopCapturer::kWidth; 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static const int kHeight = FakeDesktopCapturer::kHeight; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kBoxWidth = 140; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kBoxHeight = 140; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSpeed = 20; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(kBoxWidth < kWidth && kBoxHeight < kHeight, bad_box_size); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT((kBoxWidth % kSpeed == 0) && (kWidth % kSpeed == 0) && 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kBoxHeight % kSpeed == 0) && (kHeight % kSpeed == 0), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes_must_be_multiple_of_kSpeed); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DefaultFrameGenerator 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : public base::RefCountedThreadSafe<DefaultFrameGenerator> { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DefaultFrameGenerator() 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : bytes_per_row_(0), 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_pos_x_(0), 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_pos_y_(0), 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_speed_x_(kSpeed), 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_speed_y_(kSpeed), 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first_frame_(true) {} 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<webrtc::DesktopFrame> GenerateFrame( 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) webrtc::DesktopCapturer::Callback* callback); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) friend class base::RefCountedThreadSafe<DefaultFrameGenerator>; 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ~DefaultFrameGenerator() {} 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) webrtc::DesktopSize size_; 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int bytes_per_row_; 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int box_pos_x_; 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int box_pos_y_; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int box_speed_x_; 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int box_speed_y_; 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool first_frame_; 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DefaultFrameGenerator); 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<webrtc::DesktopFrame> DefaultFrameGenerator::GenerateFrame( 616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) webrtc::DesktopCapturer::Callback* callback) { 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kBytesPerPixel = webrtc::DesktopFrame::kBytesPerPixel; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buffer_size = kWidth * kHeight * kBytesPerPixel; 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) webrtc::SharedMemory* shared_memory = 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback->CreateSharedMemory(buffer_size); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<webrtc::DesktopFrame> frame; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (shared_memory) { 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame.reset(new webrtc::SharedMemoryDesktopFrame( 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) webrtc::DesktopSize(kWidth, kHeight), bytes_per_row_, shared_memory)); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame.reset( 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new webrtc::BasicDesktopFrame(webrtc::DesktopSize(kWidth, kHeight))); 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Move the box. 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool old_box_pos_x = box_pos_x_; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_pos_x_ += box_speed_x_; 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (box_pos_x_ + kBoxWidth >= kWidth || box_pos_x_ == 0) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_speed_x_ = -box_speed_x_; 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool old_box_pos_y = box_pos_y_; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_pos_y_ += box_speed_y_; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (box_pos_y_ + kBoxHeight >= kHeight || box_pos_y_ == 0) 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_speed_y_ = -box_speed_y_; 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) memset(frame->data(), 0xff, kHeight * frame->stride()); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Draw rectangle with the following colors in its corners: 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // cyan....yellow 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // .............. 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // blue.......red 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8* row = frame->data() + 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (box_pos_y_ * size_.width() + box_pos_x_) * kBytesPerPixel; 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int y = 0; y < kBoxHeight; ++y) { 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int x = 0; x < kBoxWidth; ++x) { 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int r = x * 255 / kBoxWidth; 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int g = y * 255 / kBoxHeight; 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int b = 255 - (x * 255 / kBoxWidth); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row[x * kBytesPerPixel] = r; 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row[x * kBytesPerPixel + 1] = g; 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row[x * kBytesPerPixel + 2] = b; 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row[x * kBytesPerPixel + 3] = 0xff; 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row += frame->stride(); 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (first_frame_) { 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame->mutable_updated_region()->SetRect( 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) webrtc::DesktopRect::MakeXYWH(0, 0, kWidth, kHeight)); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first_frame_ = false; 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame->mutable_updated_region()->SetRect(webrtc::DesktopRect::MakeXYWH( 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) old_box_pos_x, old_box_pos_y, kBoxWidth, kBoxHeight)); 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame->mutable_updated_region()->AddRect(webrtc::DesktopRect::MakeXYWH( 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) box_pos_x_, box_pos_y_, kBoxWidth, kBoxHeight)); 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return frame.Pass(); 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)FakeDesktopCapturer::FakeDesktopCapturer() 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : callback_(NULL) { 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_generator_ = base::Bind(&DefaultFrameGenerator::GenerateFrame, 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new DefaultFrameGenerator()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)FakeDesktopCapturer::~FakeDesktopCapturer() {} 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void FakeDesktopCapturer::set_frame_generator( 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const FrameGenerator& frame_generator) { 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(!callback_); 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_generator_ = frame_generator; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void FakeDesktopCapturer::Start(Callback* callback) { 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(!callback_); 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(callback); 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback_ = callback; 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void FakeDesktopCapturer::Capture(const webrtc::DesktopRegion& region) { 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time capture_start_time = base::Time::Now(); 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<webrtc::DesktopFrame> frame = frame_generator_.Run(callback_); 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame->set_capture_time_ms( 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (base::Time::Now() - capture_start_time).InMillisecondsRoundedUp()); 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback_->OnCaptureCompleted(frame.release()); 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace remoting 152