diff --git a/app/streaming/input.cpp b/app/streaming/input.cpp index fb753890..7e78f8df 100644 --- a/app/streaming/input.cpp +++ b/app/streaming/input.cpp @@ -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; diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index b5ee99d3..f24219c6 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -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(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(event->data1); av_frame_free(&frame); + SDL_AtomicDecRef(&m_QueuedFrames); } diff --git a/app/streaming/video/ffmpeg.h b/app/streaming/video/ffmpeg.h index c6e51cb6..b914b9fd 100644 --- a/app/streaming/video/ffmpeg.h +++ b/app/streaming/video/ffmpeg.h @@ -38,4 +38,5 @@ private: QByteArray m_DecodeBuffer; const AVCodecHWConfig* m_HwDecodeCfg; IFFmpegRenderer* m_Renderer; + SDL_atomic_t m_QueuedFrames; };