From 62acb5a8c0e1ea264e8f6f12d97f973d56088e28 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Fri, 19 Apr 2019 14:32:56 -0700 Subject: [PATCH] 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 Reviewed-by: Sergey Ulanov Reviewed-by: Brave Yao Reviewed-by: Jamie Walch Cr-Commit-Position: refs/heads/master@{#27697} --- modules/desktop_capture/BUILD.gn | 2 + .../cropped_desktop_frame_unittest.cc | 30 +++++++++ modules/desktop_capture/desktop_frame.cc | 2 + modules/desktop_capture/desktop_frame.h | 11 ++++ .../linux/base_capturer_pipewire.cc | 4 ++ .../linux/screen_capturer_x11.cc | 9 ++- .../linux/screen_capturer_x11.h | 3 + .../linux/window_capturer_x11.cc | 4 +- .../linux/window_list_utils.cc | 48 +------------- modules/desktop_capture/linux/x_atom_cache.cc | 4 ++ modules/desktop_capture/linux/x_atom_cache.h | 2 + .../linux/x_server_pixel_buffer.cc | 21 ++++++- .../linux/x_server_pixel_buffer.h | 7 ++- .../linux/x_window_property.cc | 43 +++++++++++++ .../desktop_capture/linux/x_window_property.h | 63 +++++++++++++++++++ .../mac/desktop_frame_cgimage.mm | 15 ++++- .../win/screen_capturer_win_directx.cc | 4 ++ 17 files changed, 217 insertions(+), 55 deletions(-) create mode 100644 modules/desktop_capture/linux/x_window_property.cc create mode 100644 modules/desktop_capture/linux/x_window_property.h diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn index 57f7a343ed..e6797bf771 100644 --- a/modules/desktop_capture/BUILD.gn +++ b/modules/desktop_capture/BUILD.gn @@ -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" ] diff --git a/modules/desktop_capture/cropped_desktop_frame_unittest.cc b/modules/desktop_capture/cropped_desktop_frame_unittest.cc index fdf51aeaff..92207e4d77 100644 --- a/modules/desktop_capture/cropped_desktop_frame_unittest.cc +++ b/modules/desktop_capture/cropped_desktop_frame_unittest.cc @@ -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 icc_profile( + fake_icc_profile_data_array, + fake_icc_profile_data_array + sizeof(fake_icc_profile_data_array)); + + std::unique_ptr 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 shared = + SharedDesktopFrame::Wrap(std::move(frame)); + EXPECT_EQ(shared->icc_profile().size(), 7UL); + EXPECT_EQ(shared->icc_profile(), icc_profile); + + std::unique_ptr shared_other = shared->Share(); + EXPECT_EQ(shared_other->icc_profile().size(), 7UL); + EXPECT_EQ(shared_other->icc_profile(), icc_profile); +} + } // namespace webrtc diff --git a/modules/desktop_capture/desktop_frame.cc b/modules/desktop_capture/desktop_frame.cc index eaee0aa26d..70af145e8b 100644 --- a/modules/desktop_capture/desktop_frame.cc +++ b/modules/desktop_capture/desktop_frame.cc @@ -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) diff --git a/modules/desktop_capture/desktop_frame.h b/modules/desktop_capture/desktop_frame.h index ef5ed7226f..5658b1c17d 100644 --- a/modules/desktop_capture/desktop_frame.h +++ b/modules/desktop_capture/desktop_frame.h @@ -13,6 +13,7 @@ #include #include +#include #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& icc_profile() const { return icc_profile_; } + void set_icc_profile(const std::vector& 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 icc_profile_; RTC_DISALLOW_COPY_AND_ASSIGN(DesktopFrame); }; diff --git a/modules/desktop_capture/linux/base_capturer_pipewire.cc b/modules/desktop_capture/linux/base_capturer_pipewire.cc index 05ad86f762..f79d0a1658 100644 --- a/modules/desktop_capture/linux/base_capturer_pipewire.cc +++ b/modules/desktop_capture/linux/base_capturer_pipewire.cc @@ -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)); } diff --git a/modules/desktop_capture/linux/screen_capturer_x11.cc b/modules/desktop_capture/linux/screen_capturer_x11.cc index 6cd40c12a6..dc81393dde 100644 --- a/modules/desktop_capture/linux/screen_capturer_x11.cc +++ b/modules/desktop_capture/linux/screen_capturer_x11.cc @@ -19,6 +19,7 @@ #include #include +#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(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."; } diff --git a/modules/desktop_capture/linux/screen_capturer_x11.h b/modules/desktop_capture/linux/screen_capturer_x11.h index 6412a7654e..b3b6604373 100644 --- a/modules/desktop_capture/linux/screen_capturer_x11.h +++ b/modules/desktop_capture/linux/screen_capturer_x11.h @@ -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 atom_cache_; + RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerX11); }; diff --git a/modules/desktop_capture/linux/window_capturer_x11.cc b/modules/desktop_capture/linux/window_capturer_x11.cc index 85a51a64c3..674c891565 100644 --- a/modules/desktop_capture/linux/window_capturer_x11.cc +++ b/modules/desktop_capture/linux/window_capturer_x11.cc @@ -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."; } diff --git a/modules/desktop_capture/linux/window_list_utils.cc b/modules/desktop_capture/linux/window_list_utils.cc index 906042aee0..e71f28a517 100644 --- a/modules/desktop_capture/linux/window_list_utils.cc +++ b/modules/desktop_capture/linux/window_list_utils.cc @@ -16,6 +16,7 @@ #include #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 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(data_); - } - PropertyType* data() { return reinterpret_cast(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 . diff --git a/modules/desktop_capture/linux/x_atom_cache.cc b/modules/desktop_capture/linux/x_atom_cache.cc index 832e6166cb..4ea024938e 100644 --- a/modules/desktop_capture/linux/x_atom_cache.cc +++ b/modules/desktop_capture/linux/x_atom_cache.cc @@ -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) { diff --git a/modules/desktop_capture/linux/x_atom_cache.h b/modules/desktop_capture/linux/x_atom_cache.h index 731b616203..0249c15978 100644 --- a/modules/desktop_capture/linux/x_atom_cache.h +++ b/modules/desktop_capture/linux/x_atom_cache.h @@ -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 diff --git a/modules/desktop_capture/linux/x_server_pixel_buffer.cc b/modules/desktop_capture/linux/x_server_pixel_buffer.cc index 364c43bbad..9d8efdd448 100644 --- a/modules/desktop_capture/linux/x_server_pixel_buffer.cc +++ b/modules/desktop_capture/linux/x_server_pixel_buffer.cc @@ -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 icc_profile_property(cache->display(), window, + cache->IccProfile()); + if (icc_profile_property.is_valid() && icc_profile_property.size() > 0) { + icc_profile_ = std::vector( + 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; } diff --git a/modules/desktop_capture/linux/x_server_pixel_buffer.h b/modules/desktop_capture/linux/x_server_pixel_buffer.h index a11ca2097d..98790e3a18 100644 --- a/modules/desktop_capture/linux/x_server_pixel_buffer.h +++ b/modules/desktop_capture/linux/x_server_pixel_buffer.h @@ -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 +#include + #include #include @@ -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 icc_profile_; RTC_DISALLOW_COPY_AND_ASSIGN(XServerPixelBuffer); }; diff --git a/modules/desktop_capture/linux/x_window_property.cc b/modules/desktop_capture/linux/x_window_property.cc new file mode 100644 index 0000000000..ba25deec3d --- /dev/null +++ b/modules/desktop_capture/linux/x_window_property.cc @@ -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 diff --git a/modules/desktop_capture/linux/x_window_property.h b/modules/desktop_capture/linux/x_window_property.h new file mode 100644 index 0000000000..ef643b6a8f --- /dev/null +++ b/modules/desktop_capture/linux/x_window_property.h @@ -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 +#include + +#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 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(data_); + } + PropertyType* data() { return reinterpret_cast(data_); } + + RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty); +}; + +} // namespace webrtc + +#endif // MODULES_DESKTOP_CAPTURE_LINUX_X_WINDOW_PROPERTY_H_ diff --git a/modules/desktop_capture/mac/desktop_frame_cgimage.mm b/modules/desktop_capture/mac/desktop_frame_cgimage.mm index 784b04f7b9..dddf4a4e1a 100644 --- a/modules/desktop_capture/mac/desktop_frame_cgimage.mm +++ b/modules/desktop_capture/mac/desktop_frame_cgimage.mm @@ -68,8 +68,21 @@ std::unique_ptr DesktopFrameCGImage::CreateFromCGImage( DesktopSize size(CGImageGetWidth(cg_image.get()), CGImageGetHeight(cg_image.get())); int stride = CGImageGetBytesPerRow(cg_image.get()); - return std::unique_ptr( + std::unique_ptr frame( new DesktopFrameCGImage(size, stride, data, cg_image, cg_data)); + + CGColorSpaceRef cg_color_space = CGImageGetColorSpace(cg_image.get()); + if (cg_color_space) { + rtc::ScopedCFTypeRef cf_icc_profile(CGColorSpaceCopyICCProfile(cg_color_space)); + const uint8_t* data_as_byte = + reinterpret_cast(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(data_as_byte, data_as_byte + data_size)); + } + } + + return frame; } DesktopFrameCGImage::DesktopFrameCGImage(DesktopSize size, diff --git a/modules/desktop_capture/win/screen_capturer_win_directx.cc b/modules/desktop_capture/win/screen_capturer_win_directx.cc index 7d4d0aa92c..ad62fb8867 100644 --- a/modules/desktop_capture/win/screen_capturer_win_directx.cc +++ b/modules/desktop_capture/win/screen_capturer_win_directx.cc @@ -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; }