cta: add support for InfoFrame Data Block

Signed-off-by: Sebastian Wick <sebastian.wick@redhat.com>
This commit is contained in:
Sebastian Wick 2023-01-12 02:30:36 +01:00
parent 23be3830c0
commit 506925a66b
9 changed files with 321 additions and 1 deletions

134
cta.c
View file

@ -1101,12 +1101,128 @@ parse_ycbcr420_cap_map(struct di_edid_cta *cta,
memcpy(ycbcr420_cap_map->svd_bitmap, data, size);
}
static struct di_cta_infoframe_descriptor *
parse_infoframe(struct di_edid_cta *cta, uint8_t type,
const uint8_t *data, size_t size)
{
struct di_cta_infoframe_descriptor infoframe = {0};
struct di_cta_infoframe_descriptor *ifp;
if (type >= 8 && type <= 0x1f) {
add_failure(cta, "InfoFrame Data Block: Type code %u is reserved.",
type);
return NULL;
}
if (type >= 0x20) {
add_failure(cta, "InfoFrame Data Block: Type code %u is forbidden.",
type);
return NULL;
}
if (type == 1) {
/* No known vendor specific InfoFrames, yet */
return NULL;
} else {
switch (type) {
case 0x02:
infoframe.type = DI_CTA_INFOFRAME_TYPE_AUXILIARY_VIDEO_INFORMATION;
break;
case 0x03:
infoframe.type = DI_CTA_INFOFRAME_TYPE_SOURCE_PRODUCT_DESCRIPTION;
break;
case 0x04:
infoframe.type = DI_CTA_INFOFRAME_TYPE_AUDIO;
break;
case 0x05:
infoframe.type = DI_CTA_INFOFRAME_TYPE_MPEG_SOURCE;
break;
case 0x06:
infoframe.type = DI_CTA_INFOFRAME_TYPE_NTSC_VBI;
break;
case 0x07:
infoframe.type = DI_CTA_INFOFRAME_TYPE_DYNAMIC_RANGE_AND_MASTERING;
break;
default:
abort(); /* unreachable */
}
}
ifp = calloc(1, sizeof(*ifp));
if (!ifp)
return NULL;
*ifp = infoframe;
return ifp;
}
static bool
parse_infoframe_block(struct di_edid_cta *cta,
struct di_cta_infoframe_block_priv *ifb,
const uint8_t *data, size_t size)
{
size_t index = 0, length;
uint8_t type;
struct di_cta_infoframe_descriptor *infoframe;
if (size < 2) {
add_failure(cta, "InfoFrame Data Block: Empty Data Block with length %u.",
size);
return false;
}
ifb->block.num_simultaneous_vsifs = data[1] + 1;
ifb->block.infoframes = (const struct di_cta_infoframe_descriptor *const *)ifb->infoframes;
index = get_bit_range(data[0], 7, 5) + 2;
if (get_bit_range(data[0], 4, 0) != 0)
add_failure(cta, "InfoFrame Data Block: InfoFrame Processing "
"Descriptor Header bits F14-F10 shall be 0.");
while (true) {
if (index == size)
break;
if (index > size) {
add_failure(cta, "InfoFrame Data Block: Payload length exceeds block size.");
return false;
}
length = get_bit_range(data[index], 7, 5);
type = get_bit_range(data[index], 4, 0);
if (type == 0) {
add_failure(cta, "InfoFrame Data Block: Short InfoFrame Descriptor with type 0 is forbidden.");
return false;
} else if (type == 1) {
length += 4;
} else {
length += 1;
}
if (index + length > size) {
add_failure(cta, "InfoFrame Data Block: Payload length exceeds block size.");
return false;
}
infoframe = parse_infoframe(cta, type, &data[index], length);
if (infoframe) {
assert(ifb->infoframes_len < EDID_CTA_INFOFRAME_BLOCK_ENTRIES);
ifb->infoframes[ifb->infoframes_len++] = infoframe;
}
index += length;
}
return true;
}
static void
destroy_data_block(struct di_cta_data_block *data_block)
{
size_t i;
struct di_cta_video_block *video;
struct di_cta_audio_block *audio;
struct di_cta_infoframe_block_priv *infoframe;
switch (data_block->tag) {
case DI_CTA_DATA_BLOCK_VIDEO:
@ -1124,6 +1240,11 @@ destroy_data_block(struct di_cta_data_block *data_block)
for (i = 0; i < audio->sads_len; i++)
free(audio->sads[i]);
break;
case DI_CTA_DATA_BLOCK_INFOFRAME:
infoframe = &data_block->infoframe;
for (i = 0; i < infoframe->infoframes_len; i++)
free(infoframe->infoframes[i]);
break;
default:
break; /* Nothing to do */
}
@ -1248,6 +1369,10 @@ parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data,
break;
case 32:
tag = DI_CTA_DATA_BLOCK_INFOFRAME;
if (!parse_infoframe_block(cta,
&data_block->infoframe,
data, size))
goto skip;
break;
case 34:
tag = DI_CTA_DATA_BLOCK_DISPLAYID_VIDEO_TIMING_VII;
@ -1530,6 +1655,15 @@ di_cta_data_block_get_ycbcr420_cap_map(const struct di_cta_data_block *block)
return &block->ycbcr420_cap_map;
}
const struct di_cta_infoframe_block *
di_cta_data_block_get_infoframe(const struct di_cta_data_block *block)
{
if (block->tag != DI_CTA_DATA_BLOCK_INFOFRAME) {
return NULL;
}
return &block->infoframe.block;
}
const struct di_edid_detailed_timing_def *const *
di_edid_cta_get_detailed_timing_defs(const struct di_edid_cta *cta)
{

View file

@ -669,6 +669,39 @@ print_ycbcr420_cap_map(const struct di_edid_cta *cta,
}
}
static const char *
cta_infoframe_type_name(enum di_cta_infoframe_type type)
{
switch (type) {
case DI_CTA_INFOFRAME_TYPE_AUXILIARY_VIDEO_INFORMATION:
return "Auxiliary Video Information InfoFrame (2)";
case DI_CTA_INFOFRAME_TYPE_SOURCE_PRODUCT_DESCRIPTION:
return "Source Product Description InfoFrame (3)";
case DI_CTA_INFOFRAME_TYPE_AUDIO:
return "Audio InfoFrame (4)";
case DI_CTA_INFOFRAME_TYPE_MPEG_SOURCE:
return "MPEG Source InfoFrame (5)";
case DI_CTA_INFOFRAME_TYPE_NTSC_VBI:
return "NTSC VBI InfoFrame (6)";
case DI_CTA_INFOFRAME_TYPE_DYNAMIC_RANGE_AND_MASTERING:
return "Dynamic Range and Mastering InfoFrame (7)";
}
abort();
}
static void
print_infoframes(const struct di_cta_infoframe_descriptor *const *infoframes)
{
size_t i;
const struct di_cta_infoframe_descriptor *infoframe;
for (i = 0; infoframes[i] != NULL; i++) {
infoframe = infoframes[i];
printf(" %s\n",
cta_infoframe_type_name(infoframe->type));
}
}
static const char *
cta_data_block_tag_name(enum di_cta_data_block_tag tag)
{
@ -757,6 +790,7 @@ print_cta(const struct di_edid_cta *cta)
const struct di_cta_vesa_transfer_characteristics *transfer_characteristics;
const struct di_cta_sad *const *sads;
const struct di_cta_ycbcr420_cap_map *ycbcr420_cap_map;
const struct di_cta_infoframe_block *infoframe;
size_t i;
const struct di_edid_detailed_timing_def *const *detailed_timing_defs;
@ -897,6 +931,11 @@ print_cta(const struct di_edid_cta *cta)
ycbcr420_cap_map = di_cta_data_block_get_ycbcr420_cap_map(data_block);
print_ycbcr420_cap_map(cta, ycbcr420_cap_map);
break;
case DI_CTA_DATA_BLOCK_INFOFRAME:
infoframe = di_cta_data_block_get_infoframe(data_block);
printf(" VSIFs: %d\n", infoframe->num_simultaneous_vsifs - 1);
print_infoframes(infoframe->infoframes);
break;
default:
break; /* Ignore */
}

