diff options
author | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2021-11-07 15:47:42 +0100 |
---|---|---|
committer | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2021-11-07 15:47:42 +0100 |
commit | 81c6bf96cb68df7ec6994d5f9a8331636f509d50 (patch) | |
tree | 60ecf762c8a92f64444a0da473d55eb6abadad6e | |
parent | 67ed12e3ccafd9e125a5eec9349043b523895dc3 (diff) |
edid-decode: improve image size checks
Carefully check if the image sizes in the base and DisplayID blocks
are consistent.
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r-- | edid-decode.h | 7 | ||||
-rw-r--r-- | parse-base-block.cpp | 19 | ||||
-rw-r--r-- | parse-displayid-block.cpp | 40 |
3 files changed, 52 insertions, 14 deletions
diff --git a/edid-decode.h b/edid-decode.h index 87cf662..67e681a 100644 --- a/edid-decode.h +++ b/edid-decode.h @@ -130,6 +130,7 @@ struct edid_state { warnings = failures = 0; has_cta = has_dispid = false; hide_serial_numbers = false; + image_width = image_height = 0; // Base block state base.edid_minor = 0; @@ -178,6 +179,7 @@ struct edid_state { dispid.has_display_parameters = dispid.has_type_1_7 = dispid.has_display_interface_features = false; dispid.block_number = 0; + dispid.image_width = dispid.image_height = 0; // Block Map block state block_map.saw_block_1 = false; @@ -202,6 +204,9 @@ struct edid_state { unsigned dtd_max_hsize_mm; unsigned dtd_max_vsize_mm; + // in 0.1 mm units + unsigned image_width, image_height; + unsigned warnings; unsigned failures; @@ -285,6 +290,8 @@ struct edid_state { bool has_display_interface_features; vec_timings_ext preferred_timings; unsigned native_width, native_height; + // in 0.1 mm units + unsigned image_width, image_height; unsigned block_number; // Keep track of the found CTA-861 Tag/Extended Tag pairs. // The unsigned value is equal to: (tag) | (OUI enum << 12) or (extended tag) | (tag << 8) | (OUI enum << 12) diff --git a/parse-base-block.cpp b/parse-base-block.cpp index 9e2ef4f..048308b 100644 --- a/parse-base-block.cpp +++ b/parse-base-block.cpp @@ -1442,6 +1442,8 @@ void edid_state::parse_base_block(const unsigned char *x) printf(" Maximum image size: %u cm x %u cm\n", x[0x15], x[0x16]); base.max_display_width_mm = x[0x15] * 10; base.max_display_height_mm = x[0x16] * 10; + image_width = base.max_display_width_mm * 10; + image_height = base.max_display_height_mm * 10; if (x[0x15] < 10 || x[0x16] < 10) warn("Dubious maximum image size (%ux%u is smaller than 10x10 cm).\n", x[0x15], x[0x16]); @@ -1701,13 +1703,16 @@ void edid_state::check_base_block() */ msg(!out_of_range || base.edid_minor >= 4, "%s", err.c_str()); } - // The base block will only go up to 255x255 cm for the display size, - // so don't fail if one or more image sizes exceeds that. - if (!base.max_display_width_mm && !base.max_display_height_mm && - dtd_max_hsize_mm && dtd_max_vsize_mm && - dtd_max_hsize_mm <= 2559 && dtd_max_vsize_mm <= 2559) { - fail("The DTD image sizes all fit inside 255x255cm, but no display size was set.\n"); - } + + if ((image_width && dtd_max_hsize_mm >= 10 + image_width / 10) || + (image_height && dtd_max_vsize_mm >= 10 + image_height / 10)) + fail("The DTD max image size is %ux%umm, which is larger than the display size %.1fx%.1fmm.\n", + dtd_max_hsize_mm, dtd_max_vsize_mm, + image_width / 10.0, image_height / 10.0); + if ((!image_width && dtd_max_hsize_mm) || (!image_height && dtd_max_vsize_mm)) + fail("The DTD max image size is %ux%umm, but the display size is not specified anywhere.\n", + dtd_max_hsize_mm, dtd_max_vsize_mm); + // Secondary GTF curves start at a specific frequency. Any legacy timings // that have a positive hsync and negative vsync must be less than that // frequency to avoid confusion. diff --git a/parse-displayid-block.cpp b/parse-displayid-block.cpp index ad5099f..0f39830 100644 --- a/parse-displayid-block.cpp +++ b/parse-displayid-block.cpp @@ -157,10 +157,18 @@ void edid_state::parse_displayid_parameters(const unsigned char *x) if (!check_displayid_datablock_length(x, 12, 12)) return; + if (dispid.has_display_parameters) + fail("Duplicate Display Parameters Data Block.\n"); dispid.has_display_parameters = true; + dispid.image_width = (x[4] << 8) + x[3]; + dispid.image_height = (x[6] << 8) + x[5]; + if (dispid.image_width > image_width || + dispid.image_height > image_height) { + image_width = dispid.image_width; + image_height = dispid.image_height; + } printf(" Image size: %.1f mm x %.1f mm\n", - ((x[4] << 8) + x[3]) / 10.0, - ((x[6] << 8) + x[5]) / 10.0); + dispid.image_width / 10.0, dispid.image_height / 10.0); unsigned w = (x[8] << 8) + x[7]; unsigned h = (x[10] << 8) + x[9]; printf(" Display native pixel format: %ux%u\n", w, h); @@ -1130,17 +1138,29 @@ void edid_state::parse_displayid_parameters_v2(const unsigned char *x, { if (!check_displayid_datablock_length(x, 29, 29)) return; + if (dispid.has_display_parameters) + fail("Duplicate Display Parameters Data Block.\n"); + dispid.has_display_parameters = true; unsigned hor_size = (x[4] << 8) + x[3]; unsigned vert_size = (x[6] << 8) + x[5]; - dispid.has_display_parameters = true; - if (x[1] & 0x80) - printf(" Image size: %u mm x %u mm\n", - hor_size, vert_size); - else + dispid.image_width = hor_size; + dispid.image_height = vert_size; + if (x[1] & 0x80) { + printf(" Image size: %u mm x %u mm\n", hor_size, vert_size); + dispid.image_width *= 10; + dispid.image_height *= 10; + } else { printf(" Image size: %.1f mm x %.1f mm\n", hor_size / 10.0, vert_size / 10.0); + } + if (dispid.image_width > image_width || + dispid.image_height > image_height) { + image_width = dispid.image_width; + image_height = dispid.image_height; + } + unsigned w = (x[8] << 8) + x[7]; unsigned h = (x[10] << 8) + x[9]; @@ -1980,4 +2000,10 @@ void edid_state::check_displayid_blocks() dispid.version >= 0x20 ? "VII" : "I"); if (dispid.preferred_timings.empty()) fail("DisplayID expects at least one preferred timing.\n"); + if (dispid.image_width && dispid.image_width < 25600 && dispid.image_height < 25600 && + (abs((int)dispid.image_width - (int)base.max_display_width_mm * 10) >= 100 || + abs((int)dispid.image_height - (int)base.max_display_height_mm * 10) >= 100)) + fail("Image size mismatch: DisplayID: %.1fx%.1fmm Base EDID: %u.0x%u.0mm.\n", + dispid.image_width / 10.0, dispid.image_height / 10.0, + base.max_display_width_mm, base.max_display_height_mm); } |