Add frame pacing toggle

This commit is contained in:
Cameron Gutman 2018-12-25 12:57:00 -08:00
parent c054536fab
commit cfabaf334e
22 changed files with 81 additions and 51 deletions

View File

@ -287,6 +287,7 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
parser.addToggleOption("mouse-acceleration", "mouse acceleration"); parser.addToggleOption("mouse-acceleration", "mouse acceleration");
parser.addToggleOption("game-optimization", "game optimizations"); parser.addToggleOption("game-optimization", "game optimizations");
parser.addToggleOption("audio-on-host", "audio on host PC"); parser.addToggleOption("audio-on-host", "audio on host PC");
parser.addToggleOption("frame-pacing", "frame pacing");
parser.addChoiceOption("video-codec", "video codec", m_VideoCodecMap.keys()); parser.addChoiceOption("video-codec", "video codec", m_VideoCodecMap.keys());
parser.addChoiceOption("video-decoder", "video decoder", m_VideoDecoderMap.keys()); parser.addChoiceOption("video-decoder", "video decoder", m_VideoDecoderMap.keys());
@ -372,6 +373,9 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
// Resolve --audio-on-host and --no-audio-on-host options // Resolve --audio-on-host and --no-audio-on-host options
preferences->playAudioOnHost = parser.getToggleOptionValue("audio-on-host", preferences->playAudioOnHost); preferences->playAudioOnHost = parser.getToggleOptionValue("audio-on-host", preferences->playAudioOnHost);
// Resolve --frame-pacing and --no-frame-pacing options
preferences->framePacing = parser.getToggleOptionValue("frame-pacing", preferences->framePacing);
// Resolve --video-codec option // Resolve --video-codec option
if (parser.isSet("video-codec")) { if (parser.isSet("video-codec")) {
preferences->videoCodecConfig = mapValue(m_VideoCodecMap, parser.getChoiceOptionValue("video-codec")); preferences->videoCodecConfig = mapValue(m_VideoCodecMap, parser.getChoiceOptionValue("video-codec"));

View File

@ -383,7 +383,7 @@ Flickable {
CheckBox { CheckBox {
id: vsyncCheck id: vsyncCheck
hoverEnabled: true hoverEnabled: true
text: "Enable V-Sync" text: "V-Sync"
font.pointSize: 12 font.pointSize: 12
checked: prefs.enableVsync checked: prefs.enableVsync
onCheckedChanged: { onCheckedChanged: {
@ -395,6 +395,22 @@ Flickable {
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.text: "Disabling V-Sync allows sub-frame rendering latency, but it can display visible tearing" ToolTip.text: "Disabling V-Sync allows sub-frame rendering latency, but it can display visible tearing"
} }
CheckBox {
id: framePacingCheck
hoverEnabled: true
text: "Frame pacing"
font.pointSize: 12
enabled: prefs.enableVsync
checked: prefs.enableVsync && prefs.framePacing
onCheckedChanged: {
prefs.framePacing = checked
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
ToolTip.text: "Frame pacing reduces micro-stutter by delaying frames that come in too early"
}
} }
} }

View File

@ -23,6 +23,7 @@
#define SER_QUITAPPAFTER "quitAppAfter" #define SER_QUITAPPAFTER "quitAppAfter"
#define SER_MOUSEACCELERATION "mouseacceleration" #define SER_MOUSEACCELERATION "mouseacceleration"
#define SER_STARTWINDOWED "startwindowed" #define SER_STARTWINDOWED "startwindowed"
#define SER_FRAMEPACING "framepacing"
StreamingPreferences::StreamingPreferences(QObject *parent) StreamingPreferences::StreamingPreferences(QObject *parent)
: QObject(parent) : QObject(parent)
@ -47,6 +48,7 @@ void StreamingPreferences::reload()
quitAppAfter = settings.value(SER_QUITAPPAFTER, false).toBool(); quitAppAfter = settings.value(SER_QUITAPPAFTER, false).toBool();
mouseAcceleration = settings.value(SER_MOUSEACCELERATION, false).toBool(); mouseAcceleration = settings.value(SER_MOUSEACCELERATION, false).toBool();
startWindowed = settings.value(SER_STARTWINDOWED, false).toBool(); startWindowed = settings.value(SER_STARTWINDOWED, false).toBool();
framePacing = settings.value(SER_FRAMEPACING, false).toBool();
audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG, audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG,
static_cast<int>(AudioConfig::AC_STEREO)).toInt()); static_cast<int>(AudioConfig::AC_STEREO)).toInt());
videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG, videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG,
@ -76,6 +78,7 @@ void StreamingPreferences::save()
settings.setValue(SER_QUITAPPAFTER, quitAppAfter); settings.setValue(SER_QUITAPPAFTER, quitAppAfter);
settings.setValue(SER_MOUSEACCELERATION, mouseAcceleration); settings.setValue(SER_MOUSEACCELERATION, mouseAcceleration);
settings.setValue(SER_STARTWINDOWED, startWindowed); settings.setValue(SER_STARTWINDOWED, startWindowed);
settings.setValue(SER_FRAMEPACING, framePacing);
settings.setValue(SER_AUDIOCFG, static_cast<int>(audioConfig)); settings.setValue(SER_AUDIOCFG, static_cast<int>(audioConfig));
settings.setValue(SER_VIDEOCFG, static_cast<int>(videoCodecConfig)); settings.setValue(SER_VIDEOCFG, static_cast<int>(videoCodecConfig));
settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection)); settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection));

