Avoid the test frame for DXVA2 and VT APIs to address flickering in full-screen on Win7

This commit is contained in:
Cameron Gutman
2018-08-19 00:59:04 -07:00
parent 91c0429e2c
commit 845e84adb7
10 changed files with 56 additions and 11 deletions
@@ -496,6 +496,13 @@ bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, i
return true; return true;
} }
bool DXVA2Renderer::needsTestFrame()
{
// We validate the DXVA2 profiles are supported
// in initialize() so no test frame is required
return false;
}
void DXVA2Renderer::renderFrameAtVsync(AVFrame *frame) void DXVA2Renderer::renderFrameAtVsync(AVFrame *frame)
{ {
IDirect3DSurface9* surface = reinterpret_cast<IDirect3DSurface9*>(frame->data[3]); IDirect3DSurface9* surface = reinterpret_cast<IDirect3DSurface9*>(frame->data[3]);
@@ -22,6 +22,7 @@ public:
int maxFps); int maxFps);
virtual bool prepareDecoderContext(AVCodecContext* context); virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
private: private:
bool initializeDecoder(); bool initializeDecoder();
@@ -16,6 +16,7 @@ public:
int maxFps) = 0; int maxFps) = 0;
virtual bool prepareDecoderContext(AVCodecContext* context) = 0; virtual bool prepareDecoderContext(AVCodecContext* context) = 0;
virtual void renderFrameAtVsync(AVFrame* frame) = 0; virtual void renderFrameAtVsync(AVFrame* frame) = 0;
virtual bool needsTestFrame() = 0;
}; };
class SdlRenderer : public IFFmpegRenderer { class SdlRenderer : public IFFmpegRenderer {
@@ -29,6 +30,7 @@ public:
int maxFps); int maxFps);
virtual bool prepareDecoderContext(AVCodecContext* context); virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
private: private:
SDL_Renderer* m_Renderer; SDL_Renderer* m_Renderer;
@@ -30,6 +30,12 @@ bool SdlRenderer::prepareDecoderContext(AVCodecContext*)
return true; return true;
} }
bool SdlRenderer::needsTestFrame()
{
// This renderer should always work
return false;
}
bool SdlRenderer::initialize(SDL_Window* window, bool SdlRenderer::initialize(SDL_Window* window,
int, int,
int width, int width,
@@ -141,6 +141,14 @@ VAAPIRenderer::prepareDecoderContext(AVCodecContext* context)
return true; return true;
} }
bool
VAAPIRenderer::needsTestFrame()
{
// We need a test frame to see if this VAAPI driver
// supports the profile used for streaming
return true;
}
void void
VAAPIRenderer::renderFrameAtVsync(AVFrame* frame) VAAPIRenderer::renderFrameAtVsync(AVFrame* frame)
{ {
@@ -37,6 +37,7 @@ public:
int maxFps); int maxFps);
virtual bool prepareDecoderContext(AVCodecContext* context); virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
private: private:
int m_WindowSystem; int m_WindowSystem;
@@ -223,6 +223,13 @@ bool VDPAURenderer::prepareDecoderContext(AVCodecContext* context)
return true; return true;
} }
bool VDPAURenderer::needsTestFrame()
{
// We need a test frame to see if this VDPAU driver
// supports the profile used for streaming
return true;
}
void VDPAURenderer::renderFrameAtVsync(AVFrame* frame) void VDPAURenderer::renderFrameAtVsync(AVFrame* frame)
{ {
VdpStatus status; VdpStatus status;
@@ -20,6 +20,7 @@ public:
int maxFps); int maxFps);
virtual bool prepareDecoderContext(AVCodecContext* context); virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame); virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
private: private:
uint32_t m_VideoWidth, m_VideoHeight; uint32_t m_VideoWidth, m_VideoHeight;
@@ -189,6 +189,12 @@ public:
return true; return true;
} }
virtual bool needsTestFrame() override
{
// We query VT to determine whether the codec is supported
return false;
}
private: private:
void setupDisplayLayer() void setupDisplayLayer()
{ {
+17 -11
View File
@@ -280,20 +280,26 @@ bool FFmpegVideoDecoder::initialize(
} }
m_HwDecodeCfg = config; m_HwDecodeCfg = config;
// Submit test frame to ensure this codec really works // Initialize the hardware codec and submit a test frame if the renderer needs it
if (m_Renderer->initialize(window, videoFormat, width, height, maxFps) && if (m_Renderer->initialize(window, videoFormat, width, height, maxFps) &&
completeInitialization(decoder, window, videoFormat, width, height, maxFps, true)) { completeInitialization(decoder, window, videoFormat, width, height, maxFps, m_Renderer->needsTestFrame())) {
// OK, it worked, so now let's initialize it for real if (m_Renderer->needsTestFrame()) {
reset(); // The test worked, so now let's initialize it for real
if ((m_Renderer = createAcceleratedRenderer(config)) != nullptr && reset();
m_Renderer->initialize(window, videoFormat, width, height, maxFps) && if ((m_Renderer = createAcceleratedRenderer(config)) != nullptr &&
completeInitialization(decoder, window, videoFormat, width, height, maxFps, false)) { m_Renderer->initialize(window, videoFormat, width, height, maxFps) &&
return true; completeInitialization(decoder, window, videoFormat, width, height, maxFps, false)) {
return true;
}
else {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
"Decoder failed to initialize after successful test");
reset();
}
} }
else { else {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, // No test required. Good to go now.
"Decoder failed to initialize after successful test"); return true;
reset();
} }
} }
else { else {