cta: add support for video data blocks

Report the SVDs inside the video data block.

We'll need to add additional APIs to get detailed SVD mode info
in the future (with a SVD table).

Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Simon Ser 2022-08-29 15:17:11 +02:00
parent 9806eb214e
commit 0c8673af02
5 changed files with 145 additions and 3 deletions

77
cta.c
View file

@ -43,6 +43,47 @@ add_failure_until(struct di_edid_cta *cta, int revision, const char fmt[], ...)
va_end(args);
}
static bool
parse_video_block(struct di_edid_cta *cta, struct di_cta_video_block *video,
const uint8_t *data, size_t size)
{
size_t i;
uint8_t raw;
struct di_cta_svd svd, *svd_ptr;
if (size == 0)
add_failure(cta, "Video Data Block: Empty Data Block");
for (i = 0; i < size; i++) {
raw = data[i];
if (raw == 0 || raw == 128 || raw >= 254) {
/* Reserved */
add_failure_until(cta, 3,
"Video Data Block: Unknown VIC %" PRIu8 ".",
raw);
continue;
} else if (raw <= 127 || raw >= 193) {
svd = (struct di_cta_svd) {
.vic = raw,
};
} else {
svd = (struct di_cta_svd) {
.vic = get_bit_range(raw, 6, 0),
.native = true,
};
}
svd_ptr = calloc(1, sizeof(*svd_ptr));
if (!svd_ptr)
return false;
*svd_ptr = svd;
video->svds[video->svds_len++] = svd_ptr;
}
return true;
}
static bool
parse_colorimetry_block(struct di_edid_cta *cta,
struct di_cta_colorimetry_block *colorimetry,
@ -133,6 +174,25 @@ parse_hdr_static_metadata_block(struct di_edid_cta *cta,
return true;
}
static void
destroy_data_block(struct di_cta_data_block *data_block)
{
size_t i;
struct di_cta_video_block *video;
switch (data_block->tag) {
case DI_CTA_DATA_BLOCK_VIDEO:
video = &data_block->video;
for (i = 0; i < video->svds_len; i++)
free(video->svds[i]);
break;
default:
break; /* Nothing to do */
}
free(data_block);
}
static bool
parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data, size_t size)
{
@ -151,6 +211,8 @@ parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data,
break;
case 2:
tag = DI_CTA_DATA_BLOCK_VIDEO;
if (!parse_video_block(cta, &data_block->video, data, size))
goto error;
break;
case 3:
/* Vendor-Specific Data Block */
@ -257,6 +319,10 @@ parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data,
skip:
free(data_block);
return true;
error:
destroy_data_block(data_block);
return false;
}
bool
@ -352,7 +418,7 @@ _di_edid_cta_finish(struct di_edid_cta *cta)
size_t i;
for (i = 0; i < cta->data_blocks_len; i++) {
free(cta->data_blocks[i]);
destroy_data_block(cta->data_blocks[i]);
}
for (i = 0; i < cta->detailed_timing_defs_len; i++) {
@ -384,6 +450,15 @@ di_cta_data_block_get_tag(const struct di_cta_data_block *block)
return block->tag;
}
const struct di_cta_svd *const *
di_cta_data_block_get_svds(const struct di_cta_data_block *block)
{
if (block->tag != DI_CTA_DATA_BLOCK_VIDEO) {
return NULL;
}
return (const struct di_cta_svd *const *) block->video.svds;
}
const struct di_cta_colorimetry_block *
di_cta_data_block_get_colorimetry(const struct di_cta_data_block *block)
{

View file

@ -474,6 +474,24 @@ display_color_type_name(enum di_edid_display_color_type type)
abort();
}
static void
printf_cta_svds(const struct di_cta_svd *const *svds)
{
size_t i;
const struct di_cta_svd *svd;
for (i = 0; svds[i] != NULL; i++) {
svd = svds[i];
printf(" VIC %3" PRIu8, svd->vic);
if (svd->native)
printf(" (native)");
printf("\n");
// TODO: print detailed mode info
}
}
static uint8_t
encode_max_luminance(float max)
{
@ -580,6 +598,7 @@ print_cta(const struct di_edid_cta *cta)
const struct di_cta_data_block *const *data_blocks;
const struct di_cta_data_block *data_block;
enum di_cta_data_block_tag data_block_tag;
const struct di_cta_svd *const *svds;
const struct di_cta_colorimetry_block *colorimetry;
const struct di_cta_hdr_static_metadata_block *hdr_static_metadata;
size_t i;
@ -610,6 +629,10 @@ print_cta(const struct di_edid_cta *cta)
printf(" %s:\n", cta_data_block_tag_name(data_block_tag));
switch (data_block_tag) {
case DI_CTA_DATA_BLOCK_VIDEO:
svds = di_cta_data_block_get_svds(data_block);
printf_cta_svds(svds);
break;
case DI_CTA_DATA_BLOCK_COLORIMETRY:
colorimetry = di_cta_data_block_get_colorimetry(data_block);
if (colorimetry->xvycc_601)

View file

@ -19,6 +19,13 @@
* 18 bytes.
*/
#define EDID_CTA_MAX_DETAILED_TIMING_DEFS 6
/**
* The maximum number of SVD entries in a video data block.
*
* Each data block has its size described in a 5-bit field, so its maximum size
* is 63 bytes, and each SVD uses 1 byte.
*/
#define EDID_CTA_MAX_VIDEO_BLOCK_ENTRIES 63
struct di_edid_cta {
int revision;
@ -41,9 +48,17 @@ struct di_cta_hdr_static_metadata_block_priv {
struct di_cta_hdr_static_metadata_block_descriptors descriptors;
};
struct di_cta_video_block {
/* NULL-terminated */
struct di_cta_svd *svds[EDID_CTA_MAX_VIDEO_BLOCK_ENTRIES + 1];
size_t svds_len;
};
struct di_cta_data_block {
enum di_cta_data_block_tag tag;
/* Used for DI_CTA_DATA_BLOCK_VIDEO */
struct di_cta_video_block video;
/* Used for DI_CTA_DATA_BLOCK_COLORIMETRY */
struct di_cta_colorimetry_block colorimetry;
/* Used for DI_CTA_DATA_BLOCK_HDR_STATIC_METADATA */

View file

@ -199,6 +199,26 @@ struct di_cta_hdr_static_metadata_block {
const struct di_cta_hdr_static_metadata_block *
di_cta_data_block_get_hdr_static_metadata(const struct di_cta_data_block *block);
/**
* A Short Video Descriptor (SVD).
*/
struct di_cta_svd {
/* Video Identification Code (VIC) */
uint8_t vic;
/* Whether this is a native video format */
bool native;
};
/**
* Get an array of short video descriptors from a CTA data block.
*
* Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_VIDEO.
*
* The returned array is NULL-terminated.
*/
const struct di_cta_svd *const *
di_cta_data_block_get_svds(const struct di_cta_data_block *block);
/**
* Get a list of EDID detailed timing definitions.
*

View file

@ -23,7 +23,7 @@
Detailed Timing Descriptors:
DTD 1: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (597 mm x 339 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P
@@ -51,32 +51,7 @@
@@ -51,32 +51,16 @@
Supports YCbCr 4:2:2
Native detailed modes: 1
Video Data Block:
@ -42,6 +42,15 @@
- DC_30bit
- DC_Y444
- Maximum TMDS clock: 310 MHz
+ VIC 16
+ VIC 4
+ VIC 3
+ VIC 2
+ VIC 31
+ VIC 19
+ VIC 18
+ VIC 17
+ VIC 1
Video Capability Data Block:
- YCbCr quantization: No Data
- RGB quantization: No Data
@ -56,7 +65,7 @@
Colorimetry Data Block:
BT2020cYCC
BT2020YCC
@@ -104,20 +79,8 @@
@@ -104,20 +88,8 @@
DTD 5: 1920x1080 74.972503 Hz 16:9 83.894 kHz 174.500000 MHz (597 mm x 339 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P
Vfront 3 Vsync 5 Vback 31 Vpol N