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