Fixing the error logging in desktop_capture for Windows
The desktop_capture code logs failed HRESULTs in several places,
the problem is that it tries to use a wchar* (when a char*
is required) for the error message and doesn't display the HRESULT
in hex. This makes the error logging less useful than it could be.
Example failure: error 08406B28, with code -2005270488
In this CL, I add a simple utility function to convert a _com_error
object to a std::string whic can be logged. With this change the
output looks like this (linebreak added for CL description):
Failed to capture frame: HRESULT: 0x887A0026,
Message: 'The keyed mutex was abandoned.'
I also adjusted the formatting of a few logging statements to be
more consistent (adding '<<' operators mostly).
Bug: webrtc:12051
Change-Id: I3e88ff6f2ff079fbe210626e1e89b2b053a742a9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188522
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Commit-Queue: Joe Downing <joedow@google.com>
Cr-Commit-Position: refs/heads/master@{#32417}
diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn
index 2cb6891..956e0a6 100644
--- a/modules/desktop_capture/BUILD.gn
+++ b/modules/desktop_capture/BUILD.gn
@@ -445,6 +445,8 @@
"win/d3d_device.h",
"win/desktop.cc",
"win/desktop.h",
+ "win/desktop_capture_utils.cc",
+ "win/desktop_capture_utils.h",
"win/display_configuration_monitor.cc",
"win/display_configuration_monitor.h",
"win/dxgi_adapter_duplicator.cc",
diff --git a/modules/desktop_capture/win/d3d_device.cc b/modules/desktop_capture/win/d3d_device.cc
index b220b13..3d46117 100644
--- a/modules/desktop_capture/win/d3d_device.cc
+++ b/modules/desktop_capture/win/d3d_device.cc
@@ -12,6 +12,7 @@
#include <utility>
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
#include "rtc_base/logging.h"
namespace webrtc {
@@ -38,17 +39,15 @@
nullptr, 0, D3D11_SDK_VERSION, d3d_device_.GetAddressOf(), &feature_level,
context_.GetAddressOf());
if (error.Error() != S_OK || !d3d_device_ || !context_) {
- RTC_LOG(LS_WARNING) << "D3D11CreateDeivce returns error "
- << error.ErrorMessage() << " with code "
- << error.Error();
+ RTC_LOG(LS_WARNING) << "D3D11CreateDevice returned: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
if (feature_level < D3D_FEATURE_LEVEL_11_0) {
RTC_LOG(LS_WARNING)
- << "D3D11CreateDevice returns an instance without DirectX "
- "11 support, level "
- << feature_level << ". Following initialization may fail.";
+ << "D3D11CreateDevice returned an instance without DirectX 11 support, "
+ << "level " << feature_level << ". Following initialization may fail.";
// D3D_FEATURE_LEVEL_11_0 is not officially documented on MSDN to be a
// requirement of Dxgi duplicator APIs.
}
@@ -57,9 +56,9 @@
if (error.Error() != S_OK || !dxgi_device_) {
RTC_LOG(LS_WARNING)
<< "ID3D11Device is not an implementation of IDXGIDevice, "
- "this usually means the system does not support DirectX "
- "11. Error "
- << error.ErrorMessage() << " with code " << error.Error();
+ << "this usually means the system does not support DirectX "
+ << "11. Error received: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
@@ -73,7 +72,8 @@
CreateDXGIFactory1(__uuidof(IDXGIFactory1),
reinterpret_cast<void**>(factory.GetAddressOf()));
if (error.Error() != S_OK || !factory) {
- RTC_LOG(LS_WARNING) << "Cannot create IDXGIFactory1.";
+ RTC_LOG(LS_WARNING) << "Cannot create IDXGIFactory1: "
+ << desktop_capture::utils::ComErrorToString(error);
return std::vector<D3dDevice>();
}
@@ -90,9 +90,8 @@
break;
} else {
RTC_LOG(LS_WARNING)
- << "IDXGIFactory1::EnumAdapters returns an unexpected "
- "error "
- << error.ErrorMessage() << " with code " << error.Error();
+ << "IDXGIFactory1::EnumAdapters returned an unexpected error: "
+ << desktop_capture::utils::ComErrorToString(error);
}
}
return result;
diff --git a/modules/desktop_capture/win/desktop_capture_utils.cc b/modules/desktop_capture/win/desktop_capture_utils.cc
new file mode 100644
index 0000000..476ddc4
--- /dev/null
+++ b/modules/desktop_capture/win/desktop_capture_utils.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 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.
+ */
+
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
+
+#include "rtc_base/strings/string_builder.h"
+
+namespace webrtc {
+namespace desktop_capture {
+namespace utils {
+
+// Generates a human-readable string from a COM error.
+std::string ComErrorToString(const _com_error& error) {
+ char buffer[1024];
+ rtc::SimpleStringBuilder string_builder(buffer);
+ // Use _bstr_t to simplify the wchar to char conversion for ErrorMessage().
+ _bstr_t error_message(error.ErrorMessage());
+ string_builder.AppendFormat("HRESULT: 0x%08X, Message: %s", error.Error(),
+ static_cast<const char*>(error_message));
+ return string_builder.str();
+}
+
+} // namespace utils
+} // namespace desktop_capture
+} // namespace webrtc
diff --git a/modules/desktop_capture/win/desktop_capture_utils.h b/modules/desktop_capture/win/desktop_capture_utils.h
new file mode 100644
index 0000000..ebf3141
--- /dev/null
+++ b/modules/desktop_capture/win/desktop_capture_utils.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020 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_DESKTOP_CAPTURE_UTILS_H_
+#define MODULES_DESKTOP_CAPTURE_WIN_DESKTOP_CAPTURE_UTILS_H_
+
+#include <comdef.h>
+
+#include <string>
+
+namespace webrtc {
+namespace desktop_capture {
+namespace utils {
+
+// Generates a human-readable string from a COM error.
+std::string ComErrorToString(const _com_error& error);
+
+} // namespace utils
+} // namespace desktop_capture
+} // namespace webrtc
+
+#endif // MODULES_DESKTOP_CAPTURE_WIN_DESKTOP_CAPTURE_UTILS_H_
diff --git a/modules/desktop_capture/win/dxgi_adapter_duplicator.cc b/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
index e3f11ac..88ec4e2 100644
--- a/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
+++ b/modules/desktop_capture/win/dxgi_adapter_duplicator.cc
@@ -15,6 +15,7 @@
#include <algorithm>
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
@@ -53,17 +54,16 @@
}
if (error.Error() == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
- RTC_LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returns "
- "NOT_CURRENTLY_AVAILABLE. This may happen when "
- "running in session 0.";
+ RTC_LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returned "
+ << "NOT_CURRENTLY_AVAILABLE. This may happen when "
+ << "running in session 0.";
break;
}
if (error.Error() != S_OK || !output) {
- RTC_LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returns an unexpected "
- "result "
- << error.ErrorMessage() << " with error code"
- << error.Error();
+ RTC_LOG(LS_WARNING) << "IDXGIAdapter::EnumOutputs returned an unexpected "
+ << "result: "
+ << desktop_capture::utils::ComErrorToString(error);
continue;
}
@@ -75,16 +75,14 @@
error = output.As(&output1);
if (error.Error() != S_OK || !output1) {
RTC_LOG(LS_WARNING)
- << "Failed to convert IDXGIOutput to IDXGIOutput1, "
- "this usually means the system does not support "
- "DirectX 11";
+ << "Failed to convert IDXGIOutput to IDXGIOutput1, this usually "
+ << "means the system does not support DirectX 11";
continue;
}
DxgiOutputDuplicator duplicator(device_, output1, desc);
if (!duplicator.Initialize()) {
RTC_LOG(LS_WARNING) << "Failed to initialize DxgiOutputDuplicator on "
- "output "
- << i;
+ << "output " << i;
continue;
}
diff --git a/modules/desktop_capture/win/dxgi_output_duplicator.cc b/modules/desktop_capture/win/dxgi_output_duplicator.cc
index 2d56b9a..c90e2f1 100644
--- a/modules/desktop_capture/win/dxgi_output_duplicator.cc
+++ b/modules/desktop_capture/win/dxgi_output_duplicator.cc
@@ -18,6 +18,7 @@
#include <algorithm>
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
#include "modules/desktop_capture/win/dxgi_texture_mapping.h"
#include "modules/desktop_capture/win/dxgi_texture_staging.h"
#include "rtc_base/checks.h"
@@ -103,9 +104,8 @@
output_->DuplicateOutput(static_cast<IUnknown*>(device_.d3d_device()),
duplication_.GetAddressOf());
if (error.Error() != S_OK || !duplication_) {
- RTC_LOG(LS_WARNING)
- << "Failed to duplicate output from IDXGIOutput1, error "
- << error.ErrorMessage() << ", with code " << error.Error();
+ RTC_LOG(LS_WARNING) << "Failed to duplicate output from IDXGIOutput1: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
@@ -113,9 +113,8 @@
duplication_->GetDesc(&desc_);
if (desc_.ModeDesc.Format != DXGI_FORMAT_B8G8R8A8_UNORM) {
RTC_LOG(LS_ERROR) << "IDXGIDuplicateOutput does not use RGBA (8 bit) "
- "format, which is required by downstream components, "
- "format is "
- << desc_.ModeDesc.Format;
+ << "format, which is required by downstream components, "
+ << "format is " << desc_.ModeDesc.Format;
return false;
}
@@ -123,7 +122,7 @@
static_cast<int>(desc_.ModeDesc.Height) != desktop_rect_.height()) {
RTC_LOG(LS_ERROR)
<< "IDXGIDuplicateOutput does not return a same size as its "
- "IDXGIOutput1, size returned by IDXGIDuplicateOutput is "
+ << "IDXGIOutput1, size returned by IDXGIDuplicateOutput is "
<< desc_.ModeDesc.Width << " x " << desc_.ModeDesc.Height
<< ", size returned by IDXGIOutput1 is " << desktop_rect_.width()
<< " x " << desktop_rect_.height();
@@ -140,9 +139,8 @@
RTC_DCHECK(duplication_);
_com_error error = duplication_->ReleaseFrame();
if (error.Error() != S_OK) {
- RTC_LOG(LS_ERROR) << "Failed to release frame from IDXGIOutputDuplication, "
- "error"
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to release frame from IDXGIOutputDuplication: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
return true;
@@ -166,8 +164,8 @@
_com_error error = duplication_->AcquireNextFrame(
kAcquireTimeoutMs, &frame_info, resource.GetAddressOf());
if (error.Error() != S_OK && error.Error() != DXGI_ERROR_WAIT_TIMEOUT) {
- RTC_LOG(LS_ERROR) << "Failed to capture frame, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to capture frame: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
@@ -269,7 +267,7 @@
if (frame_info.TotalMetadataBufferSize == 0) {
// This should not happen, since frame_info.AccumulatedFrames > 0.
RTC_LOG(LS_ERROR) << "frame_info.AccumulatedFrames > 0, "
- "but TotalMetadataBufferSize == 0";
+ << "but TotalMetadataBufferSize == 0";
return false;
}
@@ -285,8 +283,8 @@
_com_error error = duplication_->GetFrameMoveRects(
static_cast<UINT>(metadata_.capacity()), move_rects, &buff_size);
if (error.Error() != S_OK) {
- RTC_LOG(LS_ERROR) << "Failed to get move rectangles, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to get move rectangles: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
move_rects_count = buff_size / sizeof(DXGI_OUTDUPL_MOVE_RECT);
@@ -297,8 +295,8 @@
static_cast<UINT>(metadata_.capacity()) - buff_size, dirty_rects,
&buff_size);
if (error.Error() != S_OK) {
- RTC_LOG(LS_ERROR) << "Failed to get dirty rectangles, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to get dirty rectangles: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
dirty_rects_count = buff_size / sizeof(RECT);
diff --git a/modules/desktop_capture/win/dxgi_texture.cc b/modules/desktop_capture/win/dxgi_texture.cc
index 2919692..b8f5b81 100644
--- a/modules/desktop_capture/win/dxgi_texture.cc
+++ b/modules/desktop_capture/win/dxgi_texture.cc
@@ -15,6 +15,7 @@
#include <wrl/client.h>
#include "modules/desktop_capture/desktop_region.h"
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
@@ -49,9 +50,8 @@
__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(texture.GetAddressOf()));
if (error.Error() != S_OK || !texture) {
- RTC_LOG(LS_ERROR) << "Failed to convert IDXGIResource to ID3D11Texture2D, "
- "error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to convert IDXGIResource to ID3D11Texture2D: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
diff --git a/modules/desktop_capture/win/dxgi_texture_mapping.cc b/modules/desktop_capture/win/dxgi_texture_mapping.cc
index 9e138d1..7ecf1ad 100644
--- a/modules/desktop_capture/win/dxgi_texture_mapping.cc
+++ b/modules/desktop_capture/win/dxgi_texture_mapping.cc
@@ -14,6 +14,7 @@
#include <dxgi.h>
#include <dxgi1_2.h>
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
@@ -36,9 +37,8 @@
if (error.Error() != S_OK) {
*rect() = {0};
RTC_LOG(LS_ERROR)
- << "Failed to map the IDXGIOutputDuplication to a bitmap, "
- "error "
- << error.ErrorMessage() << ", code " << error.Error();
+ << "Failed to map the IDXGIOutputDuplication to a bitmap: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
@@ -48,8 +48,8 @@
bool DxgiTextureMapping::DoRelease() {
_com_error error = duplication_->UnMapDesktopSurface();
if (error.Error() != S_OK) {
- RTC_LOG(LS_ERROR) << "Failed to unmap the IDXGIOutputDuplication, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to unmap the IDXGIOutputDuplication: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
return true;
diff --git a/modules/desktop_capture/win/dxgi_texture_staging.cc b/modules/desktop_capture/win/dxgi_texture_staging.cc
index 2bd1eb9..17e8518 100644
--- a/modules/desktop_capture/win/dxgi_texture_staging.cc
+++ b/modules/desktop_capture/win/dxgi_texture_staging.cc
@@ -15,6 +15,7 @@
#include <dxgi1_2.h>
#include <unknwn.h>
+#include "modules/desktop_capture/win/desktop_capture_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/metrics.h"
@@ -64,17 +65,15 @@
_com_error error = device_.d3d_device()->CreateTexture2D(
&desc, nullptr, stage_.GetAddressOf());
if (error.Error() != S_OK || !stage_) {
- RTC_LOG(LS_ERROR)
- << "Failed to create a new ID3D11Texture2D as stage, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to create a new ID3D11Texture2D as stage: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
error = stage_.As(&surface_);
if (error.Error() != S_OK || !surface_) {
- RTC_LOG(LS_ERROR)
- << "Failed to convert ID3D11Texture2D to IDXGISurface, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to convert ID3D11Texture2D to IDXGISurface: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}
@@ -110,8 +109,8 @@
_com_error error = surface_->Map(rect(), DXGI_MAP_READ);
if (error.Error() != S_OK) {
*rect() = {0};
- RTC_LOG(LS_ERROR) << "Failed to map the IDXGISurface to a bitmap, error "
- << error.ErrorMessage() << ", code " << error.Error();
+ RTC_LOG(LS_ERROR) << "Failed to map the IDXGISurface to a bitmap: "
+ << desktop_capture::utils::ComErrorToString(error);
return false;
}