View file

@ -48,6 +48,15 @@
* is 63 bytes, and each Capability Bit Map uses 1 byte.
*/
#define EDID_CTA_MAX_YCBCR420_CAP_MAP_BLOCK_ENTRIES 63
/**
* The maximum number of Short InfoFrame Descriptor or Short Vendor-Specific
* InfoFrame Descriptor entries in a InfoFrame data block.
*
* Each data block has its size described in a 5-bit field, so its maximum size
* is 63 bytes, the header takes up at least 2 bytes and the smallest Short
* InfoFrame Descriptor is 1 byte.
*/
#define EDID_CTA_INFOFRAME_BLOCK_ENTRIES 61
struct di_edid_cta {
int revision;
@ -113,6 +122,12 @@ struct di_cta_ycbcr420_cap_map {
uint8_t svd_bitmap[EDID_CTA_MAX_YCBCR420_CAP_MAP_BLOCK_ENTRIES];
};
struct di_cta_infoframe_block_priv {
struct di_cta_infoframe_block block;
struct di_cta_infoframe_descriptor *infoframes[EDID_CTA_INFOFRAME_BLOCK_ENTRIES + 1];
size_t infoframes_len;
};
struct di_cta_data_block {
enum di_cta_data_block_tag tag;
@ -138,6 +153,8 @@ struct di_cta_data_block {
struct di_cta_vesa_transfer_characteristics vesa_transfer_characteristics;
/* Used for DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP */
struct di_cta_ycbcr420_cap_map ycbcr420_cap_map;
/* Used for DI_CTA_DATA_BLOCK_INFOFRAME */
struct di_cta_infoframe_block_priv infoframe;
};
extern const struct di_cta_video_format _di_cta_video_formats[];

View file

@ -877,6 +877,53 @@ di_cta_ycbcr420_cap_map_supported(const struct di_cta_ycbcr420_cap_map *cap_map,
const struct di_cta_ycbcr420_cap_map *
di_cta_data_block_get_ycbcr420_cap_map(const struct di_cta_data_block *block);
/**
* InfoFrame types, defined in table 7.
*
* Note, the enum values don't match the specification.
*/
enum di_cta_infoframe_type {
/* Auxiliary Video Information, defined in section 6.4. */
DI_CTA_INFOFRAME_TYPE_AUXILIARY_VIDEO_INFORMATION,
/* Source Product Description, defined in section 6.5. */
DI_CTA_INFOFRAME_TYPE_SOURCE_PRODUCT_DESCRIPTION,
/* Audio, defined in section 6.6. */
DI_CTA_INFOFRAME_TYPE_AUDIO,
/* MPEG Source, defined in section 6.7. */
DI_CTA_INFOFRAME_TYPE_MPEG_SOURCE,
/* NTSC VBI, defined in section 6.8. */
DI_CTA_INFOFRAME_TYPE_NTSC_VBI,
/* Dynamic Range and Mastering, defined in section 6.9. */
DI_CTA_INFOFRAME_TYPE_DYNAMIC_RANGE_AND_MASTERING,
};
/**
* CTA InfoFrame descriptor, defined in section 7.5.9.
*/
struct di_cta_infoframe_descriptor {
/* Type of InfoFrame */
enum di_cta_infoframe_type type;
};
/**
* CTA InfoFrame processing, defined in section 7.5.9.
*/
struct di_cta_infoframe_block {
/* Number of Vendor-specific InfoFrames that can be received
* simultaneously */
int num_simultaneous_vsifs;
/* Supported InfoFrames. The array is NULL-terminated. */
const struct di_cta_infoframe_descriptor *const *infoframes;
};
/**
* Get the InfoFrame information from a CTA data block.
*
* Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_INFOFRAME.
*/
const struct di_cta_infoframe_block *
di_cta_data_block_get_infoframe(const struct di_cta_data_block *block);
/**
* Get a list of EDID detailed timing definitions.
*

View file

@ -14,6 +14,7 @@ samsung-s27a950d-dp | ./Digital/Samsung/SAM079F/6D343EDB39F8 | cff7fe4d44
sun-gh19ps-dvi | ./Digital/Sun/SUN058C/34B2E3B9A052 | cff7fe4d44
viewsonic-vp2768-dp | ./Digital/ViewSonic/VSC2034/6B81BEA28A1E | cff7fe4d44
philips-ftv-490 | ./Digital/Philips/PHL01EA/03A4224323A6 | cff7fe4d44
hitachi-55r6+ | ./Digital/Hitachi/HEC0000/58C711CBA787 | cff7fe4d44
The following blobs originate from the [edid-decode] repository and are under
the same license as the rest of the libdisplay-info project:

View file

@ -0,0 +1,78 @@
--- ref
+++ di
@@ -102,26 +102,6 @@
Colorimetry Data Block:
BT2020YCC
BT2020RGB
- Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
- Source physical address: 3.0.0.0
- Supports_AI
- DC_36bit
- DC_30bit
- DC_Y444
- Maximum TMDS clock: 300 MHz
- Extended HDMI video details:
- Base EDID image size is in units of 1 cm
- HDMI VICs:
- HDMI VIC 1: 3840x2160 30.000000 Hz 16:9 67.500 kHz 297.000000 MHz
- HDMI VIC 3: 3840x2160 24.000000 Hz 16:9 54.000 kHz 297.000000 MHz
- HDMI VIC 4: 4096x2160 24.000000 Hz 256:135 54.000 kHz 297.000000 MHz
- Vendor-Specific Data Block (HDMI Forum), OUI C4-5D-D8:
- Version: 1
- Maximum TMDS Character Rate: 600 MHz
- SCDC Present
- Supports 12-bits/component Deep Color 4:2:0 Pixel Encoding
- Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding
- Supports Auto Low-Latency Mode
HDR Static Metadata Data Block:
Electro optical transfer functions:
Traditional gamma - SDR luminance range
@@ -129,23 +109,6 @@
Hybrid Log-Gamma
Supported static metadata descriptors:
Static metadata type 1
- Vendor-Specific Video Data Block (Dolby), OUI 00-D0-46:
- Version: 2 (12 bytes)
- Supports global dimming
- DM Version: 3.x
- Backlt Min Luma: 100 cd/m^2
- Interface: Standard + Low-Latency
- Supports 10b 12b 444: Not supported
- Target Min PQ v2: 200 (0.05768953 cd/m^2)
- Target Max PQ v2: 2445 (245 cd/m^2)
- Unique Rx, Ry: 0.62500000, 0.33203125
- Unique Gx, Gy: 0.30468750, 0.61328125
- Unique Bx, By: 0.15234375, 0.05078125
- Vendor-Specific Audio Data Block (Dolby), OUI 00-D0-46:
- Version: 1 (7 bytes)
- Height speaker zone present
- Surround speaker zone present
- Center speaker zone present
YCbCr 4:2:0 Capability Map Data Block:
VIC 97: 3840x2160 60.000000 Hz 16:9 135.000 kHz 594.000000 MHz
VIC 102: 4096x2160 60.000000 Hz 256:135 135.000 kHz 594.000000 MHz
@@ -156,22 +119,8 @@
DTD 3: 1360x768 60.015162 Hz 85:48 47.712 kHz 85.500000 MHz
Hfront 64 Hsync 112 Hback 256 Hpol P
Vfront 3 Vsync 6 Vback 18 Vpol P
-Checksum: 0x4d Unused space in Extension Block: 10 bytes
+Checksum: 0x4d
----------------
-Warnings:
-
-Block 1, CTA-861 Extension Block:
- IT Video Formats are overscanned by default, but normally this should be underscanned.
- Colorimetry Data Block: Set the sRGB colorimetry bit to avoid interop issues.
-
-Failures:
-
-Block 0, Base EDID:
- Detailed Timing Descriptor #1: Mismatch of image size 800x450 mm vs display size 1220x680 mm.
- Detailed Timing Descriptor #2: Mismatch of image size 800x450 mm vs display size 1220x680 mm.
-Block 1, CTA-861 Extension Block:
- Detailed Timing Descriptor #3: Mismatch of image size vs display size: image size is not set, but display size is.
-
-EDID conformity: FAIL
+EDID conformity: PASS

Binary file not shown.

View file

@ -0,0 +1,3 @@
make: Hisense Electric Co., Ltd.
model: 55R6+
serial: 0x000001D8

View file

@ -30,7 +30,8 @@ test_cases = [
'cvt',
'philips-ftv-490',
'samsung-q800t-hdmi2.0',
'cta-timings'
'cta-timings',
'hitachi-55r6+',
]
test_env = [