MythTV master
mythedid.cpp
Go to the documentation of this file.
1// MythTV
3#include "mythedid.h"
4
5// Qt
6#include <QObject>
7
8// Std
9#include <cmath>
10
11//static constexpr uint8_t DESCRIPTOR_ALPHANUMERIC_STRING { 0xFE };
12static constexpr uint8_t DESCRIPTOR_PRODUCT_NAME { 0xFC };
13static constexpr uint8_t DESCRIPTOR_RANGE_LIMITS { 0xFD };
14static constexpr uint8_t DESCRIPTOR_SERIAL_NUMBER { 0xFF };
15static constexpr size_t DATA_BLOCK_OFFSET { 0x36 };
16static constexpr size_t SERIAL_OFFSET { 0x0C };
17static constexpr size_t VERSION_OFFSET { 0x12 };
18//static constexpr size_t DISPLAY_OFFSET { 0x14 };
19static constexpr size_t WIDTH_OFFSET { 0x15 };
20static constexpr size_t HEIGHT_OFFSET { 0x16 };
21static constexpr size_t GAMMA_OFFSET { 0x17 };
22static constexpr size_t FEATURES_OFFSET { 0x18 };
23static constexpr size_t EXTENSIONS_OFFSET { 0x7E };
24
25#define LOC QString("EDID: ")
26
27MythEDID::MythEDID(QByteArray Data)
28 : m_data(std::move(Data))
29{
30 Parse();
31}
32
33MythEDID::MythEDID(const char* Data, int Length)
34 : m_data(Data, Length)
35{
36 Parse();
37}
38
39bool MythEDID::Valid() const
40{
41 return m_valid;
42}
43
44QStringList MythEDID::SerialNumbers() const
45{
46 return m_serialNumbers;
47}
48
50{
51 return m_displaySize;
52}
53
55{
56 return m_displayAspect;
57}
58
60{
61 return m_physicalAddress;
62}
63
64float MythEDID::Gamma() const
65{
66 return m_gamma;
67}
68
69bool MythEDID::IsHDMI() const
70{
71 return m_isHDMI;
72}
73
74bool MythEDID::IsSRGB() const
75{
76 return m_sRGB;
77}
78
80{
81 return m_likeSRGB;
82}
83
85{
86 return m_primaries;
87}
88
89int MythEDID::AudioLatency(bool Interlaced) const
90{
91 return m_audioLatency[Interlaced ? 1 : 0];
92}
93
94int MythEDID::VideoLatency(bool Interlaced) const
95{
96 return m_videoLatency[Interlaced ? 1 : 0];
97}
98
100{
102}
103
114{
115 if (m_valid && m_vrrMin && m_vrrMax)
116 return { m_vrrMin, m_vrrMax, true };
118 return { m_vrangeMin, m_vrangeMax, false };
119 return { 0, 0, false };
120}
121
122// from QEdidParser
123static QString ParseEdidString(const quint8* data, bool Replace)
124{
125 QByteArray buffer(reinterpret_cast<const char *>(data), 13);
126
127 // Erase carriage return and line feed
128 buffer = buffer.replace('\r', '\0').replace('\n', '\0');
129
130 // Replace non-printable characters with dash
131 // Earlier versions of QEdidParser got this wrong - so we potentially get
132 // different values for serialNumber from QScreen
133 if (Replace)
134 {
135 for (auto && i : buffer) {
136 if (i < '\040' || i > '\176')
137 i = '-';
138 }
139 }
140 return QString::fromLatin1(buffer.trimmed());
141}
142
144{
145 // This is adapted from various sources including QEdidParser, edid-decode and xrandr
146 if (!m_data.constData() || m_data.isEmpty())
147 {
148 LOG(VB_GENERAL, LOG_DEBUG, LOC + "Invalid EDID");
149 return;
150 }
151
152 m_size = static_cast<uint>(m_data.size());
153 const auto *data = reinterpret_cast<const quint8 *>(m_data.constData());
154
155 // EDID data should be in 128 byte blocks
156 if ((m_size % 0x80) || data[0] != 0x00 || data[1] != 0xff)
157 {
158 LOG(VB_GENERAL, LOG_DEBUG, LOC + "Invalid EDID");
159 return;
160 }
161
162 // checksum
163 // NOLINTNEXTLINE(modernize-use-transparent-functors)
164 if (auto sum = std::accumulate(m_data.cbegin(), m_data.cend(), 0, std::plus<char>()); (sum % 0xff) != 0)
165 {
166 LOG(VB_GENERAL, LOG_INFO, LOC + "Checksum error");
167 return;
168 }
169
170 if (!ParseBaseBlock(data))
171 return;
172
173 // Look at extension blocks
174 uint extensions = data[EXTENSIONS_OFFSET];
175 uint available = (m_size / 128) - 1;
176 if (extensions != available)
177 {
178 LOG(VB_GENERAL, LOG_WARNING, LOC + "Extension count error");
179 return;
180 }
181
182 if (extensions < 1)
183 return;
184
185 LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("EDID has %1 extension blocks").arg(extensions));
186 for (uint i = 1; i <= available; ++i)
187 {
188 uint offset = i * 128;
189 switch (data[offset])
190 {
191 case 0x02: m_valid &= ParseCTA861(data, offset); break;
192 default: continue;
193 }
194 }
195}
196
197bool MythEDID::ParseBaseBlock(const quint8* Data)
198{
199 // retrieve version
200 if (Data[VERSION_OFFSET] != 1)
201 {
202 LOG(VB_GENERAL, LOG_DEBUG, LOC + "Unknown major version number");
203 return false;
204 }
205 m_minorVersion = Data[VERSION_OFFSET + 1];
206
207 // retrieve serial number. This may be subsequently overridden.
208 // N.B. 0 is a valid serial number.
209 qint32 serial = Data[SERIAL_OFFSET] +
210 (Data[SERIAL_OFFSET + 1] << 8) +
211 (Data[SERIAL_OFFSET + 2] << 16) +
212 (Data[SERIAL_OFFSET + 3] << 24);
213 m_serialNumbers << QString::number(serial);
214
215 // digital or analog
216 //bool digital = Data[DISPLAY_OFFSET] & 0x80;
217
218 // Display size
219 if (Data[WIDTH_OFFSET] && Data[HEIGHT_OFFSET])
220 {
221 m_displaySize = QSize(Data[WIDTH_OFFSET] * 10, Data[HEIGHT_OFFSET] * 10);
222 }
223 else if (m_minorVersion >= 4 && (Data[WIDTH_OFFSET] || Data[HEIGHT_OFFSET]))
224 {
225 if (Data[WIDTH_OFFSET])
226 m_displayAspect = 100.0 / (Data[HEIGHT_OFFSET] + 99); // Landscape
227 else
228 m_displayAspect = 100.0 / (Data[WIDTH_OFFSET] + 99); // Portrait
229 }
230
231 // retrieve gamma
232 quint8 gamma = Data[GAMMA_OFFSET];
233 if (gamma == 0xFF)
234 {
235 // for 1.4 - this means gamma is defined in an extension block
236 if (m_minorVersion < 4)
237 m_gamma = 1.0F;
238 }
239 else
240 {
241 m_gamma = (gamma + 100.0F) / 100.0F;
242 }
243
244 // Chromaticity
245 // Note - the EDID format introduces slight rounding errors when converting
246 // to sRGB specs. If sRGB is set, the client should use the spec values - not
247 // the computed values
248 m_sRGB = ((Data[FEATURES_OFFSET] & 0x04) != 0);
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);
252
253 if (!m_sRGB && srgb)
254 m_sRGB = true;
255 else if (m_sRGB && !srgb)
256 LOG(VB_GENERAL, LOG_WARNING, LOC + "Chromaticity mismatch!");
257
258 // Red
259 m_primaries.m_primaries[0][0] = ((Data[0x1B] << 2) | (Data[0x19] >> 6)) / 1024.0F;
260 m_primaries.m_primaries[0][1] = ((Data[0x1C] << 2) | ((Data[0x19] >> 4) & 3)) / 1024.0F;
261 // Green
262 m_primaries.m_primaries[1][0] = ((Data[0x1D] << 2) | ((Data[0x19] >> 2) & 3)) / 1024.0F;
263 m_primaries.m_primaries[1][1] = ((Data[0x1E] << 2) | (Data[0x19] & 3)) / 1024.0F;
264 // Blue
265 m_primaries.m_primaries[2][0] = ((Data[0x1F] << 2) | (Data[0x1A] >> 6)) / 1024.0F;
266 m_primaries.m_primaries[2][1] = ((Data[0x20] << 2) | ((Data[0x1A] >> 4) & 3)) / 1024.0F;
267 // White
268 m_primaries.m_whitePoint[0] = ((Data[0x21] << 2) | ((Data[0x1A] >> 2) & 3)) / 1024.0F;
269 m_primaries.m_whitePoint[1] = ((Data[0x22] << 2) | (Data[0x1A] & 3)) / 1024.0F;
270
271 // Check whether this is very similar to sRGB and hence if non-exact colourspace
272 // handling is preferred, then just use sRGB.
274 qFuzzyCompare(m_gamma + 1.0F, 2.20F + 1.0F);
275
276 // Parse blocks
277 for (size_t i = 0; i < 4; ++i)
278 {
279 size_t offset = DATA_BLOCK_OFFSET + (i * 18);
280 if (Data[offset] == 0 || Data[offset + 1] == 0 || Data[offset + 2] == 0)
281 ParseDisplayDescriptor(Data, offset);
282 else
283 ParseDetailedTimingDescriptor(Data, offset);
284 }
285
286 // Set status
287 m_valid = std::any_of(m_serialNumbers.cbegin(), m_serialNumbers.cend(),
288 [](const QString& Serial) { return !Serial.isEmpty(); });
289 if (!m_valid)
290 LOG(VB_GENERAL, LOG_WARNING, LOC + "No serial number(s) in EDID");
291 return m_valid;
292}
293
294void MythEDID::ParseDisplayDescriptor(const quint8* Data, uint Offset)
295{
296 auto type = Data[Offset + 3];
297 auto offset = Offset + 5;
299 {
300 m_serialNumbers << ParseEdidString(&Data[offset], false);
301 m_serialNumbers << ParseEdidString(&Data[offset], true);
302 }
303 else if (DESCRIPTOR_PRODUCT_NAME == type)
304 {
305 m_name = ParseEdidString(&Data[offset], true);
306 }
307 else if (DESCRIPTOR_RANGE_LIMITS == type)
308 {
309 auto vminoffset = 0;
310 auto vmaxoffset = 0;
311 if (m_minorVersion > 3)
312 {
313 if (Data[Offset + 4] & 0x02)
314 {
315 vmaxoffset = 255;
316 if (Data[Offset + 4] & 0x01)
317 vminoffset = 255;
318 }
319 }
320 m_vrangeMin = Data[Offset + 5] + vminoffset;
321 m_vrangeMax = Data[Offset + 6] + vmaxoffset;
322 }
323}
324
325void MythEDID::ParseDetailedTimingDescriptor(const quint8* Data, size_t Offset)
326{
327 // We're only really interested in a more accurate display size
328 auto width = Data[Offset + 12] + ((Data[Offset + 14] & 0xF0) << 4);
329 auto height = Data[Offset + 13] + ((Data[Offset + 14] & 0x0F) << 8);
330
331 // 1.4 may have set an aspect ratio instead of size, otherwise use if this
332 // looks like a more accurate version of our current size
333 if (m_displaySize.isEmpty() ||
334 ((abs(m_displaySize.width() - width) < 10) && (abs(m_displaySize.height() - height) < 10)))
335 {
336 m_displaySize = { width, height };
337 }
338}
339
340bool MythEDID::ParseCTA861(const quint8* Data, size_t Offset)
341{
342 if (Offset >= m_size)
343 return false;
344
345 bool result = true;
346 quint8 version = Data[Offset + 1];
347 quint8 offset = Data[Offset + 2];
348
349 if (offset < 4 || version != 3)
350 return result;
351
352 for (uint i = Offset + 4; (i < (Offset + offset)) && (i < m_size); i += (Data[i] & 0x1F) + 1)
353 result &= ParseCTABlock(Data, i);
354 return result;
355}
356
357bool MythEDID::ParseCTABlock(const quint8* Data, size_t Offset)
358{
359 uint length = Data[Offset] & 0x1F;
360 uint type = (Data[Offset] & 0xE0) >> 5;
361 switch (type)
362 {
363 case 0x01: break; // Audio data block // NOLINT(bugprone-branch-clone)
364 case 0x02: break; // Video data block
365 case 0x03: ParseVSDB(Data, Offset + 1, length); break; // Vendor Specific Data Block
366 case 0x04: break; // Speaker Allocation data block // NOLINT(bugprone-branch-clone)
367 case 0x05: break; // VESA DTC data block
368 case 0x07: ParseExtended(Data, Offset + 1, length); break; // Extended tag. HDR metadata here
369 default: break;
370 }
371 return true;
372}
373
374bool MythEDID::ParseVSDB(const quint8* Data, size_t Offset, size_t Length)
375{
376 if (Offset + 3 >= m_size)
377 return false;
378
379 // N.B. Little endian
380 int registration = Data[Offset] + (Data[Offset + 1] << 8) + (Data[Offset + 2] << 16);
381
382 // "HDMI Licensing, LLC"
383 while (registration == 0x000C03)
384 {
385 m_isHDMI = true;
386
387 if (Length < 5 || (Offset + 5 >= m_size))
388 break;
389
390 // CEC physical address
391 m_physicalAddress = static_cast<uint16_t>((Data[Offset + 3] << 8) + Data[Offset + 4]);
392
393 if (Length < 6 || (Offset + 6 >= m_size))
394 break;
395
396 // Deep color
397 m_deepColor = Data[Offset + 5] & 0x78;
398
399 if (Length < 8 || (Offset + 8 >= m_size))
400 break;
401
402 // Audio and video latencies
403 m_latencies = ((Data[Offset + 7] & 0x80) != 0);
404 m_interLatencies = ((Data[Offset + 7] & 0x40) != 0) && m_latencies;
405
406 if (Length < 10 || (Offset + 10 >= m_size))
407 break;
408 if (m_latencies)
409 {
410 quint8 video = Data[Offset + 8];
411 if (video > 0 && video <= 251)
412 m_videoLatency[0] = (video - 1) << 1;
413 quint8 audio = Data[Offset + 9];
414 if (audio > 0 && audio <= 251)
415 m_audioLatency[0] = (audio - 1) << 1;
416 }
417
418 if (Length < 12 || (Offset + 12 >= m_size))
419 break;
420
422 {
423 quint8 video = Data[Offset + 10];
424 if (video > 0 && video <= 251)
425 m_videoLatency[1] = (video - 1) << 1;
426 quint8 audio = Data[Offset + 11];
427 if (audio > 0 && audio <= 251)
428 m_audioLatency[1] = (audio - 1) << 1;
429 }
430
431 break;
432 }
433
434 // "HDMI Forum"
435 while (registration == 0xC45DD8)
436 {
437 if (Length < 5 || (Offset + 5 >= m_size))
438 break;
439
440 // Deep Color 4:2:0
441 m_deepYUV = Data[Offset + 4] & 0x7;
442
443 if (Length < 11 || (Offset + 11 >= m_size))
444 break;
445
446 // Variable Refresh Rate
447 m_vrrMin = Data[Offset + 9] & 0x3f;
448 m_vrrMax = ((Data[Offset + 9] & 0xc0) << 2) | Data[Offset + 10];
449 break;
450 }
451
452 return true;
453}
454
455bool MythEDID::ParseExtended(const quint8* Data, size_t Offset, size_t Length)
456{
457 if (Offset + 1 >= m_size)
458 return false;
459
460 // HDR Static Metadata Data Block
461 if (Data[Offset] == 0x06 && Length)
462 {
463 if (Length >= 3 && (Offset + 3 < m_size))
464 {
465 int hdrsupport = Data[Offset + 1] & 0x3f;
466 if (hdrsupport & HDR10)
468 if (hdrsupport & HLG)
470 m_hdrMetaTypes = Data[Offset + 2] & 0xff;
471 }
472
473 if (Length >= 4)
474 m_maxLuminance = 50.0 * pow(2, Data[Offset + 3] / 32.0);
475
476 if (Length >= 5)
477 m_maxAvgLuminance = 50.0 * pow(2, Data[Offset + 4] / 32.0);
478
479 if (Length >= 6)
480 m_minLuminance = (50.0 * pow(2, Data[Offset + 3] / 32.0)) * pow(Data[Offset + 5] / 255.0, 2) / 100.0;
481 }
482 return true;
483}
484
485void MythEDID::Debug() const
486{
487 auto deep = [](uint8_t Deep)
488 {
489 QStringList res;
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(",");
495 };
496
497 auto deepyuv = [](uint8_t Deep)
498 {
499 QStringList res;
500 if (Deep & 0x01) res << "10bit";
501 if (Deep & 0x02) res << "12bit";
502 if (Deep & 0x04) res << "16bit";
503 return res.join(",");
504 };
505
506 if (!m_valid)
507 {
508 LOG(VB_GENERAL, LOG_INFO, LOC + "Invalid EDID");
509 return;
510 }
511
512 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Version:1.%1 Size:%2 Exensions:%3")
513 .arg(m_minorVersion).arg(m_size).arg((m_size / 128) - 1));
514 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Gamma:%1 sRGB:%2")
515 .arg(static_cast<double>(m_gamma)).arg(m_sRGB));
516 LOG(VB_GENERAL, LOG_INFO, LOC + "Display chromaticity:-");
517 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Red:\t%1,\t%2")
518 .arg(static_cast<double>(m_primaries.m_primaries[0][0]), 0, 'f', 4)
519 .arg(static_cast<double>(m_primaries.m_primaries[0][1]), 0, 'f', 4));
520 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Green:\t%1,\t%2")
521 .arg(static_cast<double>(m_primaries.m_primaries[1][0]), 0, 'f', 4)
522 .arg(static_cast<double>(m_primaries.m_primaries[1][1]), 0, 'f', 4));
523 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Blue:\t%1,\t%2")
524 .arg(static_cast<double>(m_primaries.m_primaries[2][0]), 0, 'f', 4)
525 .arg(static_cast<double>(m_primaries.m_primaries[2][1]), 0, 'f', 4));
526 LOG(VB_GENERAL, LOG_INFO, LOC + QString("White:\t%1,\t%2")
527 .arg(static_cast<double>(m_primaries.m_whitePoint[0]), 0, 'f', 4)
528 .arg(static_cast<double>(m_primaries.m_whitePoint[1]), 0, 'f', 4));
529 QString address = !m_physicalAddress ? QString("N/A") :
530 QString("%1.%2.%3.%4").arg((m_physicalAddress >> 12) & 0xF)
531 .arg((m_physicalAddress >> 8) & 0xF)
532 .arg((m_physicalAddress >> 4) & 0xF)
533 .arg(m_physicalAddress & 0xF);
534 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Physical address: %1").arg(address));
535 if (m_deepColor)
536 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Deep color: %1").arg(deep(m_deepColor)));
537 if (m_latencies)
538 {
539 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Latencies: Audio:%1 Video:%2")
540 .arg(m_audioLatency[0]).arg(m_videoLatency[0]));
542 {
543 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Latencies: Audio:%1 Video:%2 (Interlaced)")
544 .arg(m_audioLatency[1]).arg(m_videoLatency[1]));
545 }
546 }
547 if (m_deepYUV)
548 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Deep YUV 4:2:0 %1").arg(deepyuv(m_deepYUV)));
549 if (m_vrrMin || m_vrrMax)
550 LOG(VB_GENERAL, LOG_INFO, LOC + QString("VRR: %1<->%2").arg(m_vrrMin).arg(m_vrrMax));
551 if (m_hdrSupport)
552 LOG(VB_GENERAL, LOG_INFO, LOC + QString("HDR types: %1").arg(MythHDR::TypesToString(m_hdrSupport).join(",")));
553 if (m_maxLuminance > 0.0 || m_maxAvgLuminance > 0.0)
554 {
555 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Desired luminance: Min: %1 Max: %2 Avg: %3")
556 .arg(m_minLuminance, 3, 'f', 3).arg(m_maxLuminance, 3, 'f', 3).arg(m_maxAvgLuminance, 3, 'f', 3));
557 }
558}
static bool Alike(const MythColourSpace &First, const MythColourSpace &Second, float Fuzz)
MythPrimaryFloat m_whitePoint
static MythColourSpace s_sRGB
MythPrimariesFloat m_primaries
uint16_t m_physicalAddress
Definition: mythedid.h:77
MythHDRDesc GetHDRSupport() const
Definition: mythedid.cpp:99
bool ParseVSDB(const quint8 *Data, size_t Offset, size_t Length)
Definition: mythedid.cpp:374
std::array< int, 2 > m_audioLatency
Definition: mythedid.h:81
uint8_t m_deepColor
Definition: mythedid.h:78
int AudioLatency(bool Interlaced) const
Definition: mythedid.cpp:89
double m_minLuminance
Definition: mythedid.h:90
void Parse()
Definition: mythedid.cpp:143
QSize m_displaySize
Definition: mythedid.h:66
QStringList m_serialNumbers
Definition: mythedid.h:68
void Debug() const
Definition: mythedid.cpp:485
bool m_sRGB
Definition: mythedid.h:73
int m_vrrMax
Definition: mythedid.h:85
bool m_latencies
Definition: mythedid.h:79
double m_maxLuminance
Definition: mythedid.h:88
MythEDID()=default
bool IsSRGB() const
Definition: mythedid.cpp:74
bool ParseExtended(const quint8 *Data, size_t Offset, size_t Length)
Definition: mythedid.cpp:455
MythHDR::HDRTypes m_hdrSupport
Definition: mythedid.h:87
QByteArray m_data
Definition: mythedid.h:63
bool ParseCTABlock(const quint8 *Data, size_t Offset)
Definition: mythedid.cpp:357
bool m_isHDMI
Definition: mythedid.h:76
int VideoLatency(bool Interlaced) const
Definition: mythedid.cpp:94
MythColourSpace m_primaries
Definition: mythedid.h:75
size_t m_size
Definition: mythedid.h:64
bool m_valid
Definition: mythedid.h:62
QSize DisplaySize() const
Definition: mythedid.cpp:49
uint16_t PhysicalAddress() const
Definition: mythedid.cpp:59
std::array< int, 2 > m_videoLatency
Definition: mythedid.h:82
@ HDR10
Definition: mythedid.h:49
QStringList SerialNumbers() const
Definition: mythedid.cpp:44
bool m_interLatencies
Definition: mythedid.h:80
double m_displayAspect
Definition: mythedid.h:67
uint8_t m_deepYUV
Definition: mythedid.h:83
void ParseDetailedTimingDescriptor(const quint8 *Data, size_t Offset)
Definition: mythedid.cpp:325
MythColourSpace ColourPrimaries() const
Definition: mythedid.cpp:84
bool m_likeSRGB
Definition: mythedid.h:74
int m_hdrMetaTypes
Definition: mythedid.h:86
QString m_name
Definition: mythedid.h:69
float Gamma() const
Definition: mythedid.cpp:64
quint8 m_minorVersion
Definition: mythedid.h:65
bool IsHDMI() const
Definition: mythedid.cpp:69
float m_gamma
Definition: mythedid.h:72
bool IsLikeSRGB() const
Definition: mythedid.cpp:79
int m_vrangeMin
Definition: mythedid.h:70
int m_vrrMin
Definition: mythedid.h:84
bool ParseBaseBlock(const quint8 *Data)
Definition: mythedid.cpp:197
double m_maxAvgLuminance
Definition: mythedid.h:89
bool Valid() const
Definition: mythedid.cpp:39
double DisplayAspect() const
Definition: mythedid.cpp:54
void ParseDisplayDescriptor(const quint8 *Data, uint Offset)
Definition: mythedid.cpp:294
int m_vrangeMax
Definition: mythedid.h:71
bool ParseCTA861(const quint8 *Data, size_t Offset)
Definition: mythedid.cpp:340
MythVRRRange GetVRRRange() const
Return the range of supported refresh rates.
Definition: mythedid.cpp:113
QStringList TypesToString() const
Definition: mythhdr.cpp:83
@ HDR10
Definition: mythhdr.h:39
@ HLG
Definition: mythhdr.h:40
unsigned int uint
Definition: freesurround.h:24
unsigned short uint16_t
Definition: iso6937tables.h:3
#define LOC
Definition: mythedid.cpp:25
static constexpr uint8_t DESCRIPTOR_RANGE_LIMITS
Definition: mythedid.cpp:13
static constexpr size_t HEIGHT_OFFSET
Definition: mythedid.cpp:20
static constexpr size_t WIDTH_OFFSET
Definition: mythedid.cpp:19
static constexpr size_t GAMMA_OFFSET
Definition: mythedid.cpp:21
static constexpr size_t VERSION_OFFSET
Definition: mythedid.cpp:17
static constexpr size_t EXTENSIONS_OFFSET
Definition: mythedid.cpp:23
static constexpr uint8_t DESCRIPTOR_PRODUCT_NAME
Definition: mythedid.cpp:12
static constexpr size_t SERIAL_OFFSET
Definition: mythedid.cpp:16
static QString ParseEdidString(const quint8 *data, bool Replace)
Definition: mythedid.cpp:123
static constexpr uint8_t DESCRIPTOR_SERIAL_NUMBER
Definition: mythedid.cpp:14
static constexpr size_t DATA_BLOCK_OFFSET
Definition: mythedid.cpp:15
static constexpr size_t FEATURES_OFFSET
Definition: mythedid.cpp:22
std::tuple< MythHDR::HDRTypes, double, double, double > MythHDRDesc
Definition: mythedid.h:18
std::tuple< int, int, bool > MythVRRRange
Definition: mythedid.h:19
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
string version
Definition: giantbomb.py:185
STL namespace.