Check that the chosen plane supports the decoded frame pixel format

This commit is contained in:
Cameron Gutman 2023-09-29 17:22:49 -05:00
parent 0dd0112518
commit b6d4f97e96
2 changed files with 61 additions and 14 deletions

View file

@ -76,6 +76,7 @@ DrmRenderer::DrmRenderer(bool hwaccel, IFFmpegRenderer *backendRenderer)
m_CurrentFbId(0),
m_LastFullRange(false),
m_LastColorSpace(-1),
m_Plane(nullptr),
m_ColorEncodingProp(nullptr),
m_ColorRangeProp(nullptr),
m_HdrOutputMetadataProp(nullptr),
@ -135,6 +136,10 @@ DrmRenderer::~DrmRenderer()
drmModeFreeProperty(m_ColorspaceProp);
}
if (m_Plane != nullptr) {
drmModeFreePlane(m_Plane);
}
if (m_HwContext != nullptr) {
av_buffer_unref(&m_HwContext);
}
@ -452,7 +457,13 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
}
}
drmModeFreePlane(plane);
// Store the plane details for use during render format testing
if (m_PlaneId != 0) {
m_Plane = plane;
}
else {
drmModeFreePlane(plane);
}
}
}
@ -855,7 +866,7 @@ Exit:
return ret;
}
bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId)
bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId, bool testMode)
{
AVDRMFrameDescriptor mappedFrame;
AVDRMFrameDescriptor* drmFrame;
@ -933,12 +944,40 @@ bool DrmRenderer::addFbForFrame(AVFrame *frame, uint32_t* newFbId)
if (err < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"drmModeAddFB2WithModifiers() failed: %d",
"drmModeAddFB2[WithModifiers]() failed: %d",
errno);
return false;
}
return true;
if (testMode) {
// Check if plane can actually be imported
for (uint32_t i = 0; i < m_Plane->count_formats; i++) {
if (drmFrame->layers[0].format == m_Plane->formats[i]) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Selected DRM plane supports chosen decoding format: %08x",
drmFrame->layers[0].format);
return true;
}
}
// TODO: We can also check the modifier support using the IN_FORMATS property,
// but checking format alone is probably enough for real world cases since we're
// either getting linear buffers from software mapping or DMA-BUFs from the
// hardware decoder.
//
// Hopefully no actual hardware vendors are dumb enough to ship display hardware
// or drivers that lack support for the format modifiers required by their own
// video decoders.
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Selected DRM plane doesn't support chosen decoding format: %08x",
drmFrame->layers[0].format);
drmModeRmFB(m_DrmFd, *newFbId);
return false;
}
else {
return true;
}
}
void DrmRenderer::renderFrame(AVFrame* frame)
@ -958,7 +997,7 @@ void DrmRenderer::renderFrame(AVFrame* frame)
uint32_t lastFbId = m_CurrentFbId;
// Register a frame buffer object for this frame
if (!addFbForFrame(frame, &m_CurrentFbId)) {
if (!addFbForFrame(frame, &m_CurrentFbId, false)) {
m_CurrentFbId = lastFbId;
return;
}
@ -1078,16 +1117,23 @@ bool DrmRenderer::needsTestFrame()
}
bool DrmRenderer::testRenderFrame(AVFrame* frame) {
uint32_t fbId;
uint32_t fbId;
// Ensure we can export DRM PRIME frames (if applicable) and
// add a FB object with the provided DRM format.
if (!addFbForFrame(frame, &fbId)) {
return false;
}
// If we don't even have a plane, we certainly can't render
if (!m_Plane) {
return false;
}
drmModeRmFB(m_DrmFd, fbId);
return true;
// Ensure we can export DRM PRIME frames (if applicable) and
// add a FB object with the provided DRM format. Ask for the
// extended validation to ensure the chosen plane supports
// the format too.
if (!addFbForFrame(frame, &fbId, true)) {
return false;
}
drmModeRmFB(m_DrmFd, fbId);
return true;
}
bool DrmRenderer::isDirectRenderingSupported()

View file

@ -73,7 +73,7 @@ private:
const char* getDrmColorEncodingValue(AVFrame* frame);
const char* getDrmColorRangeValue(AVFrame* frame);
bool mapSoftwareFrame(AVFrame* frame, AVDRMFrameDescriptor* mappedFrame);
bool addFbForFrame(AVFrame* frame, uint32_t* newFbId);
bool addFbForFrame(AVFrame* frame, uint32_t* newFbId, bool testMode);
IFFmpegRenderer* m_BackendRenderer;
bool m_DrmPrimeBackend;
@ -90,6 +90,7 @@ private:
uint32_t m_CurrentFbId;
bool m_LastFullRange;
int m_LastColorSpace;
drmModePlanePtr m_Plane;
drmModePropertyPtr m_ColorEncodingProp;
drmModePropertyPtr m_ColorRangeProp;
drmModePropertyPtr m_HdrOutputMetadataProp;