View File

@ -76,6 +76,7 @@ public:
Q_PROPERTY(bool quitAppAfter MEMBER quitAppAfter NOTIFY quitAppAfterChanged) Q_PROPERTY(bool quitAppAfter MEMBER quitAppAfter NOTIFY quitAppAfterChanged)
Q_PROPERTY(bool mouseAcceleration MEMBER mouseAcceleration NOTIFY mouseAccelerationChanged) Q_PROPERTY(bool mouseAcceleration MEMBER mouseAcceleration NOTIFY mouseAccelerationChanged)
Q_PROPERTY(bool startWindowed MEMBER startWindowed NOTIFY startWindowedChanged) Q_PROPERTY(bool startWindowed MEMBER startWindowed NOTIFY startWindowedChanged)
Q_PROPERTY(bool framePacing MEMBER framePacing NOTIFY framePacingChanged)
Q_PROPERTY(AudioConfig audioConfig MEMBER audioConfig NOTIFY audioConfigChanged) Q_PROPERTY(AudioConfig audioConfig MEMBER audioConfig NOTIFY audioConfigChanged)
Q_PROPERTY(VideoCodecConfig videoCodecConfig MEMBER videoCodecConfig NOTIFY videoCodecConfigChanged) Q_PROPERTY(VideoCodecConfig videoCodecConfig MEMBER videoCodecConfig NOTIFY videoCodecConfigChanged)
Q_PROPERTY(VideoDecoderSelection videoDecoderSelection MEMBER videoDecoderSelection NOTIFY videoDecoderSelectionChanged) Q_PROPERTY(VideoDecoderSelection videoDecoderSelection MEMBER videoDecoderSelection NOTIFY videoDecoderSelectionChanged)
@ -95,6 +96,7 @@ public:
bool quitAppAfter; bool quitAppAfter;
bool mouseAcceleration; bool mouseAcceleration;
bool startWindowed; bool startWindowed;
bool framePacing;
AudioConfig audioConfig; AudioConfig audioConfig;
VideoCodecConfig videoCodecConfig; VideoCodecConfig videoCodecConfig;
VideoDecoderSelection videoDecoderSelection; VideoDecoderSelection videoDecoderSelection;
@ -116,5 +118,6 @@ signals:
void videoDecoderSelectionChanged(); void videoDecoderSelectionChanged();
void windowModeChanged(); void windowModeChanged();
void startWindowedChanged(); void startWindowedChanged();
void framePacingChanged();
}; };

View File

