MythTV  master
videodisplayprofile.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "videodisplayprofile.h"
3 #include "mythcorecontext.h"
4 #include "mythdb.h"
5 #include "mythlogging.h"
6 #include "mythvideoout.h"
7 #include "avformatdecoder.h"
8 
9 // Std
10 #include <algorithm>
11 #include <utility>
12 
14 {
15  m_pref.clear();
16 }
17 
19 {
20  m_profileid = Id;
21 }
22 
23 void ProfileItem::Set(const QString &Value, const QString &Data)
24 {
25  m_pref[Value] = Data;
26 }
27 
29 {
30  return m_profileid;
31 }
32 
33 QMap<QString,QString> ProfileItem::GetAll(void) const
34 {
35  return m_pref;
36 }
37 
38 QString ProfileItem::Get(const QString &Value) const
39 {
40  QMap<QString,QString>::const_iterator it = m_pref.find(Value);
41  if (it != m_pref.end())
42  return *it;
43  return QString();
44 }
45 
47 {
48  QString tmp = Get("pref_priority");
49  return tmp.isEmpty() ? 0 : tmp.toUInt();
50 }
51 
52 // options are NNN NNN-MMM 0-MMM NNN-99999 >NNN >=NNN <MMM <=MMM or blank
53 // If string is blank then assumes a match.
54 // If value is 0 or negative assume a match (i.e. value unknown assumes a match)
55 // float values must be no more than 3 decimals.
56 bool ProfileItem::CheckRange(const QString &Key, float Value, bool *Ok) const
57 {
58  return CheckRange(Key, Value, 0, true, Ok);
59 }
60 
61 bool ProfileItem::CheckRange(const QString &Key, int Value, bool *Ok) const
62 {
63  return CheckRange(Key, 0.0, Value, false, Ok);
64 }
65 
66 bool ProfileItem::CheckRange(const QString& Key,
67  float FValue, int IValue, bool IsFloat, bool *Ok) const
68 {
69  bool match = true;
70  bool isOK = true;
71  if (IsFloat)
72  IValue = int(FValue * 1000.0F);
73  QString cmp = Get(Key);
74  if (!cmp.isEmpty())
75  {
76  cmp.replace(QLatin1String(" "),QLatin1String(""));
77  QStringList expr = cmp.split("&");
78  for (int ix = 0; ix < expr.size(); ++ix)
79  {
80  if (expr[ix].isEmpty())
81  {
82  isOK = false;
83  continue;
84  }
85  if (IValue > 0)
86  {
87  QRegularExpression regex("^([0-9.]*)([^0-9.]*)([0-9.]*)$");
88  QRegularExpressionMatch rmatch = regex.match(expr[ix]);
89 
90  int value1 = 0;
91  int value2 = 0;
92  QString oper;
93  QString capture1 = rmatch.captured(1);
94  QString capture3;
95  if (!capture1.isEmpty())
96  {
97  if (IsFloat)
98  {
99  int dec=capture1.indexOf('.');
100  if (dec > -1 && (capture1.length()-dec) > 4)
101  isOK = false;
102  if (isOK)
103  {
104  double double1 = capture1.toDouble(&isOK);
105  if (double1 > 2000000.0 || double1 < 0.0)
106  isOK = false;
107  value1 = int(double1 * 1000.0);
108  }
109  }
110  else
111  value1 = capture1.toInt(&isOK);
112  }
113  if (isOK)
114  {
115  oper = rmatch.captured(2);
116  capture3 = rmatch.captured(3);
117  if (!capture3.isEmpty())
118  {
119  if (IsFloat)
120  {
121  int dec=capture3.indexOf('.');
122  if (dec > -1 && (capture3.length()-dec) > 4)
123  isOK = false;
124  if (isOK)
125  {
126  double double1 = capture3.toDouble(&isOK);
127  if (double1 > 2000000.0 || double1 < 0.0)
128  isOK = false;
129  value2 = int(double1 * 1000.0);
130  }
131  }
132  else
133  value2 = capture3.toInt(&isOK);
134  }
135  }
136  if (isOK)
137  {
138  // Invalid string
139  if (value1 == 0 && value2 == 0 && oper.isEmpty())
140  isOK=false;
141  }
142  if (isOK)
143  {
144  // Case NNN
145  if (value1 != 0 && oper.isEmpty() && value2 == 0)
146  {
147  value2 = value1;
148  oper = "-";
149  }
150  // NNN-MMM 0-MMM NNN-99999 NNN- -MMM
151  else if (oper == "-")
152  {
153  // NNN- or -NNN
154  if (capture1.isEmpty() || capture3.isEmpty())
155  isOK = false;
156  // NNN-MMM
157  if (value2 < value1)
158  isOK = false;
159  }
160  else if (capture1.isEmpty())
161  {
162  // Other operators == > < >= <=
163  // Convert to a range
164  if (oper == "==")
165  value1 = value2;
166  else if (oper == ">")
167  {
168  value1 = value2 + 1;
169  value2 = 99999999;
170  }
171  else if (oper == ">=")
172  {
173  value1 = value2;
174  value2 = 99999999;
175  }
176  else if (oper == "<")
177  value2 = value2 - 1;
178  else if (oper == "<=")
179  ;
180  else isOK = false;
181  oper = "-";
182  }
183  }
184  if (isOK)
185  {
186  if (oper == "-")
187  match = match && (IValue >= value1 && IValue <= value2);
188  else isOK = false;
189  }
190  }
191  }
192  }
193  if (Ok != nullptr)
194  *Ok = isOK;
195  if (!isOK)
196  match=false;
197  return match;
198 }
199 
200 bool ProfileItem::IsMatch(const QSize &Size, float Framerate, const QString &CodecName,
201  const QStringList &DisallowedDecoders) const
202 {
203  bool match = true;
204 
205  // cond_width, cond_height, cond_codecs, cond_framerate.
206  // These replace old settings pref_cmp0 and pref_cmp1
207  match &= CheckRange("cond_width",Size.width());
208  match &= CheckRange("cond_height",Size.height());
209  match &= CheckRange("cond_framerate",Framerate);
210  // codec
211  QString cmp = Get(QString("cond_codecs"));
212  if (!cmp.isEmpty())
213  {
214 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
215  QStringList clist = cmp.split(" ", QString::SkipEmptyParts);
216 #else
217  QStringList clist = cmp.split(" ", Qt::SkipEmptyParts);
218 #endif
219  if (!clist.empty())
220  match &= clist.contains(CodecName,Qt::CaseInsensitive);
221  }
222 
223  QString decoder = Get("pref_decoder");
224  if (DisallowedDecoders.contains(decoder))
225  match = false;
226  return match;
227 }
228 
229 bool ProfileItem::IsValid(QString *Reason) const
230 {
231 
232  bool isOK = true;
233  CheckRange("cond_width",1,&isOK);
234  if (!isOK)
235  {
236  if (Reason)
237  *Reason = QString("Invalid width condition");
238  return false;
239  }
240  CheckRange("cond_height",1,&isOK);
241  if (!isOK)
242  {
243  if (Reason)
244  *Reason = QString("Invalid height condition");
245  return false;
246  }
247  CheckRange("cond_framerate",1.0F,&isOK);
248  if (!isOK)
249  {
250  if (Reason)
251  *Reason = QString("Invalid framerate condition");
252  return false;
253  }
254 
255  QString decoder = Get("pref_decoder");
256  QString renderer = Get("pref_videorenderer");
257  if (decoder.isEmpty() || renderer.isEmpty())
258  {
259  if (Reason)
260  *Reason = "Need a decoder and renderer";
261  return false;
262  }
263 
264  QStringList decoders = VideoDisplayProfile::GetDecoders();
265  if (!decoders.contains(decoder))
266  {
267  if (Reason)
268  *Reason = QString("decoder %1 is not available").arg(decoder);
269  return false;
270  }
271 
272  QStringList renderers = VideoDisplayProfile::GetVideoRenderers(decoder);
273  if (!renderers.contains(renderer))
274  {
275  if (Reason)
276  *Reason = QString("renderer %1 is not supported with decoder %2")
277  .arg(renderer).arg(decoder);
278  return false;
279  }
280 
281  if (Reason)
282  *Reason = QString();
283 
284  return true;
285 }
286 
287 bool ProfileItem::operator< (const ProfileItem &Other) const
288 {
289  return GetPriority() < Other.GetPriority();
290 }
291 
292 QString ProfileItem::toString(void) const
293 {
294  QString cmp0 = Get("pref_cmp0");
295  QString cmp1 = Get("pref_cmp1");
296  QString width = Get("cond_width");
297  QString height = Get("cond_height");
298  QString framerate = Get("cond_framerate");
299  QString codecs = Get("cond_codecs");
300  QString decoder = Get("pref_decoder");
301  uint max_cpus = Get("pref_max_cpus").toUInt();
302  bool skiploop = Get("pref_skiploop").toInt() != 0;
303  QString renderer = Get("pref_videorenderer");
304  QString deint0 = Get("pref_deint0");
305  QString deint1 = Get("pref_deint1");
306 
307  QString cond = QString("w(%1) h(%2) framerate(%3) codecs(%4)")
308  .arg(width).arg(height).arg(framerate).arg(codecs);
309  QString str = QString("cmp(%1%2) %7 dec(%3) cpus(%4) skiploop(%5) rend(%6) ")
310  .arg(cmp0).arg(QString(cmp1.isEmpty() ? "" : ",") + cmp1)
311  .arg(decoder).arg(max_cpus).arg((skiploop) ? "enabled" : "disabled").arg(renderer)
312  .arg(cond);
313  str += QString("deint(%1,%2)").arg(deint0).arg(deint1);
314 
315  return str;
316 }
317 
319 
320 #define LOC QString("VDP: ")
321 
322 QMutex VideoDisplayProfile::s_safe_lock(QMutex::Recursive);
324 QMap<QString,QStringList> VideoDisplayProfile::s_safe_renderer;
325 QMap<QString,QStringList> VideoDisplayProfile::s_safe_renderer_group;
326 QMap<QString,QStringList> VideoDisplayProfile::s_safe_equiv_dec;
329 QMap<QString,QString> VideoDisplayProfile::s_dec_name;
330 QMap<QString,QString> VideoDisplayProfile::s_rend_name;
332 QList<QPair<QString,QString> > VideoDisplayProfile::s_deinterlacer_options;
333 
335 {
336  QMutexLocker locker(&s_safe_lock);
337  InitStatics();
338 
339  QString hostname = gCoreContext->GetHostName();
340  QString cur_profile = GetDefaultProfileName(hostname);
341  uint groupid = GetProfileGroupID(cur_profile, hostname);
342 
343  vector<ProfileItem> items = LoadDB(groupid);
344  vector<ProfileItem>::const_iterator it;
345  for (it = items.begin(); it != items.end(); ++it)
346  {
347  QString err;
348  if (!(*it).IsValid(&err))
349  {
350  LOG(VB_GENERAL, LOG_ERR, LOC + "Rejecting: " + (*it).toString() + "\n\t\t\t" + err);
351  continue;
352  }
353 
354  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Accepting: " + (*it).toString());
355  m_allowedPreferences.push_back(*it);
356  }
357 }
358 
359 void VideoDisplayProfile::SetInput(const QSize &Size, float Framerate, const QString &CodecName,
360  const QStringList &DisallowedDecoders)
361 {
362  QMutexLocker locker(&m_lock);
363  bool change = !DisallowedDecoders.isEmpty();
364 
365  if (Size != m_lastSize)
366  {
367  m_lastSize = Size;
368  change = true;
369  }
370  if (Framerate > 0.0F && !qFuzzyCompare(Framerate + 1.0F, m_lastRate + 1.0F))
371  {
372  m_lastRate = Framerate;
373  change = true;
374  }
375  if (!CodecName.isEmpty() && CodecName != m_lastCodecName)
376  {
377  m_lastCodecName = CodecName;
378  change = true;
379  }
380  if (change)
382 }
383 
384 void VideoDisplayProfile::SetOutput(float Framerate)
385 {
386  QMutexLocker locker(&m_lock);
387  if (!qFuzzyCompare(Framerate + 1.0F, m_lastRate + 1.0F))
388  {
389  m_lastRate = Framerate;
391  }
392 }
393 
395 {
396  return m_lastRate;
397 }
398 
400 {
401  return GetPreference("pref_decoder");
402 }
403 
405 {
406  return GetPreference("pref_deint0");
407 }
408 
410 {
411  return GetPreference("pref_deint1");
412 }
413 
415 {
416  return qBound(1U, GetPreference("pref_max_cpus").toUInt(), VIDEO_MAX_CPUS);
417 }
418 
420 {
421  return GetPreference("pref_skiploop").toInt() != 0;
422 }
423 
425 {
426  return GetPreference("pref_videorenderer");
427 }
428 
430 {
431  return m_lastVideoRenderer;
432 }
433 
434 void VideoDisplayProfile::SetVideoRenderer(const QString &VideoRenderer)
435 {
436  QMutexLocker locker(&m_lock);
437 
438  LOG(VB_PLAYBACK, LOG_INFO, LOC +
439  QString("SetVideoRenderer(%1)").arg(VideoRenderer));
440 
441  m_lastVideoRenderer = VideoRenderer;
442  if (VideoRenderer == GetVideoRenderer())
443  {
444  LOG(VB_PLAYBACK, LOG_INFO, LOC +
445  QString("SetVideoRender(%1) == GetVideoRenderer()").arg(VideoRenderer));
446  return; // already made preferences safe...
447  }
448 
449  // Make preferences safe...
450  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Old preferences: " + toString());
451 
452  SetPreference("pref_videorenderer", VideoRenderer);
453 
454  LOG(VB_PLAYBACK, LOG_INFO, LOC + "New preferences: " + toString());
455 }
456 
457 bool VideoDisplayProfile::CheckVideoRendererGroup(const QString &Renderer)
458 {
459  if (m_lastVideoRenderer == Renderer || m_lastVideoRenderer == "null")
460  return true;
461 
462  LOG(VB_PLAYBACK, LOG_INFO, LOC +
463  QString("Preferred video renderer: %1 (current: %2)")
464  .arg(Renderer).arg(m_lastVideoRenderer));
465 
466  for (const auto& group : qAsConst(s_safe_renderer_group))
467  if (group.contains(m_lastVideoRenderer) && group.contains(Renderer))
468  return true;
469  return false;
470 }
471 
473 {
474  const QString dec = GetDecoder();
475  if (dec == Decoder)
476  return true;
477 
478  QMutexLocker locker(&s_safe_lock);
479  return (s_safe_equiv_dec[dec].contains(Decoder));
480 }
481 
482 QString VideoDisplayProfile::GetPreference(const QString &Key) const
483 {
484  QMutexLocker locker(&m_lock);
485 
486  if (Key.isEmpty())
487  return QString();
488 
489  QMap<QString,QString>::const_iterator it = m_currentPreferences.find(Key);
490  if (it == m_currentPreferences.end())
491  return QString();
492 
493  return *it;
494 }
495 
496 void VideoDisplayProfile::SetPreference(const QString &Key, const QString &Value)
497 {
498  QMutexLocker locker(&m_lock);
499 
500  if (!Key.isEmpty())
501  m_currentPreferences[Key] = Value;
502 }
503 
504 vector<ProfileItem>::const_iterator VideoDisplayProfile::FindMatch
505  (const QSize &Size, float Framerate, const QString &CodecName, const QStringList DisallowedDecoders)
506 {
507  for (auto it = m_allowedPreferences.cbegin(); it != m_allowedPreferences.cend(); ++it)
508  if ((*it).IsMatch(Size, Framerate, CodecName, DisallowedDecoders))
509  return it;
510  return m_allowedPreferences.end();
511 }
512 
514  (const QSize &Size, float Framerate, const QString &CodecName, const QStringList &DisallowedDecoders)
515 {
516  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("LoadBestPreferences(%1x%2, %3, %4)")
517  .arg(Size.width()).arg(Size.height())
518  .arg(static_cast<double>(Framerate), 0, 'f', 3).arg(CodecName));
519 
520  m_currentPreferences.clear();
521  auto it = FindMatch(Size, Framerate, CodecName, DisallowedDecoders);
522  if (it != m_allowedPreferences.end())
523  {
524  m_currentPreferences = (*it).GetAll();
525  }
526  else
527  {
528  int threads = qBound(1, QThread::idealThreadCount(), 4);
529  LOG(VB_PLAYBACK, LOG_INFO, LOC + "No useable profile. Using defaults.");
530  SetPreference("pref_decoder", "ffmpeg");
531  SetPreference("pref_max_cpus", QString::number(threads));
532  SetPreference("pref_videorenderer", "opengl-yv12");
533  SetPreference("pref_deint0", DEINT_QUALITY_LOW);
534  SetPreference("pref_deint1", DEINT_QUALITY_LOW);
535  }
536 
537  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("LoadBestPreferences result: "
538  "priority:%1 width:%2 height:%3 fps:%4 codecs:%5")
539  .arg(GetPreference("pref_priority")).arg(GetPreference("cond_width"))
540  .arg(GetPreference("cond_height")).arg(GetPreference("cond_framerate"))
541  .arg(GetPreference("cond_codecs")));
542  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("decoder:%1 renderer:%2 deint0:%3 deint1:%4 cpus:%5")
543  .arg(GetPreference("pref_decoder")).arg(GetPreference("pref_videorenderer"))
544  .arg(GetPreference("pref_deint0")).arg(GetPreference("pref_deint1"))
545  .arg(GetPreference("pref_max_cpus")));
546 }
547 
548 vector<ProfileItem> VideoDisplayProfile::LoadDB(uint GroupId)
549 {
551  vector<ProfileItem> list;
552 
554  query.prepare(
555  "SELECT profileid, value, data "
556  "FROM displayprofiles "
557  "WHERE profilegroupid = :GROUPID "
558  "ORDER BY profileid");
559  query.bindValue(":GROUPID", GroupId);
560  if (!query.exec())
561  {
562  MythDB::DBError("loaddb 1", query);
563  return list;
564  }
565 
566  uint profileid = 0;
567 
568  while (query.next())
569  {
570  if (query.value(0).toUInt() != profileid)
571  {
572  if (profileid)
573  {
574  tmp.SetProfileID(profileid);
575  QString error;
576  bool valid = tmp.IsValid(&error);
577  if (valid)
578  list.push_back(tmp);
579  else
580  LOG(VB_PLAYBACK, LOG_NOTICE, LOC + QString("Ignoring profile %1 (%2)")
581  .arg(profileid).arg(error));
582  }
583  tmp.Clear();
584  profileid = query.value(0).toUInt();
585  }
586  tmp.Set(query.value(1).toString(), query.value(2).toString());
587  }
588 
589  if (profileid)
590  {
591  tmp.SetProfileID(profileid);
592  QString error;
593  bool valid = tmp.IsValid(&error);
594  if (valid)
595  list.push_back(tmp);
596  else
597  LOG(VB_PLAYBACK, LOG_NOTICE, LOC + QString("Ignoring profile %1 (%2)")
598  .arg(profileid).arg(error));
599  }
600 
601  sort(list.begin(), list.end());
602  return list;
603 }
604 
605 bool VideoDisplayProfile::DeleteDB(uint GroupId, const vector<ProfileItem> &Items)
606 {
608  query.prepare(
609  "DELETE FROM displayprofiles "
610  "WHERE profilegroupid = :GROUPID AND "
611  " profileid = :PROFILEID");
612 
613  bool ok = true;
614  for (const auto & item : Items)
615  {
616  if (!item.GetProfileID())
617  continue;
618 
619  query.bindValue(":GROUPID", GroupId);
620  query.bindValue(":PROFILEID", item.GetProfileID());
621  if (!query.exec())
622  {
623  MythDB::DBError("vdp::deletedb", query);
624  ok = false;
625  }
626  }
627 
628  return ok;
629 }
630 
631 bool VideoDisplayProfile::SaveDB(uint GroupId, vector<ProfileItem> &Items)
632 {
634 
635  MSqlQuery update(MSqlQuery::InitCon());
636  update.prepare(
637  "UPDATE displayprofiles "
638  "SET data = :DATA "
639  "WHERE profilegroupid = :GROUPID AND "
640  " profileid = :PROFILEID AND "
641  " value = :VALUE");
642 
643  MSqlQuery insert(MSqlQuery::InitCon());
644  insert.prepare(
645  "INSERT INTO displayprofiles "
646  " ( profilegroupid, profileid, value, data) "
647  "VALUES "
648  " (:GROUPID, :PROFILEID, :VALUE, :DATA) ");
649 
650  MSqlQuery sqldelete(MSqlQuery::InitCon());
651  sqldelete.prepare(
652  "DELETE FROM displayprofiles "
653  "WHERE profilegroupid = :GROUPID AND "
654  " profileid = :PROFILEID AND "
655  " value = :VALUE");
656 
657  bool ok = true;
658  for (auto & item : Items)
659  {
660  QMap<QString,QString> list = item.GetAll();
661  if (list.begin() == list.end())
662  continue;
663 
664  QMap<QString,QString>::const_iterator lit = list.begin();
665 
666  if (!item.GetProfileID())
667  {
668  // create new profileid
669  if (!query.exec("SELECT MAX(profileid) FROM displayprofiles"))
670  {
671  MythDB::DBError("save_profile 1", query);
672  ok = false;
673  continue;
674  }
675  if (query.next())
676  {
677  item.SetProfileID(query.value(0).toUInt() + 1);
678  }
679 
680  for (; lit != list.end(); ++lit)
681  {
682  if ((*lit).isEmpty())
683  continue;
684 
685  insert.bindValue(":GROUPID", GroupId);
686  insert.bindValue(":PROFILEID", item.GetProfileID());
687  insert.bindValue(":VALUE", lit.key());
688  insert.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
689  if (!insert.exec())
690  {
691  MythDB::DBError("save_profile 2", insert);
692  ok = false;
693  continue;
694  }
695  }
696  continue;
697  }
698 
699  for (; lit != list.end(); ++lit)
700  {
701  query.prepare(
702  "SELECT count(*) "
703  "FROM displayprofiles "
704  "WHERE profilegroupid = :GROUPID AND "
705  " profileid = :PROFILEID AND "
706  " value = :VALUE");
707  query.bindValue(":GROUPID", GroupId);
708  query.bindValue(":PROFILEID", item.GetProfileID());
709  query.bindValue(":VALUE", lit.key());
710 
711  if (!query.exec())
712  {
713  MythDB::DBError("save_profile 3", query);
714  ok = false;
715  continue;
716  }
717  if (query.next() && (1 == query.value(0).toUInt()))
718  {
719  if (lit->isEmpty())
720  {
721  sqldelete.bindValue(":GROUPID", GroupId);
722  sqldelete.bindValue(":PROFILEID", item.GetProfileID());
723  sqldelete.bindValue(":VALUE", lit.key());
724  if (!sqldelete.exec())
725  {
726  MythDB::DBError("save_profile 5a", sqldelete);
727  ok = false;
728  continue;
729  }
730  }
731  else
732  {
733  update.bindValue(":GROUPID", GroupId);
734  update.bindValue(":PROFILEID", item.GetProfileID());
735  update.bindValue(":VALUE", lit.key());
736  update.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
737  if (!update.exec())
738  {
739  MythDB::DBError("save_profile 5b", update);
740  ok = false;
741  continue;
742  }
743  }
744  }
745  else
746  {
747  insert.bindValue(":GROUPID", GroupId);
748  insert.bindValue(":PROFILEID", item.GetProfileID());
749  insert.bindValue(":VALUE", lit.key());
750  insert.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
751  if (!insert.exec())
752  {
753  MythDB::DBError("save_profile 4", insert);
754  ok = false;
755  continue;
756  }
757  }
758  }
759  }
760 
761  return ok;
762 }
763 
765 {
766  InitStatics();
767  return s_safe_decoders;
768 }
769 
771 {
772  InitStatics();
773  QStringList list;
774 
775  const QStringList decs = GetDecoders();
776  for (const auto& dec : qAsConst(decs))
777  list += GetDecoderName(dec);
778 
779  return list;
780 }
781 
783 {
784  if (Decoder.isEmpty())
785  return "";
786 
787  QMutexLocker locker(&s_safe_lock);
788  if (s_dec_name.empty())
789  {
790  s_dec_name["ffmpeg"] = QObject::tr("Standard");
791  s_dec_name["vdpau"] = QObject::tr("NVIDIA VDPAU acceleration");
792  s_dec_name["vdpau-dec"] = QObject::tr("NVIDIA VDPAU acceleration (decode only)");
793  s_dec_name["vaapi"] = QObject::tr("VAAPI acceleration");
794  s_dec_name["vaapi-dec"] = QObject::tr("VAAPI acceleration (decode only)");
795  s_dec_name["dxva2"] = QObject::tr("Windows hardware acceleration");
796  s_dec_name["mediacodec"] = QObject::tr("Android MediaCodec acceleration");
797  s_dec_name["mediacodec-dec"] = QObject::tr("Android MediaCodec acceleration (decode only)");
798  s_dec_name["nvdec"] = QObject::tr("NVIDIA NVDEC acceleration");
799  s_dec_name["nvdec-dec"] = QObject::tr("NVIDIA NVDEC acceleration (decode only)");
800  s_dec_name["vtb"] = QObject::tr("VideoToolbox acceleration");
801  s_dec_name["vtb-dec"] = QObject::tr("VideoToolbox acceleration (decode only)");
802  s_dec_name["v4l2"] = QObject::tr("V4L2 acceleration");
803  s_dec_name["v4l2-dec"] = QObject::tr("V4L2 acceleration (decode only)");
804  s_dec_name["mmal"] = QObject::tr("MMAL acceleration");
805  s_dec_name["mmal-dec"] = QObject::tr("MMAL acceleration (decode only)");
806  s_dec_name["drmprime"] = QObject::tr("DRM PRIME acceleration");
807  }
808 
809  QString ret = Decoder;
810  QMap<QString,QString>::const_iterator it = s_dec_name.find(Decoder);
811  if (it != s_dec_name.end())
812  ret = *it;
813  return ret;
814 }
815 
816 
818 {
819  QString msg = QObject::tr("Processing method used to decode video.");
820 
821  if (Decoder.isEmpty())
822  return msg;
823 
824  msg += "\n";
825 
826  if (Decoder == "ffmpeg")
827  msg += QObject::tr("Standard will use the FFmpeg library for software decoding.");
828 
829  if (Decoder.startsWith("vdpau"))
830  {
831  msg += QObject::tr(
832  "VDPAU will attempt to use the graphics hardware to "
833  "accelerate video decoding.");
834  }
835 
836  if (Decoder.startsWith("vaapi"))
837  {
838  msg += QObject::tr(
839  "VAAPI will attempt to use the graphics hardware to "
840  "accelerate video decoding and playback.");
841  }
842 
843  if (Decoder.startsWith("dxva2"))
844  {
845  msg += QObject::tr(
846  "DXVA2 will use the graphics hardware to "
847  "accelerate video decoding and playback. ");
848  }
849 
850  if (Decoder.startsWith("mediacodec"))
851  {
852  msg += QObject::tr(
853  "Mediacodec will use Android graphics hardware to "
854  "accelerate video decoding and playback. ");
855  }
856 
857  if (Decoder.startsWith("nvdec"))
858  {
859  msg += QObject::tr(
860  "Nvdec uses the NVDEC API to "
861  "accelerate video decoding and playback with NVIDIA Graphics Adapters. ");
862  }
863 
864  if (Decoder.startsWith("vtb"))
865  msg += QObject::tr(
866  "The VideoToolbox library is used to accelerate video decoding. ");
867 
868  if (Decoder.startsWith("mmal"))
869  msg += QObject::tr(
870  "MMAL is used to accelerated video decoding (Raspberry Pi only). ");
871 
872  if (Decoder == "v4l2")
873  msg += "Highly experimental: ";
874 
875  if (Decoder.startsWith("v4l2"))
876  {
877  msg += QObject::tr(
878  "Video4Linux codecs are used to accelerate video decoding on "
879  "supported platforms. ");
880  }
881 
882  if (Decoder == "drmprime")
883  {
884  msg += QObject::tr(
885  "DRM-PRIME decoders are used to accelerate video decoding on "
886  "supported platforms. ");
887  }
888 
889  if (Decoder.endsWith("-dec"))
890  {
891  msg += QObject::tr("The decoder will transfer frames back to system memory "
892  "which will significantly reduce performance but may allow "
893  "other functionality to be used (such as automatic "
894  "letterbox detection). ");
895  }
896  return msg;
897 }
898 
899 QString VideoDisplayProfile::GetVideoRendererName(const QString &Renderer)
900 {
901  QMutexLocker locker(&s_safe_lock);
902  if (s_rend_name.empty())
903  {
904  s_rend_name["opengl"] = QObject::tr("OpenGL");
905  s_rend_name["opengl-yv12"] = QObject::tr("OpenGL YV12");
906  s_rend_name["opengl-hw"] = QObject::tr("OpenGL Hardware");
907  }
908 
909  QString ret = Renderer;
910  QMap<QString,QString>::const_iterator it = s_rend_name.find(Renderer);
911  if (it != s_rend_name.end())
912  ret = *it;
913  return ret;
914 }
915 
916 QStringList VideoDisplayProfile::GetProfiles(const QString &HostName)
917 {
918  InitStatics();
919  QStringList list;
921  query.prepare(
922  "SELECT name "
923  "FROM displayprofilegroups "
924  "WHERE hostname = :HOST ");
925  query.bindValue(":HOST", HostName);
926  if (!query.exec() || !query.isActive())
927  MythDB::DBError("get_profiles", query);
928  else
929  {
930  while (query.next())
931  list += query.value(0).toString();
932  }
933  return list;
934 }
935 
936 QString VideoDisplayProfile::GetDefaultProfileName(const QString &HostName)
937 {
938  QString tmp =
939  gCoreContext->GetSettingOnHost("DefaultVideoPlaybackProfile", HostName);
940 
941  QStringList profiles = GetProfiles(HostName);
942 
943  tmp = (profiles.contains(tmp)) ? tmp : QString();
944 
945  if (tmp.isEmpty())
946  {
947  if (!profiles.empty())
948  tmp = profiles[0];
949 
950  tmp = (profiles.contains("Normal")) ? "Normal" : tmp;
951 
952  if (!tmp.isEmpty())
953  {
955  "DefaultVideoPlaybackProfile", tmp, HostName);
956  }
957  }
958 
959  return tmp;
960 }
961 
962 void VideoDisplayProfile::SetDefaultProfileName(const QString &ProfileName, const QString &HostName)
963 {
964  gCoreContext->SaveSettingOnHost("DefaultVideoPlaybackProfile", ProfileName, HostName);
965 }
966 
967 uint VideoDisplayProfile::GetProfileGroupID(const QString &ProfileName,
968  const QString &HostName)
969 {
971  query.prepare(
972  "SELECT profilegroupid "
973  "FROM displayprofilegroups "
974  "WHERE name = :NAME AND "
975  " hostname = :HOST ");
976  query.bindValue(":NAME", ProfileName);
977  query.bindValue(":HOST", HostName);
978 
979  if (!query.exec() || !query.isActive())
980  MythDB::DBError("get_profile_group_id", query);
981  else if (query.next())
982  return query.value(0).toUInt();
983 
984  return 0;
985 }
986 
988  const QString& Width, const QString& Height, const QString& Codecs,
989  const QString& Decoder, uint MaxCpus, bool SkipLoop, const QString& VideoRenderer,
990  const QString& Deint1, const QString& Deint2)
991 {
993 
994  // create new profileid
995  uint profileid = 1;
996  if (!query.exec("SELECT MAX(profileid) FROM displayprofiles"))
997  MythDB::DBError("create_profile 1", query);
998  else if (query.next())
999  profileid = query.value(0).toUInt() + 1;
1000 
1001  query.prepare(
1002  "INSERT INTO displayprofiles "
1003  "VALUES (:GRPID, :PROFID, 'pref_priority', :PRIORITY)");
1004  query.bindValue(":GRPID", GroupId);
1005  query.bindValue(":PROFID", profileid);
1006  query.bindValue(":PRIORITY", Priority);
1007  if (!query.exec())
1008  MythDB::DBError("create_profile 2", query);
1009 
1010  QStringList queryValue;
1011  QStringList queryData;
1012 
1013  queryValue += "cond_width";
1014  queryData += Width;
1015 
1016  queryValue += "cond_height";
1017  queryData += Height;
1018 
1019  queryValue += "cond_codecs";
1020  queryData += Codecs;
1021 
1022  queryValue += "pref_decoder";
1023  queryData += Decoder;
1024 
1025  queryValue += "pref_max_cpus";
1026  queryData += QString::number(MaxCpus);
1027 
1028  queryValue += "pref_skiploop";
1029  queryData += (SkipLoop) ? "1" : "0";
1030 
1031  queryValue += "pref_videorenderer";
1032  queryData += VideoRenderer;
1033 
1034  queryValue += "pref_deint0";
1035  queryData += Deint1;
1036 
1037  queryValue += "pref_deint1";
1038  queryData += Deint2;
1039 
1040  QStringList::const_iterator itV = queryValue.begin();
1041  QStringList::const_iterator itD = queryData.begin();
1042  for (; itV != queryValue.end() && itD != queryData.end(); ++itV,++itD)
1043  {
1044  if (itD->isEmpty())
1045  continue;
1046  query.prepare(
1047  "INSERT INTO displayprofiles "
1048  "VALUES (:GRPID, :PROFID, :VALUE, :DATA)");
1049  query.bindValue(":GRPID", GroupId);
1050  query.bindValue(":PROFID", profileid);
1051  query.bindValue(":VALUE", *itV);
1052  query.bindValue(":DATA", *itD);
1053  if (!query.exec())
1054  MythDB::DBError("create_profile 3", query);
1055  }
1056 }
1057 
1058 uint VideoDisplayProfile::CreateProfileGroup(const QString &ProfileName, const QString &HostName)
1059 {
1061  query.prepare(
1062  "INSERT INTO displayprofilegroups (name, hostname) "
1063  "VALUES (:NAME,:HOST)");
1064 
1065  query.bindValue(":NAME", ProfileName);
1066  query.bindValue(":HOST", HostName);
1067 
1068  if (!query.exec())
1069  {
1070  MythDB::DBError("create_profile_group", query);
1071  return 0;
1072  }
1073 
1074  return GetProfileGroupID(ProfileName, HostName);
1075 }
1076 
1077 bool VideoDisplayProfile::DeleteProfileGroup(const QString &GroupName, const QString &HostName)
1078 {
1079  bool ok = true;
1081  MSqlQuery query2(MSqlQuery::InitCon());
1082 
1083  query.prepare(
1084  "SELECT profilegroupid "
1085  "FROM displayprofilegroups "
1086  "WHERE name = :NAME AND "
1087  " hostname = :HOST ");
1088 
1089  query.bindValue(":NAME", GroupName);
1090  query.bindValue(":HOST", HostName);
1091 
1092  if (!query.exec() || !query.isActive())
1093  {
1094  MythDB::DBError("delete_profile_group 1", query);
1095  ok = false;
1096  }
1097  else
1098  {
1099  while (query.next())
1100  {
1101  query2.prepare("DELETE FROM displayprofiles "
1102  "WHERE profilegroupid = :PROFID");
1103  query2.bindValue(":PROFID", query.value(0).toUInt());
1104  if (!query2.exec())
1105  {
1106  MythDB::DBError("delete_profile_group 2", query2);
1107  ok = false;
1108  }
1109  }
1110  }
1111 
1112  query.prepare(
1113  "DELETE FROM displayprofilegroups "
1114  "WHERE name = :NAME AND "
1115  " hostname = :HOST");
1116 
1117  query.bindValue(":NAME", GroupName);
1118  query.bindValue(":HOST", HostName);
1119 
1120  if (!query.exec())
1121  {
1122  MythDB::DBError("delete_profile_group 3", query);
1123  ok = false;
1124  }
1125 
1126  return ok;
1127 }
1128 
1129 void VideoDisplayProfile::CreateProfiles(const QString &HostName)
1130 {
1131  QStringList profiles = GetProfiles(HostName);
1132 
1133 #ifdef USING_OPENGL
1134  if (!profiles.contains("OpenGL High Quality"))
1135  {
1136  (void) QObject::tr("OpenGL High Quality",
1137  "Sample: OpenGL high quality");
1138  uint groupid = CreateProfileGroup("OpenGL High Quality", HostName);
1139  CreateProfile(groupid, 1, "", "", "",
1140  "ffmpeg", 2, true, "opengl-yv12",
1141  "shader:high", "shader:high");
1142  }
1143 
1144  if (!profiles.contains("OpenGL Normal"))
1145  {
1146  (void) QObject::tr("OpenGL Normal", "Sample: OpenGL medium quality");
1147  uint groupid = CreateProfileGroup("OpenGL Normal", HostName);
1148  CreateProfile(groupid, 1, "", "", "",
1149  "ffmpeg", 2, true, "opengl-yv12",
1150  "shader:medium", "shader:medium");
1151  }
1152 
1153  if (!profiles.contains("OpenGL Slim"))
1154  {
1155  (void) QObject::tr("OpenGL Slim", "Sample: OpenGL low power GPU");
1156  uint groupid = CreateProfileGroup("OpenGL Slim", HostName);
1157  CreateProfile(groupid, 1, "", "", "",
1158  "ffmpeg", 1, true, "opengl",
1159  "medium", "medium");
1160  }
1161 #endif
1162 
1163 #ifdef USING_VAAPI
1164  if (!profiles.contains("VAAPI Normal"))
1165  {
1166  (void) QObject::tr("VAAPI Normal", "Sample: VAAPI average quality");
1167  uint groupid = CreateProfileGroup("VAAPI Normal", HostName);
1168  CreateProfile(groupid, 1, "", "", "",
1169  "vaapi", 2, true, "opengl-hw",
1170  "shader:driver:high", "shader:driver:high");
1171  CreateProfile(groupid, 1, "", "", "",
1172  "ffmpeg", 2, true, "opengl-yv12",
1173  "shader:medium", "shader:medium");
1174  }
1175 #endif
1176 
1177 #ifdef USING_VDPAU
1178  if (!profiles.contains("VDPAU Normal"))
1179  {
1180  (void) QObject::tr("VDPAU Normal", "Sample: VDPAU medium quality");
1181  uint groupid = CreateProfileGroup("VDPAU Normal", HostName);
1182  CreateProfile(groupid, 1, "", "", "",
1183  "vdpau", 1, true, "opengl-hw",
1184  "driver:medium", "driver:medium");
1185  CreateProfile(groupid, 1, "", "", "",
1186  "ffmpeg", 2, true, "opengl-yv12",
1187  "shader:medium", "shader:medium");
1188  }
1189 #endif
1190 
1191 #ifdef USING_MEDIACODEC
1192  if (!profiles.contains("MediaCodec Normal"))
1193  {
1194  (void) QObject::tr("MediaCodec Normal",
1195  "Sample: MediaCodec Normal");
1196  uint groupid = CreateProfileGroup("MediaCodec Normal", HostName);
1197  CreateProfile(groupid, 1, "", "", "",
1198  "mediacodec-dec", 4, true, "opengl-yv12",
1199  "shader:driver:medium", "shader:driver:medium");
1200  CreateProfile(groupid, 1, "", "", "",
1201  "ffmpeg", 2, true, "opengl-yv12",
1202  "shader:medium", "shader:medium");
1203 
1204  }
1205 #endif
1206 
1207 #if defined(USING_NVDEC) && defined(USING_OPENGL)
1208  if (!profiles.contains("NVDEC Normal"))
1209  {
1210  (void) QObject::tr("NVDEC Normal", "Sample: NVDEC Normal");
1211  uint groupid = CreateProfileGroup("NVDEC Normal", HostName);
1212  CreateProfile(groupid, 1, "", "", "",
1213  "nvdec", 1, true, "opengl-hw",
1214  "shader:driver:high", "shader:driver:high");
1215  CreateProfile(groupid, 1, "", "", "",
1216  "ffmpeg", 2, true, "opengl-yv12",
1217  "shader:high", "shader:high");
1218  }
1219 #endif
1220 
1221 #if defined(USING_VTB) && defined(USING_OPENGL)
1222  if (!profiles.contains("VideoToolBox Normal")) {
1223  (void) QObject::tr("VideoToolBox Normal", "Sample: VideoToolBox Normal");
1224  uint groupid = CreateProfileGroup("VideoToolBox Normal", HostName);
1225  CreateProfile(groupid, 1, "", "", "",
1226  "vtb", 1, true, "opengl-hw",
1227  "shader:driver:medium", "shader:driver:medium");
1228  CreateProfile(groupid, 1, "", "", "",
1229  "ffmpeg", 2, true, "opengl-yv12",
1230  "shader:medium", "shader:medium");
1231  }
1232 #endif
1233 
1234 #if defined(USING_MMAL) && defined(USING_OPENGL)
1235  if (!profiles.contains("MMAL"))
1236  {
1237  (void) QObject::tr("MMAL", "Sample: MMAL");
1238  uint groupid = CreateProfileGroup("MMAL", HostName);
1239  CreateProfile(groupid, 1, "", "", "",
1240  "mmal", 1, true, "opengl-hw",
1241  "shader:driver:medium", "shader:driver:medium");
1242  CreateProfile(groupid, 1, "", "", "",
1243  "ffmpeg", 2, true, "opengl-yv12",
1244  "shader:medium", "shader:medium");
1245  }
1246 #endif
1247 
1248 #if defined(USING_V4L2)
1249  if (!profiles.contains("V4L2 Codecs"))
1250  {
1251  (void) QObject::tr("V4L2 Codecs", "Sample: V4L2");
1252  uint groupid = CreateProfileGroup("V4L2 Codecs", HostName);
1253  CreateProfile(groupid, 2, "", "", "",
1254  "v4l2", 1, true, "opengl-hw",
1255  "shader:driver:medium", "shader:driver:medium");
1256  CreateProfile(groupid, 1, "", "", "",
1257  "ffmpeg", 2, true, "opengl-yv12",
1258  "shader:medium", "shader:medium");
1259  }
1260 #endif
1261 }
1262 
1264 {
1265  QMutexLocker locker(&s_safe_lock);
1266  InitStatics();
1267 
1268  QMap<QString,QStringList>::const_iterator it = s_safe_renderer.find(Decoder);
1269  QStringList tmp;
1270  if (it != s_safe_renderer.end())
1271  tmp = *it;
1272  return tmp;
1273 }
1274 
1275 QString VideoDisplayProfile::GetVideoRendererHelp(const QString &Renderer)
1276 {
1277  QString msg = QObject::tr("Video rendering method");
1278 
1279  if (Renderer.isEmpty())
1280  return msg;
1281 
1282  if (Renderer == "null")
1283  msg = QObject::tr(
1284  "Render video offscreen. Used internally.");
1285 
1286  if (Renderer == "direct3d")
1287  {
1288  msg = QObject::tr(
1289  "Windows video renderer based on Direct3D. Requires "
1290  "video card compatible with Direct3D 9. This is the preferred "
1291  "renderer for current Windows systems.");
1292  }
1293 
1294  if (Renderer == "opengl")
1295  {
1296  msg = QObject::tr(
1297  "Video is converted to an intermediate format by the CPU (YUV2) "
1298  "before OpenGL is used for color conversion, scaling, picture controls"
1299  " and optionally deinterlacing. Processing is balanced between the CPU "
1300  "and GPU.");
1301  }
1302 
1303  if (Renderer == "opengl-yv12")
1304  {
1305  msg = QObject::tr(
1306  "OpenGL is used for all color conversion, scaling, picture "
1307  "controls and optionally deinterlacing. CPU load is low but a slightly more "
1308  "powerful GPU is needed for deinterlacing.");
1309  }
1310 
1311  if (Renderer == "opengl-hw")
1312  {
1313  msg = QObject::tr(
1314  "This video renderer is used by hardware decoders to display "
1315  "frames using OpenGL.");
1316  }
1317 
1318  return msg;
1319 }
1320 
1322 {
1324 }
1325 
1326 bool VideoDisplayProfile::IsFilterAllowed(const QString &VideoRenderer)
1327 {
1328  QMutexLocker locker(&s_safe_lock);
1329  InitStatics();
1330  return s_safe_custom.contains(VideoRenderer);
1331 }
1332 
1333 QStringList VideoDisplayProfile::GetFilteredRenderers(const QString &Decoder, const QStringList &Renderers)
1334 {
1335  const QStringList dec_list = GetVideoRenderers(Decoder);
1336  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Safe renderers for '%1': %2")
1337  .arg(Decoder).arg(dec_list.join(",")));
1338  QStringList new_list;
1339 
1340  for (const auto& dec : qAsConst(dec_list))
1341  if (Renderers.contains(dec))
1342  new_list.push_back(dec);
1343 
1344  return new_list;
1345 }
1346 
1347 QString VideoDisplayProfile::GetBestVideoRenderer(const QStringList &Renderers)
1348 {
1349  QMutexLocker locker(&s_safe_lock);
1350  InitStatics();
1351 
1352  uint top_priority = 0;
1353  QString top_renderer;
1354 
1355  for (const auto& renderer : qAsConst(Renderers))
1356  {
1357  QMap<QString,uint>::const_iterator p = s_safe_renderer_priority.find(renderer);
1358  if ((p != s_safe_renderer_priority.end()) && (*p >= top_priority))
1359  {
1360  top_priority = *p;
1361  top_renderer = renderer;
1362  }
1363  }
1364 
1365  return top_renderer;
1366 }
1367 
1369 {
1370  QString renderer = GetPreference("pref_videorenderer");
1371  QString deint0 = GetPreference("pref_deint0");
1372  QString deint1 = GetPreference("pref_deint1");
1373  QString cpus = GetPreference("pref_max_cpus");
1374  return QString("rend:%1 deint:%2/%3 CPUs: %4")
1375  .arg(renderer).arg(deint0).arg(deint1).arg(cpus);
1376 }
1377 
1378 QList<QPair<QString,QString> > VideoDisplayProfile::GetDeinterlacers(void)
1379 {
1380  InitStatics();
1381  return s_deinterlacer_options;
1382 }
1383 
1384 void VideoDisplayProfile::InitStatics(bool Reinit /*= false*/)
1385 {
1386  if (Reinit)
1387  {
1388  s_safe_custom.clear();
1389  s_safe_renderer.clear();
1390  s_safe_renderer_group.clear();
1391  s_safe_renderer_priority.clear();
1392  s_safe_decoders.clear();
1393  s_safe_equiv_dec.clear();
1394  s_deinterlacer_options.clear();
1395  }
1396  else if (s_safe_initialized)
1397  {
1398  return;
1399  }
1400  s_safe_initialized = true;
1401 
1403  options.renderers = &s_safe_custom;
1404  options.safe_renderers = &s_safe_renderer;
1405  options.render_group = &s_safe_renderer_group;
1406  options.priorities = &s_safe_renderer_priority;
1407  options.decoders = &s_safe_decoders;
1408  options.equiv_decoders = &s_safe_equiv_dec;
1409 
1410  // N.B. assumes NuppelDecoder and DummyDecoder always present
1413 
1414  for (const QString& decoder : qAsConst(s_safe_decoders))
1415  {
1416  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1417  QString("decoder<->render support: %1%2")
1418  .arg(decoder, -12).arg(GetVideoRenderers(decoder).join(" ")));
1419  }
1420 
1421  s_deinterlacer_options.append(QPair<QString,QString>(DEINT_QUALITY_NONE, QObject::tr("None")));
1422  s_deinterlacer_options.append(QPair<QString,QString>(DEINT_QUALITY_LOW, QObject::tr("Low quality")));
1423  s_deinterlacer_options.append(QPair<QString,QString>(DEINT_QUALITY_MEDIUM, QObject::tr("Medium quality")));
1424  s_deinterlacer_options.append(QPair<QString,QString>(DEINT_QUALITY_HIGH, QObject::tr("High quality")));
1425 }
VideoDisplayProfile::m_lastRate
float m_lastRate
Definition: videodisplayprofile.h:132
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
VideoDisplayProfile::CreateProfiles
static void CreateProfiles(const QString &HostName)
Definition: videodisplayprofile.cpp:1129
mythvideoout.h
VideoDisplayProfile::SetInput
void SetInput(const QSize &Size, float Framerate=0, const QString &CodecName=QString(), const QStringList &DisallowedDecoders=QStringList())
Definition: videodisplayprofile.cpp:359
error
static void error(const char *str,...)
Definition: vbi.cpp:42
VideoDisplayProfile::GetPreferredVideoRenderer
static QString GetPreferredVideoRenderer(const QString &Decoder)
Definition: videodisplayprofile.cpp:1321
mythdb.h
VideoDisplayProfile::m_lock
QMutex m_lock
Definition: videodisplayprofile.h:130
VideoDisplayProfile::GetOutput
float GetOutput(void) const
Definition: videodisplayprofile.cpp:394
VideoDisplayProfile::SaveDB
static bool SaveDB(uint GroupId, vector< ProfileItem > &Items)
Definition: videodisplayprofile.cpp:631
VideoDisplayProfile::toString
QString toString(void) const
Definition: videodisplayprofile.cpp:1368
ProfileItem::CheckRange
bool CheckRange(const QString &Key, float Value, bool *Ok=nullptr) const
Definition: videodisplayprofile.cpp:56
VideoDisplayProfile::SetOutput
void SetOutput(float Framerate)
Definition: videodisplayprofile.cpp:384
ProfileItem
Definition: videodisplayprofile.h:37
VideoDisplayProfile::DeleteProfileGroup
static bool DeleteProfileGroup(const QString &GroupName, const QString &HostName)
Definition: videodisplayprofile.cpp:1077
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
arg
arg(title).arg(filename).arg(doDelete))
VideoDisplayProfile::GetActualVideoRenderer
QString GetActualVideoRenderer(void) const
Definition: videodisplayprofile.cpp:429
VideoDisplayProfile::InitStatics
static void InitStatics(bool Reinit=false)
Definition: videodisplayprofile.cpp:1384
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
VideoDisplayProfile::IsSkipLoopEnabled
bool IsSkipLoopEnabled(void) const
Definition: videodisplayprofile.cpp:419
VideoDisplayProfile::s_safe_equiv_dec
static QMap< QString, QStringList > s_safe_equiv_dec
Definition: videodisplayprofile.h:142
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
ProfileItem::GetProfileID
uint GetProfileID(void) const
Definition: videodisplayprofile.cpp:28
VideoDisplayProfile::GetDecoder
QString GetDecoder(void) const
Definition: videodisplayprofile.cpp:399
ProfileItem::GetPriority
uint GetPriority(void) const
Definition: videodisplayprofile.cpp:46
VideoDisplayProfile::VideoDisplayProfile
VideoDisplayProfile()
Definition: videodisplayprofile.cpp:334
VideoDisplayProfile::FindMatch
vector< ProfileItem >::const_iterator FindMatch(const QSize &Size, float Framerate, const QString &CodecName, QStringList DisallowedDecoders=QStringList())
Definition: videodisplayprofile.cpp:505
VideoDisplayProfile::s_safe_renderer_priority
static QMap< QString, uint > s_safe_renderer_priority
Definition: videodisplayprofile.h:144
ProfileItem::m_profileid
uint m_profileid
Definition: videodisplayprofile.h:65
VideoDisplayProfile::GetVideoRendererHelp
static QString GetVideoRendererHelp(const QString &Renderer)
Definition: videodisplayprofile.cpp:1275
VideoDisplayProfile::SetPreference
void SetPreference(const QString &Key, const QString &Value)
Definition: videodisplayprofile.cpp:496
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
VideoDisplayProfile::m_lastCodecName
QString m_lastCodecName
Definition: videodisplayprofile.h:133
videodisplayprofile.h
VideoDisplayProfile::SetDefaultProfileName
static void SetDefaultProfileName(const QString &ProfileName, const QString &HostName)
Definition: videodisplayprofile.cpp:962
LOC
#define LOC
Definition: videodisplayprofile.cpp:320
Decoder
Definition: decoder.h:65
mythlogging.h
RenderOptions
Definition: videodisplayprofile.h:27
VideoDisplayProfile::DeleteDB
static bool DeleteDB(uint GroupId, const vector< ProfileItem > &Items)
Definition: videodisplayprofile.cpp:605
VideoDisplayProfile::GetDoubleRatePreferences
QString GetDoubleRatePreferences(void) const
Definition: videodisplayprofile.cpp:409
DEINT_QUALITY_HIGH
#define DEINT_QUALITY_HIGH
Definition: videodisplayprofile.h:21
VideoDisplayProfile::GetMaxCPUs
uint GetMaxCPUs(void) const
Definition: videodisplayprofile.cpp:414
VideoDisplayProfile::GetFilteredRenderers
static QStringList GetFilteredRenderers(const QString &Decoder, const QStringList &Renderers)
Definition: videodisplayprofile.cpp:1333
hardwareprofile.config.p
p
Definition: config.py:33
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
VideoDisplayProfile::IsFilterAllowed
static bool IsFilterAllowed(const QString &VideoRenderer)
Definition: videodisplayprofile.cpp:1326
VideoDisplayProfile::s_safe_initialized
static bool s_safe_initialized
Definition: videodisplayprofile.h:139
ProfileItem::Get
QString Get(const QString &Value) const
Definition: videodisplayprofile.cpp:38
ProfileItem::GetAll
QMap< QString, QString > GetAll(void) const
Definition: videodisplayprofile.cpp:33
ProfileItem::Set
void Set(const QString &Value, const QString &Data)
Definition: videodisplayprofile.cpp:23
DEINT_QUALITY_NONE
#define DEINT_QUALITY_NONE
Definition: videodisplayprofile.h:18
VideoDisplayProfile::SetVideoRenderer
void SetVideoRenderer(const QString &VideoRenderer)
Definition: videodisplayprofile.cpp:434
VideoDisplayProfile::s_deinterlacer_options
static QList< QPair< QString, QString > > s_deinterlacer_options
Definition: videodisplayprofile.h:148
VideoDisplayProfile::m_currentPreferences
QMap< QString, QString > m_currentPreferences
Definition: videodisplayprofile.h:135
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
ProfileItem::Clear
void Clear(void)
Definition: videodisplayprofile.cpp:13
VideoDisplayProfile::GetProfileGroupID
static uint GetProfileGroupID(const QString &ProfileName, const QString &HostName)
Definition: videodisplayprofile.cpp:967
ProfileItem::toString
QString toString(void) const
Definition: videodisplayprofile.cpp:292
VideoDisplayProfile::m_lastSize
QSize m_lastSize
Definition: videodisplayprofile.h:131
VideoDisplayProfile::CreateProfileGroup
static uint CreateProfileGroup(const QString &ProfileName, const QString &HostName)
Definition: videodisplayprofile.cpp:1058
VideoDisplayProfile::GetDeinterlacers
static QList< QPair< QString, QString > > GetDeinterlacers(void)
Definition: videodisplayprofile.cpp:1378
VideoDisplayProfile::GetProfiles
static QStringList GetProfiles(const QString &HostName)
Definition: videodisplayprofile.cpp:916
VideoDisplayProfile::IsDecoderCompatible
bool IsDecoderCompatible(const QString &Decoder) const
Definition: videodisplayprofile.cpp:472
VideoDisplayProfile::s_safe_renderer_group
static QMap< QString, QStringList > s_safe_renderer_group
Definition: videodisplayprofile.h:141
VideoDisplayProfile::GetDecoderHelp
static QString GetDecoderHelp(const QString &Decoder=QString())
Definition: videodisplayprofile.cpp:817
VideoDisplayProfile::GetDecoderNames
static QStringList GetDecoderNames(void)
Definition: videodisplayprofile.cpp:770
VideoDisplayProfile::s_safe_renderer
static QMap< QString, QStringList > s_safe_renderer
Definition: videodisplayprofile.h:140
VideoDisplayProfile::s_safe_decoders
static QStringList s_safe_decoders
Definition: videodisplayprofile.h:147
ProfileItem::IsValid
bool IsValid(QString *Reason=nullptr) const
Definition: videodisplayprofile.cpp:229
ProfileItem::SetProfileID
void SetProfileID(uint Id)
Definition: videodisplayprofile.cpp:18
AvFormatDecoder::GetDecoders
static void GetDecoders(RenderOptions &opts)
Definition: avformatdecoder.cpp:309
VideoDisplayProfile::GetVideoRenderer
QString GetVideoRenderer(void) const
Definition: videodisplayprofile.cpp:424
mythcorecontext.h
VideoDisplayProfile::CreateProfile
static void CreateProfile(uint GroupId, uint Priority, const QString &Width, const QString &Height, const QString &Codecs, const QString &Decoder, uint MaxCpus, bool SkipLoop, const QString &VideoRenderer, const QString &Deint1, const QString &Deint2)
Definition: videodisplayprofile.cpp:987
MythCoreContext::GetSettingOnHost
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
Definition: mythcorecontext.cpp:923
avformatdecoder.h
VIDEO_MAX_CPUS
#define VIDEO_MAX_CPUS
Definition: videodisplayprofile.h:25
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
VideoDisplayProfile::GetDecoderName
static QString GetDecoderName(const QString &Decoder)
Definition: videodisplayprofile.cpp:782
VideoDisplayProfile::s_safe_custom
static QStringList s_safe_custom
Definition: videodisplayprofile.h:143
DEINT_QUALITY_LOW
#define DEINT_QUALITY_LOW
Definition: videodisplayprofile.h:19
VideoDisplayProfile::s_safe_lock
static QMutex s_safe_lock
Definition: videodisplayprofile.h:138
VideoDisplayProfile::s_dec_name
static QMap< QString, QString > s_dec_name
Definition: videodisplayprofile.h:145
VideoDisplayProfile::LoadBestPreferences
void LoadBestPreferences(const QSize &Size, float Framerate, const QString &CodecName, const QStringList &DisallowedDecoders=QStringList())
Definition: videodisplayprofile.cpp:514
VideoDisplayProfile::GetVideoRenderers
static QStringList GetVideoRenderers(const QString &Decoder)
Definition: videodisplayprofile.cpp:1263
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:841
VideoDisplayProfile::GetPreference
QString GetPreference(const QString &Key) const
Definition: videodisplayprofile.cpp:482
MythVideoOutput::GetRenderOptions
static void GetRenderOptions(RenderOptions &Options)
Definition: mythvideoout.cpp:28
ProfileItem::m_pref
QMap< QString, QString > m_pref
Definition: videodisplayprofile.h:66
VideoDisplayProfile::GetVideoRendererName
static QString GetVideoRendererName(const QString &Renderer)
Definition: videodisplayprofile.cpp:899
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
VideoDisplayProfile::m_lastVideoRenderer
QString m_lastVideoRenderer
Definition: videodisplayprofile.h:134
VideoDisplayProfile::LoadDB
static vector< ProfileItem > LoadDB(uint GroupId)
Definition: videodisplayprofile.cpp:548
VideoDisplayProfile::s_rend_name
static QMap< QString, QString > s_rend_name
Definition: videodisplayprofile.h:146
VideoDisplayProfile::m_allowedPreferences
vector< ProfileItem > m_allowedPreferences
Definition: videodisplayprofile.h:136
VideoDisplayProfile::GetSingleRatePreferences
QString GetSingleRatePreferences(void) const
Definition: videodisplayprofile.cpp:404
ProfileItem::IsMatch
bool IsMatch(const QSize &Size, float Framerate, const QString &CodecName, const QStringList &DisallowedDecoders=QStringList()) const
Definition: videodisplayprofile.cpp:200
query
MSqlQuery query(MSqlQuery::InitCon())
build_compdb.options
options
Definition: build_compdb.py:11
MythCoreContext::SaveSettingOnHost
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
Definition: mythcorecontext.cpp:894
ProfileItem::operator<
bool operator<(const ProfileItem &Other) const
Definition: videodisplayprofile.cpp:287
VideoDisplayProfile::GetDefaultProfileName
static QString GetDefaultProfileName(const QString &HostName)
Definition: videodisplayprofile.cpp:936
DEINT_QUALITY_MEDIUM
#define DEINT_QUALITY_MEDIUM
Definition: videodisplayprofile.h:20
Priority
Definition: channelsettings.cpp:191
VideoDisplayProfile::CheckVideoRendererGroup
bool CheckVideoRendererGroup(const QString &Renderer)
Definition: videodisplayprofile.cpp:457
VideoDisplayProfile::GetDecoders
static QStringList GetDecoders(void)
Definition: videodisplayprofile.cpp:764
VideoDisplayProfile::GetBestVideoRenderer
static QString GetBestVideoRenderer(const QStringList &Renderers)
Definition: videodisplayprofile.cpp:1347
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808