aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2021-11-07 15:47:42 +0100
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2021-11-07 15:47:42 +0100
commit81c6bf96cb68df7ec6994d5f9a8331636f509d50 (patch)
tree60ecf762c8a92f64444a0da473d55eb6abadad6e
parent67ed12e3ccafd9e125a5eec9349043b523895dc3 (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.h7
-rw-r--r--parse-base-block.cpp19
-rw-r--r--parse-displayid-block.cpp40
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);
}

Privacy Policy