tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

dxgi_output_duplicator.h (6426B)


      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_OUTPUT_DUPLICATOR_H_
     12 #define MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_
     13 
     14 #include <comdef.h>
     15 #include <dxgi.h>
     16 #include <dxgi1_2.h>
     17 #include <shellscalingapi.h>
     18 #include <wrl/client.h>
     19 
     20 #include <cstdint>
     21 #include <memory>
     22 #include <optional>
     23 #include <string>
     24 #include <vector>
     25 
     26 #include "modules/desktop_capture/desktop_frame_rotation.h"
     27 #include "modules/desktop_capture/desktop_geometry.h"
     28 #include "modules/desktop_capture/desktop_region.h"
     29 #include "modules/desktop_capture/shared_desktop_frame.h"
     30 #include "modules/desktop_capture/win/d3d_device.h"
     31 #include "modules/desktop_capture/win/dxgi_context.h"
     32 #include "modules/desktop_capture/win/dxgi_texture.h"
     33 
     34 namespace webrtc {
     35 
     36 // Duplicates the content on one IDXGIOutput, i.e. one monitor attached to one
     37 // video card. None of functions in this class is thread-safe.
     38 class DxgiOutputDuplicator {
     39 public:
     40  using Context = DxgiOutputContext;
     41 
     42  // Creates an instance of DxgiOutputDuplicator from a D3dDevice and one of its
     43  // IDXGIOutput1. Caller must maintain the lifetime of device, to make sure it
     44  // outlives this instance. Only DxgiAdapterDuplicator can create an instance.
     45  DxgiOutputDuplicator(const D3dDevice& device,
     46                       const Microsoft::WRL::ComPtr<IDXGIOutput1>& output,
     47                       const DXGI_OUTPUT_DESC& desc);
     48 
     49  // To allow this class to work with vector.
     50  DxgiOutputDuplicator(DxgiOutputDuplicator&& other);
     51 
     52  // Destructs this instance. We need to make sure texture_ has been released
     53  // before duplication_.
     54  ~DxgiOutputDuplicator();
     55 
     56  // Initializes duplication_ object.
     57  bool Initialize();
     58 
     59  // Copies the content of current IDXGIOutput to the `target`. To improve the
     60  // performance, this function copies only regions merged from
     61  // `context`->updated_region and DetectUpdatedRegion(). The `offset` decides
     62  // the offset in the `target` where the content should be copied to. i.e. this
     63  // function copies the content to the rectangle of (offset.x(), offset.y()) to
     64  // (offset.x() + desktop_rect_.width(), offset.y() + desktop_rect_.height()).
     65  // Returns false in case of a failure.
     66  // May retain a reference to `target` so that a "captured" frame can be
     67  // returned in the event that a new frame is not ready to be captured yet.
     68  // (Or in other words, if the call to IDXGIOutputDuplication::AcquireNextFrame
     69  // indicates that there is not yet a new frame, this is usually because no
     70  // updates have occurred to the frame).
     71  bool Duplicate(Context* context,
     72                 DesktopVector offset,
     73                 SharedDesktopFrame* target);
     74 
     75  // Returns the desktop rect covered by this DxgiOutputDuplicator.
     76  DesktopRect desktop_rect() const { return desktop_rect_; }
     77 
     78  // Returns the device name from DXGI_OUTPUT_DESC in utf8 encoding.
     79  const std::string& device_name() const { return device_name_; }
     80 
     81  void Setup(Context* context);
     82 
     83  void Unregister(const Context* const context);
     84 
     85  // How many frames have been captured by this DxigOutputDuplicator.
     86  int64_t num_frames_captured() const;
     87 
     88  // Device scale factor of the monitor associated with this
     89  // DxigOutputDuplicator.
     90  std::optional<float> device_scale_factor() const;
     91 
     92  // Moves `desktop_rect_`. See DxgiDuplicatorController::TranslateRect().
     93  void TranslateRect(const DesktopVector& position);
     94 
     95 private:
     96  // Calls DoDetectUpdatedRegion(). If it fails, this function sets the
     97  // `updated_region` as entire UntranslatedDesktopRect().
     98  void DetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
     99                           DesktopRegion* updated_region);
    100 
    101  // Returns untranslated updated region, which are directly returned by Windows
    102  // APIs. Returns false in case of a failure.
    103  bool DoDetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
    104                             DesktopRegion* updated_region);
    105 
    106  // Returns true if the mouse cursor is embedded in the captured frame and
    107  // false if not. Also logs the same boolean as
    108  // WebRTC.DesktopCapture.Win.DirectXCursorEmbedded UMA.
    109  bool ContainsMouseCursor(const DXGI_OUTDUPL_FRAME_INFO& frame_info);
    110 
    111  bool ReleaseFrame();
    112 
    113  // Initializes duplication_ instance. Expects duplication_ is in empty status.
    114  // Returns false if system does not support IDXGIOutputDuplication.
    115  bool DuplicateOutput();
    116 
    117  // Returns a DesktopRect with the same size of desktop_size(), but translated
    118  // by offset.
    119  DesktopRect GetTranslatedDesktopRect(DesktopVector offset) const;
    120 
    121  // Returns a DesktopRect with the same size of desktop_size(), but starts from
    122  // (0, 0).
    123  DesktopRect GetUntranslatedDesktopRect() const;
    124 
    125  // Spreads changes from `context` to other registered Context(s) in
    126  // contexts_.
    127  void SpreadContextChange(const Context* const context);
    128 
    129  // Returns the size of desktop rectangle current instance representing.
    130  DesktopSize desktop_size() const;
    131 
    132  const D3dDevice device_;
    133  const Microsoft::WRL::ComPtr<IDXGIOutput1> output_;
    134  const std::string device_name_;
    135  DesktopRect desktop_rect_;
    136  const HMONITOR monitor_;
    137  Microsoft::WRL::ComPtr<IDXGIOutputDuplication> duplication_;
    138  DXGI_OUTDUPL_DESC desc_;
    139  std::vector<uint8_t> metadata_;
    140  std::unique_ptr<DxgiTexture> texture_;
    141  Rotation rotation_;
    142  DesktopSize unrotated_size_;
    143 
    144  // After each AcquireNextFrame() function call, updated_region_(s) of all
    145  // active Context(s) need to be updated. Since they have missed the
    146  // change this time. And during next Duplicate() function call, their
    147  // updated_region_ will be merged and copied.
    148  std::vector<Context*> contexts_;
    149 
    150  // The last full frame of this output and its offset. If on AcquireNextFrame()
    151  // failed because of timeout, i.e. no update, we can copy content from
    152  // `last_frame_`.
    153  std::unique_ptr<SharedDesktopFrame> last_frame_;
    154  DesktopVector last_frame_offset_;
    155 
    156  int64_t num_frames_captured_ = 0;
    157 };
    158 
    159 }  // namespace webrtc
    160 
    161 #endif  // MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_