diff --git a/app/streaming/video/ffmpeg-renderers/dxva2.cpp b/app/streaming/video/ffmpeg-renderers/dxva2.cpp index ea457184..23590faf 100644 --- a/app/streaming/video/ffmpeg-renderers/dxva2.cpp +++ b/app/streaming/video/ffmpeg-renderers/dxva2.cpp @@ -624,6 +624,11 @@ int DXVA2Renderer::getDecoderCapabilities() return 0; } +IFFmpegRenderer::VSyncConstraint DXVA2Renderer::getVsyncConstraint() +{ + return VSYNC_ANY; +} + void DXVA2Renderer::renderFrameAtVsync(AVFrame *frame) { IDirect3DSurface9* surface = reinterpret_cast(frame->data[3]); diff --git a/app/streaming/video/ffmpeg-renderers/dxva2.h b/app/streaming/video/ffmpeg-renderers/dxva2.h index 3ffecc2e..5b0ae473 100644 --- a/app/streaming/video/ffmpeg-renderers/dxva2.h +++ b/app/streaming/video/ffmpeg-renderers/dxva2.h @@ -25,6 +25,7 @@ public: virtual void renderFrameAtVsync(AVFrame* frame); virtual bool needsTestFrame(); virtual int getDecoderCapabilities(); + virtual VSyncConstraint getVsyncConstraint(); private: bool initializeDecoder(); diff --git a/app/streaming/video/ffmpeg-renderers/renderer.h b/app/streaming/video/ffmpeg-renderers/renderer.h index 9bba8416..4ecf2a13 100644 --- a/app/streaming/video/ffmpeg-renderers/renderer.h +++ b/app/streaming/video/ffmpeg-renderers/renderer.h @@ -8,6 +8,12 @@ extern "C" { class IFFmpegRenderer { public: + enum VSyncConstraint { + VSYNC_FORCE_OFF, + VSYNC_FORCE_ON, + VSYNC_ANY + }; + virtual ~IFFmpegRenderer() {} virtual bool initialize(SDL_Window* window, int videoFormat, @@ -19,6 +25,7 @@ public: virtual void renderFrameAtVsync(AVFrame* frame) = 0; virtual bool needsTestFrame() = 0; virtual int getDecoderCapabilities() = 0; + virtual VSyncConstraint getVsyncConstraint() = 0; }; class SdlRenderer : public IFFmpegRenderer { @@ -35,6 +42,7 @@ public: virtual void renderFrameAtVsync(AVFrame* frame); virtual bool needsTestFrame(); virtual int getDecoderCapabilities(); + virtual VSyncConstraint getVsyncConstraint(); private: SDL_Renderer* m_Renderer; diff --git a/app/streaming/video/ffmpeg-renderers/sdl.cpp b/app/streaming/video/ffmpeg-renderers/sdl.cpp index 6cef3ac0..2f3d2b65 100644 --- a/app/streaming/video/ffmpeg-renderers/sdl.cpp +++ b/app/streaming/video/ffmpeg-renderers/sdl.cpp @@ -43,6 +43,11 @@ int SdlRenderer::getDecoderCapabilities() return CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC; } +IFFmpegRenderer::VSyncConstraint SdlRenderer::getVsyncConstraint() +{ + return VSYNC_ANY; +} + bool SdlRenderer::initialize(SDL_Window* window, int, int width, diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.cpp b/app/streaming/video/ffmpeg-renderers/vaapi.cpp index 27f365a9..f4951ba2 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.cpp +++ b/app/streaming/video/ffmpeg-renderers/vaapi.cpp @@ -155,6 +155,11 @@ VAAPIRenderer::getDecoderCapabilities() return 0; } +IFFmpegRenderer::VSyncConstraint VAAPIRenderer::getVsyncConstraint() +{ + return VSYNC_ANY; +} + void VAAPIRenderer::renderFrameAtVsync(AVFrame* frame) { diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.h b/app/streaming/video/ffmpeg-renderers/vaapi.h index 7ce9ea58..084420c9 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.h +++ b/app/streaming/video/ffmpeg-renderers/vaapi.h @@ -40,6 +40,7 @@ public: virtual void renderFrameAtVsync(AVFrame* frame); virtual bool needsTestFrame(); virtual int getDecoderCapabilities(); + virtual VSyncConstraint getVsyncConstraint(); private: int m_WindowSystem; diff --git a/app/streaming/video/ffmpeg-renderers/vdpau.cpp b/app/streaming/video/ffmpeg-renderers/vdpau.cpp index 7cd61e93..78ad351c 100644 --- a/app/streaming/video/ffmpeg-renderers/vdpau.cpp +++ b/app/streaming/video/ffmpeg-renderers/vdpau.cpp @@ -238,6 +238,11 @@ int VDPAURenderer::getDecoderCapabilities() return 0; } +IFFmpegRenderer::VSyncConstraint VDPAURenderer::getVsyncConstraint() +{ + return VSYNC_ANY; +} + void VDPAURenderer::renderFrameAtVsync(AVFrame* frame) { VdpStatus status; diff --git a/app/streaming/video/ffmpeg-renderers/vdpau.h b/app/streaming/video/ffmpeg-renderers/vdpau.h index 83adbd8a..c014f562 100644 --- a/app/streaming/video/ffmpeg-renderers/vdpau.h +++ b/app/streaming/video/ffmpeg-renderers/vdpau.h @@ -23,6 +23,7 @@ public: virtual void renderFrameAtVsync(AVFrame* frame); virtual bool needsTestFrame(); virtual int getDecoderCapabilities(); + virtual VSyncConstraint getVsyncConstraint(); private: uint32_t m_VideoWidth, m_VideoHeight; diff --git a/app/streaming/video/ffmpeg-renderers/vt.mm b/app/streaming/video/ffmpeg-renderers/vt.mm index fe00eeda..94b5c3ea 100644 --- a/app/streaming/video/ffmpeg-renderers/vt.mm +++ b/app/streaming/video/ffmpeg-renderers/vt.mm @@ -201,6 +201,14 @@ public: return 0; } + virtual IFFmpegRenderer::VSyncConstraint getVsyncConstraint() override + { + // This renderer is inherently tied to V-sync due how we're + // rendering with AVSampleBufferDisplay layer. Running without + // the V-Sync source leads to massive stuttering. + return VSYNC_FORCE_ON; + } + private: void setupDisplayLayer() { diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index 30dcc98b..1f3935cd 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -120,6 +120,18 @@ bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, SDL_Window* wi int videoFormat, int width, int height, int maxFps, bool enableVsync, bool testOnly) { + auto vsyncConstraint = m_Renderer->getVsyncConstraint(); + if (vsyncConstraint == IFFmpegRenderer::VSYNC_FORCE_OFF && enableVsync) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "V-sync is forcefully disabled by the active renderer"); + enableVsync = false; + } + else if (vsyncConstraint == IFFmpegRenderer::VSYNC_FORCE_ON && !enableVsync) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "V-sync is forcefully enabled by the active renderer"); + enableVsync = true; + } + m_Pacer = new Pacer(m_Renderer); if (!m_Pacer->initialize(window, maxFps, enableVsync)) { return false;