#pragma once #include "../../decoder.h" #include "../renderer.h" #include #include #include class IVsyncSource { public: virtual ~IVsyncSource() {} virtual bool initialize(SDL_Window* window, int displayFps) = 0; // Asynchronous sources produce callbacks on their own, while synchronous // sources require calls to waitForVsync(). virtual bool isAsync() = 0; virtual void waitForVsync() { // Synchronous sources must implement waitForVsync()! SDL_assert(false); } }; class Pacer { public: Pacer(IFFmpegRenderer* renderer, PVIDEO_STATS videoStats); ~Pacer(); void submitFrame(AVFrame* frame); bool initialize(SDL_Window* window, int maxVideoFps, bool enablePacing); void signalVsync(); void renderOnMainThread(); private: static int vsyncThread(void* context); static int renderThread(void* context); void handleVsync(int timeUntilNextVsyncMillis); void enqueueFrameForRenderingAndUnlock(AVFrame* frame); void renderFrame(AVFrame* frame); void dropFrameForEnqueue(QQueue& queue); QQueue m_RenderQueue; QQueue m_PacingQueue; QQueue m_PacingQueueHistory; QQueue m_RenderQueueHistory; QMutex m_FrameQueueLock; QWaitCondition m_RenderQueueNotEmpty; QWaitCondition m_PacingQueueNotEmpty; QWaitCondition m_VsyncSignalled; SDL_Thread* m_RenderThread; SDL_Thread* m_VsyncThread; bool m_Stopping; IVsyncSource* m_VsyncSource; IFFmpegRenderer* m_VsyncRenderer; int m_MaxVideoFps; int m_DisplayFps; PVIDEO_STATS m_VideoStats; int m_RendererAttributes; };