25 #define LOC QString("EDID: ")
28 : m_data(std::move(Data))
34 : m_data(Data, Length)
119 return { 0, 0,
false };
125 QByteArray buffer(
reinterpret_cast<const char *
>(data), 13);
128 buffer = buffer.replace(
'\r',
'\0').replace(
'\n',
'\0');
135 for (
auto && i : buffer) {
136 if (i < '\040' || i >
'\176')
140 return QString::fromLatin1(buffer.trimmed());
148 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Invalid EDID");
153 const auto *data =
reinterpret_cast<const quint8 *
>(
m_data.constData());
156 if ((
m_size % 0x80) || data[0] != 0x00 || data[1] != 0xff)
158 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Invalid EDID");
164 if (
auto sum = std::accumulate(
m_data.cbegin(),
m_data.cend(), 0, std::plus<char>()); (sum % 0xff) != 0)
166 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Checksum error");
176 if (extensions != available)
178 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Extension count error");
185 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"EDID has %1 extension blocks").arg(extensions));
186 for (
uint i = 1; i <= available; ++i)
188 uint offset = i * 128;
189 switch (data[offset])
202 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Unknown major version number");
241 m_gamma = (gamma + 100.0F) / 100.0F;
249 static constexpr std::array<const uint8_t,10> s_sRGB =
250 { 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54 };
251 bool srgb = std::equal(s_sRGB.cbegin(), s_sRGB.cend(), Data + 0x19);
256 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Chromaticity mismatch!");
274 qFuzzyCompare(
m_gamma + 1.0F, 2.20F + 1.0F);
277 for (
size_t i = 0; i < 4; ++i)
280 if (Data[offset] == 0 || Data[offset + 1] == 0 || Data[offset + 2] == 0)
288 [](
const QString& Serial) { return !Serial.isEmpty(); });
290 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"No serial number(s) in EDID");
296 auto type = Data[Offset + 3];
297 auto offset = Offset + 5;
313 if (Data[Offset + 4] & 0x02)
316 if (Data[Offset + 4] & 0x01)
328 auto width = Data[Offset + 12] + ((Data[Offset + 14] & 0xF0) << 4);
329 auto height = Data[Offset + 13] + ((Data[Offset + 14] & 0x0F) << 8);
346 quint8
version = Data[Offset + 1];
347 quint8 offset = Data[Offset + 2];
349 if (offset < 4 ||
version != 3)
352 for (
uint i = Offset + 4; (i < (Offset + offset)) && (i <
m_size); i += (Data[i] & 0x1F) + 1)
359 uint length = Data[Offset] & 0x1F;
360 uint type = (Data[Offset] & 0xE0) >> 5;
365 case 0x03:
ParseVSDB(Data, Offset + 1, length);
break;
380 int registration = Data[Offset] + (Data[Offset + 1] << 8) + (Data[Offset + 2] << 16);
383 while (registration == 0x000C03)
387 if (Length < 5 || (Offset + 5 >=
m_size))
393 if (Length < 6 || (Offset + 6 >=
m_size))
399 if (Length < 8 || (Offset + 8 >=
m_size))
406 if (Length < 10 || (Offset + 10 >=
m_size))
410 quint8 video = Data[Offset + 8];
411 if (video > 0 && video <= 251)
413 quint8 audio = Data[Offset + 9];
414 if (audio > 0 && audio <= 251)
418 if (Length < 12 || (Offset + 12 >=
m_size))
423 quint8 video = Data[Offset + 10];
424 if (video > 0 && video <= 251)
426 quint8 audio = Data[Offset + 11];
427 if (audio > 0 && audio <= 251)
435 while (registration == 0xC45DD8)
437 if (Length < 5 || (Offset + 5 >=
m_size))
443 if (Length < 11 || (Offset + 11 >=
m_size))
448 m_vrrMax = ((Data[Offset + 9] & 0xc0) << 2) | Data[Offset + 10];
461 if (Data[Offset] == 0x06 && Length)
463 if (Length >= 3 && (Offset + 3 <
m_size))
465 int hdrsupport = Data[Offset + 1] & 0x3f;
466 if (hdrsupport &
HDR10)
468 if (hdrsupport &
HLG)
480 m_minLuminance = (50.0 * pow(2, Data[Offset + 3] / 32.0)) * pow(Data[Offset + 5] / 255.0, 2) / 100.0;
487 auto deep = [](uint8_t Deep)
490 if (Deep & 0x08) res <<
"Y444";
491 if (Deep & 0x10) res <<
"30bit";
492 if (Deep & 0x20) res <<
"36bit";
493 if (Deep & 0x40) res <<
"48bit";
494 return res.join(
",");
497 auto deepyuv = [](uint8_t Deep)
500 if (Deep & 0x01) res <<
"10bit";
501 if (Deep & 0x02) res <<
"12bit";
502 if (Deep & 0x04) res <<
"16bit";
503 return res.join(
",");
508 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Invalid EDID");
512 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Version:1.%1 Size:%2 Exensions:%3")
514 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Gamma:%1 sRGB:%2")
516 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Display chromaticity:-");
517 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Red:\t%1,\t%2")
520 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Green:\t%1,\t%2")
523 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Blue:\t%1,\t%2")
526 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"White:\t%1,\t%2")
534 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Physical address: %1").arg(address));
536 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Deep color: %1").arg(deep(
m_deepColor)));
539 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Latencies: Audio:%1 Video:%2")
543 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Latencies: Audio:%1 Video:%2 (Interlaced)")
548 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Deep YUV 4:2:0 %1").arg(deepyuv(
m_deepYUV)));
555 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Desired luminance: Min: %1 Max: %2 Avg: %3")