aboutsummaryrefslogtreecommitdiff
path: root/modules/desktop_capture/win/dxgi_output_duplicator.h
blob: 3079d3967a9d8a520a58b4253ea84676c1a27c40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 *  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_OUTPUT_DUPLICATOR_H_
#define MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_

#include <comdef.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <wrl/client.h>

#include <memory>
#include <string>
#include <vector>

#include "modules/desktop_capture/desktop_frame_rotation.h"
#include "modules/desktop_capture/desktop_geometry.h"
#include "modules/desktop_capture/desktop_region.h"
#include "modules/desktop_capture/shared_desktop_frame.h"
#include "modules/desktop_capture/win/d3d_device.h"
#include "modules/desktop_capture/win/dxgi_context.h"
#include "modules/desktop_capture/win/dxgi_texture.h"
#include "rtc_base/thread_annotations.h"

namespace webrtc {

// Duplicates the content on one IDXGIOutput, i.e. one monitor attached to one
// video card. None of functions in this class is thread-safe.
class DxgiOutputDuplicator {
 public:
  using Context = DxgiOutputContext;

  // Creates an instance of DxgiOutputDuplicator from a D3dDevice and one of its
  // IDXGIOutput1. Caller must maintain the lifetime of device, to make sure it
  // outlives this instance. Only DxgiAdapterDuplicator can create an instance.
  DxgiOutputDuplicator(const D3dDevice& device,
                       const Microsoft::WRL::ComPtr<IDXGIOutput1>& output,
                       const DXGI_OUTPUT_DESC& desc);

  // To allow this class to work with vector.
  DxgiOutputDuplicator(DxgiOutputDuplicator&& other);

  // Destructs this instance. We need to make sure texture_ has been released
  // before duplication_.
  ~DxgiOutputDuplicator();

  // Initializes duplication_ object.
  bool Initialize();

  // Copies the content of current IDXGIOutput to the |target|. To improve the
  // performance, this function copies only regions merged from
  // |context|->updated_region and DetectUpdatedRegion(). The |offset| decides
  // the offset in the |target| where the content should be copied to. i.e. this
  // function copies the content to the rectangle of (offset.x(), offset.y()) to
  // (offset.x() + desktop_rect_.width(), offset.y() + desktop_rect_.height()).
  // Returns false in case of a failure.
  bool Duplicate(Context* context,
                 DesktopVector offset,
                 SharedDesktopFrame* target);

  // Returns the desktop rect covered by this DxgiOutputDuplicator.
  DesktopRect desktop_rect() const { return desktop_rect_; }

  // Returns the device name from DXGI_OUTPUT_DESC in utf8 encoding.
  const std::string& device_name() const { return device_name_; }

  void Setup(Context* context);

  void Unregister(const Context* const context);

  // How many frames have been captured by this DxigOutputDuplicator.
  int64_t num_frames_captured() const;

  // Moves |desktop_rect_|. See DxgiDuplicatorController::TranslateRect().
  void TranslateRect(const DesktopVector& position);

 private:
  // Calls DoDetectUpdatedRegion(). If it fails, this function sets the
  // |updated_region| as entire UntranslatedDesktopRect().
  void DetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
                           DesktopRegion* updated_region);

  // Returns untranslated updated region, which are directly returned by Windows
  // APIs. Returns false in case of a failure.
  bool DoDetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
                             DesktopRegion* updated_region);

  bool ReleaseFrame();

  // Initializes duplication_ instance. Expects duplication_ is in empty status.
  // Returns false if system does not support IDXGIOutputDuplication.
  bool DuplicateOutput();

  // Returns a DesktopRect with the same size of desktop_size(), but translated
  // by offset.
  DesktopRect GetTranslatedDesktopRect(DesktopVector offset) const;

  // Returns a DesktopRect with the same size of desktop_size(), but starts from
  // (0, 0).
  DesktopRect GetUntranslatedDesktopRect() const;

  // Spreads changes from |context| to other registered Context(s) in
  // contexts_.
  void SpreadContextChange(const Context* const context);

  // Returns the size of desktop rectangle current instance representing.
  DesktopSize desktop_size() const;

  const D3dDevice device_;
  const Microsoft::WRL::ComPtr<IDXGIOutput1> output_;
  const std::string device_name_;
  DesktopRect desktop_rect_;
  Microsoft::WRL::ComPtr<IDXGIOutputDuplication> duplication_;
  DXGI_OUTDUPL_DESC desc_;
  std::vector<uint8_t> metadata_;
  std::unique_ptr<DxgiTexture> texture_;
  Rotation rotation_;
  DesktopSize unrotated_size_;

  // After each AcquireNextFrame() function call, updated_region_(s) of all
  // active Context(s) need to be updated. Since they have missed the
  // change this time. And during next Duplicate() function call, their
  // updated_region_ will be merged and copied.
  std::vector<Context*> contexts_;

  // The last full frame of this output and its offset. If on AcquireNextFrame()
  // failed because of timeout, i.e. no update, we can copy content from
  // |last_frame_|.
  std::unique_ptr<SharedDesktopFrame> last_frame_;
  DesktopVector last_frame_offset_;

  int64_t num_frames_captured_ = 0;
};

}  // namespace webrtc

#endif  // MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_