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