| Index: webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h
|
| diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1c491f140a1875d43be24c526d636a3cc37cd4f0
|
| --- /dev/null
|
| +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h
|
| @@ -0,0 +1,153 @@
|
| +/*
|
| + * 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_CONTROLLER_H_
|
| +#define MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_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 controller 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 Duplicate() function with the DxgiContext. Consumers can also call
|
| +// Prepare() to determine whether the system supports DXGI duplicator or not. If
|
| +// a previous Prepare() function call returns true, but a later Duplicate()
|
| +// 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. If a consumer does have this requirement, one can always
|
| +// send a new DxgiContext instance to Duplicate() function to force duplicator
|
| +// to treat it as a new consumer.
|
| +class DxgiDuplicatorController {
|
| + public:
|
| + // Creates or retrieves the singleton instance of DxgiDuplicatorController.
|
| + static DxgiDuplicatorController* Instance();
|
| +
|
| + // Destructs current instance. We need to make sure COM components and their
|
| + // containers are destructed in correct order.
|
| + ~DxgiDuplicatorController();
|
| +
|
| + // Detects whether the system supports DXGI based capturer.
|
| + bool IsSupported();
|
| +
|
| + // 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,
|
| + const DesktopFrame* last_frame,
|
| + DesktopFrame* target);
|
| +
|
| + // Captures one monitor and writes into target. |monitor_id| should >= 0. If
|
| + // |monitor_id| is greater than the total screen count of all the Duplicators,
|
| + // this function returns false.
|
| + bool DuplicateMonitor(DxgiContext* context,
|
| + int monitor_id,
|
| + const DesktopFrame* last_frame,
|
| + DesktopFrame* target);
|
| +
|
| + // Returns dpi of current system. Returns an empty DesktopVector if system
|
| + // does not support DXGI based capturer.
|
| + DesktopVector dpi();
|
| +
|
| + // Returns entire desktop size. Returns an empty DesktopRect if system does
|
| + // not support DXGI based capturer.
|
| + DesktopRect 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();
|
| +
|
| + // Returns the size of one screen. |monitor_id| should be >= 0. If system does
|
| + // not support DXGI based capturer, or |monitor_id| is greater than the total
|
| + // screen count of all the Duplicators, this function returns an empty
|
| + // DesktopRect.
|
| + DesktopRect ScreenRect(int id);
|
| +
|
| + // Returns the count of screens on the system. These screens can be retrieved
|
| + // by an integer in the range of [0, ScreenCount()). If system does not
|
| + // support DXGI based capturer, this function returns 0.
|
| + int ScreenCount();
|
| +
|
| + private:
|
| + // DxgiContext calls private Unregister(DxgiContext*) function during
|
| + // destructing.
|
| + friend class DxgiContext;
|
| +
|
| + // A private constructor to ensure consumers to use
|
| + // DxgiDuplicatorController::Instance().
|
| + DxgiDuplicatorController();
|
| +
|
| + // Unregisters DxgiContext from this instance and all DxgiAdapterDuplicator(s)
|
| + // it owns.
|
| + void Unregister(const DxgiContext* const context);
|
| +
|
| + /*** All functions below should be called in lock_ locked scope. ***/
|
| +
|
| + // If current instance has not been initialized, executes DoInitialize
|
| + // function, and returns initialize result. Otherwise directly returns true.
|
| + bool Initialize();
|
| +
|
| + // Does the real initialization work.
|
| + bool DoInitialize();
|
| +
|
| + // Clears all COM components referred by this instance. So next Duplicate()
|
| + // call will eventually initialize this instance again.
|
| + void Deinitialize();
|
| +
|
| + // A helper function to check whether a DxgiContext has been expired.
|
| + bool DxgiContextExpired(const DxgiContext* const context) const;
|
| +
|
| + // Updates DxgiContext if needed.
|
| + void Setup(DxgiContext* context);
|
| +
|
| + // Do the real duplication work. |monitor_id < 0| to capture entire screen.
|
| + bool DoDuplicate(DxgiContext* context,
|
| + int monitor_id,
|
| + const DesktopFrame* last_frame,
|
| + DesktopFrame* target);
|
| +
|
| + rtc::CriticalSection lock_;
|
| +
|
| + // A self-incremented integer to compare with the one in DxgiContext, to
|
| + // ensure a DxgiContext has been initialized after DxgiDuplicatorController.
|
| + int identity_ = 0;
|
| + DesktopRect desktop_rect_;
|
| + DesktopVector dpi_;
|
| + std::vector<DxgiAdapterDuplicator> duplicators_;
|
| +};
|
| +
|
| +} // namespace webrtc
|
| +
|
| +#endif // MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_
|
|
|