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