| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 /* | 
|  | 2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 
|  | 3  * | 
|  | 4  *  Use of this source code is governed by a BSD-style license | 
|  | 5  *  that can be found in the LICENSE file in the root of the source | 
|  | 6  *  tree. An additional intellectual property rights grant can be found | 
|  | 7  *  in the file PATENTS.  All contributing project authors may | 
|  | 8  *  be found in the AUTHORS file in the root of the source tree. | 
|  | 9  */ | 
|  | 10 | 
|  | 11 #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ | 
|  | 12 #define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ | 
|  | 13 | 
|  | 14 #include <vector> | 
|  | 15 | 
|  | 16 #include "webrtc/base/criticalsection.h" | 
|  | 17 #include "webrtc/modules/desktop_capture/desktop_frame.h" | 
|  | 18 #include "webrtc/modules/desktop_capture/desktop_geometry.h" | 
|  | 19 #include "webrtc/modules/desktop_capture/desktop_region.h" | 
|  | 20 #include "webrtc/modules/desktop_capture/win/d3d_device.h" | 
|  | 21 #include "webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h" | 
|  | 22 | 
|  | 23 namespace webrtc { | 
|  | 24 | 
|  | 25 // A controller for all the objects we need to call Windows DirectX capture APIs | 
|  | 26 // It's a singleton because, only one IDXGIOutputDuplication instance per | 
|  | 27 // monitor is allowed per application. | 
|  | 28 // | 
|  | 29 // Consumers should create a DxgiDuplicatorController::Context and keep it | 
|  | 30 // throughout their lifetime, and pass it when calling Duplicate(). Consumers | 
|  | 31 // can also call IsSupported() to determine whether the system supports DXGI | 
|  | 32 // duplicator or not. If a previous IsSupported() function call returns true, | 
|  | 33 // but a later Duplicate() returns false, this usually means the display mode is | 
|  | 34 // changing. Consumers should retry after a while. (Typically 50 milliseconds, | 
|  | 35 // but according to hardware performance, this time may vary.) | 
|  | 36 // | 
|  | 37 // This class is normally used with double buffering, e.g. as in | 
|  | 38 // ScreenCapturerWinDirectx, but it should work with consumers with one buffer, | 
|  | 39 // i.e. consumers can always send nullptr for |last_frame|. Some minor changes | 
|  | 40 // in DxgiOutputDuplicator class are nice to have to reduce size of data to copy | 
|  | 41 // (Commented in dxgi_output_duplicator.cc). But this class won't work | 
|  | 42 // with three or more buffers, the updated region merging logic will be broken | 
|  | 43 // in such scenarios. If a consumer does have this requirement, one can always | 
|  | 44 // send a new Context instance to Duplicate() function to force duplicator to | 
|  | 45 // treat it as a new consumer. | 
|  | 46 class DxgiDuplicatorController { | 
|  | 47  public: | 
|  | 48   // A context to store the status of a single consumer of | 
|  | 49   // DxgiDuplicatorController. | 
|  | 50   class Context { | 
|  | 51    public: | 
|  | 52     // Unregister this Context instance from all Dxgi duplicators during | 
|  | 53     // destructing. | 
|  | 54     ~Context(); | 
|  | 55 | 
|  | 56    private: | 
|  | 57     friend class DxgiDuplicatorController; | 
|  | 58 | 
|  | 59     // A Context will have an exactly same |identity_| as | 
|  | 60     // DxgiDuplicatorController, to ensure it has been correctly setted up after | 
|  | 61     // each DxgiDuplicatorController::Initialize(). | 
|  | 62     int identity_ = 0; | 
|  | 63 | 
|  | 64     // Child DxgiAdapterDuplicator::Context belongs to this Context. | 
|  | 65     std::vector<DxgiAdapterDuplicator::Context> contexts_; | 
|  | 66   }; | 
|  | 67 | 
|  | 68   // Returns the singleton instance of DxgiDuplicatorController. | 
|  | 69   static DxgiDuplicatorController* Instance(); | 
|  | 70 | 
|  | 71   // Destructs current instance. We need to make sure COM components and their | 
|  | 72   // containers are destructed in correct order. | 
|  | 73   ~DxgiDuplicatorController(); | 
|  | 74 | 
|  | 75   // Detects whether the system supports DXGI based capturer. | 
|  | 76   bool IsSupported(); | 
|  | 77 | 
|  | 78   // Captures current screen and writes into target. Since we are using double | 
|  | 79   // buffering, |last_frame|.updated_region() is used to represent the not | 
|  | 80   // updated regions in current |target| frame, which should also be copied this | 
|  | 81   // time. | 
|  | 82   // TODO(zijiehe): Windows cannot guarantee the frames returned by each | 
|  | 83   // IDXGIOutputDuplication are synchronized. But we are using a totally | 
|  | 84   // different threading model than the way Windows suggested, it's hard to | 
|  | 85   // synchronize them manually. But we should find a way to do it. | 
|  | 86   bool Duplicate(Context* context, | 
|  | 87                  const DesktopFrame* last_frame, | 
|  | 88                  DesktopFrame* target); | 
|  | 89 | 
|  | 90   // Captures one monitor and writes into target. |monitor_id| should >= 0. If | 
|  | 91   // |monitor_id| is greater than the total screen count of all the Duplicators, | 
|  | 92   // this function returns false. | 
|  | 93   bool DuplicateMonitor(Context* context, | 
|  | 94                         int monitor_id, | 
|  | 95                         const DesktopFrame* last_frame, | 
|  | 96                         DesktopFrame* target); | 
|  | 97 | 
|  | 98   // Returns dpi of current system. Returns an empty DesktopVector if system | 
|  | 99   // does not support DXGI based capturer. | 
|  | 100   DesktopVector dpi(); | 
|  | 101 | 
|  | 102   // Returns entire desktop size. Returns an empty DesktopRect if system does | 
|  | 103   // not support DXGI based capturer. | 
|  | 104   DesktopRect desktop_rect(); | 
|  | 105 | 
|  | 106   // Returns a DesktopSize to cover entire desktop_rect. This may be different | 
|  | 107   // than desktop_rect().size(), since top-left screen does not need to start | 
|  | 108   // from (0, 0). | 
|  | 109   DesktopSize desktop_size(); | 
|  | 110 | 
|  | 111   // Returns the size of one screen. |monitor_id| should be >= 0. If system does | 
|  | 112   // not support DXGI based capturer, or |monitor_id| is greater than the total | 
|  | 113   // screen count of all the Duplicators, this function returns an empty | 
|  | 114   // DesktopRect. | 
|  | 115   DesktopRect ScreenRect(int id); | 
|  | 116 | 
|  | 117   // Returns the count of screens on the system. These screens can be retrieved | 
|  | 118   // by an integer in the range of [0, ScreenCount()). If system does not | 
|  | 119   // support DXGI based capturer, this function returns 0. | 
|  | 120   int ScreenCount(); | 
|  | 121 | 
|  | 122  private: | 
|  | 123   // Context calls private Unregister(Context*) function during | 
|  | 124   // destructing. | 
|  | 125   friend class Context; | 
|  | 126 | 
|  | 127   // A private constructor to ensure consumers to use | 
|  | 128   // DxgiDuplicatorController::Instance(). | 
|  | 129   DxgiDuplicatorController(); | 
|  | 130 | 
|  | 131   // Unregisters Context from this instance and all DxgiAdapterDuplicator(s) | 
|  | 132   // it owns. | 
|  | 133   void Unregister(const Context* const context); | 
|  | 134 | 
|  | 135   // All functions below should be called in |lock_| locked scope. | 
|  | 136 | 
|  | 137   // If current instance has not been initialized, executes DoInitialize | 
|  | 138   // function, and returns initialize result. Otherwise directly returns true. | 
|  | 139   bool Initialize(); | 
|  | 140 | 
|  | 141   bool DoInitialize(); | 
|  | 142 | 
|  | 143   // Clears all COM components referred by this instance. So next Duplicate() | 
|  | 144   // call will eventually initialize this instance again. | 
|  | 145   void Deinitialize(); | 
|  | 146 | 
|  | 147   // A helper function to check whether a Context has been expired. | 
|  | 148   bool ContextExpired(const Context* const context) const; | 
|  | 149 | 
|  | 150   // Updates Context if needed. | 
|  | 151   void Setup(Context* context); | 
|  | 152 | 
|  | 153   // Do the real duplication work. |monitor_id < 0| to capture entire screen. | 
|  | 154   bool DoDuplicate(Context* context, | 
|  | 155                    int monitor_id, | 
|  | 156                    const DesktopFrame* last_frame, | 
|  | 157                    DesktopFrame* target); | 
|  | 158 | 
|  | 159   // This lock must be locked whenever accessing any of the following objects. | 
|  | 160   rtc::CriticalSection lock_; | 
|  | 161 | 
|  | 162   // A self-incremented integer to compare with the one in Context, to | 
|  | 163   // ensure a Context has been initialized after DxgiDuplicatorController. | 
|  | 164   int identity_ = 0; | 
|  | 165   DesktopRect desktop_rect_; | 
|  | 166   DesktopVector dpi_; | 
|  | 167   std::vector<DxgiAdapterDuplicator> duplicators_; | 
|  | 168 }; | 
|  | 169 | 
|  | 170 }  // namespace webrtc | 
|  | 171 | 
|  | 172 #endif  // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ | 
| OLD | NEW | 
|---|