mirror of
https://gitlab.freedesktop.org/emersion/libdisplay-info.git
synced 2024-11-16 19:48:30 +01:00
cta: add support for Room Configuration data blocks
Signed-off-by: Sebastian Wick <sebastian.wick@redhat.com>
This commit is contained in:
parent
63b483cd46
commit
3edb81e68d
3 changed files with 122 additions and 0 deletions
88
cta.c
88
cta.c
|
@ -1226,6 +1226,81 @@ parse_infoframe_block(struct di_edid_cta *cta,
|
|||
return true;
|
||||
}
|
||||
|
||||
static double
|
||||
decode_coord(unsigned char x)
|
||||
{
|
||||
signed char s = (signed char)x;
|
||||
|
||||
return s / 64.0;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_room_config_block(struct di_edid_cta *cta,
|
||||
struct di_cta_room_configuration *rc,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
bool has_display_coords;
|
||||
bool has_speaker_count;
|
||||
|
||||
if (size < 4) {
|
||||
add_failure(cta, "Room Configuration Data Block: Empty Data Block with length %u.",
|
||||
size);
|
||||
return false;
|
||||
}
|
||||
|
||||
has_display_coords = has_bit(data[0], 7);
|
||||
has_speaker_count = has_bit(data[0], 6);
|
||||
rc->has_speaker_location_descriptors = has_bit(data[0], 5);
|
||||
|
||||
if (has_speaker_count) {
|
||||
rc->speaker_count = get_bit_range(data[0], 4, 0) + 1;
|
||||
} else {
|
||||
if (get_bit_range(data[0], 4, 0) != 0) {
|
||||
add_failure(cta, "Room Configuration Data Block: "
|
||||
"'Speaker' flag is 0, but the Speaker Count is not 0.");
|
||||
}
|
||||
|
||||
if (rc->has_speaker_location_descriptors) {
|
||||
add_failure(cta, "Room Configuration Data Block: "
|
||||
"'Speaker' flag is 0, but there are "
|
||||
"Speaker Location Descriptors.");
|
||||
}
|
||||
}
|
||||
|
||||
parse_speaker_alloc(cta, &rc->speakers, &data[1], "Room Configuration Data Block");
|
||||
|
||||
rc->max_x = 16;
|
||||
rc->max_y = 16;
|
||||
rc->max_z = 8;
|
||||
rc->display_x = 0.0;
|
||||
rc->display_y = 1.0;
|
||||
rc->display_z = 0.0;
|
||||
|
||||
if (size < 7) {
|
||||
if (has_display_coords)
|
||||
add_failure(cta, "Room Configuration Data Block: "
|
||||
"'Display' flag is 1, but the Display and Maximum coordinates are not present.");
|
||||
return true;
|
||||
}
|
||||
|
||||
rc->max_x = data[4];
|
||||
rc->max_y = data[5];
|
||||
rc->max_z = data[6];
|
||||
|
||||
if (size < 10) {
|
||||
if (has_display_coords)
|
||||
add_failure(cta, "Room Configuration Data Block: "
|
||||
"'Display' flag is 1, but the Display coordinates are not present.");
|
||||
return true;
|
||||
}
|
||||
|
||||
rc->display_x = decode_coord(data[7]);
|
||||
rc->display_y = decode_coord(data[8]);
|
||||
rc->display_z = decode_coord(data[9]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_data_block(struct di_cta_data_block *data_block)
|
||||
{
|
||||
|
@ -1373,6 +1448,10 @@ parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data,
|
|||
break;
|
||||
case 19:
|
||||
tag = DI_CTA_DATA_BLOCK_ROOM_CONFIG;
|
||||
if (!parse_room_config_block(cta,
|
||||
&data_block->room_config,
|
||||
data, size))
|
||||
goto skip;
|
||||
break;
|
||||
case 20:
|
||||
tag = DI_CTA_DATA_BLOCK_SPEAKER_LOCATION;
|
||||
|
@ -1688,3 +1767,12 @@ di_cta_data_block_get_vesa_transfer_characteristics(const struct di_cta_data_blo
|
|||
}
|
||||
return &block->vesa_transfer_characteristics;
|
||||
}
|
||||
|
||||
const struct di_cta_room_configuration *
|
||||
di_cta_data_block_get_room_configuration(const struct di_cta_data_block *block)
|
||||
{
|
||||
if (block->tag != DI_CTA_DATA_BLOCK_ROOM_CONFIG) {
|
||||
return NULL;
|
||||
}
|
||||
return &block->room_config;
|
||||
}
|
||||
|
|
|
@ -155,6 +155,8 @@ struct di_cta_data_block {
|
|||
struct di_cta_ycbcr420_cap_map ycbcr420_cap_map;
|
||||
/* Used for DI_CTA_DATA_BLOCK_INFOFRAME */
|
||||
struct di_cta_infoframe_block_priv infoframe;
|
||||
/* Used for DI_CTA_DATA_BLOCK_ROOM_CONFIG */
|
||||
struct di_cta_room_configuration room_config;
|
||||
};
|
||||
|
||||
extern const struct di_cta_video_format _di_cta_video_formats[];
|
||||
|
|
|
@ -930,6 +930,38 @@ struct di_cta_infoframe_block {
|
|||
const struct di_cta_infoframe_block *
|
||||
di_cta_data_block_get_infoframe(const struct di_cta_data_block *block);
|
||||
|
||||
/**
|
||||
* Room Configuration Data Block, defined in section 7.5.15.
|
||||
*/
|
||||
struct di_cta_room_configuration {
|
||||
/* Present speakers */
|
||||
struct di_cta_speaker_allocation speakers;
|
||||
/* Total number of L-PCM channels */
|
||||
int speaker_count;
|
||||
/* All speakers are defined by Speaker Location Descriptors */
|
||||
bool has_speaker_location_descriptors;
|
||||
/* Rectangular box that contains all of the components of interest
|
||||
* centered on the Primary Listening Position.
|
||||
* See 7.5.16.1 Room Coordinate System
|
||||
* Only valid if any Speaker Location Descriptor has coordinates set. */
|
||||
int max_x; /* in dm */
|
||||
int max_y; /* in dm */
|
||||
int max_z; /* in dm */
|
||||
/* The position of the center of the display in normalized coordinates.
|
||||
* Only valid if any Speaker Location Descriptor has coordinates set. */
|
||||
double display_x; /* normalized to max_x */
|
||||
double display_y; /* normalized to max_y */
|
||||
double display_z; /* normalized to max_z */
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the Room Configuration from a CTA data block.
|
||||
*
|
||||
* Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_ROOM_CONFIG.
|
||||
*/
|
||||
const struct di_cta_room_configuration *
|
||||
di_cta_data_block_get_room_configuration(const struct di_cta_data_block *block);
|
||||
|
||||
/**
|
||||
* Get a list of EDID detailed timing definitions.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue