diff options
Diffstat (limited to 'third_party/libwebrtc/modules/desktop_capture/desktop_frame.cc')
-rw-r--r-- | third_party/libwebrtc/modules/desktop_capture/desktop_frame.cc | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/desktop_capture/desktop_frame.cc b/third_party/libwebrtc/modules/desktop_capture/desktop_frame.cc new file mode 100644 index 0000000000..d6f574588c --- /dev/null +++ b/third_party/libwebrtc/modules/desktop_capture/desktop_frame.cc @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2013 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.h" + +#include <string.h> + +#include <cmath> +#include <memory> +#include <utility> + +#include "modules/desktop_capture/desktop_capture_types.h" +#include "modules/desktop_capture/desktop_geometry.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" + +namespace webrtc { + +DesktopFrame::DesktopFrame(DesktopSize size, + int stride, + uint8_t* data, + SharedMemory* shared_memory) + : data_(data), + shared_memory_(shared_memory), + size_(size), + stride_(stride), + capture_time_ms_(0), + capturer_id_(DesktopCapturerId::kUnknown) { + RTC_DCHECK(size_.width() >= 0); + RTC_DCHECK(size_.height() >= 0); +} + +DesktopFrame::~DesktopFrame() = default; + +void DesktopFrame::CopyPixelsFrom(const uint8_t* src_buffer, + int src_stride, + const DesktopRect& dest_rect) { + RTC_CHECK(DesktopRect::MakeSize(size()).ContainsRect(dest_rect)); + + uint8_t* dest = GetFrameDataAtPos(dest_rect.top_left()); + libyuv::CopyPlane(src_buffer, src_stride, dest, stride(), + DesktopFrame::kBytesPerPixel * dest_rect.width(), + dest_rect.height()); +} + +void DesktopFrame::CopyPixelsFrom(const DesktopFrame& src_frame, + const DesktopVector& src_pos, + const DesktopRect& dest_rect) { + RTC_CHECK(DesktopRect::MakeSize(src_frame.size()) + .ContainsRect( + DesktopRect::MakeOriginSize(src_pos, dest_rect.size()))); + + CopyPixelsFrom(src_frame.GetFrameDataAtPos(src_pos), src_frame.stride(), + dest_rect); +} + +bool DesktopFrame::CopyIntersectingPixelsFrom(const DesktopFrame& src_frame, + double horizontal_scale, + double vertical_scale) { + const DesktopVector& origin = top_left(); + const DesktopVector& src_frame_origin = src_frame.top_left(); + + DesktopVector src_frame_offset = src_frame_origin.subtract(origin); + + // Determine the intersection, first adjusting its origin to account for any + // DPI scaling. + DesktopRect intersection_rect = src_frame.rect(); + if (horizontal_scale != 1.0 || vertical_scale != 1.0) { + DesktopVector origin_adjustment( + static_cast<int>( + std::round((horizontal_scale - 1.0) * src_frame_offset.x())), + static_cast<int>( + std::round((vertical_scale - 1.0) * src_frame_offset.y()))); + + intersection_rect.Translate(origin_adjustment); + + src_frame_offset = src_frame_offset.add(origin_adjustment); + } + + intersection_rect.IntersectWith(rect()); + if (intersection_rect.is_empty()) { + return false; + } + + // Translate the intersection rect to be relative to the outer rect. + intersection_rect.Translate(-origin.x(), -origin.y()); + + // Determine source position for the copy (offsets of outer frame from + // source origin, if positive). + int32_t src_pos_x = std::max(0, -src_frame_offset.x()); + int32_t src_pos_y = std::max(0, -src_frame_offset.y()); + + CopyPixelsFrom(src_frame, DesktopVector(src_pos_x, src_pos_y), + intersection_rect); + return true; +} + +DesktopRect DesktopFrame::rect() const { + const float scale = scale_factor(); + // Only scale the size. + return DesktopRect::MakeXYWH(top_left().x(), top_left().y(), + size().width() / scale, size().height() / scale); +} + +float DesktopFrame::scale_factor() const { + float scale = 1.0f; + +#if defined(WEBRTC_MAC) || defined(CHROMEOS) + // At least on Windows the logical and physical pixel are the same + // See http://crbug.com/948362. + if (!dpi().is_zero() && dpi().x() == dpi().y()) + scale = dpi().x() / kStandardDPI; +#endif + + return scale; +} + +uint8_t* DesktopFrame::GetFrameDataAtPos(const DesktopVector& pos) const { + return data() + stride() * pos.y() + DesktopFrame::kBytesPerPixel * pos.x(); +} + +void DesktopFrame::CopyFrameInfoFrom(const DesktopFrame& other) { + set_dpi(other.dpi()); + set_capture_time_ms(other.capture_time_ms()); + set_capturer_id(other.capturer_id()); + *mutable_updated_region() = other.updated_region(); + set_top_left(other.top_left()); + set_icc_profile(other.icc_profile()); +} + +void DesktopFrame::MoveFrameInfoFrom(DesktopFrame* other) { + set_dpi(other->dpi()); + set_capture_time_ms(other->capture_time_ms()); + set_capturer_id(other->capturer_id()); + mutable_updated_region()->Swap(other->mutable_updated_region()); + set_top_left(other->top_left()); + set_icc_profile(other->icc_profile()); +} + +BasicDesktopFrame::BasicDesktopFrame(DesktopSize size) + : DesktopFrame(size, + kBytesPerPixel * size.width(), + new uint8_t[kBytesPerPixel * size.width() * size.height()](), + nullptr) {} + +BasicDesktopFrame::~BasicDesktopFrame() { + delete[] data_; +} + +// static +DesktopFrame* BasicDesktopFrame::CopyOf(const DesktopFrame& frame) { + DesktopFrame* result = new BasicDesktopFrame(frame.size()); + // TODO(crbug.com/1330019): Temporary workaround for a known libyuv crash when + // the height or width is 0. Remove this once this change has been merged. + if (frame.size().width() && frame.size().height()) { + libyuv::CopyPlane(frame.data(), frame.stride(), result->data(), + result->stride(), frame.size().width() * kBytesPerPixel, + frame.size().height()); + } + result->CopyFrameInfoFrom(frame); + return result; +} + +// static +std::unique_ptr<DesktopFrame> SharedMemoryDesktopFrame::Create( + DesktopSize size, + SharedMemoryFactory* shared_memory_factory) { + RTC_DCHECK(shared_memory_factory); + + size_t buffer_size = size.height() * size.width() * kBytesPerPixel; + std::unique_ptr<SharedMemory> shared_memory = + shared_memory_factory->CreateSharedMemory(buffer_size); + if (!shared_memory) + return nullptr; + + return std::make_unique<SharedMemoryDesktopFrame>( + size, size.width() * kBytesPerPixel, std::move(shared_memory)); +} + +SharedMemoryDesktopFrame::SharedMemoryDesktopFrame(DesktopSize size, + int stride, + SharedMemory* shared_memory) + : DesktopFrame(size, + stride, + reinterpret_cast<uint8_t*>(shared_memory->data()), + shared_memory) {} + +SharedMemoryDesktopFrame::SharedMemoryDesktopFrame( + DesktopSize size, + int stride, + std::unique_ptr<SharedMemory> shared_memory) + : SharedMemoryDesktopFrame(size, stride, shared_memory.release()) {} + +SharedMemoryDesktopFrame::~SharedMemoryDesktopFrame() { + delete shared_memory_; +} + +} // namespace webrtc |