MythTV  master
mythdisplaymode.cpp
Go to the documentation of this file.
1 // QT
2 #include <QStringList>
3 
4 // MythTV
5 #include "mythdisplaymode.h"
6 
7 // Std
8 #include <cmath>
9 
10 MythDisplayMode::MythDisplayMode(QSize Resolution, QSize PhysicalSize,
11  double AspectRatio, double RefreshRate)
12  : m_width(Resolution.width()),
13  m_height(Resolution.height()),
14  m_widthMM(PhysicalSize.width()),
15  m_heightMM(PhysicalSize.height())
16 {
18  if (RefreshRate > 0)
19  m_refreshRates.push_back(RefreshRate);
20 }
21 MythDisplayMode::MythDisplayMode(int Width, int Height, int MMWidth, int MMHeight,
22  double AspectRatio, double RefreshRate)
23  : m_width(Width),
24  m_height(Height),
25  m_widthMM(MMWidth),
26  m_heightMM(MMHeight)
27 {
29  if (RefreshRate > 0)
30  m_refreshRates.push_back(RefreshRate);
31 }
32 
34 {
35  if (m_width < Other.m_width)
36  return true;
37  if (m_height < Other.m_height)
38  return true;
39  return false;
40 }
41 
43 {
44  return m_width == Other.m_width && m_height == Other.m_height;
45 }
46 
48 {
50  m_aspect = -1.0;
51 }
52 
54 {
55  return { m_width, m_height };
56 }
57 
59 {
60  return m_width;
61 }
62 
64 {
65  return m_height;
66 }
67 
69 {
70  return m_widthMM;
71 }
72 
74 {
75  return m_heightMM;
76 }
77 
79 {
80  return m_refreshRates;
81 }
82 
84 {
85  if (m_aspect <= 0.0)
86  {
87  if (0 == m_heightMM)
88  return 1.0;
89  return static_cast<double>(m_widthMM) / m_heightMM;
90  }
91  return m_aspect;
92 }
93 
95 {
96  if (!m_refreshRates.empty())
97  return m_refreshRates[0];
98  return 0.0;
99 }
100 
101 void MythDisplayMode::SetAspectRatio(double AspectRatio)
102 {
103  if (AspectRatio > 0.0)
105  else if (HeightMM())
106  m_aspect = static_cast<double>(m_widthMM) / m_heightMM;
107 }
108 
110 {
111  m_refreshRates.push_back(Rate);
112  std::sort(m_refreshRates.begin(), m_refreshRates.end());
113 }
114 
116 {
117  m_refreshRates.clear();
118 }
119 
121 {
123  AddRefreshRate(Rate);
124 }
125 
126 uint64_t MythDisplayMode::CalcKey(QSize Size, double Rate)
127 {
128  return (static_cast<uint64_t>(Size.width()) << 34) |
129  (static_cast<uint64_t>(Size.height()) << 18) |
130  (static_cast<uint64_t>(Rate * 1000.0));
131 }
132 
134 bool MythDisplayMode::CompareRates(double First, double Second, double Precision)
135 {
136  return qAbs(First - Second) < Precision;
137 }
138 
140  const MythDisplayMode& Mode, double &TargetRate)
141 {
142  double videorate = Mode.RefreshRate();
143  bool rate2x = false;
144  bool end = false;
145 
146  // We will give priority to refresh rates that are twice what is looked for
147  if ((videorate > 24.5) && (videorate < 30.5))
148  {
149  rate2x = true;
150  videorate *= 2.0;
151  }
152 
153  // Amend vector with custom list
154  for (size_t i = 0; i < Modes.size(); ++i)
155  {
156  if (Modes[i].Width() == Mode.Width() && Modes[i].Height() == Mode.Height())
157  {
158  auto rates = Modes[i].RefreshRates();
159  if (!rates.empty() && !qFuzzyCompare(videorate + 1.0, 1.0))
160  {
161  while (!end)
162  {
163  for (double precision : { 0.001, 0.01, 0.1 })
164  {
165  for (double rate : rates)
166  {
167  // Multiple of target_rate will do
168  if (CompareRates(videorate, rate, precision) ||
169  (qAbs(videorate - fmod(rate, videorate))
170  <= precision) ||
171  (fmod(rate,videorate) <= precision))
172  {
173  TargetRate = rate;
174  return static_cast<int>(i);
175  }
176  }
177  }
178  // Can't find exact frame rate, so try rounding to the
179  // nearest integer, so 23.97Hz will work with 24Hz etc
180  for (double precision : { 0.01, 0.1, 1.0 })
181  {
182  double rounded = round(videorate);
183  for (double rate : rates)
184  {
185  // Multiple of target_rate will do
186  if (CompareRates(rounded, rate, precision) ||
187  (qAbs(rounded - fmod(rate, rounded)) <= precision) ||
188  (fmod(rate,rounded) <= precision))
189  {
190  TargetRate = rate;
191  return static_cast<int>(i);
192  }
193  }
194  }
195  if (rate2x)
196  {
197  videorate /= 2.0;
198  rate2x = false;
199  }
200  else
201  {
202  end = true;
203  }
204  }
205  TargetRate = rates[rates.size() - 1];
206  }
207  else if (!rates.empty())
208  {
209  TargetRate = rates[rates.size() - 1];
210  }
211  return static_cast<int>(i);
212  }
213  }
214  return -1;
215 }
216 
217 #define extract_key(key) \
218 double rate = ((key) & ((1 << 18) - 1)) / 1000.0; \
219 int height = ((key) >> 18) & ((1 << 16) - 1); \
220 int width = ((key) >> 34) & ((1 << 16) - 1);
221 
223  int Width, int Height, double Rate)
224 {
225  // 1. search for exact match (width, height, rate)
226  // 2. search for resolution, ignoring rate
227  // 3. search for matching height and rate (or any rate if rate = 0)
228  // 4. search for 2x rate
229  // 5. search for 1x rate
230 
231  for (auto it = Map.cbegin(); it != Map.cend(); ++it)
232  {
233  extract_key(it->first)
234  if (width == Width && height == Height && CompareRates(Rate, rate, 0.01))
235  return it->first;
236  }
237 
238  for (auto it = Map.cbegin(); it != Map.cend(); ++it)
239  {
240  extract_key(it->first)
241  if (width == Width && height == Height && qFuzzyCompare(rate + 1.0, 1.0))
242  return it->first;
243  }
244 
245  for (auto it = Map.cbegin(); it != Map.cend(); ++it)
246  {
247  extract_key(it->first)
248  if ((width == 0 && height == Height &&
249  (CompareRates(Rate, rate, 0.01) || qFuzzyCompare(rate + 1.0, 1.0))) ||
250  (width == 0 && height == 0 && CompareRates(Rate, rate * 2.0, 0.01)) ||
251  (width == 0 && height == 0 && CompareRates(Rate, rate, 0.01)))
252  {
253  return it->first;
254  }
255  }
256 
257  return 0;
258 }
mythdisplaymode.h
MythDisplayMode::AspectRatio
double AspectRatio() const
Definition: mythdisplaymode.cpp:83
MythDisplayMode::AddRefreshRate
void AddRefreshRate(double Rate)
Definition: mythdisplaymode.cpp:109
MythDisplayMode::FindBestScreen
static uint64_t FindBestScreen(const DisplayModeMap &Map, int Width, int Height, double Rate)
Definition: mythdisplaymode.cpp:222
MythDisplayMode::MythDisplayMode
MythDisplayMode()=default
MythDisplayMode::m_refreshRates
MythDisplayRates m_refreshRates
Definition: mythdisplaymode.h:59
MythDisplayModes
std::vector< MythDisplayMode > MythDisplayModes
Definition: mythdisplaymode.h:18
MythDisplayMode::m_height
int m_height
Definition: mythdisplaymode.h:55
MythDisplayMode::CalcKey
static uint64_t CalcKey(QSize Size, double Rate)
Definition: mythdisplaymode.cpp:126
MythDisplayMode::m_width
int m_width
Definition: mythdisplaymode.h:54
MythDisplayMode::m_aspect
double m_aspect
Definition: mythdisplaymode.h:58
MythDisplayMode::operator==
bool operator==(const MythDisplayMode &Other) const
Definition: mythdisplaymode.cpp:42
MythDisplayMode::HeightMM
int HeightMM() const
Definition: mythdisplaymode.cpp:73
MythDisplayMode::WidthMM
int WidthMM() const
Definition: mythdisplaymode.cpp:68
MythDisplayMode::SetAspectRatio
void SetAspectRatio(double AspectRatio)
Definition: mythdisplaymode.cpp:101
MythDisplayMode::m_heightMM
int m_heightMM
Definition: mythdisplaymode.h:57
MythDisplayMode::ClearRefreshRates
void ClearRefreshRates()
Definition: mythdisplaymode.cpp:115
extract_key
#define extract_key(key)
Definition: mythdisplaymode.cpp:217
MythDisplayMode
Definition: mythdisplaymode.h:22
MythDisplayMode::m_widthMM
int m_widthMM
Definition: mythdisplaymode.h:56
MythDisplayMode::Height
int Height() const
Definition: mythdisplaymode.cpp:63
MythDisplayRates
std::vector< double > MythDisplayRates
Definition: mythdisplaymode.h:20
MythDisplayMode::Init
void Init()
Definition: mythdisplaymode.cpp:47
MythDisplayMode::SetRefreshRate
void SetRefreshRate(double Rate)
Definition: mythdisplaymode.cpp:120
MythDisplayMode::RefreshRate
double RefreshRate() const
Definition: mythdisplaymode.cpp:94
DisplayModeMap
std::map< uint64_t, MythDisplayMode > DisplayModeMap
Definition: mythdisplaymode.h:19
MythDisplayMode::CompareRates
static bool CompareRates(double First, double Second, double Precision=0.01)
Determine whether two rates are considered equal with the given precision.
Definition: mythdisplaymode.cpp:134
MythDisplayMode::RefreshRates
const MythDisplayRates & RefreshRates() const
Definition: mythdisplaymode.cpp:78
MythDisplayMode::Resolution
QSize Resolution() const
Definition: mythdisplaymode.cpp:53
round
#define round(x)
Definition: mythplayer.cpp:59
MythDisplayMode::operator<
bool operator<(const MythDisplayMode &Other) const
Definition: mythdisplaymode.cpp:33
MythDisplayMode::FindBestMatch
static int FindBestMatch(const MythDisplayModes &Modes, const MythDisplayMode &Mode, double &TargetRate)
Definition: mythdisplaymode.cpp:139
MythDisplayMode::Width
int Width() const
Definition: mythdisplaymode.cpp:58