@ -99,11 +99,11 @@ void Session::clLogMessage(const char* format, ...)
va_end(ap); va_end(ap);
} }
#define CALL_INITIALIZE(dec) (dec)->initialize(vds, window, videoFormat, width, height, frameRate, enableVsync) #define CALL_INITIALIZE(dec) (dec)->initialize(vds, window, videoFormat, width, height, frameRate, enableVsync, enableFramePacing)
bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
SDL_Window* window, int videoFormat, int width, int height, SDL_Window* window, int videoFormat, int width, int height,
int frameRate, bool enableVsync, IVideoDecoder*& chosenDecoder) int frameRate, bool enableVsync, bool enableFramePacing, IVideoDecoder*& chosenDecoder)
{ {
#ifdef HAVE_SLVIDEO #ifdef HAVE_SLVIDEO
chosenDecoder = new SLVideoDecoder(); chosenDecoder = new SLVideoDecoder();
@ -217,7 +217,7 @@ bool Session::isHardwareDecodeAvailable(StreamingPreferences::VideoDecoderSelect
return false; return false;
} }
if (!chooseDecoder(vds, window, videoFormat, width, height, frameRate, true, decoder)) { if (!chooseDecoder(vds, window, videoFormat, width, height, frameRate, true, false, decoder)) {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_QuitSubSystem(SDL_INIT_VIDEO);
return false; return false;
@ -257,7 +257,7 @@ int Session::getDecoderCapabilities(StreamingPreferences::VideoDecoderSelection
return false; return false;
} }
if (!chooseDecoder(vds, window, videoFormat, width, height, frameRate, true, decoder)) { if (!chooseDecoder(vds, window, videoFormat, width, height, frameRate, true, false, decoder)) {
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_QuitSubSystem(SDL_INIT_VIDEO);
return false; return false;
@ -1120,6 +1120,7 @@ void Session::exec(int displayOriginX, int displayOriginY)
m_Window, m_ActiveVideoFormat, m_ActiveVideoWidth, m_Window, m_ActiveVideoFormat, m_ActiveVideoWidth,
m_ActiveVideoHeight, m_ActiveVideoFrameRate, m_ActiveVideoHeight, m_ActiveVideoFrameRate,
enableVsync, enableVsync,
enableVsync && m_Preferences->framePacing,
s_ActiveSession->m_VideoDecoder)) { s_ActiveSession->m_VideoDecoder)) {
SDL_AtomicUnlock(&m_DecoderLock); SDL_AtomicUnlock(&m_DecoderLock);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,

View File

@ -72,7 +72,8 @@ private:
static static
bool chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, bool chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
SDL_Window* window, int videoFormat, int width, int height, SDL_Window* window, int videoFormat, int width, int height,
int frameRate, bool enableVsync, IVideoDecoder*& chosenDecoder); int frameRate, bool enableVsync, bool enableFramePacing,
IVideoDecoder*& chosenDecoder);
static static
void clStageStarting(int stage); void clStageStarting(int stage);

View File

@ -33,7 +33,8 @@ public:
int width, int width,
int height, int height,
int frameRate, int frameRate,
bool enableVsync) = 0; bool enableVsync,
bool enableFramePacing) = 0;
virtual bool isHardwareAccelerated() = 0; virtual bool isHardwareAccelerated() = 0;
virtual int getDecoderCapabilities() = 0; virtual int getDecoderCapabilities() = 0;
virtual int submitDecodeUnit(PDECODE_UNIT du) = 0; virtual int submitDecodeUnit(PDECODE_UNIT du) = 0;

View File

@ -644,9 +644,9 @@ int DXVA2Renderer::getDecoderCapabilities()
return 0; return 0;
} }
IFFmpegRenderer::VSyncConstraint DXVA2Renderer::getVsyncConstraint() IFFmpegRenderer::FramePacingConstraint DXVA2Renderer::getFramePacingConstraint()
{ {
return VSYNC_ANY; return PACING_ANY;
} }
void DXVA2Renderer::renderFrameAtVsync(AVFrame *frame) void DXVA2Renderer::renderFrameAtVsync(AVFrame *frame)

View File

@ -25,7 +25,7 @@ public:
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame(); virtual bool needsTestFrame();
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities();
virtual VSyncConstraint getVsyncConstraint(); virtual FramePacingConstraint getFramePacingConstraint();
private: private:
bool initializeDecoder(); bool initializeDecoder();

View File

@ -124,15 +124,14 @@ RenderNextFrame:
av_frame_free(&frame); av_frame_free(&frame);
} }
bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enableVsync) bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enablePacing)
{ {
m_MaxVideoFps = maxVideoFps; m_MaxVideoFps = maxVideoFps;
m_EnableVsync = enableVsync;
m_DisplayFps = StreamUtils::getDisplayRefreshRate(window); m_DisplayFps = StreamUtils::getDisplayRefreshRate(window);
if (m_EnableVsync) { if (enablePacing) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Frame pacing in tear-free mode: target %d Hz with %d FPS stream", "Frame pacing active: target %d Hz with %d FPS stream",
m_DisplayFps, m_MaxVideoFps); m_DisplayFps, m_MaxVideoFps);
#if defined(Q_OS_DARWIN) #if defined(Q_OS_DARWIN)
@ -150,7 +149,7 @@ bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enableVsync)
} }
else { else {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Minimal latency tearing mode: target %d Hz with %d FPS stream", "Frame pacing disabled: target %d Hz with %d FPS stream",
m_DisplayFps, m_MaxVideoFps); m_DisplayFps, m_MaxVideoFps);
} }

