mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-03 08:15:37 +00:00
Allow fallback from EGL to direct on EGLImage export failure
This commit is contained in:
parent
4a8c9ad17f
commit
e74753bec1
@ -836,3 +836,21 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
av_frame_unref(m_LastFrame);
|
||||
av_frame_move_ref(m_LastFrame, frame);
|
||||
}
|
||||
|
||||
bool EGLRenderer::testRenderFrame(AVFrame* frame)
|
||||
{
|
||||
EGLImage imgs[EGL_MAX_PLANES];
|
||||
|
||||
// Make sure we can get working EGLImages from the backend renderer.
|
||||
// Some devices (Raspberry Pi) will happily decode into DRM formats that
|
||||
// its own GL implementation won't accept in eglCreateImage().
|
||||
ssize_t plane_count = m_Backend->exportEGLImages(frame, m_EGLDisplay, imgs);
|
||||
if (plane_count <= 0) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Backend failed to export EGL image for test frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Backend->freeEGLImages(m_EGLDisplay, imgs);
|
||||
return true;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ public:
|
||||
virtual bool initialize(PDECODER_PARAMETERS params) override;
|
||||
virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) override;
|
||||
virtual void renderFrame(AVFrame* frame) override;
|
||||
virtual bool testRenderFrame(AVFrame* frame) override;
|
||||
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
|
||||
virtual bool isPixelFormatSupported(int videoFormat, enum AVPixelFormat pixelFormat) override;
|
||||
virtual AVPixelFormat getPreferredPixelFormat(int videoFormat) override;
|
||||
|
@ -86,6 +86,13 @@ public:
|
||||
virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary** options) = 0;
|
||||
virtual void renderFrame(AVFrame* frame) = 0;
|
||||
|
||||
virtual bool testRenderFrame(AVFrame*) {
|
||||
// If the renderer doesn't provide an explicit test routine,
|
||||
// we will always assume that any returned AVFrame can be
|
||||
// rendered successfully.
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool needsTestFrame() {
|
||||
// No test frame required by default
|
||||
return false;
|
||||
|
@ -193,8 +193,9 @@ void FFmpegVideoDecoder::reset()
|
||||
}
|
||||
}
|
||||
|
||||
bool FFmpegVideoDecoder::createFrontendRenderer(PDECODER_PARAMETERS params)
|
||||
bool FFmpegVideoDecoder::createFrontendRenderer(PDECODER_PARAMETERS params, bool eglOnly)
|
||||
{
|
||||
if (eglOnly) {
|
||||
#ifdef HAVE_EGL
|
||||
if (m_BackendRenderer->canExportEGL()) {
|
||||
m_FrontendRenderer = new EGLRenderer(m_BackendRenderer);
|
||||
@ -202,8 +203,12 @@ bool FFmpegVideoDecoder::createFrontendRenderer(PDECODER_PARAMETERS params)
|
||||
return true;
|
||||
}
|
||||
delete m_FrontendRenderer;
|
||||
m_FrontendRenderer = nullptr;
|
||||
}
|
||||
#endif
|
||||
// If we made it here, we failed to create the EGLRenderer
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_BackendRenderer->isDirectRenderingSupported()) {
|
||||
// The backend renderer can render to the display
|
||||
@ -221,13 +226,13 @@ bool FFmpegVideoDecoder::createFrontendRenderer(PDECODER_PARAMETERS params)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, PDECODER_PARAMETERS params, bool testFrame)
|
||||
bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, PDECODER_PARAMETERS params, bool testFrame, bool eglOnly)
|
||||
{
|
||||
// In test-only mode, we should only see test frames
|
||||
SDL_assert(!m_TestOnly || testFrame);
|
||||
|
||||
// Create the frontend renderer based on the capabilities of the backend renderer
|
||||
if (!createFrontendRenderer(params)) {
|
||||
if (!createFrontendRenderer(params, eglOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -365,6 +370,14 @@ bool FFmpegVideoDecoder::completeInitialization(AVCodec* decoder, PDECODER_PARAM
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the renderer to do any validation it wants on this frame
|
||||
if (!m_FrontendRenderer->testRenderFrame(frame)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Render test failed");
|
||||
av_frame_free(&frame);
|
||||
return false;
|
||||
}
|
||||
|
||||
av_frame_free(&frame);
|
||||
if (err < 0) {
|
||||
char errorstring[512];
|
||||
@ -555,12 +568,15 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(AVCodec* decoder,
|
||||
const AVCodecHWConfig* hwConfig,
|
||||
std::function<IFFmpegRenderer*()> createRendererFunc)
|
||||
{
|
||||
m_BackendRenderer = createRendererFunc();
|
||||
m_HwDecodeCfg = hwConfig;
|
||||
|
||||
if (m_BackendRenderer != nullptr &&
|
||||
// i == 0 - Indirect via EGL frontend with zero-copy DMA-BUF passing
|
||||
// i == 1 - Direct rendering or indirect via SDL read-back
|
||||
for (int i = 0; i < 2; i++) {
|
||||
SDL_assert(m_BackendRenderer == nullptr);
|
||||
if ((m_BackendRenderer = createRendererFunc()) != nullptr &&
|
||||
m_BackendRenderer->initialize(params) &&
|
||||
completeInitialization(decoder, params, m_TestOnly || m_BackendRenderer->needsTestFrame())) {
|
||||
completeInitialization(decoder, params, m_TestOnly || m_BackendRenderer->needsTestFrame(), i == 0 /* EGL */)) {
|
||||
if (m_TestOnly) {
|
||||
// This decoder is only for testing capabilities, so don't bother
|
||||
// creating a usable renderer
|
||||
@ -572,7 +588,7 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(AVCodec* decoder,
|
||||
reset();
|
||||
if ((m_BackendRenderer = createRendererFunc()) != nullptr &&
|
||||
m_BackendRenderer->initialize(params) &&
|
||||
completeInitialization(decoder, params, false)) {
|
||||
completeInitialization(decoder, params, false, i == 0 /* EGL */)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@ -587,10 +603,13 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(AVCodec* decoder,
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Failed to initialize or test frame failed, so keep looking
|
||||
// Failed to initialize, so keep looking
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
// reset() must be called before we reach this point!
|
||||
SDL_assert(m_BackendRenderer == nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
virtual IFFmpegRenderer* getBackendRenderer();
|
||||
|
||||
private:
|
||||
bool completeInitialization(AVCodec* decoder, PDECODER_PARAMETERS params, bool testFrame);
|
||||
bool completeInitialization(AVCodec* decoder, PDECODER_PARAMETERS params, bool testFrame, bool eglOnly);
|
||||
|
||||
void stringifyVideoStats(VIDEO_STATS& stats, char* output);
|
||||
|
||||
@ -34,7 +34,7 @@ private:
|
||||
|
||||
void addVideoStats(VIDEO_STATS& src, VIDEO_STATS& dst);
|
||||
|
||||
bool createFrontendRenderer(PDECODER_PARAMETERS params);
|
||||
bool createFrontendRenderer(PDECODER_PARAMETERS params, bool eglOnly);
|
||||
|
||||
bool tryInitializeRendererForDecoderByName(const char* decoderName,
|
||||
PDECODER_PARAMETERS params);
|
||||
|
Loading…
x
Reference in New Issue
Block a user