Fix DrmRenderer not falling back to swframes if DRM PRIME is available

This commit is contained in:
Cameron Gutman 2023-10-05 18:13:52 -05:00
parent a2f23b7053
commit 9d73aa6b4a
2 changed files with 37 additions and 14 deletions

View file

@ -177,8 +177,9 @@ enum AVPixelFormat FFmpegVideoDecoder::ffGetFormat(AVCodecContext* context,
}
}
// Failed to match the preferred pixel formats. Try non-preferred options for non-hwaccel decoders.
if (decoder->m_HwDecodeCfg == nullptr) {
// Failed to match the preferred pixel formats. Try non-preferred pixel format options
// for non-hwaccel decoders if we didn't have a required pixel format to use.
if (decoder->m_HwDecodeCfg == nullptr && decoder->m_RequiredPixelFormat == AV_PIX_FMT_NONE) {
for (p = pixFmts; *p != -1; p++) {
if (decoder->m_FrontendRenderer->isPixelFormatSupported(decoder->m_VideoFormat, *p) &&
decoder->m_BackendRenderer->prepareDecoderContextInGetFormat(context, *p)) {
@ -193,6 +194,7 @@ enum AVPixelFormat FFmpegVideoDecoder::ffGetFormat(AVCodecContext* context,
FFmpegVideoDecoder::FFmpegVideoDecoder(bool testOnly)
: m_Pkt(av_packet_alloc()),
m_VideoDecoderCtx(nullptr),
m_RequiredPixelFormat(AV_PIX_FMT_NONE),
m_DecodeBuffer(1024 * 1024, 0),
m_HwDecodeCfg(nullptr),
m_BackendRenderer(nullptr),
@ -356,7 +358,7 @@ bool FFmpegVideoDecoder::createFrontendRenderer(PDECODER_PARAMETERS params, bool
return true;
}
bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, PDECODER_PARAMETERS params, bool testFrame, bool useAlternateFrontend)
bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVPixelFormat requiredFormat, PDECODER_PARAMETERS params, bool testFrame, bool useAlternateFrontend)
{
// In test-only mode, we should only see test frames
SDL_assert(!m_TestOnly || testFrame);
@ -366,6 +368,7 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, PDECODER
return false;
}
m_RequiredPixelFormat = requiredFormat;
m_StreamFps = params->frameRate;
m_VideoFormat = params->videoFormat;
@ -414,7 +417,7 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, PDECODER
// Setup decoding parameters
m_VideoDecoderCtx->width = params->width;
m_VideoDecoderCtx->height = params->height;
m_VideoDecoderCtx->pix_fmt = m_FrontendRenderer->getPreferredPixelFormat(params->videoFormat);
m_VideoDecoderCtx->pix_fmt = requiredFormat != AV_PIX_FMT_NONE ? requiredFormat : m_FrontendRenderer->getPreferredPixelFormat(params->videoFormat);
m_VideoDecoderCtx->get_format = ffGetFormat;
AVDictionary* options = nullptr;
@ -821,6 +824,7 @@ IFFmpegRenderer* FFmpegVideoDecoder::createHwAccelRenderer(const AVCodecHWConfig
}
bool FFmpegVideoDecoder::tryInitializeRenderer(const AVCodec* decoder,
enum AVPixelFormat requiredFormat,
PDECODER_PARAMETERS params,
const AVCodecHWConfig* hwConfig,
std::function<IFFmpegRenderer*()> createRendererFunc)
@ -850,7 +854,10 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const AVCodec* decoder,
SDL_assert(m_BackendRenderer == nullptr);
if ((m_BackendRenderer = createRendererFunc()) != nullptr &&
m_BackendRenderer->initialize((m_TestOnly || m_BackendRenderer->needsTestFrame()) ? &testFrameDecoderParams : params) &&
completeInitialization(decoder, (m_TestOnly || m_BackendRenderer->needsTestFrame()) ? &testFrameDecoderParams : params, m_TestOnly || m_BackendRenderer->needsTestFrame(), i == 0 /* EGL/DRM */)) {
completeInitialization(decoder, requiredFormat,
(m_TestOnly || m_BackendRenderer->needsTestFrame()) ? &testFrameDecoderParams : params,
m_TestOnly || m_BackendRenderer->needsTestFrame(),
i == 0 /* EGL/DRM */)) {
if (m_TestOnly) {
// This decoder is only for testing capabilities, so don't bother
// creating a usable renderer
@ -862,7 +869,7 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const AVCodec* decoder,
reset();
if ((m_BackendRenderer = createRendererFunc()) != nullptr &&
m_BackendRenderer->initialize(params) &&
completeInitialization(decoder, params, false, i == 0 /* EGL/DRM */)) {
completeInitialization(decoder, requiredFormat, params, false, i == 0 /* EGL/DRM */)) {
return true;
}
else {
@ -891,7 +898,10 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const AVCodec* decoder,
{ \
RENDERER_TYPE renderer; \
if (renderer.getPreferredPixelFormat(params->videoFormat) == decoder->pix_fmts[i]) { \
if (tryInitializeRenderer(decoder, params, nullptr, \
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
"Trying " #RENDERER_TYPE " for codec %s due to preferred pixel format: 0x%x", \
decoder->name, decoder->pix_fmts[i]); \
if (tryInitializeRenderer(decoder, decoder->pix_fmts[i], params, nullptr, \
[]() -> IFFmpegRenderer* { return new RENDERER_TYPE(); })) { \
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
"Chose " #RENDERER_TYPE " for codec %s due to preferred pixel format: 0x%x", \
@ -906,7 +916,10 @@ bool FFmpegVideoDecoder::tryInitializeRenderer(const AVCodec* decoder,
RENDERER_TYPE renderer; \
if (decoder->pix_fmts[i] != renderer.getPreferredPixelFormat(params->videoFormat) && \
renderer.isPixelFormatSupported(params->videoFormat, decoder->pix_fmts[i])) { \
if (tryInitializeRenderer(decoder, params, nullptr, \
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
"Trying " #RENDERER_TYPE " for codec %s due to compatible pixel format: 0x%x", \
decoder->name, decoder->pix_fmts[i]); \
if (tryInitializeRenderer(decoder, decoder->pix_fmts[i], params, nullptr, \
[]() -> IFFmpegRenderer* { return new RENDERER_TYPE(); })) { \
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, \
"Chose " #RENDERER_TYPE " for codec %s due to compatible pixel format: 0x%x", \
@ -945,7 +958,7 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnknownDecoder(const AVCodec* d
}
// Initialize the hardware codec and submit a test frame if the renderer needs it
if (tryInitializeRenderer(decoder, params, config,
if (tryInitializeRenderer(decoder, AV_PIX_FMT_NONE, params, config,
[config]() -> IFFmpegRenderer* { return createHwAccelRenderer(config, 0); })) {
return true;
}
@ -956,13 +969,13 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnknownDecoder(const AVCodec* d
// Supported output pixel formats are unknown. We'll just try DRM/SDL and hope it can cope.
#if defined(HAVE_DRM) && defined(GL_IS_SLOW)
if (tryInitializeRenderer(decoder, params, nullptr,
if (tryInitializeRenderer(decoder, AV_PIX_FMT_NONE, params, nullptr,
[]() -> IFFmpegRenderer* { return new DrmRenderer(); })) {
return true;
}
#endif
if (tryInitializeRenderer(decoder, params, nullptr,
if (tryInitializeRenderer(decoder, AV_PIX_FMT_NONE, params, nullptr,
[]() -> IFFmpegRenderer* { return new SdlRenderer(); })) {
return true;
}
@ -1018,6 +1031,10 @@ bool FFmpegVideoDecoder::tryInitializeRendererForUnknownDecoder(const AVCodec* d
}
#endif
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"No renderer can handle output from decoder: %s",
decoder->name);
// If we made it here, we couldn't find anything
return false;
}
@ -1122,7 +1139,7 @@ bool FFmpegVideoDecoder::initialize(PDECODER_PARAMETERS params)
}
// Initialize the hardware codec and submit a test frame if the renderer needs it
if (tryInitializeRenderer(decoder, params, config,
if (tryInitializeRenderer(decoder, AV_PIX_FMT_NONE, params, config,
[config]() -> IFFmpegRenderer* { return createHwAccelRenderer(config, 0); })) {
return true;
}
@ -1180,7 +1197,7 @@ bool FFmpegVideoDecoder::initialize(PDECODER_PARAMETERS params)
}
// Initialize the hardware codec and submit a test frame if the renderer needs it
if (tryInitializeRenderer(decoder, params, config,
if (tryInitializeRenderer(decoder, AV_PIX_FMT_NONE, params, config,
[config]() -> IFFmpegRenderer* { return createHwAccelRenderer(config, 1); })) {
return true;
}

View file

@ -30,7 +30,11 @@ public:
virtual IFFmpegRenderer* getBackendRenderer();
private:
bool completeInitialization(const AVCodec* decoder, PDECODER_PARAMETERS params, bool testFrame, bool useAlternateFrontend);
bool completeInitialization(const AVCodec* decoder,
enum AVPixelFormat requiredFormat,
PDECODER_PARAMETERS params,
bool testFrame,
bool useAlternateFrontend);
void stringifyVideoStats(VIDEO_STATS& stats, char* output, int length);
@ -45,6 +49,7 @@ private:
bool tryHwAccel);
bool tryInitializeRenderer(const AVCodec* decoder,
enum AVPixelFormat requiredFormat,
PDECODER_PARAMETERS params,
const AVCodecHWConfig* hwConfig,
std::function<IFFmpegRenderer*()> createRendererFunc);
@ -65,6 +70,7 @@ private:
AVPacket* m_Pkt;
AVCodecContext* m_VideoDecoderCtx;
enum AVPixelFormat m_RequiredPixelFormat;
QByteArray m_DecodeBuffer;
const AVCodecHWConfig* m_HwDecodeCfg;
IFFmpegRenderer* m_BackendRenderer;