The branch, master has been updated
via 61835e1d8be9ace611e82b64f136a50f191a6e25 (commit)
via c4e537793b5939262cabb708ff798a732b8aba33 (commit)
via 1849068c657c23e979e804cf90e63ae2f7381ec5 (commit)
via 4879c9f4e2f2afc269d305d941cf70d18f3883a8 (commit)
via 23d9412ff9598b8989072e53d5474a41d2f14042 (commit)
via 983fed34f8172228c2e5490882531668d9d35105 (commit)
from 8accbbdf9a99a1999e7e0c19f6cc91085b3b1905 (commit)
- Log -----------------------------------------------------------------
commit 61835e1d8be9ace611e82b64f136a50f191a6e25
Author: Timo Rothenpieler <[email protected]>
AuthorDate: Wed Sep 17 22:03:28 2025 +0200
Commit: Timo Rothenpieler <[email protected]>
CommitDate: Thu Sep 18 01:04:59 2025 +0000
avfilter/vsrc_gfxcapture: keep cbdata object alive
Depending on the threading backend the stdlib uses, creating a
mutex/condvar can be quite expensive.
So keep this object alive in the ctx, on which we synchronize via the
uninit mutex anyway.
diff --git a/libavfilter/vsrc_gfxcapture_winrt.cpp
b/libavfilter/vsrc_gfxcapture_winrt.cpp
index 62b1a94802..1738fa23af 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.cpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.cpp
@@ -149,6 +149,7 @@ struct GfxCaptureContextCpp {
volatile int wgc_thread_init_res { INT_MAX };
std::recursive_mutex wgc_thread_uninit_mutex;
volatile int wgc_thread_res { 0 };
+ std::shared_ptr<void> wgc_thread_cb_data;
HWND capture_hwnd { nullptr };
HMONITOR capture_hmonitor { nullptr };
@@ -716,11 +717,17 @@ static int run_on_wgc_thread(AVFilterContext *avctx, F
&&cb)
struct CBData {
std::mutex mutex;
std::condition_variable cond;
- bool done { false };
- bool cancel { false };
- int ret { AVERROR_BUG };
+ bool done;
+ bool cancel;
+ int ret;
};
- auto cbdata = std::make_shared<CBData>();
+ auto cbdata = ctx->wgc_thread_cb_data ?
+ std::static_pointer_cast<CBData>(ctx->wgc_thread_cb_data) :
+ std::make_shared<CBData>();
+ ctx->wgc_thread_cb_data = cbdata;
+
+ cbdata->done = cbdata->cancel = false;
+ cbdata->ret = AVERROR_BUG;
boolean res = 0;
CHECK_HR_RET(wgctx->dispatcher_queue->TryEnqueue(
commit c4e537793b5939262cabb708ff798a732b8aba33
Author: Timo Rothenpieler <[email protected]>
AuthorDate: Wed Sep 17 21:31:56 2025 +0200
Commit: Timo Rothenpieler <[email protected]>
CommitDate: Thu Sep 18 01:04:59 2025 +0000
avfilter/vsrc_gfxcapture: fix leaking all callback handlers
Fixes #20537
diff --git a/libavfilter/vsrc_gfxcapture_winrt.hpp
b/libavfilter/vsrc_gfxcapture_winrt.hpp
index a02e768c8f..ba1979b1c1 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.hpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.hpp
@@ -159,9 +159,9 @@ private:
template<class Iface, typename... Args, typename F>
static Microsoft::WRL::ComPtr<Iface> create_cb_handler(F&& cb_func)
{
- return Microsoft::WRL::ComPtr<Iface>(
- new FFTypedCBHandler<Iface, F, Args...>(std::forward<F>(cb_func))
- );
+ Microsoft::WRL::ComPtr<Iface> res;
+ res.Attach(new FFTypedCBHandler<Iface, F,
Args...>(std::forward<F>(cb_func)));
+ return res;
}
/******************************************
commit 1849068c657c23e979e804cf90e63ae2f7381ec5
Author: Timo Rothenpieler <[email protected]>
AuthorDate: Wed Sep 17 20:23:37 2025 +0200
Commit: Timo Rothenpieler <[email protected]>
CommitDate: Thu Sep 18 01:04:59 2025 +0000
avfilter/vsrc_gfxcapture: use free threaded capture frame pool
Apparently, using a normal frame pool in a multithreaded environment
leads to strange resource leaks on shutdown, which vanish when using a
free threaded pool.
diff --git a/libavfilter/vsrc_gfxcapture_winrt.cpp
b/libavfilter/vsrc_gfxcapture_winrt.cpp
index 47c3b2db88..62b1a94802 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.cpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.cpp
@@ -327,7 +327,7 @@ static int wgc_setup_gfxcapture_session(AVFilterContext
*avctx)
std::unique_ptr<GfxCaptureContextWgc> &wgctx = ctx->wgc;
int ret;
- ComPtr<IDirect3D11CaptureFramePoolStatics> frame_pool_statics;
+ ComPtr<IDirect3D11CaptureFramePoolStatics2> frame_pool_statics;
ComPtr<ID3D11Device> d3d11_device = ctx->device_hwctx->device;
ComPtr<ID3D10Multithread> d3d10_multithread;
ComPtr<IDXGIDevice> dxgi_device;
@@ -350,8 +350,8 @@ static int wgc_setup_gfxcapture_session(AVFilterContext
*avctx)
CHECK_HR_RET(d3d11_device.As(&dxgi_device));
CHECK_HR_RET(ctx->fn.CreateDirect3D11DeviceFromDXGIDevice(dxgi_device.Get(),
&wgctx->d3d_device));
-
CHECK_HR_RET(get_activation_factory<IDirect3D11CaptureFramePoolStatics>(ctx,
RuntimeClass_Windows_Graphics_Capture_Direct3D11CaptureFramePool,
&frame_pool_statics));
- CHECK_HR_RET(frame_pool_statics->Create(wgctx->d3d_device.Get(), fmt,
CAPTURE_POOL_SIZE, wgctx->cap_size, &wgctx->frame_pool));
+
CHECK_HR_RET(get_activation_factory<IDirect3D11CaptureFramePoolStatics2>(ctx,
RuntimeClass_Windows_Graphics_Capture_Direct3D11CaptureFramePool,
&frame_pool_statics));
+
CHECK_HR_RET(frame_pool_statics->CreateFreeThreaded(wgctx->d3d_device.Get(),
fmt, CAPTURE_POOL_SIZE, wgctx->cap_size, &wgctx->frame_pool));
CHECK_HR_RET(wgctx->frame_pool->CreateCaptureSession(wgctx->capture_item.Get(),
&wgctx->capture_session));
if (SUCCEEDED(wgctx->capture_session.As(&session2))) {
commit 4879c9f4e2f2afc269d305d941cf70d18f3883a8
Author: Timo Rothenpieler <[email protected]>
AuthorDate: Wed Sep 17 19:13:29 2025 +0200
Commit: Timo Rothenpieler <[email protected]>
CommitDate: Thu Sep 18 01:04:59 2025 +0000
avfilter/vsrc_gfxcapture: stop capture session before initializing capture
thread shutdown
It might have things going on in the background that still need cleaned
up, and this gives it a chance to enqueue them on the dispatch queue.
diff --git a/libavfilter/vsrc_gfxcapture_winrt.cpp
b/libavfilter/vsrc_gfxcapture_winrt.cpp
index ade14d297f..47c3b2db88 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.cpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.cpp
@@ -229,7 +229,7 @@ static void wgc_stop_capture_session(AVFilterContext
*avctx) noexcept
if (wgctx->capture_session) {
ComPtr<IClosable> closable;
if (SUCCEEDED(wgctx->capture_session.As(&closable))) {
- closable->Close();
+ CHECK_HR_LOG(closable->Close());
} else {
av_log(avctx, AV_LOG_ERROR, "Failed to get capture session
IClosable interface\n");
}
@@ -243,6 +243,11 @@ static void wgc_stop_capture_session(AVFilterContext
*avctx) noexcept
av_log(avctx, AV_LOG_ERROR, "Failed to get frame pool IClosable
interface\n");
}
}
+
+ wgctx->capture_session.Reset();
+ wgctx->frame_pool.Reset();
+ wgctx->capture_item.Reset();
+ wgctx->d3d_device.Reset();
}
static int wgc_calculate_client_area(AVFilterContext *avctx)
@@ -557,6 +562,9 @@ static int wgc_thread_worker(AVFilterContext *avctx)
if (!msg.hwnd && msg.message == WM_WGC_THREAD_SHUTDOWN) {
av_log(avctx, AV_LOG_DEBUG, "Initializing WGC thread shutdown\n");
+
+ wgc_stop_capture_session(avctx);
+
if
(FAILED(wgctx->dispatcher_queue_controller->ShutdownQueueAsync(&async))) {
av_log(avctx, AV_LOG_ERROR, "Failed to shutdown dispatcher
queue\n");
return AVERROR_EXTERNAL;
commit 23d9412ff9598b8989072e53d5474a41d2f14042
Author: Timo Rothenpieler <[email protected]>
AuthorDate: Wed Sep 17 19:12:53 2025 +0200
Commit: Timo Rothenpieler <[email protected]>
CommitDate: Thu Sep 18 01:04:59 2025 +0000
avfilter/vsrc_gfxcapture: fix re-using ret variable from outside of lambda
scope
diff --git a/libavfilter/vsrc_gfxcapture_winrt.cpp
b/libavfilter/vsrc_gfxcapture_winrt.cpp
index b037dc89aa..ade14d297f 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.cpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.cpp
@@ -1394,9 +1394,9 @@ static int process_frame_if_exists(AVFilterLink *outlink)
ComPtr<ID3D11Texture2D> frame_texture;
TimeSpan frame_time = { 0 };
- ret = wgc_try_get_next_frame(avctx, capture_frame);
- if (ret < 0)
- return ret;
+ int res = wgc_try_get_next_frame(avctx, capture_frame);
+ if (res < 0)
+ return res;
CHECK_HR_RET(capture_frame->get_SystemRelativeTime(&frame_time));
commit 983fed34f8172228c2e5490882531668d9d35105
Author: Timo Rothenpieler <[email protected]>
AuthorDate: Wed Sep 17 18:31:11 2025 +0200
Commit: Timo Rothenpieler <[email protected]>
CommitDate: Thu Sep 18 01:04:59 2025 +0000
avfilter/vsrc_gfxcapture: don't pass pointer to ComPtr
While it does appear to work fine, with all the operator overloads, it
at least has potential for surprises, so pass it by reference instead.
diff --git a/libavfilter/vsrc_gfxcapture_winrt.cpp
b/libavfilter/vsrc_gfxcapture_winrt.cpp
index 9562863d7f..b037dc89aa 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.cpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.cpp
@@ -436,7 +436,7 @@ static int wgc_setup_gfxcapture_capture(AVFilterContext
*avctx)
return 0;
}
-static int wgc_try_get_next_frame(AVFilterContext *avctx,
ComPtr<IDirect3D11CaptureFrame> *capture_frame)
+static int wgc_try_get_next_frame(AVFilterContext *avctx,
ComPtr<IDirect3D11CaptureFrame> &capture_frame)
{
GfxCaptureContext *cctx = CCTX(avctx->priv);
GfxCaptureContextCpp *ctx = cctx->ctx;
@@ -447,11 +447,11 @@ static int wgc_try_get_next_frame(AVFilterContext *avctx,
ComPtr<IDirect3D11Capt
ComPtr<ID3D11Texture2D> frame_texture;
SizeInt32 frame_size = { 0, 0 };
-
CHECK_HR_RET(wgctx->frame_pool->TryGetNextFrame(capture_frame->ReleaseAndGetAddressOf()));
- if (!capture_frame->Get())
+ CHECK_HR_RET(wgctx->frame_pool->TryGetNextFrame(&capture_frame));
+ if (!capture_frame)
return AVERROR(EAGAIN);
- CHECK_HR_RET(capture_frame->Get()->get_ContentSize(&frame_size));
+ CHECK_HR_RET(capture_frame->get_ContentSize(&frame_size));
if (frame_size.Width != wgctx->cap_size.Width || frame_size.Height !=
wgctx->cap_size.Height) {
av_log(avctx, AV_LOG_VERBOSE, "Capture size changed to %dx%d\n",
frame_size.Width, frame_size.Height);
@@ -1394,7 +1394,7 @@ static int process_frame_if_exists(AVFilterLink *outlink)
ComPtr<ID3D11Texture2D> frame_texture;
TimeSpan frame_time = { 0 };
- ret = wgc_try_get_next_frame(avctx, &capture_frame);
+ ret = wgc_try_get_next_frame(avctx, capture_frame);
if (ret < 0)
return ret;
-----------------------------------------------------------------------
Summary of changes:
libavfilter/vsrc_gfxcapture_winrt.cpp | 45 +++++++++++++++++++++++------------
libavfilter/vsrc_gfxcapture_winrt.hpp | 6 ++---
2 files changed, 33 insertions(+), 18 deletions(-)
hooks/post-receive
--
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]