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}
diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn
index 57f7a34..e6797bf 100644
--- a/modules/desktop_capture/BUILD.gn
+++ b/modules/desktop_capture/BUILD.gn
@@ -398,6 +398,8 @@
       "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 fdf51ae..92207e4 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, 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
diff --git a/modules/desktop_capture/desktop_frame.cc b/modules/desktop_capture/desktop_frame.cc
index eaee0aa..70af145 100644
--- a/modules/desktop_capture/desktop_frame.cc
+++ b/modules/desktop_capture/desktop_frame.cc
@@ -90,6 +90,7 @@
   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 @@
   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 ef5ed72..5658b1c 100644
--- a/modules/desktop_capture/desktop_frame.h
+++ b/modules/desktop_capture/desktop_frame.h
@@ -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 @@
   // 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 @@
   DesktopVector dpi_;
   int64_t capture_time_ms_;
   uint32_t capturer_id_;
+  std::vector<uint8_t> 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 05ad86f..f79d0a1 100644
--- a/modules/desktop_capture/linux/base_capturer_pipewire.cc
+++ b/modules/desktop_capture/linux/base_capturer_pipewire.cc
@@ -849,6 +849,10 @@
     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 6cd40c1..dc81393 100644
--- a/modules/desktop_capture/linux/screen_capturer_x11.cc
+++ b/modules/desktop_capture/linux/screen_capturer_x11.cc
@@ -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 @@
   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 @@
   // 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 @@
   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 6412a76..b3b6604 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 @@
   // current with the last buffer used.
   DesktopRegion last_invalid_region_;
 
+  std::unique_ptr<XAtomCache> 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 85a51a6..674c891 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::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 @@
     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 906042a..e71f28a 100644
--- a/modules/desktop_capture/linux/window_list_utils.cc
+++ b/modules/desktop_capture/linux/window_list_utils.cc
@@ -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 @@
     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 .
diff --git a/modules/desktop_capture/linux/x_atom_cache.cc b/modules/desktop_capture/linux/x_atom_cache.cc
index 832e616..4ea0249 100644
--- a/modules/desktop_capture/linux/x_atom_cache.cc
+++ b/modules/desktop_capture/linux/x_atom_cache.cc
@@ -36,6 +36,10 @@
   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 731b616..0249c15 100644
--- a/modules/desktop_capture/linux/x_atom_cache.h
+++ b/modules/desktop_capture/linux/x_atom_cache.h
@@ -27,6 +27,7 @@
   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 @@
   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 364c43b..9d8efdd 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 @@
   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 @@
     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 a11ca20..98790e3 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 <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 @@
 
   // 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 @@
   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);
 };
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 0000000..ba25dee
--- /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 0000000..ef643b6
--- /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 <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_
diff --git a/modules/desktop_capture/mac/desktop_frame_cgimage.mm b/modules/desktop_capture/mac/desktop_frame_cgimage.mm
index 784b04f..dddf4a4 100644
--- a/modules/desktop_capture/mac/desktop_frame_cgimage.mm
+++ b/modules/desktop_capture/mac/desktop_frame_cgimage.mm
@@ -68,8 +68,21 @@
   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,
diff --git a/modules/desktop_capture/win/screen_capturer_win_directx.cc b/modules/desktop_capture/win/screen_capturer_win_directx.cc
index 7d4d0aa..ad62fb8 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 @@
       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;
     }