From 017fd0a37da0fc3dddcd635d09770c123f133e57 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 1 Feb 2024 18:06:26 +0100 Subject: Add support for hdr capture on amd/intel Nvidia support will be added in the future. Note that hdr metadata is missing from the output file as amd and intel both have bugged drivers that dont add hdr metadata to the output file. Need to find a workaround for this (patching the video bitstream?). Add -cr limited|full, to set color range --- kms/server/kms_server.c | 68 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 21 deletions(-) (limited to 'kms/server') diff --git a/kms/server/kms_server.c b/kms/server/kms_server.c index 6062074..8bc5d8c 100644 --- a/kms/server/kms_server.c +++ b/kms/server/kms_server.c @@ -25,6 +25,7 @@ typedef struct { typedef struct { uint32_t connector_id; uint64_t crtc_id; + uint64_t hdr_metadata_blob_id; } connector_crtc_pair; typedef struct { @@ -188,12 +189,12 @@ static uint32_t plane_get_properties(int drmfd, uint32_t plane_id, bool *is_curs } /* Returns 0 if not found */ -static uint32_t get_connector_by_crtc_id(const connector_to_crtc_map *c2crtc_map, uint32_t crtc_id) { +static const connector_crtc_pair* get_connector_pair_by_crtc_id(const connector_to_crtc_map *c2crtc_map, uint32_t crtc_id) { for(int i = 0; i < c2crtc_map->num_maps; ++i) { if(c2crtc_map->maps[i].crtc_id == crtc_id) - return c2crtc_map->maps[i].connector_id; + return &c2crtc_map->maps[i]; } - return 0; + return NULL; } static void map_crtc_to_connector_ids(gsr_drm *drm, connector_to_crtc_map *c2crtc_map) { @@ -210,8 +211,12 @@ static void map_crtc_to_connector_ids(gsr_drm *drm, connector_to_crtc_map *c2crt uint64_t crtc_id = 0; connector_get_property_by_name(drm->drmfd, connector, "CRTC_ID", &crtc_id); + uint64_t hdr_output_metadata_blob_id = 0; + connector_get_property_by_name(drm->drmfd, connector, "HDR_OUTPUT_METADATA", &hdr_output_metadata_blob_id); + c2crtc_map->maps[c2crtc_map->num_maps].connector_id = connector->connector_id; c2crtc_map->maps[c2crtc_map->num_maps].crtc_id = crtc_id; + c2crtc_map->maps[c2crtc_map->num_maps].hdr_metadata_blob_id = hdr_output_metadata_blob_id; ++c2crtc_map->num_maps; drmModeFreeConnector(connector); @@ -239,6 +244,18 @@ static void drm_mode_cleanup_handles(int drmfd, drmModeFB2Ptr drmfb) { } } +static bool get_hdr_metadata(int drm_fd, uint64_t hdr_metadata_blob_id, struct hdr_output_metadata *hdr_metadata) { + drmModePropertyBlobPtr hdr_metadata_blob = drmModeGetPropertyBlob(drm_fd, hdr_metadata_blob_id); + if(!hdr_metadata_blob) + return false; + + if(hdr_metadata_blob->length >= sizeof(struct hdr_output_metadata)) + *hdr_metadata = *(struct hdr_output_metadata*)hdr_metadata_blob->data; + + drmModeFreePropertyBlob(hdr_metadata_blob); + return true; +} + static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response, connector_to_crtc_map *c2crtc_map) { int result = -1; @@ -289,30 +306,39 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response, connector_to_crt goto cleanup_handles; } + const int fd_index = response->num_fds; + bool is_cursor = false; int x = 0, y = 0, src_x = 0, src_y = 0, src_w = 0, src_h = 0; plane_get_properties(drm->drmfd, plane->plane_id, &is_cursor, &x, &y, &src_x, &src_y, &src_w, &src_h); - response->fds[response->num_fds].fd = fb_fd; - response->fds[response->num_fds].width = drmfb->width; - response->fds[response->num_fds].height = drmfb->height; - response->fds[response->num_fds].pitch = drmfb->pitches[0]; - response->fds[response->num_fds].offset = drmfb->offsets[0]; - response->fds[response->num_fds].pixel_format = drmfb->pixel_format; - response->fds[response->num_fds].modifier = drmfb->modifier; - response->fds[response->num_fds].connector_id = get_connector_by_crtc_id(c2crtc_map, plane->crtc_id); - response->fds[response->num_fds].is_cursor = is_cursor; - response->fds[response->num_fds].is_combined_plane = false; + const connector_crtc_pair *crtc_pair = get_connector_pair_by_crtc_id(c2crtc_map, plane->crtc_id); + if(crtc_pair && crtc_pair->hdr_metadata_blob_id) { + response->fds[fd_index].has_hdr_metadata = get_hdr_metadata(drm->drmfd, crtc_pair->hdr_metadata_blob_id, &response->fds[fd_index].hdr_metadata); + } else { + response->fds[fd_index].has_hdr_metadata = false; + } + + response->fds[fd_index].fd = fb_fd; + response->fds[fd_index].width = drmfb->width; + response->fds[fd_index].height = drmfb->height; + response->fds[fd_index].pitch = drmfb->pitches[0]; + response->fds[fd_index].offset = drmfb->offsets[0]; + response->fds[fd_index].pixel_format = drmfb->pixel_format; + response->fds[fd_index].modifier = drmfb->modifier; + response->fds[fd_index].connector_id = crtc_pair ? crtc_pair->connector_id : 0; + response->fds[fd_index].is_cursor = is_cursor; + response->fds[fd_index].is_combined_plane = false; if(is_cursor) { - response->fds[response->num_fds].x = x; - response->fds[response->num_fds].y = y; - response->fds[response->num_fds].src_w = 0; - response->fds[response->num_fds].src_h = 0; + response->fds[fd_index].x = x; + response->fds[fd_index].y = y; + response->fds[fd_index].src_w = 0; + response->fds[fd_index].src_h = 0; } else { - response->fds[response->num_fds].x = src_x; - response->fds[response->num_fds].y = src_y; - response->fds[response->num_fds].src_w = src_w; - response->fds[response->num_fds].src_h = src_h; + response->fds[fd_index].x = src_x; + response->fds[fd_index].y = src_y; + response->fds[fd_index].src_w = src_w; + response->fds[fd_index].src_h = src_h; } ++response->num_fds; -- cgit v1.2.3