MythTV  master
DisplayResScreen.cpp
Go to the documentation of this file.
1 
2 // Own header
3 #include "DisplayResScreen.h"
4 
5 // QT headers
6 #include <QStringList>
7 
8 // C++ headers
9 #include <cmath>
10 
11 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
12  double aspectRatio, double refreshRate)
13  : m_width(w), m_height(h), m_width_mm(mw), m_height_mm(mh)
14 {
15  SetAspectRatio(aspectRatio);
16  if (refreshRate > 0)
17  m_refreshRates.push_back(refreshRate);
18 }
19 
20 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
21  const std::vector<double>& refreshRate)
22  : m_width(w), m_height(h), m_width_mm(mw), m_height_mm(mh), m_refreshRates(refreshRate)
23 {
24  SetAspectRatio(-1.0);
25 }
26 
27 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
28  const std::vector<double>& refreshRate,
29  const std::map<double, short>& realrates)
30 : realRates(realrates), m_width(w), m_height(h), m_width_mm(mw), m_height_mm(mh),
31  m_refreshRates(refreshRate), m_custom(true)
32 {
33  SetAspectRatio(-1.0);
34 }
35 
36 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
37  const double* refreshRate, uint rr_length)
38  : m_width(w), m_height(h), m_width_mm(mw), m_height_mm(mh)
39 {
40  SetAspectRatio(-1.0);
41  for (uint i = 0; i < rr_length; ++i)
42  m_refreshRates.push_back(refreshRate[i]);
43 
44  std::sort(m_refreshRates.begin(), m_refreshRates.end());
45 }
46 
47 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
48  const short* refreshRate, uint rr_length)
49  : m_width(w), m_height(h), m_width_mm(mw), m_height_mm(mh)
50 {
51  SetAspectRatio(-1.0);
52  for (uint i = 0; i < rr_length; ++i)
53  m_refreshRates.push_back((double)refreshRate[i]);
54  std::sort(m_refreshRates.begin(), m_refreshRates.end());
55 }
56 
58 {
59  m_refreshRates.clear();
60  QStringList slist = str.split(':');
61  if (slist.size()<4)
62  slist = str.split(','); // for backward compatibility
63  if (slist.size() >= 4)
64  {
65  m_width = slist[0].toInt();
66  m_height = slist[1].toInt();
67  m_width_mm = slist[2].toInt();
68  m_height_mm = slist[3].toInt();
69  m_aspect = slist[4].toDouble();
70  for (int i = 5; i<slist.size(); ++i)
71  m_refreshRates.push_back(slist[i].toDouble());
72  }
73 }
74 
76 {
77  if (a>0.0)
78  m_aspect = a;
79  else if (Height_mm())
80  m_aspect = ((double)(Width_mm())) / ((double)(Height_mm()));
81 }
82 
84 {
85  QString str = QString("%1:%2:%3:%4:%5")
86  .arg(m_width).arg(m_height).arg(m_width_mm).arg(m_height_mm).arg(m_aspect);
87  for (size_t i=0; i<m_refreshRates.size(); ++i)
88  str.append(QString(":%1").arg(m_refreshRates[i]));
89  return str;
90 }
91 
93 {
94  QStringList slist;
95  for (size_t i=0; i<dsr.size(); ++i)
96  slist += dsr[i].toString();
97  return slist;
98 }
99 
101 {
102  std::vector<DisplayResScreen> dsr;
103  dsr.reserve(slist.size());
104  for (int i=0; i<slist.size(); ++i)
105  dsr.emplace_back(slist[i]);
106  return dsr;
107 }
108 
109 //compares if the double f1 is equal with f2 and returns 1 if true and 0 if false
110 bool DisplayResScreen::compare_rates(double f1, double f2, double precision)
111 {
112  return ((f1 - precision) < f2) &&
113  ((f1 + precision) > f2);
114 }
115 
117  const DisplayResScreen& d,
118  double& target_rate)
119 {
120  double videorate = d.RefreshRate();
121  bool rate2x = false;
122  bool end = false;
123 
124  // We will give priority to refresh rates that are twice what is looked for
125  if ((videorate > 24.5) && (videorate < 30.5))
126  {
127  rate2x = true;
128  videorate *= 2.0;
129  }
130 
131  // Amend vector with custom list
132  for (size_t i=0; i<dsr.size(); ++i)
133  {
134  if (dsr[i].Width()==d.Width() && dsr[i].Height()==d.Height())
135  {
136  const std::vector<double>& rates = dsr[i].RefreshRates();
137  if (!rates.empty() && videorate != 0)
138  {
139  while (!end)
140  {
141  for (double precision = 0.001;
142  precision < 1.0;
143  precision *= 10.0)
144  {
145  for (size_t j=0; j < rates.size(); ++j)
146  {
147  // Multiple of target_rate will do
148  if (compare_rates(videorate,rates[j], precision) ||
149  (fabs(videorate - fmod(rates[j],videorate))
150  <= precision) ||
151  (fmod(rates[j],videorate) <= precision))
152  {
153  target_rate = rates[j];
154  return i;
155  }
156  }
157  }
158  // Can't find exact frame rate, so try rounding to the
159  // nearest integer, so 23.97Hz will work with 24Hz etc
160  for (double precision = 0.01;
161  precision < 2.0;
162  precision *= 10.0)
163  {
164  double rounded = round(videorate);
165  for (size_t j=0; j < rates.size(); ++j)
166  {
167  // Multiple of target_rate will do
168  if (compare_rates(rounded,rates[j], precision) ||
169  (fabs(rounded - fmod(rates[j],rounded))
170  <= precision) ||
171  (fmod(rates[j],rounded) <= precision))
172  {
173  target_rate = rates[j];
174  return i;
175  }
176  }
177  }
178  if (rate2x)
179  {
180  videorate /= 2.0;
181  rate2x = false;
182  }
183  else
184  end = true;
185  }
186  target_rate = rates[rates.size() - 1];
187  }
188  return i;
189  }
190  }
191  return -1;
192 }
193 
194 #define extract_key(key) { \
195  r = ((key) & ((1<<18) - 1)) / 1000.0; \
196  h = ((key) >> 18) & ((1<<16) - 1); \
197  w = ((key) >> 34) & ((1<<16) - 1); }
198 
200  int iwidth, int iheight, double frate)
201 {
202  DisplayResMapCIt it;
203  int w, h;
204  double r;
205 
206  // 1. search for exact match (width, height, rate)
207  // 2. search for resolution, ignoring rate
208  // 3. search for matching height and rate (or any rate if rate = 0)
209  // 4. search for 2x rate
210  // 5. search for 1x rate
211  for (it = resmap.begin(); it != resmap.end(); ++it)
212  {
213  extract_key(it->first);
214  if (w == iwidth && h == iheight && compare_rates(frate, r, 0.01))
215  return it->first;
216  }
217  for (it = resmap.begin(); it != resmap.end(); ++it)
218  {
219  extract_key(it->first);
220  if (w == iwidth && h == iheight && r == 0)
221  return it->first;
222  }
223  for (it = resmap.begin(); it != resmap.end(); ++it)
224  {
225  extract_key(it->first);
226  if ((w == 0 && h == iheight &&
227  (compare_rates(frate, r, 0.01) || r == 0)) ||
228  (w == 0 && h == 0 && compare_rates(frate, r * 2.0, 0.01)) ||
229  (w == 0 && h == 0 && compare_rates(frate, r, 0.01)))
230  {
231  return it->first;
232  }
233  }
234  // not found
235  return 0;
236 }
#define extract_key(key)
QString toString() const
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
void SetAspectRatio(double a)
#define round(x)
Definition: mythplayer.cpp:66
DisplayResMap::const_iterator DisplayResMapCIt
unsigned int uint
Definition: compat.h:140
int Height_mm() const
unsigned char r
Definition: ParseText.cpp:329
static QStringList Convert(const DisplayResVector &dsr)
std::vector< double > m_refreshRates
int Width_mm() const
DisplayResScreen()=default
static const uint16_t * d
std::vector< DisplayResScreen > DisplayResVector
std::map< uint64_t, DisplayResScreen > DisplayResMap
static int FindBestMatch(const DisplayResVector &dsr, const DisplayResScreen &d, double &target_rate)
static bool compare_rates(double f1, double f2, double precision=0.01)
static uint64_t FindBestScreen(const DisplayResMap &resmap, int iwidth, int iheight, double frate)