Index: webrtc/modules/desktop_capture/win/dxgi_duplicator_container.h |
diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_container.h b/webrtc/modules/desktop_capture/win/dxgi_duplicator_container.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..65f6d91288f96add59bd0b30d8a23474b7bbaa16 |
--- /dev/null |
+++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_container.h |
@@ -0,0 +1,159 @@ |
+/* |
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#ifndef MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTAINER_H_ |
+#define MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTAINER_H_ |
+ |
+#include <vector> |
+ |
+#include "webrtc/base/criticalsection.h" |
+#include "webrtc/modules/desktop_capture/desktop_frame.h" |
+#include "webrtc/modules/desktop_capture/desktop_geometry.h" |
+#include "webrtc/modules/desktop_capture/desktop_region.h" |
+#include "webrtc/modules/desktop_capture/win/d3d_device.h" |
+#include "webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h" |
+#include "webrtc/modules/desktop_capture/win/dxgi_context.h" |
+ |
+namespace webrtc { |
+ |
+// A container for all the objects we need to call Windows DirectX based capture |
+// APIs. Note, one application can only have one IDXGIOutputDuplication instance |
+// per output, so this class should be singleton. |
+// |
+// Consumers should create a DxgiContext and keep it through their lifetime. |
+// Calls Prepare() function with the DxgiContext before each Duplicate() |
+// function calls. If a previous Prepare() function call returns true, but a |
+// later one returns false, this usually means the display mode is changing. |
+// Consumers should retry after a while. (Typically 50 milliseconds, but |
+// according to hardware performance, this time may be various.) |
+// |
+// This implementation is typically for ScreenCapturer(s) with double buffering, |
+// such as ScreenCapturerWinDirectx. And it should work with consumers with one |
+// buffer, i.e. Consumers can always send nullptr for |last_frame|. Some minor |
+// changes in DxgiOutputDuplicator class are nice to have to reduce size of data |
+// to copy (Commented in dxgi_output_duplicator.cc). But this class won't work |
+// with three or more buffers, the updated region merging logic will be broken |
+// in such scenarios. |
+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.
|
+ public: |
+ // Creates or retrieves the singleton instance of DxgiDuplicatorContainer. |
+ static DxgiDuplicatorContainer* Instance(); |
+ |
+ // Destructs current instance. We need to make sure COM components and their |
+ // containers are destructed in correct order. |
+ ~DxgiDuplicatorContainer(); |
+ |
+ // Initializes all the components and updates |context|. This function equals |
+ // to call Prepare() and Setup(DxgiContext*) sequentially. |
+ bool Prepare(DxgiContext* context); |
+ |
+ // Initializes all the components. Returns false if system does not support |
+ // DirectX based capture, or system resource is not enough to support to |
+ // capture all monitors. By default, only four applications can capture the |
+ // screen with DirectX based capture simultaneously. Returns true if this |
+ // instance has been initialized already. |
+ bool Prepare(); |
+ |
+ // Captures current screen and writes into target. Since we are using double |
+ // buffering, |last_frame|.updated_region() is used to represent the not |
+ // updated regions in current |target| frame, which should also be copied this |
+ // time. |
+ // TODO(zijiehe): Windows cannot guarantee the frames returned by each |
+ // IDXGIOutputDuplication are synchronized. But we are using a totally |
+ // different threading model than the way Windows suggested, it's hard to |
+ // synchronize them manually. But we should find a way to do it. |
+ bool Duplicate(DxgiContext* context, |
+ DesktopFrame* target, |
+ const DesktopFrame* last_frame); |
+ |
+ // Captures one screen and writes into target. If id < 0 or greater than |
+ // the total screen count of all the Duplicators, this function returns false. |
+ bool Duplicate(DxgiContext* context, |
+ int id, |
+ DesktopFrame* target, |
+ const DesktopFrame* last_frame); |
+ |
+ DesktopVector dpi() const { return dpi_; } |
+ |
+ // Returns entire desktop size. |
+ DesktopRect desktop_rect() const { return desktop_rect_; } |
+ |
+ // Returns a DesktopSize to cover entire desktop_rect. This may be different |
+ // than desktop_rect().size(), since top-left screen does not need to start |
+ // from (0, 0). |
+ DesktopSize desktop_size() const { |
+ return DesktopSize(desktop_rect_.right(), desktop_rect_.bottom()); |
+ } |
+ |
+ // Returns the size of one screen. If id < 0 or greater than the total screen |
+ // count of all the Duplicators, this function returns an empty DesktopRect. |
+ DesktopRect ScreenRect(int id) const; |
+ |
+ // Returns the count of screens on the system. These screens can be retrieved |
+ // by an integer in the range of [0, ScreenCount()). |
+ int ScreenCount() const; |
+ |
+ private: |
+ // DxgiContext calls private Unregister(DxgiContext*) function during |
+ // destructing. |
+ friend class DxgiContext; |
+ |
+ // A class to allow only one thread to enter. This class is used to make sure |
+ // only one Initialize function call is being performed. |
+ class SingleEntry { |
+ public: |
+ bool Enter(); |
+ void Exit(); |
+ bool Hold() const; |
+ |
+ private: |
+ rtc::CriticalSection lock_; |
+ bool entered_ = false; |
+ }; |
+ |
+ // A helper class to execute SingleEntry::Exit in its destructor. |
+ class AutoExit; |
+ |
+ // A private constructor to ensure consumers to use |
+ // DxgiDuplicatorContainer::Instance(). |
+ DxgiDuplicatorContainer(); |
+ |
+ // A helper function to check whether a DxgiContext has been expired. This |
+ // function should be called in lock_ locked scope. |
+ bool DxgiContextExpired(const DxgiContext* const context) const; |
+ |
+ // Updates DxgiContext if needed. |
+ void Setup(DxgiContext* context); |
+ |
+ // Unregisters DxgiContext from this instance and all DxgiAdapterDuplicator(s) |
+ // it owns. |
+ void Unregister(const DxgiContext* const context); |
+ |
+ // Does the real initialization work. |
+ bool DoInitialize(); |
+ |
+ // Clears all COM components referred by this instance. So next Prepare() |
+ // call will eventually initialize this instance again. |
+ void Deinitialize(); |
+ |
+ rtc::CriticalSection lock_; |
+ SingleEntry initializing_; |
+ |
+ // A self-incremented integer to compare with the one in DxgiContext, to |
+ // ensure a DxgiContext has been initialized after DxgiDuplicatorContainer. |
+ int identity_ = 0; |
+ DesktopRect desktop_rect_; |
+ DesktopVector dpi_; |
+ std::vector<DxgiAdapterDuplicator> duplicators_; |
+}; |
+ |
+} // namespace webrtc |
+ |
+#endif // MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTAINER_H_ |