From 4236c28c580941c456eb904591260d73816d7f32 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 23 Sep 2022 02:56:04 +0200 Subject: [PATCH] ffmpeg/hwapi/d3d11: Only Release() the immediate ID3D11DeviceContext once While this had no actual effect due to the immediate ID3D11DeviceContext being tied to the ID3D11Device itself, it shouldn't have occured at all. With this there should now only be a single Release() call for every AddRef() call. --- source/ffmpeg/hwapi/d3d11.cpp | 48 ++++++++++++++++++----------------- source/ffmpeg/hwapi/d3d11.hpp | 2 +- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/source/ffmpeg/hwapi/d3d11.cpp b/source/ffmpeg/hwapi/d3d11.cpp index 1d2bb38..5f80a61 100644 --- a/source/ffmpeg/hwapi/d3d11.cpp +++ b/source/ffmpeg/hwapi/d3d11.cpp @@ -102,10 +102,9 @@ std::list d3d11::enumerate_adapters() std::shared_ptr d3d11::create(const device& target) { - std::shared_ptr inst; - ATL::CComPtr device; - ATL::CComPtr context; - IDXGIAdapter1* adapter = nullptr; + std::shared_ptr inst; + ATL::CComPtr device; + IDXGIAdapter1* adapter = nullptr; // Find the correct "Adapter" (device). IDXGIAdapter1* dxgi_adapter = nullptr; @@ -125,12 +124,11 @@ std::shared_ptr d3d11::create(const device& target) D3D_FEATURE_LEVEL_11_1}; if (FAILED(_D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, device_flags, feature_levels.data(), - static_cast(feature_levels.size()), D3D11_SDK_VERSION, &device, NULL, - &context))) { + static_cast(feature_levels.size()), D3D11_SDK_VERSION, &device, NULL, NULL))) { throw std::runtime_error("Failed to create D3D11 device for target."); } - return std::make_shared(device, context); + return std::make_shared(device); } std::shared_ptr d3d11::create_from_obs() @@ -143,21 +141,24 @@ std::shared_ptr d3d11::create_from_obs() ATL::CComPtr device = ATL::CComPtr(reinterpret_cast(gs_get_device_obj())); - ATL::CComPtr context; - device->GetImmediateContext(&context); - return std::make_shared(device, context); + return std::make_shared(device); } struct D3D11AVFrame { ATL::CComPtr handle; }; -d3d11_instance::d3d11_instance(ATL::CComPtr device, ATL::CComPtr context) - : _device(device), _context(context) -{} +d3d11_instance::d3d11_instance(ATL::CComPtr device) : _device(device) +{ + // Acquire immediate rendering context. + device->GetImmediateContext(&_context); +} -d3d11_instance::~d3d11_instance() {} +d3d11_instance::~d3d11_instance() +{ + //_context.Release(); // Automatically performed by ATL::CComPtr. +} AVBufferRef* d3d11_instance::create_device_context() { @@ -165,17 +166,18 @@ AVBufferRef* d3d11_instance::create_device_context() if (!dctx_ref) throw std::runtime_error("Failed to allocate AVHWDeviceContext."); - AVHWDeviceContext* dctx = reinterpret_cast(dctx_ref->data); - AVD3D11VADeviceContext* d3d11va = reinterpret_cast(dctx->hwctx); + AVHWDeviceContext* hwdev = reinterpret_cast(dctx_ref->data); + AVD3D11VADeviceContext* device_hwctx = reinterpret_cast(hwdev->hwctx); - // TODO: Determine if these need an additional reference. - d3d11va->device = _device; - d3d11va->device->AddRef(); - d3d11va->device_context = _context; - d3d11va->device_context->AddRef(); - d3d11va->lock = [](void*) { obs_enter_graphics(); }; - d3d11va->unlock = [](void*) { obs_leave_graphics(); }; + // Provide the base device information only. + device_hwctx->device = _device; + device_hwctx->device->AddRef(); + // And a way to lock/unlock the device. + device_hwctx->lock = [](void*) { obs_enter_graphics(); }; + device_hwctx->unlock = [](void*) { obs_leave_graphics(); }; + + // Then let FFmpeg do the rest for us. int ret = av_hwdevice_ctx_init(dctx_ref); if (ret < 0) throw std::runtime_error("Failed to initialize AVHWDeviceContext."); diff --git a/source/ffmpeg/hwapi/d3d11.hpp b/source/ffmpeg/hwapi/d3d11.hpp index b7b36f8..44a5ec1 100644 --- a/source/ffmpeg/hwapi/d3d11.hpp +++ b/source/ffmpeg/hwapi/d3d11.hpp @@ -62,7 +62,7 @@ namespace streamfx::ffmpeg::hwapi { ATL::CComPtr _context; public: - d3d11_instance(ATL::CComPtr device, ATL::CComPtr context); + d3d11_instance(ATL::CComPtr device); virtual ~d3d11_instance(); virtual AVBufferRef* create_device_context() override;