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