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