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:
zijiehe 2016-09-21 17:19:10 -07:00 committed by Commit bot
parent 6f79d840ba
commit 66cadfc0e3
7 changed files with 25 additions and 20 deletions

View File

@ -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)) {

View File

@ -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_;

View File

@ -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 "

View File

@ -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();

View File

@ -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_;

View File

@ -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();

View File

@ -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_;
};