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