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 static void extract_key(uint64_t key, double& rate, int& height, int& width)
219 {
220  rate = (key & ((1 << 18) - 1)) / 1000.0;
221  height = (key >> 18) & ((1 << 16) - 1);
222  width = (key >> 34) & ((1 << 16) - 1);
223 }
224 
226  int Width, int Height, double Rate)
227 {
228  // 1. search for exact match (width, height, rate)
229  // 2. search for resolution, ignoring rate
230  // 3. search for matching height and rate (or any rate if rate = 0)
231  // 4. search for 2x rate
232  // 5. search for 1x rate
233 
234  for (const auto & it : Map)
235  {
236  double rate { 0.0 };
237  int height { 0 };
238  int width { 0 };
239  extract_key(it.first, rate, height, width);
240  if (width == Width && height == Height && CompareRates(Rate, rate, 0.01))
241  return it.first;
242  }
243 
244  for (const auto & it : Map)
245  {
246  double rate { 0.0 };
247  int height { 0 };
248  int width { 0 };
249  extract_key(it.first, rate, height, width);
250  if (width == Width && height == Height && qFuzzyCompare(rate + 1.0, 1.0))
251  return it.first;
252  }
253 
254  for (const auto & it : Map)
255  {
256  double rate { 0.0 };
257  int height { 0 };
258  int width { 0 };
259  extract_key(it.first, rate, height, width);
260  if ((width == 0 && height == Height &&
261  (CompareRates(Rate, rate, 0.01) || qFuzzyCompare(rate + 1.0, 1.0))) ||
262  (width == 0 && height == 0 && CompareRates(Rate, rate * 2.0, 0.01)) ||
263  (width == 0 && height == 0 && CompareRates(Rate, rate, 0.01)))
264  {
265  return it.first;
266  }
267  }
268 
269  return 0;
270 }
271 
273 {
274  QStringList rates;
275  for (auto rate : m_refreshRates)
276  rates << QString::number(rate, 'f', 2);
277  return QObject::tr("%1x%2@%3Hz").arg(m_width).arg(m_height).arg(rates.join(", "));
278 }
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:225
MythDisplayMode::MythDisplayMode
MythDisplayMode()=default
MythDisplayMode::m_refreshRates
MythDisplayRates m_refreshRates
Definition: mythdisplaymode.h:60
Mode
Mode
Definition: synaesthesia.h:23
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
extract_key
static void extract_key(uint64_t key, double &rate, int &height, int &width)
Definition: mythdisplaymode.cpp:218
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
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:272
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
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