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 |