| Index: webrtc/modules/desktop_capture/desktop_frame_generator.cc
|
| diff --git a/webrtc/modules/desktop_capture/desktop_frame_generator.cc b/webrtc/modules/desktop_capture/desktop_frame_generator.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ae5c9492cb92f5806846668cb9a92559cb637a20
|
| --- /dev/null
|
| +++ b/webrtc/modules/desktop_capture/desktop_frame_generator.cc
|
| @@ -0,0 +1,179 @@
|
| +/*
|
| + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "webrtc/modules/desktop_capture/desktop_frame_generator.h"
|
| +
|
| +#include <stdint.h>
|
| +#include <string.h>
|
| +
|
| +#include <memory>
|
| +
|
| +#include "webrtc/base/random.h"
|
| +#include "webrtc/base/timeutils.h"
|
| +
|
| +namespace webrtc {
|
| +
|
| +namespace {
|
| +
|
| +// Sets |updated_region| to |frame|. If |enlarge_updated_region| is
|
| +// true, this function will randomly enlarge each DesktopRect in
|
| +// |updated_region|. But the enlarged DesktopRegion won't excceed the
|
| +// frame->size(). If |add_random_updated_region| is true, several random
|
| +// rectangles will also be included in |frame|.
|
| +void SetUpdatedRegion(DesktopFrame* frame,
|
| + const DesktopRegion& updated_region,
|
| + bool enlarge_updated_region,
|
| + int enlarge_range,
|
| + bool add_random_updated_region) {
|
| + const DesktopRect screen_rect = DesktopRect::MakeSize(frame->size());
|
| + Random random(rtc::TimeMicros());
|
| + frame->mutable_updated_region()->Clear();
|
| + for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
|
| + it.Advance()) {
|
| + DesktopRect rect = it.rect();
|
| + if (enlarge_updated_region && enlarge_range > 0) {
|
| + rect.Extend(random.Rand(enlarge_range), random.Rand(enlarge_range),
|
| + random.Rand(enlarge_range), random.Rand(enlarge_range));
|
| + rect.IntersectWith(screen_rect);
|
| + }
|
| + frame->mutable_updated_region()->AddRect(rect);
|
| + }
|
| +
|
| + if (add_random_updated_region) {
|
| + for (int i = random.Rand(10); i >= 0; i--) {
|
| + // At least a 1 x 1 updated region.
|
| + const int left = random.Rand(0, frame->size().width() - 2);
|
| + const int top = random.Rand(0, frame->size().height() - 2);
|
| + const int right = random.Rand(left + 1, frame->size().width());
|
| + const int bottom = random.Rand(top + 1, frame->size().height());
|
| + frame->mutable_updated_region()->AddRect(
|
| + DesktopRect::MakeLTRB(left, top, right, bottom));
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Paints pixels in |rect| of |frame| to |color|.
|
| +void PaintRect(DesktopFrame* frame, DesktopRect rect, uint32_t color) {
|
| + static_assert(DesktopFrame::kBytesPerPixel == sizeof(uint32_t),
|
| + "kBytesPerPixel should be 4.");
|
| + RTC_DCHECK(frame->size().width() >= rect.right() &&
|
| + frame->size().height() >= rect.bottom());
|
| + uint8_t* row = frame->GetFrameDataAtPos(rect.top_left());
|
| + for (int i = 0; i < rect.height(); i++) {
|
| + uint32_t* column = reinterpret_cast<uint32_t*>(row);
|
| + for (int j = 0; j < rect.width(); j++) {
|
| + column[j] = color;
|
| + }
|
| + row += frame->stride();
|
| + }
|
| +}
|
| +
|
| +// Paints pixels in |region| of |frame| to |color|.
|
| +void PaintRegion(DesktopFrame* frame, DesktopRegion* region, uint32_t color) {
|
| + region->IntersectWith(DesktopRect::MakeSize(frame->size()));
|
| + for (DesktopRegion::Iterator it(*region); !it.IsAtEnd(); it.Advance()) {
|
| + PaintRect(frame, it.rect(), color);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +DesktopFrameGenerator::DesktopFrameGenerator() {}
|
| +DesktopFrameGenerator::~DesktopFrameGenerator() {}
|
| +
|
| +DesktopFramePainter::DesktopFramePainter() {}
|
| +DesktopFramePainter::~DesktopFramePainter() {}
|
| +
|
| +PainterDesktopFrameGenerator::PainterDesktopFrameGenerator()
|
| + : size_(1024, 768),
|
| + return_frame_(true),
|
| + provide_updated_region_hints_(false),
|
| + enlarge_updated_region_(false),
|
| + enlarge_range_(20),
|
| + add_random_updated_region_(false),
|
| + painter_(nullptr) {}
|
| +PainterDesktopFrameGenerator::~PainterDesktopFrameGenerator() {}
|
| +
|
| +std::unique_ptr<DesktopFrame> PainterDesktopFrameGenerator::GetNextFrame(
|
| + SharedMemoryFactory* factory) {
|
| + if (!return_frame_) {
|
| + return nullptr;
|
| + }
|
| +
|
| + std::unique_ptr<DesktopFrame> frame = std::unique_ptr<DesktopFrame>(
|
| + factory ? SharedMemoryDesktopFrame::Create(size_, factory).release()
|
| + : new BasicDesktopFrame(size_));
|
| + if (painter_) {
|
| + DesktopRegion updated_region;
|
| + if (!painter_->Paint(frame.get(), &updated_region)) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (provide_updated_region_hints_) {
|
| + SetUpdatedRegion(frame.get(), updated_region, enlarge_updated_region_,
|
| + enlarge_range_, add_random_updated_region_);
|
| + } else {
|
| + frame->mutable_updated_region()->SetRect(
|
| + DesktopRect::MakeSize(frame->size()));
|
| + }
|
| + }
|
| +
|
| + return frame;
|
| +}
|
| +
|
| +DesktopSize* PainterDesktopFrameGenerator::size() {
|
| + return &size_;
|
| +}
|
| +
|
| +void PainterDesktopFrameGenerator::set_return_frame(bool return_frame) {
|
| + return_frame_ = return_frame;
|
| +}
|
| +
|
| +void PainterDesktopFrameGenerator::set_provide_updated_region_hints(
|
| + bool provide_updated_region_hints) {
|
| + provide_updated_region_hints_ = provide_updated_region_hints;
|
| +}
|
| +
|
| +void PainterDesktopFrameGenerator::set_enlarge_updated_region(
|
| + bool enlarge_updated_region) {
|
| + enlarge_updated_region_ = enlarge_updated_region;
|
| +}
|
| +
|
| +void PainterDesktopFrameGenerator::set_enlarge_range(int enlarge_range) {
|
| + enlarge_range_ = enlarge_range;
|
| +}
|
| +
|
| +void PainterDesktopFrameGenerator::set_add_random_updated_region(
|
| + bool add_random_updated_region) {
|
| + add_random_updated_region_ = add_random_updated_region;
|
| +}
|
| +
|
| +void PainterDesktopFrameGenerator::set_desktop_frame_painter(
|
| + DesktopFramePainter* painter) {
|
| + painter_ = painter;
|
| +}
|
| +
|
| +BlackWhiteDesktopFramePainter::BlackWhiteDesktopFramePainter() {}
|
| +BlackWhiteDesktopFramePainter::~BlackWhiteDesktopFramePainter() {}
|
| +
|
| +DesktopRegion* BlackWhiteDesktopFramePainter::updated_region() {
|
| + return &updated_region_;
|
| +}
|
| +
|
| +bool BlackWhiteDesktopFramePainter::Paint(DesktopFrame* frame,
|
| + DesktopRegion* updated_region) {
|
| + RTC_DCHECK(updated_region->is_empty());
|
| + memset(frame->data(), 0, frame->stride() * frame->size().height());
|
| + PaintRegion(frame, &updated_region_, UINT32_MAX);
|
| + updated_region_.Swap(updated_region);
|
| + return true;
|
| +}
|
| +
|
| +} // namespace webrtc
|
|
|