mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-31 11:20:05 +01:00
avfilter/vsrc_gfxcapture: fix possible missed wakeup race in capture loop
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user