1 // SPDX-License-Identifier: MIT
3 * Copyright 2024 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 * Author: Hans Verkuil <hverkuil-cisco@xs4all.nl>
10 #include "edid-decode.h"
12 int edid_state::parse_if_hdr(const unsigned char *x
, unsigned size
, unsigned char mask
)
14 unsigned char length
= x
[2];
16 printf("%s\n", data_block
.c_str());
17 printf(" Version: %u\n", x
[1] & mask
);
18 printf(" Length: %u\n", length
);
20 if (length
+ 3U > size
) {
21 fail("Expected InfoFrame total length of %d, but have only %d bytes.\n",
25 if (length
+ 3U < size
) {
26 warn("There are %d dummy bytes after the payload.\n", length
+ 3 - size
);
27 if (!memchk(x
+ length
+ 3, length
+ 3 - size
))
28 warn("There are non-zero dummy bytes after the payload.\n");
33 static const char *Structure_map
[] = {
37 "Side-by-Side (Full)",
39 "L + depth + graphics + graphics-depth",
42 "Side-by-Side (Half)",
52 static const char *ExtData_map
[] = {
53 "Horizontal sub-sampling (0)",
54 "Horizontal sub-sampling (1)",
55 "Horizontal sub-sampling (2)",
56 "Horizontal sub-sampling (3)",
57 "Quincunx matrix: Odd/Left picture, Odd/Right picture",
58 "Quincunx matrix: Odd/Left picture, Even/Right picture",
59 "Quincunx matrix: Even/Left picture, Odd/Right picture",
60 "Quincunx matrix: Even/Left picture, Even/Right picture"
63 void edid_state::parse_if_hdmi(const unsigned char *x
, unsigned len
)
66 fail("Expected InfoFrame length of at least 4, got %d.\n", len
);
70 fail("Bits 4-0 of PB4 are not 0.\n");
72 printf(" HDMI Video Format: ");
78 printf("No additional data\n");
79 if (!memchk(x
+ 5, len
- 4))
80 fail("Trailing non-0 bytes.\n");
83 printf("HDMI_VIC is present\n");
86 fail("Expected InfoFrame length of at least 5, got %d.\n", len
);
89 sprintf(buf
, "HDMI VIC %u", x
[5]);
90 const struct timings
*t
= find_hdmi_vic_id(x
[5]);
92 printf(" HDMI VIC: %d (0x%02x)\n", x
[5], x
[5]);
93 fail("Unknown HDMI VIC code.\n");
95 print_timings(" ", t
, buf
);
97 if (!memchk(x
+ 6, len
- 5))
98 fail("Trailing non-0 bytes.\n");
102 printf("3D format indication present\n");
105 fail("Expected InfoFrame length of at least 5, got %d.\n", len
);
110 printf("Reserved (%d)\n", x
[4] >> 5);
111 fail("Invalid HDMI Video Format (%d).\n", x
[4] >> 5);
115 // Parsing of 3D extension continues here
116 unsigned char v
= x
[5] >> 4;
118 printf(" 3D Structure: %s\n", Structure_map
[v
]);
120 fail("Bits 2-0 of PB5 are not 0.\n");
121 printf("3D Metadata Present: %s\n", (x
[5] & 8) ? "Yes" : "No");
124 if (!memchk(x
+ 6, len
- 5))
125 fail("Trailing non-0 bytes.\n");
130 fail("Expected InfoFrame length of at least 6, got %d.\n", len
);
135 fail("Bits 3-0 of PB6 are not 0.\n");
137 if ((x
[6] >> 4) >= 8)
138 printf(" 3D Extended Data: Reserved (%d)\n", (x
[6] >> 4));
140 printf(" 3D Extended Data: %s\n", ExtData_map
[x
[6] >> 4]);
143 if (!memchk(x
+ 7, len
- 6))
144 fail("Trailing non-0 bytes.\n");
149 fail("Expected InfoFrame length of at least 7, got %d.\n", len
);
152 unsigned mlen
= x
[7] & 0x1f;
153 if (len
< mlen
+ 7) {
154 fail("Expected InfoFrame length of at least %d, got %d.\n", mlen
+ 7, len
);
157 if (!memchk(x
+ mlen
+ 7, len
- mlen
- 6))
158 fail("Trailing non-0 bytes.\n");
160 printf(" 3D Metadata Type: Reserved (%d)\n", x
[7] >> 5);
161 fail("Invalid 3D Metadata Type.\n");
164 printf(" 3D Metadata Type: Parallax Information\n");
166 printf(" Metadata: Parallax Zero: %u\n", (x
[8] << 8) | x
[9]);
167 printf(" Metadata: Parallax Scale: %u\n", (x
[10] << 8) | x
[11]);
168 printf(" Metadata: DRef: %u\n", (x
[12] << 8) | x
[13]);
169 printf(" Metadata: WRef: %u\n", (x
[14] << 8) | x
[15]);
172 void edid_state::parse_if_hdmi_forum(const unsigned char *x
, unsigned len
)
175 fail("Expected InfoFrame length of at least 5, got %d.\n", len
);
179 fail("Bits 3-2 of PB5 are not 0.\n");
180 unsigned char v
= x
[5] >> 4;
181 printf(" Color Content Bits Per Component: ");
183 printf("No Indication\n");
185 printf("Reserved (%d)\n", v
);
187 printf("%d bits\n", v
+ 7);
189 printf(" 3D Valid\n");
190 printf(" Auto Low-Latency Mode: %s\n", (x
[5] & 2) ? "Yes" : "No");
192 if (!memchk(x
+ 6, len
- 5))
193 fail("Trailing non-0 bytes.\n");
197 // Parsing of 3D extension continues here
204 printf(" 3D Structure: %s\n", Structure_map
[v
]);
206 fail("Bit 0 of PB6 is not 0.\n");
207 printf("3D Additional Info Present: %s\n", (x
[offset
] & 8) ? "Yes" : "No");
208 printf("3D Disparity Data Present: %s\n", (x
[offset
] & 4) ? "Yes" : "No");
209 printf("3D Metadata Present: %s\n", (x
[offset
] & 2) ? "Yes" : "No");
217 fail("Bits 3-0 of PB7 are not 0.\n");
219 if ((x
[offset
] >> 4) >= 8)
220 printf(" 3D Extended Data: Reserved (%d)\n", (x
[offset
] >> 4));
222 printf(" 3D Extended Data: %s\n", ExtData_map
[x
[offset
] >> 4]);
230 if (x
[offset
] & 0xe0)
231 fail("Bits 7-5 if PB%d are not 0.\n", offset
);
232 printf(" 3D Dual View: %s\n", (x
[offset
] & 0x10) ? "Yes" : "No");
234 static const char *ViewDep_map
[] = {
236 "Independent Right View",
237 "Independent Left View",
238 "Independent Right and Left Views"
240 printf(" 3D View Dependency: %s\n", ViewDep_map
[(x
[offset
] & 0x0c) >> 2]);
242 static const char *Pref2DView_map
[] = {
248 printf(" 3D Preferred 2D View: %s\n", Pref2DView_map
[x
[offset
] & 3]);
256 printf(" Disparity Data Version: %d\n", x
[offset
] >> 5);
257 unsigned dlen
= x
[offset
] & 0x1f;
258 printf(" Disparity Data Length: %d\n", dlen
);
259 if (len
< offset
+ dlen
)
263 hex_block(" Disparity Data Payload: ", x
+ offset
, dlen
, false, dlen
);
272 if (x
[offset
] >> 5) {
273 printf(" 3D Metadata Type: Reserved (%d)\n", x
[offset
] >> 5);
274 fail("Invalid 3D Metadata Type.\n");
277 printf(" 3D Metadata Type: Parallax Information\n");
278 printf(" 3D Metadata Length: %d\n", x
[offset
] & 0x1f);
279 if (len
< offset
+ (x
[offset
] & 0x1f))
283 printf(" Metadata: Parallax Zero: %u\n", (x
[offset
] << 8) | x
[offset
+1]);
284 printf(" Metadata: Parallax Scale: %u\n", (x
[offset
+2] << 8) | x
[offset
+3]);
285 printf(" Metadata: DRef: %u\n", (x
[offset
+4] << 8) | x
[offset
+5]);
286 printf(" Metadata: WRef: %u\n", (x
[offset
+6] << 8) | x
[offset
+7]);
288 offset
+= x
[offset
- 1] & 0x1f;
291 if (!memchk(x
+ offset
+ 1, len
- offset
))
292 fail("Trailing non-0 bytes.\n");
296 fail("Expected InfoFrame length of at least %d, got %d.\n", offset
, len
);
300 void edid_state::parse_if_vendor(const unsigned char *x
, unsigned size
)
302 data_block
= "Vendor-Specific InfoFrame";
305 unsigned char len
= x
[2];
307 data_block_oui(data_block
, x
+ 3, 3, &oui
, false, false, false, true);
309 if (parse_if_hdr(x
, size
, (x
[1] & 0x7f) == 2 ? 0x7f : 0xff))
312 if (x
[1] != 1 && (x
[1] & 0x7f) != 2) {
313 fail("Invalid version %d\n", x
[1] & 0x7f);
317 fail("Expected InfoFrame length of at least 3, got %d.\n", len
);
322 printf(" VSIF Change: %s\n", (x
[1] & 0x80) ? "Yes" : "No");
324 // After this x[1] will refer to Data Byte 1
329 parse_if_hdmi(x
, len
);
332 parse_if_hdmi_forum(x
, len
);
335 hex_block(" Payload: ", x
+ 4, len
- 3, false, len
- 3);
340 void edid_state::parse_if_avi(const unsigned char *x
, unsigned size
)
342 unsigned char version
= x
[1];
343 unsigned char length
= x
[2];
345 data_block
= "AVI InfoFrame";
347 if (parse_if_hdr(x
, size
))
350 if (version
== 0 || version
> 4) {
351 fail("Invalid version %u\n", version
);
355 fail("Sources shall not use version 1.\n");
357 fail("Expected InfoFrame length of 13, got %u.\n", length
);
361 // After this x[1] will refer to Data Byte 1
366 fail("Bits F37-F32 are not 0.\n");
368 fail("Bits F47-F40 are not 0.\n");
370 fail("Bits F57-F50 are not 0.\n");
374 fail("Bit Y2 is not 0.\n");
376 fail("Bit VIC7 is not 0.\n");
378 if (version
== 4 && length
== 15) {
380 fail("Bit F157 is not 0.\n");
382 if (version
== 4 && length
< 14) {
383 fail("Version 4 expects a length of >= 14, got %u\n", length
);
388 if (version
> cta
.avi_version
)
389 warn("AVI version is %u, but EDID indicates support for %u only.\n",
390 version
, cta
.avi_version
);
391 if (version
== 4 && length
> cta
.avi_v4_length
)
392 warn("AVI version 4 length is %u, but EDID indicates support for %u only.\n",
393 length
, cta
.avi_v4_length
);
397 unsigned vic_fps
= 0;
398 unsigned char vic
= x
[4];
399 unsigned char rid
= length
>= 14 ? x
[15] & 0x3f : 0;
401 sprintf(buf
, "VIC %3u", vic
);
402 const struct timings
*t
= find_vic_id(vic
);
404 print_timings(" ", t
, buf
);
405 vic_fps
= calc_fps(t
);
407 printf(" VIC: %d (0x%02x)\n", vic
, vic
);
408 fail("Unknown VIC code.\n");
411 static const char *Y_map
[] = {
421 unsigned char y
= x
[1] >> 5;
424 printf(" Y: Color Component Sample Format: %s\n", Y_map
[y
]);
425 if (y
== 7 && version
== 2)
426 warn("Y == 7 but AVI Version == 2.\n");
428 if ((y
== 1 && !cta
.has_ycbcr422
) ||
429 (y
== 2 && !cta
.has_ycbcr444
) ||
430 (y
== 3 && !cta
.has_ycbcr420
))
431 fail("Y == %s, but this capability is not enabled in the EDID.\n", Y_map
[y
]);
434 printf(" A: Active Format Information Present: %s\n",
435 ((x
[1] >> 4) & 1) ? "Yes" : "No");
437 static const char *B_map
[] = {
438 "Bar Data not present",
439 "Vertical Bar Info present",
440 "Horizontal Bar Info present",
441 "Vertical and Horizontal Bar Info present"
443 printf(" B: Bar Data Present: %s\n", B_map
[(x
[1] >> 2) & 3]);
445 static const char *S_map
[] = {
447 "Composed for an overscanned display",
448 "Composed for an underscanned display",
451 printf(" S: Scan Information: %s\n", S_map
[x
[1] & 3]);
453 static const char *C_map
[] = {
457 "Extended Colorimetry Information Valid"
459 printf(" C: Colorimetry: %s\n", C_map
[x
[2] >> 6]);
461 static const char *M_map
[] = {
468 printf(" M: Picture Aspect Ratio: %s\n", M_map
[v
]);
469 if ((vic
|| rid
) && v
)
470 warn("If a VID or RID is specified, then set M to 0.\n");
471 printf(" R: Active Portion Aspect Ratio: %d\n", x
[2] & 0xf);
473 static const char *ITC_map
[] = {
475 "IT Content (CN is valid)"
477 printf(" ITC: IT Content: %s\n", ITC_map
[x
[3] >> 7]);
479 static const char *EC_map
[] = {
485 "Rec. ITU-R BR.2020 YcCbcCrc",
486 "Rec. ITU-R BR.2020 RGB or YCbCr",
487 "Additional Colorimetry Extension Information Valid"
489 printf(" EC: Extended Colorimetry: %s\n", EC_map
[(x
[3] >> 4) & 7]);
491 static const char *Q_map
[] = {
497 printf(" Q: RGB Quantization Range: %s\n", Q_map
[(x
[3] >> 2) & 3]);
499 static const char *SC_map
[] = {
500 "No Known non-uniform scaling",
501 "Picture has been scaled horizontally",
502 "Picture has been scaled vertically",
503 "Picture has been scaled horizontally and vertically"
505 printf(" SC: Non-Uniform Picture Scaling: %s\n", SC_map
[x
[3] & 3]);
507 static const char *YQ_map
[] = {
513 printf(" YQ: YCC Quantization Range: %s\n", YQ_map
[x
[5] >> 6]);
515 static const char *CN_map
[] = {
521 printf(" CN: IT Content Type: %s\n", CN_map
[(x
[5] >> 4) & 3]);
522 unsigned char pr
= x
[5] & 0xf;
523 printf(" PR: Pixel Data Repetition Count: %d\n", pr
);
525 const unsigned short pr_2
= 2;
526 const unsigned short pr_1_10
= 0x3ff;
527 const unsigned short pr_1_2
= 3;
528 const unsigned short pr_1_2_4
= 0xb;
529 static const unsigned short vic_valid_pr
[] = {
531 0, 0, 0, 0, 0, 0, pr_2
, pr_2
,
533 pr_2
, pr_2
, pr_1_10
, pr_1_10
, pr_1_10
, pr_1_10
, pr_1_2
, pr_1_2
,
535 0, 0, 0, 0, 0, pr_2
, pr_2
, pr_2
,
537 pr_2
, pr_1_10
, pr_1_10
, pr_1_10
, pr_1_10
, pr_1_2
, pr_1_2
, 0,
539 0, 0, 0, pr_1_2_4
, pr_1_2_4
, pr_1_2_4
, pr_1_2_4
, 0,
541 0, 0, 0, 0, pr_2
, pr_2
, 0, 0,
543 0, 0, pr_2
, pr_2
, 0, 0, pr_2
, pr_2
,
549 fail("PR >= 10 is a reserved value.\n");
550 else if (pr
&& (vic
>= ARRAY_SIZE(vic_valid_pr
) ||
551 !(vic_valid_pr
[vic
] & (1 << pr
))))
552 fail("PR %u is not supported by VIC %u.\n", pr
, vic
);
554 printf(" Line Number of End of Top Bar: %d\n", (x
[7] << 8) | x
[6]);
555 printf(" Line Number of Start of Bottom Bar: %d\n", (x
[9] << 8) | x
[8]);
556 printf(" Pixel Number of End of Left Bar: %d\n", (x
[11] << 8) | x
[10]);
557 printf(" Pixel Number of Start of Right Bar: %d\n", (x
[13] << 8) | x
[12]);
561 static const char *ACE_map
[] = {
562 "SMPTE ST 2113 P3D65 RGB",
563 "SMPTE ST 2113 P3DCI RGB",
564 "Rec. ITU-R BT.2100 ICtCp",
579 printf(" ACE: Additional Colorimetry Extension: %s\n", ACE_map
[x
[14] >> 4]);
582 printf(" FR: %d\n", x
[14] & 0xf);
583 fail("InfoFrame length is 14, but FR != 0.\n");
588 unsigned fr
= ((x
[15] & 0x40) >> 2) | (x
[14] >> 4);
590 printf(" RID/FR: %u/%u\n", rid
, fr
);
592 fail("Both a RID and a VIC were specified.\n");
598 fail("RID is set, but FR is 0.\n");
602 static const unsigned fr_rate_values
[] = {
604 0, 24, 24, 25, 30, 30, 48, 48,
606 50, 60, 60, 100, 120, 120, 144, 144,
608 200, 240, 240, 300, 360, 360, 400, 480,
612 static const bool fr_ntsc
[] = {
614 0, 1, 0, 0, 1, 0, 1, 0,
616 0, 1, 0, 0, 1, 0, 1, 0,
618 0, 1, 0, 0, 1, 0, 0, 1,
623 if (fr
>= ARRAY_SIZE(fr_rate_values
)) {
624 fail("Unknown FR %u.\n", fr
);
627 unsigned fps
= fr_rate_values
[fr
];
628 bool ntsc
= fr_ntsc
[fr
];
630 printf(" Frame Rate: %u%s\n", fps
, ntsc
? "/1.001" : "");
634 warn("VIC %u is %u fps, while FR indicates %u fps.\n",
642 const struct cta_rid
*crid
= find_rid(rid
);
645 fail("Unknown RID %u.\n", rid
);
649 unsigned char rid_vic
= rid_fps_to_vic(rid
, fps
);
651 sprintf(buf
, "VIC %3u", rid_vic
);
652 const struct timings
*t
= find_vic_id(rid_vic
);
653 print_timings(" ", t
, buf
);
654 warn("RID/FR %u/%u maps to VIC %d.\n", rid
, fr
, rid_vic
);
656 sprintf(buf
, "RID/FR %u/%u", rid
, fr
);
657 timings t
= calc_ovt_mode(crid
->hact
, crid
->vact
,
658 crid
->hratio
, crid
->vratio
, fps
);
659 print_timings("", &t
, buf
, "", false, false, ntsc
);
663 void edid_state::parse_if_spd(const unsigned char *x
, unsigned size
)
665 data_block
= "Source Product Description InfoFrame";
667 if (parse_if_hdr(x
, size
))
671 fail("Invalid version %d\n", x
[1]);
675 fail("Expected InfoFrame length of 25, got %d.\n", x
[2]);
679 // After this x[1] will refer to Data Byte 1
682 for (unsigned i
= 1; i
<= 24; i
++) {
684 fail("SPD contains ASCII character with bit 7 set.\n");
688 memcpy(vendor
, x
+ 1, 8);
689 printf(" Vendor Name: '%s'\n", vendor
);
690 unsigned len
= strlen(vendor
);
691 if (!memchk(x
+ 1 + len
, 8 - len
))
692 fail("Vendor name has trailing non-zero characters.\n");
694 char product
[17] = {};
695 memcpy(product
, x
+ 9, 16);
696 printf(" Product Description: '%s'\n", product
);
697 len
= strlen(product
);
698 if (!memchk(x
+ 9 + len
, 16 - len
))
699 fail("Product name has trailing non-zero characters.\n");
702 printf(" Source Information: %d (Reserved)\n", x
[25]);
703 fail("Source Information value %d is reserved.\n", x
[25]);
705 static const char *SI_map
[] = {
716 "Blu-Ray Disck (DB)",
721 printf(" Source Information: %s\n", SI_map
[x
[25]]);
725 void edid_state::parse_if_audio(const unsigned char *x
, unsigned size
)
727 data_block
= "Audio InfoFrame";
729 if (parse_if_hdr(x
, size
))
733 fail("Invalid version %d\n", x
[1]);
737 fail("Expected InfoFrame length of 10, got %d.\n", x
[2]);
741 // After this x[1] will refer to Data Byte 1
745 fail("Bit F13 is not 0.\n");
747 fail("Bits F27-F25 are not 0.\n");
749 fail("Bits F37-F35 are not 0.\n");
751 fail("Bit F52 is not 0.\n");
752 if (x
[4] <= 0x31 && !memchk(x
+ 6, 5))
753 fail("Bits F107-F60 are not 0.\n");
754 else if (x
[4] == 0xfe && (x
[10] || x
[9] || (x
[8] & 0xf8)))
755 fail("Bits F107-F90 and/or F87-F83 are not 0.\n");
756 else if (x
[4] == 0xff && x
[10])
757 fail("Bits F107-F100 are not 0.\n");
759 static const char *CT_map
[] = {
760 "Refer to Stream Header",
775 "Refer to Audio Coding Extension Type (CXT) Field"
777 printf(" CT: Audio Coding Type: %s\n", CT_map
[x
[1] >> 4]);
779 printf(" CC: Audio Channel Count: %d\n", (x
[1] & 7) + 1);
781 printf(" CC: Audio Channel Count: Refer to Stream Header\n");
783 static const char *SF_map
[] = {
784 "Refer to Stream Header",
793 printf(" SF: Sampling Frequency: %s\n", SF_map
[(x
[2] >> 2) & 7]);
795 static const char *SS_map
[] = {
796 "Refer to Stream Header",
801 printf(" SS: Bits/Sample: %s\n", SS_map
[x
[2] & 3]);
803 static const char *CXT_map
[] = {
804 "Refer to Audio Coding Type (CT) Field",
812 "MPEG-4 HE AAC + MPEG Surround",
814 "MPEG-4 AAC LC + MPEG Surround",
821 if ((x
[3] & 0x1f) < ARRAY_SIZE(CXT_map
))
822 printf(" CXT: Audio Coding Extension Type: %s\n", CXT_map
[x
[3] & 0x1f]);
824 printf(" CXT: Audio Coding Extension Type: Reserved (%d)\n", x
[3] & 0x1f);
825 if ((x
[3] & 0x1f) == 9 || (x
[3] & 0x1f) >= ARRAY_SIZE(CXT_map
))
826 fail("CXT: Reserved value.\n");
828 static const char *CA_map
[] = {
836 "BC, FC, LFE1, FR/FL",
838 "RS/LS, LFE1, FR/FL",
840 "RS/LS, FC, LFE1, FR/FL",
842 "BC, RS/LS, LFE1, FR/FL",
843 "BC, RS/LS, FC, FR/FL",
844 "BC, RS/LS, FC, LFE1, FR/FL",
845 "BR/BL, RS/LS, FR/FL",
846 "BR/BL, RS/LS, LFE1, FR/FL",
847 "BR/BL, RS/LS, FC, FR/FL",
848 "BR/BL, RS/LS, FC, LFE1, FR/FL",
850 "FRc/FLc, LFE1, FR/FL",
851 "FRc/FLc, FC, FR/FL",
852 "FRc/FLc, FC, LFE1, FR/FL",
853 "FRc/FLc, BC, FR/FL",
854 "FRc/FLc, BC, LFE1, FR/FL",
855 "FRc/FLc, BC, FC, FR/FL",
856 "FRc/FLc, BC, FC, LFE1, FR/FL",
857 "FRc/FLc, RS/LS, FR/FL",
858 "FRc/FLc, RS/LS, LFE1, FR/FL",
859 "FRc/FLc, RS/LS, FC, FR/FL",
860 "FRc/FLc, RS/LS, FC, LFE1, FR/FL",
861 "TpFC, RS/LS, FC, FR/FL",
862 "TpFC, RS/LS, FC, LFE1, FR/FL",
863 "TpC, RS/LS, FC, FR/FL",
864 "TpC, RS/LS, FC, LFE1, FR/FL",
865 "TpFR/TpFL, RS/LS, FR/FL",
866 "TpFR/TpFL, RS/LS, LFE1, FR/FL",
867 "FRw/FLw, RS/LS, FR/FL",
868 "FRw/FLw, RS/LS, LFE1, FR/FL",
869 "TpC, BC, RS/LS, FC, FR/FL",
870 "TpC, BC, RS/LS, FC, LFE1, FR/FL",
871 "TpFC, BC, RS/LS, FC, FR/FL",
872 "TpFC, BC, RS/LS, FC, FR/FL",
873 "TpC, TpFC, RS/LS, FC, FR/FL",
874 "TpC, TpFC, RS/LS, FC, FR/FL",
875 "TpFR/TpFL, RS/LS, FC, FR/FL",
876 "TpFR/TpFL, RS/LS, FC, FR/FL",
877 "FRw/FLw, RS/LS, FC, FR/FL",
878 "FRw/FLw, RS/LS, FC, FR/FL"
880 if (x
[4] < ARRAY_SIZE(CA_map
))
881 printf(" CA: Channel Allocation: %s\n", CA_map
[x
[4]]);
882 else if (x
[4] < 0xfe) {
883 printf(" CA: Channel Allocation: Reserved (%d, 0x%02x)\n", x
[4], x
[4]);
884 fail("CA: Reserved value.\n");
886 else if (x
[4] == 0xfe)
887 printf(" CA: Channel Allocation: According to the Speaker Mask\n");
889 printf(" CA: Channel Allocation: According to Channel Index\n");
890 printf(" LSV: Level Shift Value: %d dB\n", (x
[5] >> 3) & 0xf);
891 printf(" DM_INH: Allow the Down Mixed Stereo Output: %s\n",
892 (x
[5] & 0x80) ? "Prohibited" : "Yes");
894 static const char *LFEPBL_map
[] = {
895 "Unknown or refer to other information",
900 printf(" LFEPBL: LFE Playback Level compared to other channels: %s\n", LFEPBL_map
[x
[5] & 3]);
902 fail("LFEPBL: Reserved value.\n");
909 warn("F66 is not 0, the use of this bit is deprecated.\n");
911 warn("F83 is not 0, the use of this bit is deprecated.\n");
912 printf(" SPM: Speaker Mask:\n");
914 unsigned spm
= (x
[8] << 16) | (x
[7] << 8) | x
[6];
916 for (unsigned i
= 0; cta_speaker_map
[i
]; i
++) {
918 printf(" %s\n", cta_speaker_map
[i
]);
924 printf(" CID: Channel Index: ");
926 unsigned cid
= (x
[9] << 24) | (x
[8] << 16) | (x
[7] << 8) | x
[6];
929 for (unsigned i
= 0; i
< 32; i
++) {
930 if ((cid
>> i
) & 1) {
940 void edid_state::parse_if_mpeg_source(const unsigned char *x
, unsigned size
)
942 data_block
= "MPEG Source InfoFrame";
944 warn("The use of the %s is not recommended.\n", data_block
.c_str());
946 if (parse_if_hdr(x
, size
))
950 fail("Invalid version %d\n", x
[1]);
954 fail("Expected InfoFrame length of 10, got %d.\n", x
[2]);
958 // After this x[1] will refer to Data Byte 1
961 unsigned mb
= (x
[4] << 24) | (x
[3] << 16) | (x
[2] << 8) | x
[1];
964 printf(" MB: MPEG Bit Rate: %u Hz\n", mb
);
966 printf(" MB: MPEG Bit Rate: Unknown/Does Not Apply\n");
968 static const char *MF_map
[] = {
974 printf(" MF: MPEG Frame: %s\n", MF_map
[x
[5] & 3]);
975 printf(" FR: Field Repeat: %s\n", (x
[5] & 0x10) ? "Repeated Field" : "New Field (Picture)");
977 fail("Bits F57-F55 and/or F53-F52 are not 0.\n");
978 if (x
[6] || x
[7] || x
[8] || x
[9] || x
[10])
979 fail("Bits F100-F60 are not 0.\n");
982 void edid_state::parse_if_ntsc_vbi(const unsigned char *x
, unsigned size
)
984 data_block
= "NTSC VBI InfoFrame";
986 if (parse_if_hdr(x
, size
))
992 fail("Invalid version %d\n", x
[1]);
996 // After this x[1] will refer to Data Byte 1
999 // See SCTE 127, Table 2 for more details
1000 hex_block(" PES_data_field: ", x
+ 1, len
, false, len
);
1003 void edid_state::parse_if_drm(const unsigned char *x
, unsigned size
)
1005 unsigned length
= x
[2];
1007 data_block
= "Dynamic Range and Mastering InfoFrame";
1009 if (parse_if_hdr(x
, size
))
1013 fail("Invalid version %d\n", x
[1]);
1017 // After this x[1] will refer to Data Byte 1
1021 fail("Bits F17-F13 are not 0.\n");
1023 static const char *TF_map
[] = {
1024 "Traditional Gamma - SDR Luminance Range",
1025 "Traditional Gamma - HDR Luminance Range",
1026 "Perceptual Quantization (PQ) based on SMPTE ST 2084",
1027 "Hybrid Log-Gamma (HLG) based on Rec. ITU-R BT.2100",
1033 printf("Transfer Function: %s\n",
1039 fail("Bits F27-F23 are not 0.\n");
1041 printf("Static Metadata Descriptor ID: Reserved (%d)\n", x
[2] & 7);
1042 if (!memchk(x
+ 3, length
- 2))
1043 fail("Trailing non-zero bytes.\n");
1046 printf("Static Metadata Descriptor ID: Type 1\n");
1048 fail("Expected a length of 26, got %d.\n", length
);
1051 if (!memchk(x
+ 3, 12)) {
1052 printf(" Display Primary 0: (%.5f, %.5f)\n", chrom2d(x
+ 3), chrom2d(x
+ 5));
1053 printf(" Display Primary 1: (%.5f, %.5f)\n", chrom2d(x
+ 7), chrom2d(x
+ 7));
1054 printf(" Display Primary 2: (%.5f, %.5f)\n", chrom2d(x
+ 11), chrom2d(x
+ 13));
1056 if (!memchk(x
+ 15, 4)) {
1057 printf(" White Point: (%.5f, %.5f)\n", chrom2d(x
+ 15), chrom2d(x
+ 17));
1059 if (!memchk(x
+ 19, 2)) {
1060 printf(" Max Display Mastering Luminance: %u cd/m^2\n",
1061 x
[19] + (x
[20] << 8));
1063 if (!memchk(x
+ 21, 2)) {
1064 printf(" Min Display Mastering Luminance: %f cd/m^2\n",
1065 (x
[21] + (x
[22] << 8)) * 0.0001);
1067 if (!memchk(x
+ 23, 2)) {
1068 printf(" Maximum Content Light Level (MaxCLL): %u cd/m^2\n",
1069 x
[23] + (x
[24] << 8));
1071 if (!memchk(x
+ 25, 2)) {
1072 printf(" Maximum Frame-Average Light Level (MaxFALL): %u cd/m^2\n",
1073 x
[25] + (x
[26] << 8));