Several minor improvements of DirectX capturer
1. It looks like ComPtr cannot work well with vector::emplace_back, I got a
consistent crash on one of my machine, but not the other. Move constructor
should have no impact to lvalue reference, but I may be wrong here. The
impact here is ComPtr released before it should be. So a simple solution is to
use copy instead of reference. The D3dDevice is a collection of reference
counted pointers (Microsoft::WRL::ComPtr), there is almost no extra cost.
2. Actively set several fields in D3D11_TEXTURE2D_DESC to avoid potential break
if there are some platform changes later.
3. AcquireNextFrame returns both a DXGI_OUTDUPL_FRAME_INFO with
AccumulatedFrames and an IDXGIResource. But there is no comment in MSDN to
ensure IDXGIResource won't be nullptr if AccumulatedFrames > 0. Adding an extra
check in DxgiOutputDuplicator makes it a safer.
BUG=314516
Review-Url: https://codereview.webrtc.org/2345163002
Cr-Commit-Position: refs/heads/master@{#14341}
diff --git a/webrtc/modules/desktop_capture/win/d3d_device.cc b/webrtc/modules/desktop_capture/win/d3d_device.cc
index 15233e6..f7c419f 100644
--- a/webrtc/modules/desktop_capture/win/d3d_device.cc
+++ b/webrtc/modules/desktop_capture/win/d3d_device.cc
@@ -47,7 +47,7 @@
return false;
}
- error = _com_error(d3d_device_.As(&dxgi_device_));
+ error = d3d_device_.As(&dxgi_device_);
if (error.Error() != S_OK || !dxgi_device_) {
LOG(LS_WARNING) << "ID3D11Device is not an implementation of IDXGIDevice, "
"this usually means the system does not support DirectX "
@@ -61,9 +61,8 @@
// static
std::vector<D3dDevice> D3dDevice::EnumDevices() {
ComPtr<IDXGIFactory1> factory;
- _com_error error = _com_error(
- CreateDXGIFactory1(__uuidof(IDXGIFactory1),
- reinterpret_cast<void**>(factory.GetAddressOf())));
+ _com_error error = CreateDXGIFactory1(__uuidof(IDXGIFactory1),
+ reinterpret_cast<void**>(factory.GetAddressOf()));
if (error.Error() != S_OK || !factory) {
return std::vector<D3dDevice>();
}
@@ -71,7 +70,7 @@
std::vector<D3dDevice> result;
for (int i = 0;; i++) {
ComPtr<IDXGIAdapter> adapter;
- error = _com_error(factory->EnumAdapters(i, adapter.GetAddressOf()));
+ error = factory->EnumAdapters(i, adapter.GetAddressOf());
if (error.Error() == S_OK) {
D3dDevice device;
if (!device.Initialize(adapter)) {
diff --git a/webrtc/modules/desktop_capture/win/d3d_device.h b/webrtc/modules/desktop_capture/win/d3d_device.h
index 94a263e..fc1533a 100644
--- a/webrtc/modules/desktop_capture/win/d3d_device.h
+++ b/webrtc/modules/desktop_capture/win/d3d_device.h
@@ -43,7 +43,7 @@
// function.
D3dDevice();
- // Initialize the D3dDevice from an IDXGIAdapter.
+ // Initializes the D3dDevice from an IDXGIAdapter.
bool Initialize(const Microsoft::WRL::ComPtr<IDXGIAdapter>& adapter);
Microsoft::WRL::ComPtr<ID3D11Device> d3d_device_;
diff --git a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
index 1b82216..46d4e89 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
+++ b/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
@@ -62,11 +62,11 @@
}
DXGI_OUTPUT_DESC desc;
- error = _com_error(output->GetDesc(&desc));
+ error = output->GetDesc(&desc);
if (error.Error() == S_OK) {
if (desc.AttachedToDesktop && IsValidRect(desc.DesktopCoordinates)) {
ComPtr<IDXGIOutput1> output1;
- error = _com_error(output.As(&output1));
+ error = output.As(&output1);
if (error.Error() != S_OK || !output1) {
LOG(LS_WARNING) << "Failed to convert IDXGIOutput to IDXGIOutput1, "
"this usually means the system does not support "
diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
index d7eb335..b17c195 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
+++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.cc
@@ -147,7 +147,9 @@
// after it has been merged to updated_region.
DesktopRegion updated_region;
updated_region.Swap(&context->updated_region);
- if (error.Error() == S_OK && frame_info.AccumulatedFrames > 0) {
+ if (error.Error() == S_OK &&
+ frame_info.AccumulatedFrames > 0 &&
+ resource) {
DetectUpdatedRegion(frame_info, offset, &context->updated_region);
if (!texture_->CopyFrom(frame_info, resource.Get(),
context->updated_region)) {
@@ -224,8 +226,8 @@
DXGI_OUTDUPL_MOVE_RECT* move_rects =
reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(metadata.data());
size_t move_rects_count = 0;
- _com_error error = _com_error(duplication_->GetFrameMoveRects(
- static_cast<UINT>(metadata.capacity()), move_rects, &buff_size));
+ _com_error error = duplication_->GetFrameMoveRects(
+ static_cast<UINT>(metadata.capacity()), move_rects, &buff_size);
if (error.Error() != S_OK) {
LOG(LS_ERROR) << "Failed to get move rectangles, error "
<< error.ErrorMessage() << ", code " << error.Error();
@@ -235,9 +237,9 @@
RECT* dirty_rects = reinterpret_cast<RECT*>(metadata.data() + buff_size);
size_t dirty_rects_count = 0;
- error = _com_error(duplication_->GetFrameDirtyRects(
+ error = duplication_->GetFrameDirtyRects(
static_cast<UINT>(metadata.capacity()) - buff_size, dirty_rects,
- &buff_size));
+ &buff_size);
if (error.Error() != S_OK) {
LOG(LS_ERROR) << "Failed to get dirty rectangles, error "
<< error.ErrorMessage() << ", code " << error.Error();
diff --git a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h
index 020ca64..0d5b134 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h
+++ b/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h
@@ -111,7 +111,7 @@
// Returns a DesktopRect in the coordinate of |offset|.
DesktopRect TargetRect(DesktopRect rect, DesktopVector offset);
- const D3dDevice& device_;
+ const D3dDevice device_;
const Microsoft::WRL::ComPtr<IDXGIOutput1> output_;
const DesktopRect desktop_rect_;
Microsoft::WRL::ComPtr<IDXGIOutputDuplication> duplication_;
diff --git a/webrtc/modules/desktop_capture/win/dxgi_texture_staging.cc b/webrtc/modules/desktop_capture/win/dxgi_texture_staging.cc
index 7478728..6866d1e 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_texture_staging.cc
+++ b/webrtc/modules/desktop_capture/win/dxgi_texture_staging.cc
@@ -38,9 +38,13 @@
return false;
}
+ desc.ArraySize = 1;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.MipLevels = 1;
desc.MiscFlags = 0;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING;
if (stage_) {
AssertStageAndSurfaceAreSameObject();
@@ -58,15 +62,15 @@
RTC_DCHECK(!surface_);
}
- _com_error error = _com_error(device_.d3d_device()->CreateTexture2D(
- &desc, nullptr, stage_.GetAddressOf()));
+ _com_error error = device_.d3d_device()->CreateTexture2D(
+ &desc, nullptr, stage_.GetAddressOf());
if (error.Error() != S_OK || !stage_) {
LOG(LS_ERROR) << "Failed to create a new ID3D11Texture2D as stage, error "
<< error.ErrorMessage() << ", code " << error.Error();
return false;
}
- error = _com_error(stage_.As(&surface_));
+ error = stage_.As(&surface_);
if (error.Error() != S_OK || !surface_) {
LOG(LS_ERROR) << "Failed to convert ID3D11Texture2D to IDXGISurface, error "
<< error.ErrorMessage() << ", code " << error.Error();
@@ -123,7 +127,7 @@
}
rect_ = {0};
- error = _com_error(surface_->Map(&rect_, DXGI_MAP_READ));
+ error = surface_->Map(&rect_, DXGI_MAP_READ);
if (error.Error() != S_OK) {
rect_ = {0};
LOG(LS_ERROR) << "Failed to map the IDXGISurface to a bitmap, error "
@@ -135,7 +139,7 @@
}
bool DxgiTextureStaging::DoRelease() {
- _com_error error = _com_error(surface_->Unmap());
+ _com_error error = surface_->Unmap();
if (error.Error() != S_OK) {
stage_.Reset();
surface_.Reset();
diff --git a/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h b/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h
index 2da1600..47f75fa 100644
--- a/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h
+++ b/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h
@@ -58,7 +58,7 @@
void AssertStageAndSurfaceAreSameObject();
const DesktopRect desktop_rect_;
- const D3dDevice& device_;
+ const D3dDevice device_;
Microsoft::WRL::ComPtr<ID3D11Texture2D> stage_;
Microsoft::WRL::ComPtr<IDXGISurface> surface_;
};