summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Rothenpieler <[email protected]>2025-09-16 00:13:46 +0200
committerTimo Rothenpieler <[email protected]>2025-09-16 15:52:11 +0000
commit61378d6b911d30ef7ec095bcbb25b243ea07673c (patch)
tree6876e7cc63d022cb2d4534abf37b34df7acbd6ff
parentaf35a13f6d269a2400fd36ecc70b74ea2da1f1a8 (diff)
avfilter/vsrc_gfxcapture: fix possible missed wakeup race in capture loop
-rw-r--r--libavfilter/vsrc_gfxcapture_winrt.cpp25
1 files changed, 15 insertions, 10 deletions
diff --git a/libavfilter/vsrc_gfxcapture_winrt.cpp b/libavfilter/vsrc_gfxcapture_winrt.cpp
index 6477e56918..0849380b3a 100644
--- a/libavfilter/vsrc_gfxcapture_winrt.cpp
+++ b/libavfilter/vsrc_gfxcapture_winrt.cpp
@@ -123,8 +123,8 @@ struct GfxCaptureContextWgc {
std::mutex frame_arrived_mutex;
std::condition_variable frame_arrived_cond;
- std::atomic<bool> window_closed { false };
- std::atomic<uint64_t> frame_seq { 0 };
+ bool window_closed { false };
+ uint64_t frame_seq { 0 };
SizeInt32 cap_size { 0, 0 };
RECT client_area_offsets { 0, 0, 0, 0 };
@@ -196,12 +196,18 @@ static HRESULT get_activation_factory(GfxCaptureContextCpp *ctx, PCWSTR clsid, T
****************************************************/
static void wgc_frame_arrived_handler(const std::unique_ptr<GfxCaptureContextWgc> &wgctx) {
- wgctx->frame_seq.fetch_add(1, std::memory_order_release);
+ {
+ std::lock_guard lock(wgctx->frame_arrived_mutex);
+ wgctx->frame_seq += 1;
+ }
wgctx->frame_arrived_cond.notify_one();
}
static void wgc_closed_handler(const std::unique_ptr<GfxCaptureContextWgc> &wgctx) {
- wgctx->window_closed.store(true, std::memory_order_release);
+ {
+ std::lock_guard lock(wgctx->frame_arrived_mutex);
+ wgctx->window_closed = true;
+ }
wgctx->frame_arrived_cond.notify_one();
}
@@ -1455,23 +1461,22 @@ static int gfxcapture_activate(AVFilterContext *avctx)
if (!ff_outlink_frame_wanted(outlink))
return FFERROR_NOT_READY;
- std::unique_lock frame_lock(wgctx->frame_arrived_mutex);
-
for (;;) {
- uint64_t last_seq = wgctx->frame_seq.load(std::memory_order_acquire);
+ uint64_t last_seq = wgctx->frame_seq;
int ret = process_frame_if_exists(outlink);
if (ret != AVERROR(EAGAIN))
return ret;
- if (wgctx->window_closed.load(std::memory_order_acquire)) {
+ std::unique_lock frame_lock(wgctx->frame_arrived_mutex);
+
+ if (wgctx->window_closed && wgctx->frame_seq == last_seq) {
ff_outlink_set_status(outlink, AVERROR_EOF, ctx->last_pts - ctx->first_pts + 1);
break;
}
if (!wgctx->frame_arrived_cond.wait_for(frame_lock, std::chrono::seconds(1), [&]() {
- return wgctx->frame_seq.load(std::memory_order_acquire) != last_seq ||
- wgctx->window_closed.load(std::memory_order_acquire);
+ return wgctx->frame_seq != last_seq || wgctx->window_closed;
}))
break;
}