summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/desktop_capture/desktop_frame_generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/desktop_capture/desktop_frame_generator.cc')
-rw-r--r--third_party/libwebrtc/modules/desktop_capture/desktop_frame_generator.cc184
1 files changed, 184 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/desktop_capture/desktop_frame_generator.cc b/third_party/libwebrtc/modules/desktop_capture/desktop_frame_generator.cc
new file mode 100644
index 0000000000..b5dfc28e46
--- /dev/null
+++ b/third_party/libwebrtc/modules/desktop_capture/desktop_frame_generator.cc
@@ -0,0 +1,184 @@
+/*
+ * 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 "modules/desktop_capture/desktop_frame_generator.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+
+#include "modules/desktop_capture/rgba_color.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/random.h"
+#include "rtc_base/time_utils.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, RgbaColor rgba_color) {
+ static_assert(DesktopFrame::kBytesPerPixel == sizeof(uint32_t),
+ "kBytesPerPixel should be 4.");
+ RTC_DCHECK_GE(frame->size().width(), rect.right());
+ RTC_DCHECK_GE(frame->size().height(), rect.bottom());
+ uint32_t color = rgba_color.ToUInt32();
+ 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,
+ RgbaColor rgba_color) {
+ region->IntersectWith(DesktopRect::MakeSize(frame->size()));
+ for (DesktopRegion::Iterator it(*region); !it.IsAtEnd(); it.Advance()) {
+ PaintRect(frame, it.rect(), rgba_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_, RgbaColor(0xFFFFFFFF));
+ updated_region_.Swap(updated_region);
+ return true;
+}
+
+} // namespace webrtc