Add ICC profile to DesktopFrame
And fill-in icc profile from the various window and screen capturers. Done on WindowCapturerMac, ScreenCapturerMac, WindowCapturerX11 and ScreenCapturerX11. Follow-up CLs will do it on ScreenCapturerWinDirectx and ScreenCapturerPipeWire. Useful to build the gfx::ColorSpace in chromium, especially from src/content/browser/media/capture/desktop_capture_device.cc. We do not build the color space directly here to avoid duplicating ui/gfx/icc_profile.h,cc code from chromium, which one implements icc profile caching. Bug: chromium:945468 Change-Id: Id6e3920233771e035f7578847406bf1f519dcd49 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133580 Commit-Queue: Julien Isorce <julien.isorce@chromium.org> Reviewed-by: Sergey Ulanov <sergeyu@chromium.org> Reviewed-by: Brave Yao <braveyao@webrtc.org> Reviewed-by: Jamie Walch <jamiewalch@chromium.org> Cr-Commit-Position: refs/heads/master@{#27697}
This commit is contained in:
committed by
Commit Bot
parent
5665572f47
commit
62acb5a8c0
@ -398,6 +398,8 @@ rtc_static_library("desktop_capture_generic") {
|
||||
"linux/x_error_trap.h",
|
||||
"linux/x_server_pixel_buffer.cc",
|
||||
"linux/x_server_pixel_buffer.h",
|
||||
"linux/x_window_property.cc",
|
||||
"linux/x_window_property.h",
|
||||
]
|
||||
configs += [ "//build/config/linux:x11" ]
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "absl/memory/memory.h"
|
||||
#include "modules/desktop_capture/cropped_desktop_frame.h"
|
||||
#include "modules/desktop_capture/desktop_frame.h"
|
||||
#include "modules/desktop_capture/shared_desktop_frame.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -77,4 +78,33 @@ TEST(CroppedDesktopFrameTest, InitializedWithZeros) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CroppedDesktopFrameTest, IccProfile) {
|
||||
const uint8_t fake_icc_profile_data_array[] = {0x1a, 0x00, 0x2b, 0x00,
|
||||
0x3c, 0x00, 0x4d};
|
||||
const std::vector<uint8_t> icc_profile(
|
||||
fake_icc_profile_data_array,
|
||||
fake_icc_profile_data_array + sizeof(fake_icc_profile_data_array));
|
||||
|
||||
std::unique_ptr<DesktopFrame> frame = CreateTestFrame();
|
||||
EXPECT_EQ(frame->icc_profile().size(), 0UL);
|
||||
|
||||
frame->set_icc_profile(icc_profile);
|
||||
EXPECT_EQ(frame->icc_profile().size(), 7UL);
|
||||
EXPECT_EQ(frame->icc_profile(), icc_profile);
|
||||
|
||||
frame = CreateCroppedDesktopFrame(std::move(frame),
|
||||
DesktopRect::MakeLTRB(2, 2, 8, 18));
|
||||
EXPECT_EQ(frame->icc_profile().size(), 7UL);
|
||||
EXPECT_EQ(frame->icc_profile(), icc_profile);
|
||||
|
||||
std::unique_ptr<SharedDesktopFrame> shared =
|
||||
SharedDesktopFrame::Wrap(std::move(frame));
|
||||
EXPECT_EQ(shared->icc_profile().size(), 7UL);
|
||||
EXPECT_EQ(shared->icc_profile(), icc_profile);
|
||||
|
||||
std::unique_ptr<DesktopFrame> shared_other = shared->Share();
|
||||
EXPECT_EQ(shared_other->icc_profile().size(), 7UL);
|
||||
EXPECT_EQ(shared_other->icc_profile(), icc_profile);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -90,6 +90,7 @@ void DesktopFrame::CopyFrameInfoFrom(const DesktopFrame& other) {
|
||||
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) {
|
||||
@ -98,6 +99,7 @@ void DesktopFrame::MoveFrameInfoFrom(DesktopFrame* other) {
|
||||
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)
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/desktop_capture/desktop_geometry.h"
|
||||
#include "modules/desktop_capture/desktop_region.h"
|
||||
@ -110,6 +111,15 @@ class RTC_EXPORT DesktopFrame {
|
||||
// DesktopFrameWithCursor.
|
||||
void MoveFrameInfoFrom(DesktopFrame* other);
|
||||
|
||||
// Set and get the ICC profile of the frame data pixels. Useful to build the
|
||||
// a ColorSpace object from clients of webrtc library like chromium. The
|
||||
// format of an ICC profile is defined in the following specification
|
||||
// http://www.color.org/specification/ICC1v43_2010-12.pdf.
|
||||
const std::vector<uint8_t>& icc_profile() const { return icc_profile_; }
|
||||
void set_icc_profile(const std::vector<uint8_t>& icc_profile) {
|
||||
icc_profile_ = icc_profile;
|
||||
}
|
||||
|
||||
protected:
|
||||
DesktopFrame(DesktopSize size,
|
||||
int stride,
|
||||
@ -131,6 +141,7 @@ class RTC_EXPORT DesktopFrame {
|
||||
DesktopVector dpi_;
|
||||
int64_t capture_time_ms_;
|
||||
uint32_t capturer_id_;
|
||||
std::vector<uint8_t> icc_profile_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(DesktopFrame);
|
||||
};
|
||||
|
||||
@ -849,6 +849,10 @@ void BaseCapturerPipeWire::CaptureFrame() {
|
||||
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on the
|
||||
// frame, see ScreenCapturerX11::CaptureFrame.
|
||||
|
||||
callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "modules/desktop_capture/desktop_capturer.h"
|
||||
#include "modules/desktop_capture/desktop_frame.h"
|
||||
@ -51,6 +52,8 @@ bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) {
|
||||
TRACE_EVENT0("webrtc", "ScreenCapturerX11::Init");
|
||||
options_ = options;
|
||||
|
||||
atom_cache_ = absl::make_unique<XAtomCache>(display());
|
||||
|
||||
root_window_ = RootWindow(display(), DefaultScreen(display()));
|
||||
if (root_window_ == BadValue) {
|
||||
RTC_LOG(LS_ERROR) << "Unable to get the root window";
|
||||
@ -79,7 +82,8 @@ bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) {
|
||||
// Register for changes to the dimensions of the root window.
|
||||
XSelectInput(display(), root_window_, StructureNotifyMask);
|
||||
|
||||
if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
|
||||
if (!x_server_pixel_buffer_.Init(atom_cache_.get(),
|
||||
DefaultRootWindow(display()))) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to initialize pixel buffer.";
|
||||
return false;
|
||||
}
|
||||
@ -272,7 +276,8 @@ void ScreenCapturerX11::ScreenConfigurationChanged() {
|
||||
queue_.Reset();
|
||||
|
||||
helper_.ClearInvalidRegion();
|
||||
if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) {
|
||||
if (!x_server_pixel_buffer_.Init(atom_cache_.get(),
|
||||
DefaultRootWindow(display()))) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen "
|
||||
"configuration change.";
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include "modules/desktop_capture/desktop_frame.h"
|
||||
#include "modules/desktop_capture/desktop_region.h"
|
||||
#include "modules/desktop_capture/linux/shared_x_display.h"
|
||||
#include "modules/desktop_capture/linux/x_atom_cache.h"
|
||||
#include "modules/desktop_capture/linux/x_server_pixel_buffer.h"
|
||||
#include "modules/desktop_capture/screen_capture_frame_queue.h"
|
||||
#include "modules/desktop_capture/screen_capturer_helper.h"
|
||||
@ -116,6 +117,8 @@ class ScreenCapturerX11 : public DesktopCapturer,
|
||||
// current with the last buffer used.
|
||||
DesktopRegion last_invalid_region_;
|
||||
|
||||
std::unique_ptr<XAtomCache> atom_cache_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerX11);
|
||||
};
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ bool WindowCapturerX11::GetSourceList(SourceList* sources) {
|
||||
}
|
||||
|
||||
bool WindowCapturerX11::SelectSource(SourceId id) {
|
||||
if (!x_server_pixel_buffer_.Init(display(), id))
|
||||
if (!x_server_pixel_buffer_.Init(&atom_cache_, id))
|
||||
return false;
|
||||
|
||||
// Tell the X server to send us window resizing events.
|
||||
@ -194,7 +194,7 @@ bool WindowCapturerX11::HandleXEvent(const XEvent& event) {
|
||||
if (xce.window == selected_window_) {
|
||||
if (!DesktopRectFromXAttributes(xce).equals(
|
||||
x_server_pixel_buffer_.window_rect())) {
|
||||
if (!x_server_pixel_buffer_.Init(display(), selected_window_)) {
|
||||
if (!x_server_pixel_buffer_.Init(&atom_cache_, selected_window_)) {
|
||||
RTC_LOG(LS_ERROR)
|
||||
<< "Failed to initialize pixel buffer after resizing.";
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "modules/desktop_capture/linux/x_error_trap.h"
|
||||
#include "modules/desktop_capture/linux/x_window_property.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/logging.h"
|
||||
@ -38,53 +39,6 @@ DeferXFree::~DeferXFree() {
|
||||
XFree(data_);
|
||||
}
|
||||
|
||||
// Convenience wrapper for XGetWindowProperty() results.
|
||||
template <class PropertyType>
|
||||
class XWindowProperty {
|
||||
public:
|
||||
XWindowProperty(Display* display, Window window, Atom property) {
|
||||
const int kBitsPerByte = 8;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long bytes_after; // NOLINT: type required by XGetWindowProperty
|
||||
int status = XGetWindowProperty(
|
||||
display, window, property, 0L, ~0L, False, AnyPropertyType,
|
||||
&actual_type, &actual_format, &size_, &bytes_after, &data_);
|
||||
if (status != Success) {
|
||||
data_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (sizeof(PropertyType) * kBitsPerByte != actual_format) {
|
||||
size_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
~XWindowProperty() {
|
||||
if (data_)
|
||||
XFree(data_);
|
||||
}
|
||||
|
||||
// True if we got properly value successfully.
|
||||
bool is_valid() const { return is_valid_; }
|
||||
|
||||
// Size and value of the property.
|
||||
size_t size() const { return size_; }
|
||||
const PropertyType* data() const {
|
||||
return reinterpret_cast<PropertyType*>(data_);
|
||||
}
|
||||
PropertyType* data() { return reinterpret_cast<PropertyType*>(data_); }
|
||||
|
||||
private:
|
||||
bool is_valid_ = false;
|
||||
unsigned long size_ = 0; // NOLINT: type required by XGetWindowProperty
|
||||
unsigned char* data_ = nullptr;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty);
|
||||
};
|
||||
|
||||
// Iterates through |window| hierarchy to find first visible window, i.e. one
|
||||
// that has WM_STATE property set to NormalState.
|
||||
// See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
|
||||
|
||||
@ -36,6 +36,10 @@ Atom XAtomCache::WindowTypeNormal() {
|
||||
return CreateIfNotExist(&window_type_normal_, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
}
|
||||
|
||||
Atom XAtomCache::IccProfile() {
|
||||
return CreateIfNotExist(&icc_profile_, "_ICC_PROFILE");
|
||||
}
|
||||
|
||||
Atom XAtomCache::CreateIfNotExist(Atom* atom, const char* name) {
|
||||
RTC_DCHECK(atom);
|
||||
if (*atom == None) {
|
||||
|
||||
@ -27,6 +27,7 @@ class XAtomCache final {
|
||||
Atom WmState();
|
||||
Atom WindowType();
|
||||
Atom WindowTypeNormal();
|
||||
Atom IccProfile();
|
||||
|
||||
private:
|
||||
// If |*atom| is None, this function uses XInternAtom() to retrieve an Atom.
|
||||
@ -36,6 +37,7 @@ class XAtomCache final {
|
||||
Atom wm_state_ = None;
|
||||
Atom window_type_ = None;
|
||||
Atom window_type_normal_ = None;
|
||||
Atom icc_profile_ = None;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "modules/desktop_capture/desktop_frame.h"
|
||||
#include "modules/desktop_capture/linux/window_list_utils.h"
|
||||
#include "modules/desktop_capture/linux/x_error_trap.h"
|
||||
#include "modules/desktop_capture/linux/x_window_property.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
@ -172,15 +173,28 @@ void XServerPixelBuffer::ReleaseSharedMemorySegment() {
|
||||
shm_segment_info_ = nullptr;
|
||||
}
|
||||
|
||||
bool XServerPixelBuffer::Init(Display* display, Window window) {
|
||||
bool XServerPixelBuffer::Init(XAtomCache* cache, Window window) {
|
||||
Release();
|
||||
display_ = display;
|
||||
display_ = cache->display();
|
||||
|
||||
XWindowAttributes attributes;
|
||||
if (!GetWindowRect(display_, window, &window_rect_, &attributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cache->IccProfile() != None) {
|
||||
// |window| is the root window when doing screen capture.
|
||||
XWindowProperty<uint8_t> icc_profile_property(cache->display(), window,
|
||||
cache->IccProfile());
|
||||
if (icc_profile_property.is_valid() && icc_profile_property.size() > 0) {
|
||||
icc_profile_ = std::vector<uint8_t>(
|
||||
icc_profile_property.data(),
|
||||
icc_profile_property.data() + icc_profile_property.size());
|
||||
} else {
|
||||
RTC_LOG(LS_WARNING) << "Failed to get icc profile";
|
||||
}
|
||||
}
|
||||
|
||||
window_ = window;
|
||||
InitShm(attributes);
|
||||
|
||||
@ -348,6 +362,9 @@ bool XServerPixelBuffer::CaptureRect(const DesktopRect& rect,
|
||||
SlowBlit(image, data, rect, frame);
|
||||
}
|
||||
|
||||
if (!icc_profile_.empty())
|
||||
frame->set_icc_profile(icc_profile_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,9 @@
|
||||
#ifndef MODULES_DESKTOP_CAPTURE_LINUX_X_SERVER_PIXEL_BUFFER_H_
|
||||
#define MODULES_DESKTOP_CAPTURE_LINUX_X_SERVER_PIXEL_BUFFER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
|
||||
@ -22,6 +25,7 @@
|
||||
namespace webrtc {
|
||||
|
||||
class DesktopFrame;
|
||||
class XAtomCache;
|
||||
|
||||
// A class to allow the X server's pixel buffer to be accessed as efficiently
|
||||
// as possible.
|
||||
@ -34,7 +38,7 @@ class XServerPixelBuffer {
|
||||
|
||||
// Allocate (or reallocate) the pixel buffer for |window|. Returns false in
|
||||
// case of an error (e.g. window doesn't exist).
|
||||
bool Init(Display* display, Window window);
|
||||
bool Init(XAtomCache* cache, Window window);
|
||||
|
||||
bool is_initialized() { return window_ != 0; }
|
||||
|
||||
@ -75,6 +79,7 @@ class XServerPixelBuffer {
|
||||
Pixmap shm_pixmap_ = 0;
|
||||
GC shm_gc_ = nullptr;
|
||||
bool xshm_get_image_succeeded_ = false;
|
||||
std::vector<uint8_t> icc_profile_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(XServerPixelBuffer);
|
||||
};
|
||||
|
||||
43
modules/desktop_capture/linux/x_window_property.cc
Normal file
43
modules/desktop_capture/linux/x_window_property.cc
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2019 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/linux/x_window_property.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
XWindowPropertyBase::XWindowPropertyBase(Display* display,
|
||||
Window window,
|
||||
Atom property,
|
||||
int expected_size) {
|
||||
const int kBitsPerByte = 8;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long bytes_after; // NOLINT: type required by XGetWindowProperty
|
||||
int status = XGetWindowProperty(display, window, property, 0L, ~0L, False,
|
||||
AnyPropertyType, &actual_type, &actual_format,
|
||||
&size_, &bytes_after, &data_);
|
||||
if (status != Success) {
|
||||
data_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if ((expected_size * kBitsPerByte) != actual_format) {
|
||||
size_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
XWindowPropertyBase::~XWindowPropertyBase() {
|
||||
if (data_)
|
||||
XFree(data_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
63
modules/desktop_capture/linux/x_window_property.h
Normal file
63
modules/desktop_capture/linux/x_window_property.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2019 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.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_DESKTOP_CAPTURE_LINUX_X_WINDOW_PROPERTY_H_
|
||||
#define MODULES_DESKTOP_CAPTURE_LINUX_X_WINDOW_PROPERTY_H_
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class XWindowPropertyBase {
|
||||
public:
|
||||
XWindowPropertyBase(Display* display,
|
||||
Window window,
|
||||
Atom property,
|
||||
int expected_size);
|
||||
virtual ~XWindowPropertyBase();
|
||||
|
||||
// True if we got properly value successfully.
|
||||
bool is_valid() const { return is_valid_; }
|
||||
|
||||
// Size and value of the property.
|
||||
size_t size() const { return size_; }
|
||||
|
||||
protected:
|
||||
unsigned char* data_ = nullptr;
|
||||
|
||||
private:
|
||||
bool is_valid_ = false;
|
||||
unsigned long size_ = 0; // NOLINT: type required by XGetWindowProperty
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(XWindowPropertyBase);
|
||||
};
|
||||
|
||||
// Convenience wrapper for XGetWindowProperty() results.
|
||||
template <class PropertyType>
|
||||
class XWindowProperty : public XWindowPropertyBase {
|
||||
public:
|
||||
XWindowProperty(Display* display, const Window window, const Atom property)
|
||||
: XWindowPropertyBase(display, window, property, sizeof(PropertyType)) {}
|
||||
~XWindowProperty() override = default;
|
||||
|
||||
const PropertyType* data() const {
|
||||
return reinterpret_cast<PropertyType*>(data_);
|
||||
}
|
||||
PropertyType* data() { return reinterpret_cast<PropertyType*>(data_); }
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_DESKTOP_CAPTURE_LINUX_X_WINDOW_PROPERTY_H_
|
||||
@ -68,8 +68,21 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateFromCGImage(
|
||||
DesktopSize size(CGImageGetWidth(cg_image.get()), CGImageGetHeight(cg_image.get()));
|
||||
int stride = CGImageGetBytesPerRow(cg_image.get());
|
||||
|
||||
return std::unique_ptr<DesktopFrameCGImage>(
|
||||
std::unique_ptr<DesktopFrameCGImage> frame(
|
||||
new DesktopFrameCGImage(size, stride, data, cg_image, cg_data));
|
||||
|
||||
CGColorSpaceRef cg_color_space = CGImageGetColorSpace(cg_image.get());
|
||||
if (cg_color_space) {
|
||||
rtc::ScopedCFTypeRef<CFDataRef> cf_icc_profile(CGColorSpaceCopyICCProfile(cg_color_space));
|
||||
const uint8_t* data_as_byte =
|
||||
reinterpret_cast<const uint8_t*>(CFDataGetBytePtr(cf_icc_profile.get()));
|
||||
const size_t data_size = CFDataGetLength(cf_icc_profile.get());
|
||||
if (data_as_byte && data_size > 0) {
|
||||
frame->set_icc_profile(std::vector<uint8_t>(data_as_byte, data_as_byte + data_size));
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
DesktopFrameCGImage::DesktopFrameCGImage(DesktopSize size,
|
||||
|
||||
@ -172,6 +172,10 @@ void ScreenCapturerWinDirectx::CaptureFrame() {
|
||||
frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) /
|
||||
rtc::kNumNanosecsPerMillisec);
|
||||
frame->set_capturer_id(DesktopCapturerId::kScreenCapturerWinDirectx);
|
||||
|
||||
// TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on
|
||||
// the frame, see WindowCapturerMac::CaptureFrame.
|
||||
|
||||
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user