mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-11-15 15:57:59 +00:00
Add color properties to DRM renderer
This commit is contained in:
parent
b4665b6e5a
commit
f5bc4e7a24
2 changed files with 134 additions and 8 deletions
|
@ -31,9 +31,16 @@ DrmRenderer::DrmRenderer()
|
|||
m_DrmFd(-1),
|
||||
m_SdlOwnsDrmFd(false),
|
||||
m_SupportsDirectRendering(false),
|
||||
m_ConnectorId(0),
|
||||
m_EncoderId(0),
|
||||
m_CrtcId(0),
|
||||
m_PlaneId(0),
|
||||
m_CurrentFbId(0)
|
||||
m_CurrentFbId(0),
|
||||
m_LastColorRange(AVCOL_RANGE_UNSPECIFIED),
|
||||
m_LastColorSpace(AVCOL_SPC_UNSPECIFIED),
|
||||
m_ColorEncodingProp(nullptr),
|
||||
m_ColorRangeProp(nullptr),
|
||||
m_HdrOutputMetadataProp(nullptr)
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
m_EGLExtDmaBuf = false;
|
||||
|
@ -50,6 +57,18 @@ DrmRenderer::~DrmRenderer()
|
|||
drmModeRmFB(m_DrmFd, m_CurrentFbId);
|
||||
}
|
||||
|
||||
if (m_ColorEncodingProp != nullptr) {
|
||||
drmModeFreeProperty(m_ColorEncodingProp);
|
||||
}
|
||||
|
||||
if (m_ColorRangeProp != nullptr) {
|
||||
drmModeFreeProperty(m_ColorRangeProp);
|
||||
}
|
||||
|
||||
if (m_HdrOutputMetadataProp != nullptr) {
|
||||
drmModeFreeProperty(m_HdrOutputMetadataProp);
|
||||
}
|
||||
|
||||
if (m_HwContext != nullptr) {
|
||||
av_buffer_unref(&m_HwContext);
|
||||
}
|
||||
|
@ -176,19 +195,21 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
|||
}
|
||||
|
||||
// Look for a connected connector and get the associated encoder
|
||||
uint32_t encoderId = 0;
|
||||
for (i = 0; i < resources->count_connectors && encoderId == 0; i++) {
|
||||
m_ConnectorId = 0;
|
||||
m_EncoderId = 0;
|
||||
for (i = 0; i < resources->count_connectors && m_EncoderId == 0; i++) {
|
||||
drmModeConnector* connector = drmModeGetConnector(m_DrmFd, resources->connectors[i]);
|
||||
if (connector != nullptr) {
|
||||
if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) {
|
||||
encoderId = connector->encoder_id;
|
||||
m_ConnectorId = resources->connectors[i];
|
||||
m_EncoderId = connector->encoder_id;
|
||||
}
|
||||
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
}
|
||||
|
||||
if (encoderId == 0) {
|
||||
if (m_EncoderId == 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No connected displays found!");
|
||||
drmModeFreeResources(resources);
|
||||
|
@ -200,7 +221,7 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
|||
for (i = 0; i < resources->count_encoders && m_CrtcId == 0; i++) {
|
||||
drmModeEncoder* encoder = drmModeGetEncoder(m_DrmFd, resources->encoders[i]);
|
||||
if (encoder != nullptr) {
|
||||
if (encoder->encoder_id == encoderId) {
|
||||
if (encoder->encoder_id == m_EncoderId) {
|
||||
m_CrtcId = encoder->crtc_id;
|
||||
}
|
||||
|
||||
|
@ -283,14 +304,22 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
|||
if ((plane->possible_crtcs & (1 << crtcIndex)) && plane->crtc_id == 0) {
|
||||
drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(m_DrmFd, planeRes->planes[i], DRM_MODE_OBJECT_PLANE);
|
||||
if (props != nullptr) {
|
||||
for (uint32_t j = 0; j < props->count_props && m_PlaneId == 0; j++) {
|
||||
for (uint32_t j = 0; j < props->count_props; j++) {
|
||||
drmModePropertyPtr prop = drmModeGetProperty(m_DrmFd, props->props[j]);
|
||||
if (prop != nullptr) {
|
||||
if (!strcmp(prop->name, "type") && props->prop_values[j] == DRM_PLANE_TYPE_OVERLAY) {
|
||||
m_PlaneId = plane->plane_id;
|
||||
}
|
||||
|
||||
drmModeFreeProperty(prop);
|
||||
if (!strcmp(prop->name, "COLOR_ENCODING")) {
|
||||
m_ColorEncodingProp = prop;
|
||||
}
|
||||
else if (!strcmp(prop->name, "COLOR_RANGE")) {
|
||||
m_ColorRangeProp = prop;
|
||||
}
|
||||
else {
|
||||
drmModeFreeProperty(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,6 +339,23 @@ bool DrmRenderer::initialize(PDECODER_PARAMETERS params)
|
|||
return DIRECT_RENDERING_INIT_FAILED;
|
||||
}
|
||||
|
||||
drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(m_DrmFd, m_ConnectorId, DRM_MODE_OBJECT_CONNECTOR);
|
||||
if (props != nullptr) {
|
||||
for (uint32_t j = 0; j < props->count_props; j++) {
|
||||
drmModePropertyPtr prop = drmModeGetProperty(m_DrmFd, props->props[j]);
|
||||
if (prop != nullptr) {
|
||||
if (!strcmp(prop->name, "HDR_OUTPUT_METADATA")) {
|
||||
m_HdrOutputMetadataProp = prop;
|
||||
}
|
||||
else {
|
||||
drmModeFreeProperty(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFreeObjectProperties(props);
|
||||
}
|
||||
|
||||
// If we got this far, we can do direct rendering via the DRM FD.
|
||||
m_SupportsDirectRendering = true;
|
||||
|
||||
|
@ -397,6 +443,50 @@ void DrmRenderer::renderFrame(AVFrame* frame)
|
|||
return;
|
||||
}
|
||||
|
||||
if (frame->color_range != m_LastColorRange) {
|
||||
const char* desiredValue = getDrmColorRangeValue(frame);
|
||||
|
||||
if (m_ColorRangeProp != nullptr && desiredValue != nullptr) {
|
||||
for (int i = 0; i < m_ColorRangeProp->count_enums; i++) {
|
||||
if (!strcmp(desiredValue, m_ColorRangeProp->enums[i].name)) {
|
||||
err = drmModeObjectSetProperty(m_DrmFd, m_PlaneId, DRM_MODE_OBJECT_PLANE,
|
||||
m_ColorRangeProp->prop_id, m_ColorRangeProp->enums[i].value);
|
||||
if (err < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"drmModeObjectSetProperty(%s) failed: %d",
|
||||
m_ColorRangeProp->name,
|
||||
errno);
|
||||
// Non-fatal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_LastColorRange = frame->color_range;
|
||||
}
|
||||
|
||||
if (frame->colorspace != m_LastColorSpace) {
|
||||
const char* desiredValue = getDrmColorEncodingValue(frame);
|
||||
|
||||
if (m_ColorEncodingProp != nullptr && desiredValue != nullptr) {
|
||||
for (int i = 0; i < m_ColorEncodingProp->count_enums; i++) {
|
||||
if (!strcmp(desiredValue, m_ColorEncodingProp->enums[i].name)) {
|
||||
err = drmModeObjectSetProperty(m_DrmFd, m_PlaneId, DRM_MODE_OBJECT_PLANE,
|
||||
m_ColorEncodingProp->prop_id, m_ColorEncodingProp->enums[i].value);
|
||||
if (err < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"drmModeObjectSetProperty(%s) failed: %d",
|
||||
m_ColorEncodingProp->name,
|
||||
errno);
|
||||
// Non-fatal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_LastColorSpace = frame->colorspace;
|
||||
}
|
||||
|
||||
// Update the overlay
|
||||
err = drmModeSetPlane(m_DrmFd, m_PlaneId, m_CrtcId, m_CurrentFbId, 0,
|
||||
dst.x, dst.y,
|
||||
|
@ -427,6 +517,32 @@ bool DrmRenderer::isDirectRenderingSupported()
|
|||
return m_SupportsDirectRendering;
|
||||
}
|
||||
|
||||
const char* DrmRenderer::getDrmColorEncodingValue(AVFrame* frame)
|
||||
{
|
||||
switch (frame->colorspace) {
|
||||
case AVCOL_SPC_SMPTE170M:
|
||||
return "ITU-R BT.601 YCbCr";
|
||||
case AVCOL_SPC_BT709:
|
||||
return "ITU-R BT.709 YCbCr";
|
||||
case AVCOL_SPC_BT2020_NCL:
|
||||
return "ITU-R BT.2020 YCbCr";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* DrmRenderer::getDrmColorRangeValue(AVFrame* frame)
|
||||
{
|
||||
switch (frame->color_range) {
|
||||
case AVCOL_RANGE_MPEG:
|
||||
return "YCbCr limited range";
|
||||
case AVCOL_RANGE_JPEG:
|
||||
return "YCbCr full range";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
|
||||
bool DrmRenderer::canExportEGL() {
|
||||
|
|
|
@ -25,13 +25,23 @@ public:
|
|||
#endif
|
||||
|
||||
private:
|
||||
const char* getDrmColorEncodingValue(AVFrame* frame);
|
||||
const char* getDrmColorRangeValue(AVFrame* frame);
|
||||
|
||||
AVBufferRef* m_HwContext;
|
||||
int m_DrmFd;
|
||||
bool m_SdlOwnsDrmFd;
|
||||
bool m_SupportsDirectRendering;
|
||||
uint32_t m_ConnectorId;
|
||||
uint32_t m_EncoderId;
|
||||
uint32_t m_CrtcId;
|
||||
uint32_t m_PlaneId;
|
||||
uint32_t m_CurrentFbId;
|
||||
AVColorRange m_LastColorRange;
|
||||
AVColorSpace m_LastColorSpace;
|
||||
drmModePropertyPtr m_ColorEncodingProp;
|
||||
drmModePropertyPtr m_ColorRangeProp;
|
||||
drmModePropertyPtr m_HdrOutputMetadataProp;
|
||||
SDL_Rect m_OutputRect;
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
|
|
Loading…
Reference in a new issue