View File

@ -20,7 +20,7 @@ public:
void submitFrame(AVFrame* frame); void submitFrame(AVFrame* frame);
bool initialize(SDL_Window* window, int maxVideoFps, bool enableVsync); bool initialize(SDL_Window* window, int maxVideoFps, bool enablePacing);
void vsyncCallback(int timeUntilNextVsyncMillis); void vsyncCallback(int timeUntilNextVsyncMillis);
@ -35,6 +35,5 @@ private:
IFFmpegRenderer* m_VsyncRenderer; IFFmpegRenderer* m_VsyncRenderer;
int m_MaxVideoFps; int m_MaxVideoFps;
int m_DisplayFps; int m_DisplayFps;
bool m_EnableVsync;
PVIDEO_STATS m_VideoStats; PVIDEO_STATS m_VideoStats;
}; };

View File

@ -8,10 +8,10 @@ extern "C" {
class IFFmpegRenderer { class IFFmpegRenderer {
public: public:
enum VSyncConstraint { enum FramePacingConstraint {
VSYNC_FORCE_OFF, PACING_FORCE_OFF,
VSYNC_FORCE_ON, PACING_FORCE_ON,
VSYNC_ANY PACING_ANY
}; };
virtual ~IFFmpegRenderer() {} virtual ~IFFmpegRenderer() {}
@ -25,7 +25,7 @@ public:
virtual void renderFrameAtVsync(AVFrame* frame) = 0; virtual void renderFrameAtVsync(AVFrame* frame) = 0;
virtual bool needsTestFrame() = 0; virtual bool needsTestFrame() = 0;
virtual int getDecoderCapabilities() = 0; virtual int getDecoderCapabilities() = 0;
virtual VSyncConstraint getVsyncConstraint() = 0; virtual FramePacingConstraint getFramePacingConstraint() = 0;
}; };
class SdlRenderer : public IFFmpegRenderer { class SdlRenderer : public IFFmpegRenderer {
@ -42,7 +42,7 @@ public:
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame(); virtual bool needsTestFrame();
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities();
virtual VSyncConstraint getVsyncConstraint(); virtual FramePacingConstraint getFramePacingConstraint();
private: private:
SDL_Renderer* m_Renderer; SDL_Renderer* m_Renderer;

View File

@ -43,9 +43,9 @@ int SdlRenderer::getDecoderCapabilities()
return CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC; return CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC;
} }
IFFmpegRenderer::VSyncConstraint SdlRenderer::getVsyncConstraint() IFFmpegRenderer::FramePacingConstraint SdlRenderer::getFramePacingConstraint()
{ {
return VSYNC_ANY; return PACING_ANY;
} }
bool SdlRenderer::initialize(SDL_Window* window, bool SdlRenderer::initialize(SDL_Window* window,

View File

@ -177,9 +177,9 @@ VAAPIRenderer::getDecoderCapabilities()
return 0; return 0;
} }
IFFmpegRenderer::VSyncConstraint VAAPIRenderer::getVsyncConstraint() IFFmpegRenderer::FramePacingConstraint VAAPIRenderer::getFramePacingConstraint()
{ {
return VSYNC_ANY; return PACING_ANY;
} }
void void

View File

@ -40,7 +40,7 @@ public:
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame(); virtual bool needsTestFrame();
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities();
virtual VSyncConstraint getVsyncConstraint(); virtual FramePacingConstraint getFramePacingConstraint();
private: private:
int m_WindowSystem; int m_WindowSystem;

View File

@ -246,9 +246,9 @@ int VDPAURenderer::getDecoderCapabilities()
return 0; return 0;
} }
IFFmpegRenderer::VSyncConstraint VDPAURenderer::getVsyncConstraint() IFFmpegRenderer::FramePacingConstraint VDPAURenderer::getFramePacingConstraint()
{ {
return VSYNC_ANY; return PACING_ANY;
} }
void VDPAURenderer::renderFrameAtVsync(AVFrame* frame) void VDPAURenderer::renderFrameAtVsync(AVFrame* frame)

