diff options
author | Timo Rothenpieler <[email protected]> | 2025-09-16 00:13:46 +0200 |
---|---|---|
committer | Timo Rothenpieler <[email protected]> | 2025-09-16 15:52:11 +0000 |
commit | 61378d6b911d30ef7ec095bcbb25b243ea07673c (patch) | |
tree | 6876e7cc63d022cb2d4534abf37b34df7acbd6ff | |
parent | af35a13f6d269a2400fd36ecc70b74ea2da1f1a8 (diff) |
avfilter/vsrc_gfxcapture: fix possible missed wakeup race in capture loop
-rw-r--r-- | libavfilter/vsrc_gfxcapture_winrt.cpp | 25 |
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; } |