xref: /aosp_15_r20/external/webrtc/modules/desktop_capture/desktop_frame.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_H_
12*d9f75844SAndroid Build Coastguard Worker #define MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "modules/desktop_capture/desktop_geometry.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/desktop_capture/desktop_region.h"
21*d9f75844SAndroid Build Coastguard Worker #include "modules/desktop_capture/shared_memory.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/rtc_export.h"
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker const float kStandardDPI = 96.0f;
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker // DesktopFrame represents a video frame captured from the screen.
29*d9f75844SAndroid Build Coastguard Worker class RTC_EXPORT DesktopFrame {
30*d9f75844SAndroid Build Coastguard Worker  public:
31*d9f75844SAndroid Build Coastguard Worker   // DesktopFrame objects always hold BGRA data.
32*d9f75844SAndroid Build Coastguard Worker   static const int kBytesPerPixel = 4;
33*d9f75844SAndroid Build Coastguard Worker 
34*d9f75844SAndroid Build Coastguard Worker   virtual ~DesktopFrame();
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker   DesktopFrame(const DesktopFrame&) = delete;
37*d9f75844SAndroid Build Coastguard Worker   DesktopFrame& operator=(const DesktopFrame&) = delete;
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker   // Returns the rectangle in full desktop coordinates to indicate it covers
40*d9f75844SAndroid Build Coastguard Worker   // the area of top_left() to top_letf() + size() / scale_factor().
41*d9f75844SAndroid Build Coastguard Worker   DesktopRect rect() const;
42*d9f75844SAndroid Build Coastguard Worker 
43*d9f75844SAndroid Build Coastguard Worker   // Returns the scale factor from DIPs to physical pixels of the frame.
44*d9f75844SAndroid Build Coastguard Worker   // Assumes same scale in both X and Y directions at present.
45*d9f75844SAndroid Build Coastguard Worker   float scale_factor() const;
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker   // Size of the frame. In physical coordinates, mapping directly from the
48*d9f75844SAndroid Build Coastguard Worker   // underlying buffer.
size()49*d9f75844SAndroid Build Coastguard Worker   const DesktopSize& size() const { return size_; }
50*d9f75844SAndroid Build Coastguard Worker 
51*d9f75844SAndroid Build Coastguard Worker   // The top-left of the frame in full desktop coordinates. E.g. the top left
52*d9f75844SAndroid Build Coastguard Worker   // monitor should start from (0, 0). The desktop coordinates may be scaled by
53*d9f75844SAndroid Build Coastguard Worker   // OS, but this is always consistent with the MouseCursorMonitor.
top_left()54*d9f75844SAndroid Build Coastguard Worker   const DesktopVector& top_left() const { return top_left_; }
set_top_left(const DesktopVector & top_left)55*d9f75844SAndroid Build Coastguard Worker   void set_top_left(const DesktopVector& top_left) { top_left_ = top_left; }
56*d9f75844SAndroid Build Coastguard Worker 
57*d9f75844SAndroid Build Coastguard Worker   // Distance in the buffer between two neighboring rows in bytes.
stride()58*d9f75844SAndroid Build Coastguard Worker   int stride() const { return stride_; }
59*d9f75844SAndroid Build Coastguard Worker 
60*d9f75844SAndroid Build Coastguard Worker   // Data buffer used for the frame.
data()61*d9f75844SAndroid Build Coastguard Worker   uint8_t* data() const { return data_; }
62*d9f75844SAndroid Build Coastguard Worker 
63*d9f75844SAndroid Build Coastguard Worker   // SharedMemory used for the buffer or NULL if memory is allocated on the
64*d9f75844SAndroid Build Coastguard Worker   // heap. The result is guaranteed to be deleted only after the frame is
65*d9f75844SAndroid Build Coastguard Worker   // deleted (classes that inherit from DesktopFrame must ensure it).
shared_memory()66*d9f75844SAndroid Build Coastguard Worker   SharedMemory* shared_memory() const { return shared_memory_; }
67*d9f75844SAndroid Build Coastguard Worker 
68*d9f75844SAndroid Build Coastguard Worker   // Indicates region of the screen that has changed since the previous frame.
updated_region()69*d9f75844SAndroid Build Coastguard Worker   const DesktopRegion& updated_region() const { return updated_region_; }
mutable_updated_region()70*d9f75844SAndroid Build Coastguard Worker   DesktopRegion* mutable_updated_region() { return &updated_region_; }
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker   // DPI of the screen being captured. May be set to zero, e.g. if DPI is
73*d9f75844SAndroid Build Coastguard Worker   // unknown.
dpi()74*d9f75844SAndroid Build Coastguard Worker   const DesktopVector& dpi() const { return dpi_; }
set_dpi(const DesktopVector & dpi)75*d9f75844SAndroid Build Coastguard Worker   void set_dpi(const DesktopVector& dpi) { dpi_ = dpi; }
76*d9f75844SAndroid Build Coastguard Worker 
77*d9f75844SAndroid Build Coastguard Worker   // Indicates if this frame may have the mouse cursor in it. Capturers that
78*d9f75844SAndroid Build Coastguard Worker   // support cursor capture may set this to true. If the cursor was
79*d9f75844SAndroid Build Coastguard Worker   // outside of the captured area, this may be true even though the cursor is
80*d9f75844SAndroid Build Coastguard Worker   // not in the image.
may_contain_cursor()81*d9f75844SAndroid Build Coastguard Worker   bool may_contain_cursor() const { return may_contain_cursor_; }
set_may_contain_cursor(bool may_contain_cursor)82*d9f75844SAndroid Build Coastguard Worker   void set_may_contain_cursor(bool may_contain_cursor) {
83*d9f75844SAndroid Build Coastguard Worker     may_contain_cursor_ = may_contain_cursor;
84*d9f75844SAndroid Build Coastguard Worker   }
85*d9f75844SAndroid Build Coastguard Worker 
86*d9f75844SAndroid Build Coastguard Worker   // Time taken to capture the frame in milliseconds.
capture_time_ms()87*d9f75844SAndroid Build Coastguard Worker   int64_t capture_time_ms() const { return capture_time_ms_; }
set_capture_time_ms(int64_t time_ms)88*d9f75844SAndroid Build Coastguard Worker   void set_capture_time_ms(int64_t time_ms) { capture_time_ms_ = time_ms; }
89*d9f75844SAndroid Build Coastguard Worker 
90*d9f75844SAndroid Build Coastguard Worker   // Copies pixels from a buffer or another frame. `dest_rect` rect must lay
91*d9f75844SAndroid Build Coastguard Worker   // within bounds of this frame.
92*d9f75844SAndroid Build Coastguard Worker   void CopyPixelsFrom(const uint8_t* src_buffer,
93*d9f75844SAndroid Build Coastguard Worker                       int src_stride,
94*d9f75844SAndroid Build Coastguard Worker                       const DesktopRect& dest_rect);
95*d9f75844SAndroid Build Coastguard Worker   void CopyPixelsFrom(const DesktopFrame& src_frame,
96*d9f75844SAndroid Build Coastguard Worker                       const DesktopVector& src_pos,
97*d9f75844SAndroid Build Coastguard Worker                       const DesktopRect& dest_rect);
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker   // Copies pixels from another frame, with the copied & overwritten regions
100*d9f75844SAndroid Build Coastguard Worker   // representing the intersection between the two frames. Returns true if
101*d9f75844SAndroid Build Coastguard Worker   // pixels were copied, or false if there's no intersection. The scale factors
102*d9f75844SAndroid Build Coastguard Worker   // represent the ratios between pixel space & offset coordinate space (e.g.
103*d9f75844SAndroid Build Coastguard Worker   // 2.0 would indicate the frames are scaled down by 50% for display, so any
104*d9f75844SAndroid Build Coastguard Worker   // offset between their origins should be doubled).
105*d9f75844SAndroid Build Coastguard Worker   bool CopyIntersectingPixelsFrom(const DesktopFrame& src_frame,
106*d9f75844SAndroid Build Coastguard Worker                                   double horizontal_scale,
107*d9f75844SAndroid Build Coastguard Worker                                   double vertical_scale);
108*d9f75844SAndroid Build Coastguard Worker 
109*d9f75844SAndroid Build Coastguard Worker   // A helper to return the data pointer of a frame at the specified position.
110*d9f75844SAndroid Build Coastguard Worker   uint8_t* GetFrameDataAtPos(const DesktopVector& pos) const;
111*d9f75844SAndroid Build Coastguard Worker 
112*d9f75844SAndroid Build Coastguard Worker   // The DesktopCapturer implementation which generates current DesktopFrame.
113*d9f75844SAndroid Build Coastguard Worker   // Not all DesktopCapturer implementations set this field; it's set to
114*d9f75844SAndroid Build Coastguard Worker   // kUnknown by default.
capturer_id()115*d9f75844SAndroid Build Coastguard Worker   uint32_t capturer_id() const { return capturer_id_; }
set_capturer_id(uint32_t capturer_id)116*d9f75844SAndroid Build Coastguard Worker   void set_capturer_id(uint32_t capturer_id) { capturer_id_ = capturer_id; }
117*d9f75844SAndroid Build Coastguard Worker 
118*d9f75844SAndroid Build Coastguard Worker   // Copies various information from `other`. Anything initialized in
119*d9f75844SAndroid Build Coastguard Worker   // constructor are not copied.
120*d9f75844SAndroid Build Coastguard Worker   // This function is usually used when sharing a source DesktopFrame with
121*d9f75844SAndroid Build Coastguard Worker   // several clients: the original DesktopFrame should be kept unchanged. For
122*d9f75844SAndroid Build Coastguard Worker   // example, BasicDesktopFrame::CopyOf() and SharedDesktopFrame::Share().
123*d9f75844SAndroid Build Coastguard Worker   void CopyFrameInfoFrom(const DesktopFrame& other);
124*d9f75844SAndroid Build Coastguard Worker 
125*d9f75844SAndroid Build Coastguard Worker   // Copies various information from `other`. Anything initialized in
126*d9f75844SAndroid Build Coastguard Worker   // constructor are not copied. Not like CopyFrameInfoFrom() function, this
127*d9f75844SAndroid Build Coastguard Worker   // function uses swap or move constructor to avoid data copy. It won't break
128*d9f75844SAndroid Build Coastguard Worker   // the `other`, but some of its information may be missing after this
129*d9f75844SAndroid Build Coastguard Worker   // operation. E.g. other->updated_region_;
130*d9f75844SAndroid Build Coastguard Worker   // This function is usually used when wrapping a DesktopFrame: the wrapper
131*d9f75844SAndroid Build Coastguard Worker   // instance takes the ownership of `other`, so other components cannot access
132*d9f75844SAndroid Build Coastguard Worker   // `other` anymore. For example, CroppedDesktopFrame and
133*d9f75844SAndroid Build Coastguard Worker   // DesktopFrameWithCursor.
134*d9f75844SAndroid Build Coastguard Worker   void MoveFrameInfoFrom(DesktopFrame* other);
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker   // Set and get the ICC profile of the frame data pixels. Useful to build the
137*d9f75844SAndroid Build Coastguard Worker   // a ColorSpace object from clients of webrtc library like chromium. The
138*d9f75844SAndroid Build Coastguard Worker   // format of an ICC profile is defined in the following specification
139*d9f75844SAndroid Build Coastguard Worker   // http://www.color.org/specification/ICC1v43_2010-12.pdf.
icc_profile()140*d9f75844SAndroid Build Coastguard Worker   const std::vector<uint8_t>& icc_profile() const { return icc_profile_; }
set_icc_profile(const std::vector<uint8_t> & icc_profile)141*d9f75844SAndroid Build Coastguard Worker   void set_icc_profile(const std::vector<uint8_t>& icc_profile) {
142*d9f75844SAndroid Build Coastguard Worker     icc_profile_ = icc_profile;
143*d9f75844SAndroid Build Coastguard Worker   }
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker  protected:
146*d9f75844SAndroid Build Coastguard Worker   DesktopFrame(DesktopSize size,
147*d9f75844SAndroid Build Coastguard Worker                int stride,
148*d9f75844SAndroid Build Coastguard Worker                uint8_t* data,
149*d9f75844SAndroid Build Coastguard Worker                SharedMemory* shared_memory);
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   // Ownership of the buffers is defined by the classes that inherit from this
152*d9f75844SAndroid Build Coastguard Worker   // class. They must guarantee that the buffer is not deleted before the frame
153*d9f75844SAndroid Build Coastguard Worker   // is deleted.
154*d9f75844SAndroid Build Coastguard Worker   uint8_t* const data_;
155*d9f75844SAndroid Build Coastguard Worker   SharedMemory* const shared_memory_;
156*d9f75844SAndroid Build Coastguard Worker 
157*d9f75844SAndroid Build Coastguard Worker  private:
158*d9f75844SAndroid Build Coastguard Worker   const DesktopSize size_;
159*d9f75844SAndroid Build Coastguard Worker   const int stride_;
160*d9f75844SAndroid Build Coastguard Worker 
161*d9f75844SAndroid Build Coastguard Worker   DesktopRegion updated_region_;
162*d9f75844SAndroid Build Coastguard Worker   DesktopVector top_left_;
163*d9f75844SAndroid Build Coastguard Worker   DesktopVector dpi_;
164*d9f75844SAndroid Build Coastguard Worker   bool may_contain_cursor_ = false;
165*d9f75844SAndroid Build Coastguard Worker   int64_t capture_time_ms_;
166*d9f75844SAndroid Build Coastguard Worker   uint32_t capturer_id_;
167*d9f75844SAndroid Build Coastguard Worker   std::vector<uint8_t> icc_profile_;
168*d9f75844SAndroid Build Coastguard Worker };
169*d9f75844SAndroid Build Coastguard Worker 
170*d9f75844SAndroid Build Coastguard Worker // A DesktopFrame that stores data in the heap.
171*d9f75844SAndroid Build Coastguard Worker class RTC_EXPORT BasicDesktopFrame : public DesktopFrame {
172*d9f75844SAndroid Build Coastguard Worker  public:
173*d9f75844SAndroid Build Coastguard Worker   // The entire data buffer used for the frame is initialized with zeros.
174*d9f75844SAndroid Build Coastguard Worker   explicit BasicDesktopFrame(DesktopSize size);
175*d9f75844SAndroid Build Coastguard Worker 
176*d9f75844SAndroid Build Coastguard Worker   ~BasicDesktopFrame() override;
177*d9f75844SAndroid Build Coastguard Worker 
178*d9f75844SAndroid Build Coastguard Worker   BasicDesktopFrame(const BasicDesktopFrame&) = delete;
179*d9f75844SAndroid Build Coastguard Worker   BasicDesktopFrame& operator=(const BasicDesktopFrame&) = delete;
180*d9f75844SAndroid Build Coastguard Worker 
181*d9f75844SAndroid Build Coastguard Worker   // Creates a BasicDesktopFrame that contains copy of `frame`.
182*d9f75844SAndroid Build Coastguard Worker   // TODO(zijiehe): Return std::unique_ptr<DesktopFrame>
183*d9f75844SAndroid Build Coastguard Worker   static DesktopFrame* CopyOf(const DesktopFrame& frame);
184*d9f75844SAndroid Build Coastguard Worker };
185*d9f75844SAndroid Build Coastguard Worker 
186*d9f75844SAndroid Build Coastguard Worker // A DesktopFrame that stores data in shared memory.
187*d9f75844SAndroid Build Coastguard Worker class RTC_EXPORT SharedMemoryDesktopFrame : public DesktopFrame {
188*d9f75844SAndroid Build Coastguard Worker  public:
189*d9f75844SAndroid Build Coastguard Worker   // May return nullptr if `shared_memory_factory` failed to create a
190*d9f75844SAndroid Build Coastguard Worker   // SharedMemory instance.
191*d9f75844SAndroid Build Coastguard Worker   // `shared_memory_factory` should not be nullptr.
192*d9f75844SAndroid Build Coastguard Worker   static std::unique_ptr<DesktopFrame> Create(
193*d9f75844SAndroid Build Coastguard Worker       DesktopSize size,
194*d9f75844SAndroid Build Coastguard Worker       SharedMemoryFactory* shared_memory_factory);
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker   // Takes ownership of `shared_memory`.
197*d9f75844SAndroid Build Coastguard Worker   // Deprecated, use the next constructor.
198*d9f75844SAndroid Build Coastguard Worker   SharedMemoryDesktopFrame(DesktopSize size,
199*d9f75844SAndroid Build Coastguard Worker                            int stride,
200*d9f75844SAndroid Build Coastguard Worker                            SharedMemory* shared_memory);
201*d9f75844SAndroid Build Coastguard Worker 
202*d9f75844SAndroid Build Coastguard Worker   // Preferred.
203*d9f75844SAndroid Build Coastguard Worker   SharedMemoryDesktopFrame(DesktopSize size,
204*d9f75844SAndroid Build Coastguard Worker                            int stride,
205*d9f75844SAndroid Build Coastguard Worker                            std::unique_ptr<SharedMemory> shared_memory);
206*d9f75844SAndroid Build Coastguard Worker 
207*d9f75844SAndroid Build Coastguard Worker   ~SharedMemoryDesktopFrame() override;
208*d9f75844SAndroid Build Coastguard Worker 
209*d9f75844SAndroid Build Coastguard Worker   SharedMemoryDesktopFrame(const SharedMemoryDesktopFrame&) = delete;
210*d9f75844SAndroid Build Coastguard Worker   SharedMemoryDesktopFrame& operator=(const SharedMemoryDesktopFrame&) = delete;
211*d9f75844SAndroid Build Coastguard Worker 
212*d9f75844SAndroid Build Coastguard Worker  private:
213*d9f75844SAndroid Build Coastguard Worker   // Avoid unexpected order of parameter evaluation.
214*d9f75844SAndroid Build Coastguard Worker   // Executing both std::unique_ptr<T>::operator->() and
215*d9f75844SAndroid Build Coastguard Worker   // std::unique_ptr<T>::release() in the member initializer list is not safe.
216*d9f75844SAndroid Build Coastguard Worker   // Depends on the order of parameter evaluation,
217*d9f75844SAndroid Build Coastguard Worker   // std::unique_ptr<T>::operator->() may trigger assertion failure if it has
218*d9f75844SAndroid Build Coastguard Worker   // been evaluated after std::unique_ptr<T>::release(). By using this
219*d9f75844SAndroid Build Coastguard Worker   // constructor, std::unique_ptr<T>::operator->() won't be involved anymore.
220*d9f75844SAndroid Build Coastguard Worker   SharedMemoryDesktopFrame(DesktopRect rect,
221*d9f75844SAndroid Build Coastguard Worker                            int stride,
222*d9f75844SAndroid Build Coastguard Worker                            SharedMemory* shared_memory);
223*d9f75844SAndroid Build Coastguard Worker };
224*d9f75844SAndroid Build Coastguard Worker 
225*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
226*d9f75844SAndroid Build Coastguard Worker 
227*d9f75844SAndroid Build Coastguard Worker #endif  // MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_H_
228