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}
This commit is contained in:
parent
6f79d840ba
commit
66cadfc0e3
@ -47,7 +47,7 @@ bool D3dDevice::Initialize(const ComPtr<IDXGIAdapter>& adapter) {
|
||||
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 @@ bool D3dDevice::Initialize(const ComPtr<IDXGIAdapter>& adapter) {
|
||||
// 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> D3dDevice::EnumDevices() {
|
||||
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)) {
|
||||
|
||||
@ -43,7 +43,7 @@ class D3dDevice {
|
||||
// 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_;
|
||||
|
||||
@ -62,11 +62,11 @@ bool DxgiAdapterDuplicator::DoInitialize() {
|
||||
}
|
||||
|
||||
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 "
|
||||
|
||||
@ -147,7 +147,9 @@ bool DxgiOutputDuplicator::Duplicate(Context* context,
|
||||
// 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 @@ bool DxgiOutputDuplicator::DoDetectUpdatedRegion(
|
||||
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 @@ bool DxgiOutputDuplicator::DoDetectUpdatedRegion(
|
||||
|
||||
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();
|
||||
|
||||
@ -111,7 +111,7 @@ class DxgiOutputDuplicator {
|
||||
// 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_;
|
||||
|
||||
@ -38,9 +38,13 @@ bool DxgiTextureStaging::InitializeStage(ID3D11Texture2D* texture) {
|
||||
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 @@ bool DxgiTextureStaging::InitializeStage(ID3D11Texture2D* texture) {
|
||||
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 @@ bool DxgiTextureStaging::CopyFrom(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
|
||||
}
|
||||
|
||||
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::CopyFrom(const DXGI_OUTDUPL_FRAME_INFO& frame_info,
|
||||
}
|
||||
|
||||
bool DxgiTextureStaging::DoRelease() {
|
||||
_com_error error = _com_error(surface_->Unmap());
|
||||
_com_error error = surface_->Unmap();
|
||||
if (error.Error() != S_OK) {
|
||||
stage_.Reset();
|
||||
surface_.Reset();
|
||||
|
||||
@ -58,7 +58,7 @@ class DxgiTextureStaging : public DxgiTexture {
|
||||
void AssertStageAndSurfaceAreSameObject();
|
||||
|
||||
const DesktopRect desktop_rect_;
|
||||
const D3dDevice& device_;
|
||||
const D3dDevice device_;
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> stage_;
|
||||
Microsoft::WRL::ComPtr<IDXGISurface> surface_;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user