Fix crashes when restarting streaming with DXVA2 renderer due to leaked surface references

This commit is contained in:
Cameron Gutman 2018-07-20 13:10:54 -07:00
parent 9c2befc386
commit faaf9dfa07
3 changed files with 31 additions and 4 deletions

View file

@ -65,11 +65,11 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Detected quit key combo");
SDL_Event event;
// Uncapture the mouse to avoid processing any
// further keyboard input
SDL_SetRelativeMouseMode(SDL_FALSE);
// Drain the event queue of any additional input
// that might be processed before our quit message.
while (SDL_PollEvent(&event));
SDL_Event event;
// Push a quit event to the main loop
event.type = SDL_QUIT;

View file

@ -98,6 +98,7 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
m_Renderer(nullptr)
{
av_init_packet(&m_Pkt);
SDL_AtomicSet(&m_QueuedFrames, 0);
// Use linear filtering when renderer scaling is required
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
@ -105,6 +106,28 @@ FFmpegVideoDecoder::FFmpegVideoDecoder()
FFmpegVideoDecoder::~FFmpegVideoDecoder()
{
// Drop any frames still queued to ensure
// they are properly freed.
SDL_Event event;
while (SDL_AtomicGet(&m_QueuedFrames) > 0) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Waiting for %d frames to return",
SDL_AtomicGet(&m_QueuedFrames));
if (SDL_PeepEvents(&event,
1,
SDL_GETEVENT,
SDL_USEREVENT,
SDL_USEREVENT) == 1) {
dropFrame(&event.user);
}
else {
SDL_Delay(100);
SDL_PumpEvents();
}
}
avcodec_close(m_VideoDecoderCtx);
av_free(m_VideoDecoderCtx);
m_VideoDecoderCtx = nullptr;
@ -218,6 +241,7 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
err = avcodec_receive_frame(m_VideoDecoderCtx, frame);
if (err == 0) {
// Queue the frame for rendering from the main thread
SDL_AtomicIncRef(&m_QueuedFrames);
queueFrame(frame);
}
else {
@ -232,6 +256,7 @@ void FFmpegVideoDecoder::renderFrame(SDL_UserEvent* event)
{
AVFrame* frame = reinterpret_cast<AVFrame*>(event->data1);
m_Renderer->renderFrame(frame);
SDL_AtomicDecRef(&m_QueuedFrames);
}
// Called on main thread
@ -239,4 +264,5 @@ void FFmpegVideoDecoder::dropFrame(SDL_UserEvent* event)
{
AVFrame* frame = reinterpret_cast<AVFrame*>(event->data1);
av_frame_free(&frame);
SDL_AtomicDecRef(&m_QueuedFrames);
}

View file

@ -38,4 +38,5 @@ private:
QByteArray m_DecodeBuffer;
const AVCodecHWConfig* m_HwDecodeCfg;
IFFmpegRenderer* m_Renderer;
SDL_atomic_t m_QueuedFrames;
};