cellVdec: Postpone Context Destruction

This commit is contained in:
Antonino Di Guardo
2026-09-26 14:37:31 +00:00
committed by GitHub
parent 3aab4c5d59
commit a1c317a8c4
+43 -2
View File
@@ -298,9 +298,15 @@ struct vdec_context final
}
~vdec_context()
{
release_decoder();
}
// Frees the FFmpeg decoder, which may take milliseconds
void release_decoder()
{
avcodec_free_context(&ctx);
sws_freeContext(sws);
sws_freeContext(std::exchange(sws, nullptr));
}
static u32 freq_to_framerate_code(f64 freq)
@@ -653,6 +659,38 @@ struct vdec_context final
}
};
// Frees the FFmpeg decoders of closed contexts on a host thread.
// Freeing a decoder takes milliseconds, which would otherwise delay the guest thread closing it.
struct vdec_context_reaper
{
lf_queue<shared_ptr<vdec_context>> contexts;
void operator()()
{
while (thread_ctrl::state() != thread_state::aborting)
{
thread_ctrl::wait_on(contexts);
// Let the closing sequence of the caller complete first: freeing this much memory slows down the other threads
thread_ctrl::wait_for(100'000);
for (auto&& vdec : contexts.pop_all())
{
if (vdec.use_count() > 1)
{
// Still used by an HLE call in progress, retry later
contexts.push(std::move(vdec));
continue;
}
vdec->release_decoder();
}
}
}
static constexpr auto thread_name = "HLE Video Decoder Reaper"sv;
};
extern bool check_if_vdec_contexts_exist()
{
bool context_exists = false;
@@ -1493,12 +1531,15 @@ error_code cellVdecClose(ppu_thread& ppu, u32 handle)
vdec->seq_state = sequence_state::closed;
vdec->mutex.lock_unlock();
if (!idm::remove_verify<vdec_context>(handle, std::move(vdec)))
if (!idm::remove_verify<vdec_context>(handle, vdec))
{
// Other thread removed it beforehead
return { CELL_VDEC_ERROR_ARG, "remove_verify failed" };
}
// Let the reaper free the decoder so that the caller does not pay for it
g_fxo->get<named_thread<vdec_context_reaper>>().contexts.push(std::move(vdec));
return CELL_OK;
}