Chromium Code Reviews| 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 MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTAINER_H_ | |
| 12 #define MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTAINER_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 #include "webrtc/modules/desktop_capture/win/dxgi_context.h" | |
| 23 | |
| 24 namespace webrtc { | |
| 25 | |
| 26 // A container for all the objects we need to call Windows DirectX based capture | |
| 27 // APIs. Note, one application can only have one IDXGIOutputDuplication instance | |
| 28 // per output, so this class should be singleton. | |
| 29 // | |
| 30 // Consumers should create a DxgiContext and keep it through their lifetime. | |
| 31 // Calls Prepare() function with the DxgiContext before each Duplicate() | |
| 32 // function calls. If a previous Prepare() function call returns true, but a | |
| 33 // later one returns false, this usually means the display mode is changing. | |
| 34 // Consumers should retry after a while. (Typically 50 milliseconds, but | |
| 35 // according to hardware performance, this time may be various.) | |
| 36 // | |
| 37 // This implementation is typically for ScreenCapturer(s) with double buffering, | |
| 38 // such as ScreenCapturerWinDirectx. And it should work with consumers with one | |
| 39 // buffer, i.e. Consumers can always send nullptr for |last_frame|. Some minor | |
| 40 // changes in DxgiOutputDuplicator class are nice to have to reduce size of data | |
| 41 // to copy (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. | |
| 44 class DxgiDuplicatorContainer { | |
|
Sergey Ulanov
2016/07/28 22:15:32
Maybe call this DxgiDuplicatorController to make t
Hzj_jie
2016/07/29 02:12:23
Done.
| |
| 45 public: | |
| 46 // Creates or retrieves the singleton instance of DxgiDuplicatorContainer. | |
| 47 static DxgiDuplicatorContainer* Instance(); | |
| 48 | |
| 49 // Destructs current instance. We need to make sure COM components and their | |
| 50 // containers are destructed in correct order. | |
| 51 ~DxgiDuplicatorContainer(); | |
| 52 | |
| 53 // Initializes all the components and updates |context|. This function equals | |
| 54 // to call Prepare() and Setup(DxgiContext*) sequentially. | |
| 55 bool Prepare(DxgiContext* context); | |
| 56 | |
| 57 // Initializes all the components. Returns false if system does not support | |
| 58 // DirectX based capture, or system resource is not enough to support to | |
| 59 // capture all monitors. By default, only four applications can capture the | |
| 60 // screen with DirectX based capture simultaneously. Returns true if this | |
| 61 // instance has been initialized already. | |
| 62 bool Prepare(); | |
| 63 | |
| 64 // Captures current screen and writes into target. Since we are using double | |
| 65 // buffering, |last_frame|.updated_region() is used to represent the not | |
| 66 // updated regions in current |target| frame, which should also be copied this | |
| 67 // time. | |
| 68 // TODO(zijiehe): Windows cannot guarantee the frames returned by each | |
| 69 // IDXGIOutputDuplication are synchronized. But we are using a totally | |
| 70 // different threading model than the way Windows suggested, it's hard to | |
| 71 // synchronize them manually. But we should find a way to do it. | |
| 72 bool Duplicate(DxgiContext* context, | |
| 73 DesktopFrame* target, | |
| 74 const DesktopFrame* last_frame); | |
| 75 | |
| 76 // Captures one screen and writes into target. If id < 0 or greater than | |
| 77 // the total screen count of all the Duplicators, this function returns false. | |
| 78 bool Duplicate(DxgiContext* context, | |
| 79 int id, | |
| 80 DesktopFrame* target, | |
| 81 const DesktopFrame* last_frame); | |
| 82 | |
| 83 DesktopVector dpi() const { return dpi_; } | |
| 84 | |
| 85 // Returns entire desktop size. | |
| 86 DesktopRect desktop_rect() const { return desktop_rect_; } | |
| 87 | |
| 88 // Returns a DesktopSize to cover entire desktop_rect. This may be different | |
| 89 // than desktop_rect().size(), since top-left screen does not need to start | |
| 90 // from (0, 0). | |
| 91 DesktopSize desktop_size() const { | |
| 92 return DesktopSize(desktop_rect_.right(), desktop_rect_.bottom()); | |
| 93 } | |
| 94 | |
| 95 // Returns the size of one screen. If id < 0 or greater than the total screen | |
| 96 // count of all the Duplicators, this function returns an empty DesktopRect. | |
| 97 DesktopRect ScreenRect(int id) const; | |
| 98 | |
| 99 // Returns the count of screens on the system. These screens can be retrieved | |
| 100 // by an integer in the range of [0, ScreenCount()). | |
| 101 int ScreenCount() const; | |
| 102 | |
| 103 private: | |
| 104 // DxgiContext calls private Unregister(DxgiContext*) function during | |
| 105 // destructing. | |
| 106 friend class DxgiContext; | |
| 107 | |
| 108 // A class to allow only one thread to enter. This class is used to make sure | |
| 109 // only one Initialize function call is being performed. | |
| 110 class SingleEntry { | |
| 111 public: | |
| 112 bool Enter(); | |
| 113 void Exit(); | |
| 114 bool Hold() const; | |
| 115 | |
| 116 private: | |
| 117 rtc::CriticalSection lock_; | |
| 118 bool entered_ = false; | |
| 119 }; | |
| 120 | |
| 121 // A helper class to execute SingleEntry::Exit in its destructor. | |
| 122 class AutoExit; | |
| 123 | |
| 124 // A private constructor to ensure consumers to use | |
| 125 // DxgiDuplicatorContainer::Instance(). | |
| 126 DxgiDuplicatorContainer(); | |
| 127 | |
| 128 // A helper function to check whether a DxgiContext has been expired. This | |
| 129 // function should be called in lock_ locked scope. | |
| 130 bool DxgiContextExpired(const DxgiContext* const context) const; | |
| 131 | |
| 132 // Updates DxgiContext if needed. | |
| 133 void Setup(DxgiContext* context); | |
| 134 | |
| 135 // Unregisters DxgiContext from this instance and all DxgiAdapterDuplicator(s) | |
| 136 // it owns. | |
| 137 void Unregister(const DxgiContext* const context); | |
| 138 | |
| 139 // Does the real initialization work. | |
| 140 bool DoInitialize(); | |
| 141 | |
| 142 // Clears all COM components referred by this instance. So next Prepare() | |
| 143 // call will eventually initialize this instance again. | |
| 144 void Deinitialize(); | |
| 145 | |
| 146 rtc::CriticalSection lock_; | |
| 147 SingleEntry initializing_; | |
| 148 | |
| 149 // A self-incremented integer to compare with the one in DxgiContext, to | |
| 150 // ensure a DxgiContext has been initialized after DxgiDuplicatorContainer. | |
| 151 int identity_ = 0; | |
| 152 DesktopRect desktop_rect_; | |
| 153 DesktopVector dpi_; | |
| 154 std::vector<DxgiAdapterDuplicator> duplicators_; | |
| 155 }; | |
| 156 | |
| 157 } // namespace webrtc | |
| 158 | |
| 159 #endif // MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTAINER_H_ | |
| OLD | NEW |