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