Chromium Code Reviews| 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_ |