View File

@ -23,7 +23,7 @@ public:
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame(); virtual bool needsTestFrame();
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities();
virtual VSyncConstraint getVsyncConstraint(); virtual FramePacingConstraint getFramePacingConstraint();
private: private:
uint32_t m_VideoWidth, m_VideoHeight; uint32_t m_VideoWidth, m_VideoHeight;

View File

@ -211,12 +211,12 @@ public:
return 0; return 0;
} }
virtual IFFmpegRenderer::VSyncConstraint getVsyncConstraint() override virtual IFFmpegRenderer::FramePacingConstraint getFramePacingConstraint() override
{ {
// This renderer is inherently tied to V-sync due how we're // This renderer is inherently tied to V-sync due how we're
// rendering with AVSampleBufferDisplay layer. Running without // rendering with AVSampleBufferDisplay layer. Running without
// the V-Sync source leads to massive stuttering. // the V-Sync source leads to massive stuttering.
return VSYNC_FORCE_ON; return PACING_FORCE_ON;
} }
private: private:

View File

@ -131,27 +131,27 @@ void FFmpegVideoDecoder::reset()
bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, SDL_Window* window, bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, SDL_Window* window,
int videoFormat, int width, int height, int videoFormat, int width, int height,
int maxFps, bool enableVsync, bool testOnly) int maxFps, bool enableFramePacing, bool testOnly)
{ {
auto vsyncConstraint = m_Renderer->getVsyncConstraint(); auto vsyncConstraint = m_Renderer->getFramePacingConstraint();
if (vsyncConstraint == IFFmpegRenderer::VSYNC_FORCE_OFF && enableVsync) { if (vsyncConstraint == IFFmpegRenderer::PACING_FORCE_OFF && enableFramePacing) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"V-sync is forcefully disabled by the active renderer"); "Frame pacing is forcefully disabled by the active renderer");
enableVsync = false; enableFramePacing = false;
} }
else if (vsyncConstraint == IFFmpegRenderer::VSYNC_FORCE_ON && !enableVsync) { else if (vsyncConstraint == IFFmpegRenderer::PACING_FORCE_ON && !enableFramePacing) {
// FIXME: This duplicates logic in Session.cpp // FIXME: This duplicates logic in Session.cpp
int displayHz = StreamUtils::getDisplayRefreshRate(window); int displayHz = StreamUtils::getDisplayRefreshRate(window);
if (displayHz + 5 >= maxFps) { if (displayHz + 5 >= maxFps) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"V-sync is forcefully enabled by the active renderer"); "Frame pacing is forcefully enabled by the active renderer");
enableVsync = true; enableFramePacing = true;
} }
} }
m_StreamFps = maxFps; m_StreamFps = maxFps;
m_Pacer = new Pacer(m_Renderer, &m_ActiveWndVideoStats); m_Pacer = new Pacer(m_Renderer, &m_ActiveWndVideoStats);
if (!m_Pacer->initialize(window, maxFps, enableVsync)) { if (!m_Pacer->initialize(window, maxFps, enableFramePacing)) {
return false; return false;
} }
@ -363,7 +363,8 @@ bool FFmpegVideoDecoder::initialize(
int width, int width,
int height, int height,
int maxFps, int maxFps,
bool enableVsync) bool enableVsync,
bool enableFramePacing)
{ {
AVCodec* decoder; AVCodec* decoder;
@ -399,7 +400,7 @@ bool FFmpegVideoDecoder::initialize(
m_Renderer = new SdlRenderer(); m_Renderer = new SdlRenderer();
if (vds != StreamingPreferences::VDS_FORCE_HARDWARE && if (vds != StreamingPreferences::VDS_FORCE_HARDWARE &&
m_Renderer->initialize(window, videoFormat, width, height, maxFps, enableVsync) && m_Renderer->initialize(window, videoFormat, width, height, maxFps, enableVsync) &&
completeInitialization(decoder, window, videoFormat, width, height, maxFps, enableVsync, false)) { completeInitialization(decoder, window, videoFormat, width, height, maxFps, enableFramePacing, false)) {
return true; return true;
} }
else { else {
@ -416,13 +417,13 @@ bool FFmpegVideoDecoder::initialize(
m_HwDecodeCfg = config; m_HwDecodeCfg = config;
// Initialize the hardware codec and submit a test frame if the renderer needs it // Initialize the hardware codec and submit a test frame if the renderer needs it
if (m_Renderer->initialize(window, videoFormat, width, height, maxFps, enableVsync) && if (m_Renderer->initialize(window, videoFormat, width, height, maxFps, enableVsync) &&
completeInitialization(decoder, window, videoFormat, width, height, maxFps, enableVsync, m_Renderer->needsTestFrame())) { completeInitialization(decoder, window, videoFormat, width, height, maxFps, enableFramePacing, m_Renderer->needsTestFrame())) {
if (m_Renderer->needsTestFrame()) { if (m_Renderer->needsTestFrame()) {
// The test worked, so now let's initialize it for real // The test worked, so now let's initialize it for real
reset(); reset();
if ((m_Renderer = createAcceleratedRenderer(config)) != nullptr && if ((m_Renderer = createAcceleratedRenderer(config)) != nullptr &&
m_Renderer->initialize(window, videoFormat, width, height, maxFps, enableVsync) && m_Renderer->initialize(window, videoFormat, width, height, maxFps, enableVsync) &&
completeInitialization(decoder, window, videoFormat, width, height, maxFps, enableVsync, false)) { completeInitialization(decoder, window, videoFormat, width, height, maxFps, enableFramePacing, false)) {
return true; return true;
} }
else { else {
@ -493,7 +494,7 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
// Flip stats windows roughly every second // Flip stats windows roughly every second
if (m_ActiveWndVideoStats.receivedFrames == m_StreamFps) { if (m_ActiveWndVideoStats.receivedFrames == m_StreamFps) {
#if 0 #if 1
VIDEO_STATS lastTwoWndStats = {}; VIDEO_STATS lastTwoWndStats = {};
addVideoStats(m_LastWndVideoStats, lastTwoWndStats); addVideoStats(m_LastWndVideoStats, lastTwoWndStats);
addVideoStats(m_ActiveWndVideoStats, lastTwoWndStats); addVideoStats(m_ActiveWndVideoStats, lastTwoWndStats);

View File

@ -18,7 +18,8 @@ public:
int width, int width,
int height, int height,
int maxFps, int maxFps,
bool enableVsync) override; bool enableVsync,
bool enableFramePacing) override;
virtual bool isHardwareAccelerated() override; virtual bool isHardwareAccelerated() override;
virtual int getDecoderCapabilities() override; virtual int getDecoderCapabilities() override;
virtual int submitDecodeUnit(PDECODE_UNIT du) override; virtual int submitDecodeUnit(PDECODE_UNIT du) override;
@ -30,7 +31,7 @@ public:
private: private:
bool completeInitialization(AVCodec* decoder, SDL_Window* window, bool completeInitialization(AVCodec* decoder, SDL_Window* window,
int videoFormat, int width, int height, int videoFormat, int width, int height,
int maxFps, bool enableVsync, bool testOnly); int maxFps, bool enableFramePacing, bool testOnly);
void logVideoStats(VIDEO_STATS& stats, const char* title); void logVideoStats(VIDEO_STATS& stats, const char* title);

View File

@ -34,7 +34,7 @@ SLVideoDecoder::getDecoderCapabilities()
bool bool
SLVideoDecoder::initialize(StreamingPreferences::VideoDecoderSelection vds, SLVideoDecoder::initialize(StreamingPreferences::VideoDecoderSelection vds,
SDL_Window*, SDL_Window*,
int videoFormat, int, int, int frameRate, bool) int videoFormat, int, int, int frameRate, bool, bool)
{ {
// SLVideo only supports hardware decoding // SLVideo only supports hardware decoding
if (vds == StreamingPreferences::VDS_FORCE_SOFTWARE) { if (vds == StreamingPreferences::VDS_FORCE_SOFTWARE) {

View File

@ -15,7 +15,8 @@ public:
int width, int width,
int height, int height,
int frameRate, int frameRate,
bool enableVsync); bool enableVsync,
bool enableFramePacing);
virtual bool isHardwareAccelerated(); virtual bool isHardwareAccelerated();
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities();
virtual int submitDecodeUnit(PDECODE_UNIT du); virtual int submitDecodeUnit(PDECODE_UNIT du);