MythTV  master
videodisplayprofile.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 #include <algorithm>
3 #include <utility>
4 using namespace std;
5 
6 #include "videodisplayprofile.h"
7 #include "mythcorecontext.h"
8 #include "mythdb.h"
9 #include "mythlogging.h"
10 #include "videooutbase.h"
11 #include "avformatdecoder.h"
12 #include "mythcodeccontext.h"
13 
14 
15 // options are NNN NNN-MMM 0-MMM NNN-99999 >NNN >=NNN <MMM <=MMM or blank
16 // If string is blank then assumes a match.
17 // If value is 0 or negative assume a match (i.e. value unknown assumes a match)
18 // float values must be no more than 3 decimals.
19 
20 bool ProfileItem::checkRange(QString key, float fvalue, bool *ok) const
21 {
22  return checkRange(std::move(key), fvalue, 0, true, ok);
23 }
24 
25 bool ProfileItem::checkRange(QString key, int ivalue, bool *ok) const
26 {
27  return checkRange(std::move(key), 0.0, ivalue, false, ok);
28 }
29 
30 bool ProfileItem::checkRange(const QString& key,
31  float fvalue, int ivalue, bool isFloat, bool *ok) const
32 {
33  bool match = true;
34  bool isOK = true;
35  if (isFloat)
36  ivalue = int(fvalue * 1000.0F);
37  QString cmp = Get(key);
38  if (!cmp.isEmpty())
39  {
40  cmp.replace(QLatin1String(" "),QLatin1String(""));
41  QStringList expr = cmp.split("&");
42  for (int ix = 0; ix < expr.size(); ++ix)
43  {
44  if (expr[ix].isEmpty())
45  {
46  isOK = false;
47  continue;
48  }
49  if (ivalue > 0)
50  {
51  QRegularExpression regex("^([0-9.]*)([^0-9.]*)([0-9.]*)$");
52  QRegularExpressionMatch rmatch = regex.match(expr[ix]);
53 
54  int value1 = 0;
55  int value2 = 0;
56  QString oper;
57  QString capture1 = rmatch.captured(1);
58  QString capture3;
59  if (!capture1.isEmpty())
60  {
61  if (isFloat)
62  {
63  int dec=capture1.indexOf('.');
64  if (dec > -1 && (capture1.length()-dec) > 4)
65  isOK = false;
66  if (isOK)
67  {
68  double double1 = capture1.toDouble(&isOK);
69  if (double1 > 2000000.0 || double1 < 0.0)
70  isOK = false;
71  value1 = int(double1 * 1000.0);
72  }
73  }
74  else
75  value1 = capture1.toInt(&isOK);
76  }
77  if (isOK)
78  {
79  oper = rmatch.captured(2);
80  capture3 = rmatch.captured(3);
81  if (!capture3.isEmpty())
82  {
83  if (isFloat)
84  {
85  int dec=capture3.indexOf('.');
86  if (dec > -1 && (capture3.length()-dec) > 4)
87  isOK = false;
88  if (isOK)
89  {
90  double double1 = capture3.toDouble(&isOK);
91  if (double1 > 2000000.0 || double1 < 0.0)
92  isOK = false;
93  value2 = int(double1 * 1000.0);
94  }
95  }
96  else
97  value2 = capture3.toInt(&isOK);
98  }
99  }
100  if (isOK)
101  {
102  // Invalid string
103  if (value1 == 0 && value2 == 0 && oper.isEmpty())
104  isOK=false;
105  }
106  if (isOK)
107  {
108  // Case NNN
109  if (value1 != 0 && oper.isEmpty() && value2 == 0)
110  {
111  value2 = value1;
112  oper = "-";
113  }
114  // NNN-MMM 0-MMM NNN-99999 NNN- -MMM
115  else if (oper == "-")
116  {
117  // NNN- or -NNN
118  if (capture1.isEmpty() || capture3.isEmpty())
119  isOK = false;
120  // NNN-MMM
121  if (value2 < value1)
122  isOK = false;
123  }
124  else if (capture1.isEmpty())
125  {
126  // Other operators == > < >= <=
127  // Convert to a range
128  if (oper == "==")
129  value1 = value2;
130  else if (oper == ">")
131  {
132  value1 = value2 + 1;
133  value2 = 99999999;
134  }
135  else if (oper == ">=")
136  {
137  value1 = value2;
138  value2 = 99999999;
139  }
140  else if (oper == "<")
141  value2 = value2 - 1;
142  else if (oper == "<=")
143  ;
144  else isOK = false;
145  oper = "-";
146  }
147  }
148  if (isOK)
149  {
150  if (oper == "-")
151  match = match && (ivalue >= value1 && ivalue <= value2);
152  else isOK = false;
153  }
154  }
155  }
156  }
157  if (ok != nullptr)
158  *ok = isOK;
159  if (!isOK)
160  match=false;
161  return match;
162 }
163 
164 bool ProfileItem::IsMatch(const QSize &size,
165  float framerate, const QString &codecName) const
166 {
167  bool match = true;
168 
169  QString cmp;
170 
171  // cond_width, cond_height, cond_codecs, cond_framerate.
172  // These replace old settings pref_cmp0 and pref_cmp1
173  match &= checkRange("cond_width",size.width());
174  match &= checkRange("cond_height",size.height());
175  match &= checkRange("cond_framerate",framerate);
176  // codec
177  cmp = Get(QString("cond_codecs"));
178  if (!cmp.isEmpty())
179  {
180  QStringList clist = cmp.split(" ", QString::SkipEmptyParts);
181  if (!clist.empty())
182  match &= clist.contains(codecName,Qt::CaseInsensitive);
183  }
184 
185  return match;
186 }
187 
188 
189 static QString toCommaList(const QStringList &list)
190 {
191  QString ret = "";
192  for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
193  ret += *it + ",";
194 
195  if (ret.length())
196  return ret.left(ret.length()-1);
197 
198  return "";
199 }
200 
201 bool ProfileItem::IsValid(QString *reason) const
202 {
203 
204  bool isOK = true;
205  checkRange("cond_width",1,&isOK);
206  if (!isOK)
207  {
208  if (reason)
209  *reason = QString("Invalid width condition");
210  return false;
211  }
212  checkRange("cond_height",1,&isOK);
213  if (!isOK)
214  {
215  if (reason)
216  *reason = QString("Invalid height condition");
217  return false;
218  }
219  checkRange("cond_framerate",1.0F,&isOK);
220  if (!isOK)
221  {
222  if (reason)
223  *reason = QString("Invalid framerate condition");
224  return false;
225  }
226 
227  QString decoder = Get("pref_decoder");
228  QString renderer = Get("pref_videorenderer");
229  if (decoder.isEmpty() || renderer.isEmpty())
230  {
231  if (reason)
232  *reason = "Need a decoder and renderer";
233 
234  return false;
235  }
236 
237  QStringList decoders = VideoDisplayProfile::GetDecoders();
238  if (!decoders.contains(decoder))
239  {
240  if (reason)
241  {
242  *reason = QString("decoder %1 is not supported (supported: %2)")
243  .arg(decoder).arg(toCommaList(decoders));
244  }
245 
246  return false;
247  }
248 
249  QStringList renderers = VideoDisplayProfile::GetVideoRenderers(decoder);
250  if (!renderers.contains(renderer))
251  {
252  if (reason)
253  {
254  *reason = QString("renderer %1 is not supported "
255  "w/decoder %2 (supported: %3)")
256  .arg(renderer).arg(decoder).arg(toCommaList(renderers));
257  }
258 
259  return false;
260  }
261 
262  QStringList deints = VideoDisplayProfile::GetDeinterlacers(renderer);
263  QStringList decoderdeints = MythCodecContext::GetDeinterlacers(decoder);
264  deints.append(decoderdeints);
265  QString deint0 = Get("pref_deint0");
266  QString deint1 = Get("pref_deint1");
267  if (!deint0.isEmpty() && !deints.contains(deint0))
268  {
269  if (reason)
270  {
271  *reason = QString("deinterlacer %1 is not supported "
272  "w/renderer %2 (supported: %3)")
273  .arg(deint0).arg(renderer).arg(toCommaList(deints));
274  }
275 
276  return false;
277  }
278 
279  if (!deint1.isEmpty() &&
280  (!deints.contains(deint1) ||
281  deint1.contains("bobdeint") ||
282  deint1.contains("doublerate") ||
283  deint1.contains("doubleprocess")))
284  {
285  if (reason)
286  {
287  if (deint1.contains("bobdeint") ||
288  deint1.contains("doublerate") ||
289  deint1.contains("doubleprocess"))
290  deints.removeAll(deint1);
291 
292  *reason = QString("deinterlacer %1 is not supported w/renderer %2 "
293  "as second deinterlacer (supported: %3)")
294  .arg(deint1).arg(renderer).arg(toCommaList(deints));
295  }
296 
297  return false;
298  }
299 
300  QStringList osds = VideoDisplayProfile::GetOSDs(renderer);
301  QString osd = Get("pref_osdrenderer");
302  if (!osds.contains(osd))
303  {
304  if (reason)
305  {
306  *reason = QString("OSD Renderer %1 is not supported "
307  "w/renderer %2 (supported: %3)")
308  .arg(osd).arg(renderer).arg(toCommaList(osds));
309  }
310 
311  return false;
312  }
313 
314  QString filter = Get("pref_filters");
315  if (!filter.isEmpty() && !VideoDisplayProfile::IsFilterAllowed(renderer))
316  {
317  if (reason)
318  {
319  *reason = QString("Filter %1 is not supported w/renderer %2")
320  .arg(filter).arg(renderer);
321  }
322 
323  return false;
324  }
325 
326  if (reason)
327  *reason = QString();
328 
329  return true;
330 }
331 
332 bool ProfileItem::operator< (const ProfileItem &other) const
333 {
334  return GetPriority() < other.GetPriority();
335 }
336 
337 QString ProfileItem::toString(void) const
338 {
339  QString cmp0 = Get("pref_cmp0");
340  QString cmp1 = Get("pref_cmp1");
341  QString width = Get("cond_width");
342  QString height = Get("cond_height");
343  QString framerate = Get("cond_framerate");
344  QString codecs = Get("cond_codecs");
345  QString decoder = Get("pref_decoder");
346  uint max_cpus = Get("pref_max_cpus").toUInt();
347  bool skiploop = Get("pref_skiploop").toInt() != 0;
348  QString renderer = Get("pref_videorenderer");
349  QString osd = Get("pref_osdrenderer");
350  QString deint0 = Get("pref_deint0");
351  QString deint1 = Get("pref_deint1");
352  QString filter = Get("pref_filters");
353  bool osdfade = Get("pref_osdfade").toInt() != 0;
354 
355  QString cond = QString("w(%1) h(%2) framerate(%3) codecs(%4)")
356  .arg(width).arg(height).arg(framerate).arg(codecs);
357  QString str = QString("cmp(%1%2) %7 dec(%3) cpus(%4) skiploop(%5) rend(%6) ")
358  .arg(cmp0).arg(QString(cmp1.isEmpty() ? "" : ",") + cmp1)
359  .arg(decoder).arg(max_cpus).arg((skiploop) ? "enabled" : "disabled").arg(renderer)
360  .arg(cond);
361  str += QString("osd(%1) osdfade(%2) deint(%3,%4) filt(%5)")
362  .arg(osd).arg((osdfade) ? "enabled" : "disabled")
363  .arg(deint0).arg(deint1).arg(filter);
364 
365  return str;
366 }
367 
369 
370 #define LOC QString("VDP: ")
371 
372 QMutex VideoDisplayProfile::s_safe_lock(QMutex::Recursive);
383 
385  : lock(QMutex::Recursive), last_size(0,0), last_rate(0.0F)
386 {
387  QMutexLocker locker(&s_safe_lock);
388  init_statics();
389 
390  QString hostname = gCoreContext->GetHostName();
391  QString cur_profile = GetDefaultProfileName(hostname);
392  uint groupid = GetProfileGroupID(cur_profile, hostname);
393 
394  item_list_t items = LoadDB(groupid);
395  item_list_t::const_iterator it;
396  for (it = items.begin(); it != items.end(); ++it)
397  {
398  QString err;
399  if (!(*it).IsValid(&err))
400  {
401  LOG(VB_GENERAL, LOG_ERR, LOC + "Rejecting: " + (*it).toString() +
402  "\n\t\t\t" + err);
403 
404  continue;
405  }
406  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Accepting: " + (*it).toString());
407  all_pref.push_back(*it);
408  }
409 }
410 
411 void VideoDisplayProfile::SetInput(const QSize &size,
412  float framerate, const QString &codecName)
413 {
414  QMutexLocker locker(&lock);
415  bool change = false;
416 
417  if (size != last_size)
418  {
419  last_size = size;
420  change = true;
421  }
422  if (framerate > 0.0F && framerate != last_rate)
423  {
424  last_rate = framerate;
425  change = true;
426  }
427  if (!codecName.isEmpty() && codecName != last_codecName)
428  {
429  last_codecName = codecName;
430  change = true;
431  }
432  if (change)
434 }
435 
436 void VideoDisplayProfile::SetOutput(float framerate)
437 {
438  QMutexLocker locker(&lock);
439  if (framerate != last_rate)
440  {
441  last_rate = framerate;
443  }
444 }
445 
446 void VideoDisplayProfile::SetVideoRenderer(const QString &video_renderer)
447 {
448  QMutexLocker locker(&lock);
449 
450  LOG(VB_PLAYBACK, LOG_INFO, LOC +
451  QString("SetVideoRenderer(%1)").arg(video_renderer));
452 
453  last_video_renderer = video_renderer;
454  if (video_renderer == GetVideoRenderer())
455  {
456  LOG(VB_PLAYBACK, LOG_INFO, LOC +
457  QString("SetVideoRender(%1) == GetVideoRenderer()")
458  .arg(video_renderer));
459  return; // already made preferences safe...
460  }
461 
462  // Make preferences safe...
463 
464  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Old preferences: " + toString());
465 
466  SetPreference("pref_videorenderer", video_renderer);
467 
468  QStringList osds = GetOSDs(video_renderer);
469  if (!osds.contains(GetOSDRenderer()))
470  SetPreference("pref_osdrenderer", osds[0]);
471 
472  QStringList deints = GetDeinterlacers(video_renderer);
473  if (!deints.contains(GetDeinterlacer()))
474  SetPreference("pref_deint0", deints[0]);
475  if (!deints.contains(GetFallbackDeinterlacer()))
476  SetPreference("pref_deint1", deints[0]);
477  if (GetFallbackDeinterlacer().contains("bobdeint") ||
478  GetFallbackDeinterlacer().contains("doublerate") ||
479  GetFallbackDeinterlacer().contains("doubleprocess"))
480  {
481  SetPreference("pref_deint1", deints[1]);
482  }
483 
484  SetPreference("pref_filters", "");
485 
486  LOG(VB_PLAYBACK, LOG_INFO, LOC + "New preferences: " + toString());
487 }
488 
489 bool VideoDisplayProfile::CheckVideoRendererGroup(const QString &renderer)
490 {
491  if (last_video_renderer == renderer ||
492  last_video_renderer == "null")
493  return true;
494 
495  LOG(VB_PLAYBACK, LOG_INFO, LOC +
496  QString("Preferred video renderer: %1 (current: %2)")
497  .arg(renderer).arg(last_video_renderer));
498 
499  safe_map_t::const_iterator it = s_safe_renderer_group.begin();
500  for (; it != s_safe_renderer_group.end(); ++it)
501  if (it->contains(last_video_renderer) &&
502  it->contains(renderer))
503  return true;
504  return false;
505 }
506 
507 bool VideoDisplayProfile::IsDecoderCompatible(const QString &decoder)
508 {
509  const QString dec = GetDecoder();
510  if (dec == decoder)
511  return true;
512 
513  QMutexLocker locker(&s_safe_lock);
514  return (s_safe_equiv_dec[dec].contains(decoder));
515 }
516 
517 QString VideoDisplayProfile::GetFilteredDeint(const QString &override)
518 {
519  QString renderer = GetActualVideoRenderer();
520  QString deint = GetDeinterlacer();
521 
522  QMutexLocker locker(&lock);
523 
524  if (!override.isEmpty() && GetDeinterlacers(renderer).contains(override))
525  deint = override;
526 
527  LOG(VB_PLAYBACK, LOG_INFO,
528  LOC + QString("GetFilteredDeint(%1) : %2 -> '%3'")
529  .arg(override).arg(renderer).arg(deint));
530 
531  return deint;
532 }
533 
534 QString VideoDisplayProfile::GetPreference(const QString &key) const
535 {
536  QMutexLocker locker(&lock);
537 
538  if (key.isEmpty())
539  return QString();
540 
541  pref_map_t::const_iterator it = pref.find(key);
542  if (it == pref.end())
543  return QString();
544 
545  return *it;
546 }
547 
549  const QString &key, const QString &value)
550 {
551  QMutexLocker locker(&lock);
552 
553  if (!key.isEmpty())
554  {
555  pref[key] = value;
556  }
557 }
558 
559 item_list_t::const_iterator VideoDisplayProfile::FindMatch
560  (const QSize &size, float framerate, const QString &codecName)
561 {
562  item_list_t::const_iterator it = all_pref.begin();
563  for (; it != all_pref.end(); ++it)
564  {
565  if ((*it).IsMatch(size, framerate, codecName))
566  return it;
567  }
568 
569  return all_pref.end();
570 }
571 
573  (const QSize &size, float framerate, const QString &codecName)
574 {
575  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("LoadBestPreferences(%1x%2, %3, %4)")
576  .arg(size.width()).arg(size.height()).arg(framerate,0,'f',3).arg(codecName));
577 
578  pref.clear();
579  item_list_t::const_iterator it = FindMatch(size, framerate, codecName);
580  if (it != all_pref.end())
581  pref = (*it).GetAll();
582 
583  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("LoadBestPreferences Result "
584  "prio:%1, w:%2, h:%3, fps:%4,"
585  " codecs:%5, decoder:%6, renderer:%7, deint:%8")
586  .arg(GetPreference("pref_priority")).arg(GetPreference("cond_width"))
587  .arg(GetPreference("cond_height")).arg(GetPreference("cond_framerate"))
588  .arg(GetPreference("cond_codecs")).arg(GetPreference("pref_decoder"))
589  .arg(GetPreference("pref_videorenderer")).arg(GetPreference("pref_deint0"))
590  );
591 }
592 
594 // static methods
595 
597 {
599  item_list_t list;
600 
601  MSqlQuery query(MSqlQuery::InitCon());
602  query.prepare(
603  "SELECT profileid, value, data "
604  "FROM displayprofiles "
605  "WHERE profilegroupid = :GROUPID "
606  "ORDER BY profileid");
607  query.bindValue(":GROUPID", groupid);
608  if (!query.exec())
609  {
610  MythDB::DBError("loaddb 1", query);
611  return list;
612  }
613 
614  uint profileid = 0;
615  while (query.next())
616  {
617  if (query.value(0).toUInt() != profileid)
618  {
619  if (profileid)
620  {
621  tmp.SetProfileID(profileid);
622  QString error;
623  bool valid = tmp.IsValid(&error);
624  if (valid)
625  list.push_back(tmp);
626  else
627  LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
628  QString("Ignoring profile item %1 (%2)")
629  .arg(profileid).arg(error));
630  }
631  tmp.Clear();
632  profileid = query.value(0).toUInt();
633  }
634  tmp.Set(query.value(1).toString(), query.value(2).toString());
635  }
636  if (profileid)
637  {
638  tmp.SetProfileID(profileid);
639  QString error;
640  bool valid = tmp.IsValid(&error);
641  if (valid)
642  list.push_back(tmp);
643  else
644  LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
645  QString("Ignoring profile item %1 (%2)")
646  .arg(profileid).arg(error));
647  }
648 
649  sort(list.begin(), list.end());
650  return list;
651 }
652 
653 bool VideoDisplayProfile::DeleteDB(uint groupid, const item_list_t &items)
654 {
655  MSqlQuery query(MSqlQuery::InitCon());
656  query.prepare(
657  "DELETE FROM displayprofiles "
658  "WHERE profilegroupid = :GROUPID AND "
659  " profileid = :PROFILEID");
660 
661  bool ok = true;
662  item_list_t::const_iterator it = items.begin();
663  for (; it != items.end(); ++it)
664  {
665  if (!(*it).GetProfileID())
666  continue;
667 
668  query.bindValue(":GROUPID", groupid);
669  query.bindValue(":PROFILEID", (*it).GetProfileID());
670  if (!query.exec())
671  {
672  MythDB::DBError("vdp::deletedb", query);
673  ok = false;
674  }
675  }
676 
677  return ok;
678 }
679 
681 {
682  MSqlQuery query(MSqlQuery::InitCon());
683 
684  MSqlQuery update(MSqlQuery::InitCon());
685  update.prepare(
686  "UPDATE displayprofiles "
687  "SET data = :DATA "
688  "WHERE profilegroupid = :GROUPID AND "
689  " profileid = :PROFILEID AND "
690  " value = :VALUE");
691 
692  MSqlQuery insert(MSqlQuery::InitCon());
693  insert.prepare(
694  "INSERT INTO displayprofiles "
695  " ( profilegroupid, profileid, value, data) "
696  "VALUES "
697  " (:GROUPID, :PROFILEID, :VALUE, :DATA) ");
698 
699  MSqlQuery sqldelete(MSqlQuery::InitCon());
700  sqldelete.prepare(
701  "DELETE FROM displayprofiles "
702  "WHERE profilegroupid = :GROUPID AND "
703  " profileid = :PROFILEID AND "
704  " value = :VALUE");
705 
706  bool ok = true;
707  item_list_t::iterator it = items.begin();
708  for (; it != items.end(); ++it)
709  {
710  pref_map_t list = (*it).GetAll();
711  if (list.begin() == list.end())
712  continue;
713 
714  pref_map_t::const_iterator lit = list.begin();
715 
716  if (!(*it).GetProfileID())
717  {
718  // create new profileid
719  if (!query.exec("SELECT MAX(profileid) FROM displayprofiles"))
720  {
721  MythDB::DBError("save_profile 1", query);
722  ok = false;
723  continue;
724  }
725  if (query.next())
726  {
727  (*it).SetProfileID(query.value(0).toUInt() + 1);
728  }
729 
730  for (; lit != list.end(); ++lit)
731  {
732  if ((*lit).isEmpty())
733  continue;
734 
735  insert.bindValue(":GROUPID", groupid);
736  insert.bindValue(":PROFILEID", (*it).GetProfileID());
737  insert.bindValue(":VALUE", lit.key());
738  insert.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
739  if (!insert.exec())
740  {
741  MythDB::DBError("save_profile 2", insert);
742  ok = false;
743  continue;
744  }
745  }
746  continue;
747  }
748 
749  for (; lit != list.end(); ++lit)
750  {
751  query.prepare(
752  "SELECT count(*) "
753  "FROM displayprofiles "
754  "WHERE profilegroupid = :GROUPID AND "
755  " profileid = :PROFILEID AND "
756  " value = :VALUE");
757  query.bindValue(":GROUPID", groupid);
758  query.bindValue(":PROFILEID", (*it).GetProfileID());
759  query.bindValue(":VALUE", lit.key());
760 
761  if (!query.exec())
762  {
763  MythDB::DBError("save_profile 3", query);
764  ok = false;
765  continue;
766  }
767  if (query.next() && (1 == query.value(0).toUInt()))
768  {
769  if (lit->isEmpty())
770  {
771  sqldelete.bindValue(":GROUPID", groupid);
772  sqldelete.bindValue(":PROFILEID", (*it).GetProfileID());
773  sqldelete.bindValue(":VALUE", lit.key());
774  if (!sqldelete.exec())
775  {
776  MythDB::DBError("save_profile 5a", sqldelete);
777  ok = false;
778  continue;
779  }
780  }
781  else
782  {
783  update.bindValue(":GROUPID", groupid);
784  update.bindValue(":PROFILEID", (*it).GetProfileID());
785  update.bindValue(":VALUE", lit.key());
786  update.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
787  if (!update.exec())
788  {
789  MythDB::DBError("save_profile 5b", update);
790  ok = false;
791  continue;
792  }
793  }
794  }
795  else
796  {
797  insert.bindValue(":GROUPID", groupid);
798  insert.bindValue(":PROFILEID", (*it).GetProfileID());
799  insert.bindValue(":VALUE", lit.key());
800  insert.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
801  if (!insert.exec())
802  {
803  MythDB::DBError("save_profile 4", insert);
804  ok = false;
805  continue;
806  }
807  }
808  }
809  }
810 
811  return ok;
812 }
813 
815 {
816  init_statics();
817  return s_safe_decoders;
818 }
819 
821 {
822  init_statics();
823  QStringList list;
824 
825  const QStringList decs = GetDecoders();
826  QStringList::const_iterator it = decs.begin();
827  for (; it != decs.end(); ++it)
828  list += GetDecoderName(*it);
829 
830  return list;
831 }
832 
833 QString VideoDisplayProfile::GetDecoderName(const QString &decoder)
834 {
835  if (decoder.isEmpty())
836  return "";
837 
838  QMutexLocker locker(&s_safe_lock);
839  if (s_dec_name.empty())
840  {
841  s_dec_name["ffmpeg"] = QObject::tr("Standard");
842  s_dec_name["macaccel"] = QObject::tr("Mac hardware acceleration");
843  s_dec_name["vdpau"] = QObject::tr("NVidia VDPAU acceleration");
844  s_dec_name["vaapi"] = QObject::tr("VAAPI acceleration");
845  s_dec_name["dxva2"] = QObject::tr("Windows hardware acceleration");
846  s_dec_name["vda"] = QObject::tr("Mac VDA hardware acceleration");
847  s_dec_name["mediacodec"] = QObject::tr("Android MediaCodec decoder");
848  s_dec_name["vaapi2"] = QObject::tr("VAAPI2 acceleration");
849  s_dec_name["nvdec"] = QObject::tr("NVidia NVDEC acceleration");
850  }
851 
852  QString ret = decoder;
853  pref_map_t::const_iterator it = s_dec_name.find(decoder);
854  if (it != s_dec_name.end())
855  ret = *it;
856  return ret;
857 }
858 
859 
860 QString VideoDisplayProfile::GetDecoderHelp(const QString& decoder)
861 {
862  QString msg = QObject::tr("Processing method used to decode video.");
863 
864  if (decoder.isEmpty())
865  return msg;
866 
867  msg += "\n";
868 
869  if (decoder == "ffmpeg")
870  msg += QObject::tr("Standard will use ffmpeg library.");
871 
872  if (decoder == "macaccel")
873  msg += QObject::tr(
874  "Mac hardware will try to use the graphics "
875  "processor - this may hang or crash your Mac!");
876 
877  if (decoder == "vdpau")
878  msg += QObject::tr(
879  "VDPAU will attempt to use the graphics hardware to "
880  "accelerate video decoding and playback.");
881 
882  if (decoder == "dxva2")
883  msg += QObject::tr(
884  "DXVA2 will use the graphics hardware to "
885  "accelerate video decoding and playback "
886  "(requires Windows Vista or later).");
887 
888  if (decoder == "vaapi")
889  msg += QObject::tr(
890  "VAAPI will attempt to use the graphics hardware to "
891  "accelerate video decoding. REQUIRES OPENGL PAINTER.");
892 
893  if (decoder == "vda")
894  msg += QObject::tr(
895  "VDA will attempt to use the graphics hardware to "
896  "accelerate video decoding. "
897  "(H264 only, requires Mac OS 10.6.3)");
898 
899  if (decoder == "openmax")
900  msg += QObject::tr(
901  "Openmax will use the graphics hardware to "
902  "accelerate video decoding on Raspberry Pi. ");
903 
904  if (decoder == "mediacodec")
905  msg += QObject::tr(
906  "Mediacodec will use the graphics hardware to "
907  "accelerate video decoding on Android. ");
908 
909  if (decoder == "vaapi2")
910  msg += QObject::tr(
911  "VAAPI2 is a new implementation of VAAPI to will use the graphics hardware to "
912  "accelerate video decoding on Intel CPUs. ");
913 
914  if (decoder == "nvdec")
915  msg += QObject::tr(
916  "Nvdec uses the new NVDEC API to "
917  "accelerate video decoding on NVidia Graphics Adapters. ");
918 
919  return msg;
920 }
921 
922 QString VideoDisplayProfile::GetDeinterlacerName(const QString &short_name)
923 {
924  if ("none" == short_name)
925  return QObject::tr("None");
926  if ("linearblend" == short_name)
927  return QObject::tr("Linear blend");
928  if ("kerneldeint" == short_name)
929  return QObject::tr("Kernel");
930  if ("kerneldoubleprocessdeint" == short_name)
931  return QObject::tr("Kernel (2x)");
932  if ("greedyhdeint" == short_name)
933  return QObject::tr("Greedy HighMotion");
934  if ("greedyhdoubleprocessdeint" == short_name)
935  return QObject::tr("Greedy HighMotion (2x)");
936  if ("yadifdeint" == short_name)
937  return QObject::tr("Yadif");
938  if ("yadifdoubleprocessdeint" == short_name)
939  return QObject::tr("Yadif (2x)");
940  if ("bobdeint" == short_name)
941  return QObject::tr("Bob (2x)");
942  if ("onefield" == short_name)
943  return QObject::tr("One field");
944  if ("fieldorderdoubleprocessdeint" == short_name)
945  return QObject::tr("Interlaced (2x)");
946  if ("opengllinearblend" == short_name)
947  return QObject::tr("Linear blend (HW-GL)");
948  if ("openglkerneldeint" == short_name)
949  return QObject::tr("Kernel (HW-GL)");
950  if ("openglbobdeint" == short_name)
951  return QObject::tr("Bob (2x, HW-GL)");
952  if ("openglonefield" == short_name)
953  return QObject::tr("One field (HW-GL)");
954  if ("opengldoubleratekerneldeint" == short_name)
955  return QObject::tr("Kernel (2x, HW-GL)");
956  if ("opengldoubleratelinearblend" == short_name)
957  return QObject::tr("Linear blend (2x, HW-GL)");
958  if ("opengldoubleratefieldorder" == short_name)
959  return QObject::tr("Interlaced (2x, HW-GL)");
960  if ("vdpauonefield" == short_name)
961  return QObject::tr("One Field (1x, HW)");
962  if ("vdpaubobdeint" == short_name)
963  return QObject::tr("Bob (2x, HW)");
964  if ("vdpaubasic" == short_name)
965  return QObject::tr("Temporal (1x, HW)");
966  if ("vdpaubasicdoublerate" == short_name)
967  return QObject::tr("Temporal (2x, HW)");
968  if ("vdpauadvanced" == short_name)
969  return QObject::tr("Advanced (1x, HW)");
970  if ("vdpauadvanceddoublerate" == short_name)
971  return QObject::tr("Advanced (2x, HW)");
972  if ("vaapionefield" == short_name)
973  return QObject::tr("One Field (1x, HW)");
974  if ("vaapibobdeint" == short_name)
975  return QObject::tr("Bob (2x, HW)");
976 #ifdef USING_OPENMAX
977  if ("openmaxadvanced" == short_name)
978  return QObject::tr("Advanced (HW)");
979  if ("openmaxfast" == short_name)
980  return QObject::tr("Fast (HW)");
981  if ("openmaxlinedouble" == short_name)
982  return QObject::tr("Line double (HW)");
983 #endif // def USING_OPENMAX
984 #ifdef USING_VAAPI2
985  if ("vaapi2default" == short_name)
986  return QObject::tr("Advanced (HW-VA)");
987  if ("vaapi2bob" == short_name)
988  return QObject::tr("Bob (HW-VA)");
989  if ("vaapi2weave" == short_name)
990  return QObject::tr("Weave (HW-VA)");
991  if ("vaapi2motion_adaptive" == short_name)
992  return QObject::tr("Motion Adaptive (HW-VA)");
993  if ("vaapi2motion_compensated" == short_name)
994  return QObject::tr("Motion Compensated (HW-VA)");
995  if ("vaapi2doubleratedefault" == short_name)
996  return QObject::tr("Advanced (2x, HW-VA)");
997  if ("vaapi2doubleratebob" == short_name)
998  return QObject::tr("Bob (2x, HW-VA)");
999  if ("vaapi2doublerateweave" == short_name)
1000  return QObject::tr("Weave (2x, HW-VA)");
1001  if ("vaapi2doubleratemotion_adaptive" == short_name)
1002  return QObject::tr("Motion Adaptive (2x, HW-VA)");
1003  if ("vaapi2doubleratemotion_compensated" == short_name)
1004  return QObject::tr("Motion Compensated (2x, HW-VA)");
1005 #endif
1006 #ifdef USING_NVDEC
1007  if ("nvdecweave" == short_name)
1008  return QObject::tr("Weave (HW-NV)");
1009  if ("nvdecbob" == short_name)
1010  return QObject::tr("Bob (HW-NV)");
1011  if ("nvdecadaptive" == short_name)
1012  return QObject::tr("Adaptive (HW-NV)");
1013  if ("nvdecdoublerateweave" == short_name)
1014  return QObject::tr("Weave (2x, HW-NV)");
1015  if ("nvdecdoubleratebob" == short_name)
1016  return QObject::tr("Bob (2x, HW-NV)");
1017  if ("nvdecdoublerateadaptive" == short_name)
1018  return QObject::tr("Adaptive (2x, HW-NV)");
1019 #endif // USING_NVDEC
1020 
1021  return "";
1022 }
1023 
1024 QStringList VideoDisplayProfile::GetProfiles(const QString &hostname)
1025 {
1026  init_statics();
1027  QStringList list;
1028  MSqlQuery query(MSqlQuery::InitCon());
1029  query.prepare(
1030  "SELECT name "
1031  "FROM displayprofilegroups "
1032  "WHERE hostname = :HOST ");
1033  query.bindValue(":HOST", hostname);
1034  if (!query.exec() || !query.isActive())
1035  MythDB::DBError("get_profiles", query);
1036  else
1037  {
1038  while (query.next())
1039  list += query.value(0).toString();
1040  }
1041  return list;
1042 }
1043 
1045 {
1046  QString tmp =
1047  gCoreContext->GetSettingOnHost("DefaultVideoPlaybackProfile", hostname);
1048 
1049  QStringList profiles = GetProfiles(hostname);
1050 
1051  tmp = (profiles.contains(tmp)) ? tmp : QString();
1052 
1053  if (tmp.isEmpty())
1054  {
1055  if (!profiles.empty())
1056  tmp = profiles[0];
1057 
1058  tmp = (profiles.contains("Normal")) ? "Normal" : tmp;
1059 
1060  if (!tmp.isEmpty())
1061  {
1063  "DefaultVideoPlaybackProfile", tmp, hostname);
1064  }
1065  }
1066 
1067  return tmp;
1068 }
1069 
1071  const QString &profilename, const QString &hostname)
1072 {
1074  "DefaultVideoPlaybackProfile", profilename, hostname);
1075 }
1076 
1078  const QString &hostname)
1079 {
1080  MSqlQuery query(MSqlQuery::InitCon());
1081  query.prepare(
1082  "SELECT profilegroupid "
1083  "FROM displayprofilegroups "
1084  "WHERE name = :NAME AND "
1085  " hostname = :HOST ");
1086  query.bindValue(":NAME", profilename);
1087  query.bindValue(":HOST", hostname);
1088 
1089  if (!query.exec() || !query.isActive())
1090  MythDB::DBError("get_profile_group_id", query);
1091  else if (query.next())
1092  return query.value(0).toUInt();
1093 
1094  return 0;
1095 }
1096 
1098 {
1099  MSqlQuery query(MSqlQuery::InitCon());
1100  MSqlQuery query2(MSqlQuery::InitCon());
1101  query.prepare(
1102  "SELECT profilegroupid "
1103  "FROM displayprofilegroups "
1104  "WHERE hostname = :HOST ");
1105  query.bindValue(":HOST", hostname);
1106  if (!query.exec() || !query.isActive())
1107  MythDB::DBError("delete_profiles 1", query);
1108  else
1109  {
1110  while (query.next())
1111  {
1112  query2.prepare("DELETE FROM displayprofiles "
1113  "WHERE profilegroupid = :PROFID");
1114  query2.bindValue(":PROFID", query.value(0).toUInt());
1115  if (!query2.exec())
1116  MythDB::DBError("delete_profiles 2", query2);
1117  }
1118  }
1119  query.prepare("DELETE FROM displayprofilegroups WHERE hostname = :HOST");
1120  query.bindValue(":HOST", hostname);
1121  if (!query.exec() || !query.isActive())
1122  MythDB::DBError("delete_profiles 3", query);
1123 }
1124 
1125 //displayprofilegroups pk(name, hostname), uk(profilegroupid)
1126 //displayprofiles k(profilegroupid), k(profileid), value, data
1127 
1128 // Old style
1130  uint groupid, uint priority,
1131  const QString& cmp0, uint width0, uint height0,
1132  const QString& cmp1, uint width1, uint height1,
1133  QString decoder, uint max_cpus, bool skiploop, QString videorenderer,
1134  QString osdrenderer, bool osdfade,
1135  QString deint0, QString deint1, QString filters)
1136 {
1137  QString width;
1138  QString height;
1139  if (!cmp0.isEmpty()
1140  && ! (cmp0 == ">" && width0 == 0 && height0 == 0))
1141  {
1142  width.append(QString("%1%2").arg(cmp0).arg(width0));
1143  height.append(QString("%1%2").arg(cmp0).arg(height0));
1144  if (!cmp1.isEmpty())
1145  {
1146  width.append("&");
1147  height.append("&");
1148  }
1149  }
1150  if (!cmp1.isEmpty()
1151  && ! (cmp1 == ">" && width1 == 0 && height1 == 0))
1152  {
1153  width.append(QString("%1%2").arg(cmp1).arg(width1));
1154  height.append(QString("%1%2").arg(cmp1).arg(height1));
1155  }
1156  CreateProfile(
1157  groupid, priority,
1158  width, height, QString(),
1159  std::move(decoder), max_cpus, skiploop, std::move(videorenderer),
1160  std::move(osdrenderer), osdfade,
1161  std::move(deint0), std::move(deint1), std::move(filters));
1162 }
1163 
1164 // New Style
1166  uint groupid, uint priority,
1167  const QString& width, const QString& height, const QString& codecs,
1168  const QString& decoder, uint max_cpus, bool skiploop, const QString& videorenderer,
1169  const QString& osdrenderer, bool osdfade,
1170  const QString& deint0, const QString& deint1, const QString& filters)
1171 {
1172  MSqlQuery query(MSqlQuery::InitCon());
1173 
1174  // create new profileid
1175  uint profileid = 1;
1176  if (!query.exec("SELECT MAX(profileid) FROM displayprofiles"))
1177  MythDB::DBError("create_profile 1", query);
1178  else if (query.next())
1179  profileid = query.value(0).toUInt() + 1;
1180 
1181  query.prepare(
1182  "INSERT INTO displayprofiles "
1183  "VALUES (:GRPID, :PROFID, 'pref_priority', :PRIORITY)");
1184  query.bindValue(":GRPID", groupid);
1185  query.bindValue(":PROFID", profileid);
1186  query.bindValue(":PRIORITY", priority);
1187  if (!query.exec())
1188  MythDB::DBError("create_profile 2", query);
1189 
1190  QStringList queryValue;
1191  QStringList queryData;
1192 
1193  queryValue += "cond_width";
1194  queryData += width;
1195 
1196  queryValue += "cond_height";
1197  queryData += height;
1198 
1199  queryValue += "cond_codecs";
1200  queryData += codecs;
1201 
1202  queryValue += "pref_decoder";
1203  queryData += decoder;
1204 
1205  queryValue += "pref_max_cpus";
1206  queryData += QString::number(max_cpus);
1207 
1208  queryValue += "pref_skiploop";
1209  queryData += (skiploop) ? "1" : "0";
1210 
1211  queryValue += "pref_videorenderer";
1212  queryData += videorenderer;
1213 
1214  queryValue += "pref_osdrenderer";
1215  queryData += osdrenderer;
1216 
1217  queryValue += "pref_osdfade";
1218  queryData += (osdfade) ? "1" : "0";
1219 
1220  queryValue += "pref_deint0";
1221  queryData += deint0;
1222 
1223  queryValue += "pref_deint1";
1224  queryData += deint1;
1225 
1226  queryValue += "pref_filters";
1227  queryData += filters;
1228 
1229  QStringList::const_iterator itV = queryValue.begin();
1230  QStringList::const_iterator itD = queryData.begin();
1231  for (; itV != queryValue.end() && itD != queryData.end(); ++itV,++itD)
1232  {
1233  if (itD->isEmpty())
1234  continue;
1235  query.prepare(
1236  "INSERT INTO displayprofiles "
1237  "VALUES (:GRPID, :PROFID, :VALUE, :DATA)");
1238  query.bindValue(":GRPID", groupid);
1239  query.bindValue(":PROFID", profileid);
1240  query.bindValue(":VALUE", *itV);
1241  query.bindValue(":DATA", *itD);
1242  if (!query.exec())
1243  MythDB::DBError("create_profile 3", query);
1244  }
1245 }
1246 
1248  const QString &profilename, const QString &hostname)
1249 {
1250  MSqlQuery query(MSqlQuery::InitCon());
1251  query.prepare(
1252  "INSERT INTO displayprofilegroups (name, hostname) "
1253  "VALUES (:NAME,:HOST)");
1254 
1255  query.bindValue(":NAME", profilename);
1256  query.bindValue(":HOST", hostname);
1257 
1258  if (!query.exec())
1259  {
1260  MythDB::DBError("create_profile_group", query);
1261  return 0;
1262  }
1263 
1264  return GetProfileGroupID(profilename, hostname);
1265 }
1266 
1268  const QString &groupname, const QString &hostname)
1269 {
1270  bool ok = true;
1271  MSqlQuery query(MSqlQuery::InitCon());
1272  MSqlQuery query2(MSqlQuery::InitCon());
1273 
1274  query.prepare(
1275  "SELECT profilegroupid "
1276  "FROM displayprofilegroups "
1277  "WHERE name = :NAME AND "
1278  " hostname = :HOST ");
1279 
1280  query.bindValue(":NAME", groupname);
1281  query.bindValue(":HOST", hostname);
1282 
1283  if (!query.exec() || !query.isActive())
1284  {
1285  MythDB::DBError("delete_profile_group 1", query);
1286  ok = false;
1287  }
1288  else
1289  {
1290  while (query.next())
1291  {
1292  query2.prepare("DELETE FROM displayprofiles "
1293  "WHERE profilegroupid = :PROFID");
1294  query2.bindValue(":PROFID", query.value(0).toUInt());
1295  if (!query2.exec())
1296  {
1297  MythDB::DBError("delete_profile_group 2", query2);
1298  ok = false;
1299  }
1300  }
1301  }
1302 
1303  query.prepare(
1304  "DELETE FROM displayprofilegroups "
1305  "WHERE name = :NAME AND "
1306  " hostname = :HOST");
1307 
1308  query.bindValue(":NAME", groupname);
1309  query.bindValue(":HOST", hostname);
1310 
1311  if (!query.exec())
1312  {
1313  MythDB::DBError("delete_profile_group 3", query);
1314  ok = false;
1315  }
1316 
1317  return ok;
1318 }
1319 
1321 {
1322  QStringList profiles = GetProfiles(hostname);
1323  uint groupid;
1324 
1325 #ifdef USING_XV
1326  if (!profiles.contains("High Quality")) {
1327  (void) QObject::tr("High Quality", "Sample: high quality");
1328  groupid = CreateProfileGroup("High Quality", hostname);
1329  CreateProfile(groupid, 1, ">=", 1920, 1080, "", 0, 0,
1330  "ffmpeg", 2, true, "xv-blit", "softblend", true,
1331  "linearblend", "linearblend", "");
1332  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1333  "ffmpeg", 1, true, "xv-blit", "softblend", true,
1334  "yadifdoubleprocessdeint", "yadifdeint", "");
1335  }
1336 
1337  if (!profiles.contains("Normal")) {
1338  (void) QObject::tr("Normal", "Sample: average quality");
1339  groupid = CreateProfileGroup("Normal", hostname);
1340  CreateProfile(groupid, 1, ">=", 1280, 720, "", 0, 0,
1341  "ffmpeg", 1, true, "xv-blit", "softblend", false,
1342  "linearblend", "linearblend", "");
1343  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1344  "ffmpeg", 1, true, "xv-blit", "softblend", true,
1345  "greedyhdoubleprocessdeint", "kerneldeint", "");
1346  }
1347 
1348  if (!profiles.contains("Slim")) {
1349  (void) QObject::tr("Slim", "Sample: low CPU usage");
1350  groupid = CreateProfileGroup("Slim", hostname);
1351  CreateProfile(groupid, 1, ">=", 1280, 720, "", 0, 0,
1352  "ffmpeg", 1, true, "xv-blit", "softblend", false,
1353  "onefield", "onefield", "");
1354  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1355  "ffmpeg", 1, true, "xv-blit", "softblend", false,
1356  "linearblend", "linearblend", "");
1357  }
1358 #endif
1359 
1360 #ifdef USING_VDPAU
1361  if (!profiles.contains("VDPAU High Quality")) {
1362  (void) QObject::tr("VDPAU High Quality", "Sample: VDPAU high quality");
1363  groupid = CreateProfileGroup("VDPAU High Quality", hostname);
1364  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1365  "vdpau", 1, true, "vdpau", "vdpau", true,
1366  "vdpauadvanceddoublerate", "vdpauadvanced",
1367  "vdpaucolorspace=auto");
1368  }
1369 
1370  if (!profiles.contains("VDPAU Normal")) {
1371  (void) QObject::tr("VDPAU Normal", "Sample: VDPAU average quality");
1372  groupid = CreateProfileGroup("VDPAU Normal", hostname);
1373  CreateProfile(groupid, 1, ">=", 0, 720, "", 0, 0,
1374  "vdpau", 1, true, "vdpau", "vdpau", true,
1375  "vdpaubasicdoublerate", "vdpaubasic",
1376  "vdpaucolorspace=auto");
1377  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1378  "vdpau", 1, true, "vdpau", "vdpau", true,
1379  "vdpauadvanceddoublerate", "vdpauadvanced",
1380  "vdpaucolorspace=auto");
1381  }
1382 
1383  if (!profiles.contains("VDPAU Slim")) {
1384  (void) QObject::tr("VDPAU Slim", "Sample: VDPAU low power GPU");
1385  groupid = CreateProfileGroup("VDPAU Slim", hostname);
1386  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1387  "vdpau", 1, true, "vdpau", "vdpau", true,
1388  "vdpaubobdeint", "vdpauonefield",
1389  "vdpauskipchroma,vdpaucolorspace=auto");
1390  }
1391 #endif
1392 
1393 #if defined(Q_OS_MACX)
1394  if (!profiles.contains("VDA High Quality")) {
1395  (void) QObject::tr("VDA High Quality", "Sample: VDA high quality");
1396  groupid = CreateProfileGroup("VDA High Quality", hostname);
1397  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1398  "vda", 2, true, "opengl", "opengl2", true,
1399  "greedyhdoubleprocessdeint", "greedyhdeint",
1400  "");
1401  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1402  "ffmpeg", 2, true, "opengl", "opengl2", true,
1403  "greedyhdoubleprocessdeint", "greedyhdeint",
1404  "");
1405  }
1406 
1407  if (!profiles.contains("VDA Normal")) {
1408  (void) QObject::tr("VDA Normal", "Sample: VDA average quality");
1409  groupid = CreateProfileGroup("VDA Normal", hostname);
1410  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1411  "vda", 2, true, "opengl", "opengl2", true,
1412  "opengldoubleratekerneldeint", "openglkerneldeint",
1413  "");
1414  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1415  "ffmpeg", 2, true, "opengl", "opengl2", true,
1416  "opengldoubleratekerneldeint", "openglkerneldeint",
1417  "");
1418  }
1419 
1420  if (!profiles.contains("VDA Slim")) {
1421  (void) QObject::tr("VDA Slim", "Sample: VDA low power GPU");
1422  groupid = CreateProfileGroup("VDA Slim", hostname);
1423  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1424  "vda", 2, true, "opengl", "opengl2", true,
1425  "opengldoubleratelinearblend", "opengllinearblend",
1426  "");
1427  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1428  "ffmpeg", 2, true, "opengl", "opengl2", true,
1429  "opengldoubleratelinearblend", "opengllinearblend",
1430  "");
1431  }
1432 #endif
1433 
1434 #ifdef USING_OPENGL_VIDEO
1435  if (!profiles.contains("OpenGL High Quality")) {
1436  (void) QObject::tr("OpenGL High Quality",
1437  "Sample: OpenGL high quality");
1438  groupid = CreateProfileGroup("OpenGL High Quality", hostname);
1439  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1440  "ffmpeg", 2, true, "opengl", "opengl2", true,
1441  "greedyhdoubleprocessdeint", "greedyhdeint",
1442  "");
1443  }
1444 
1445  if (!profiles.contains("OpenGL Normal")) {
1446  (void) QObject::tr("OpenGL Normal", "Sample: OpenGL average quality");
1447  groupid = CreateProfileGroup("OpenGL Normal", hostname);
1448  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1449  "ffmpeg", 2, true, "opengl", "opengl2", true,
1450  "opengldoubleratekerneldeint", "openglkerneldeint",
1451  "");
1452  }
1453 
1454  if (!profiles.contains("OpenGL Slim")) {
1455  (void) QObject::tr("OpenGL Slim", "Sample: OpenGL low power GPU");
1456  groupid = CreateProfileGroup("OpenGL Slim", hostname);
1457  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1458  "ffmpeg", 1, true, "opengl", "opengl2", true,
1459  "opengldoubleratelinearblend", "opengllinearblend",
1460  "");
1461  }
1462 #endif
1463 
1464 #ifdef USING_GLVAAPI
1465  if (!profiles.contains("VAAPI Normal")) {
1466  (void) QObject::tr("VAAPI Normal", "Sample: VAAPI average quality");
1467  groupid = CreateProfileGroup("VAAPI Normal", hostname);
1468  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1469  "vaapi", 2, true, "openglvaapi", "opengl2", true,
1470  "vaapibobdeint", "vaapionefield",
1471  "");
1472  CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
1473  "ffmpeg", 2, true, "opengl", "opengl2", true,
1474  "opengldoubleratekerneldeint", "openglkerneldeint",
1475  "");
1476  }
1477 #endif
1478 
1479 #ifdef USING_OPENMAX
1480 #ifdef USING_OPENGLES
1481  if (!profiles.contains("OpenMAX High Quality")) {
1482  (void) QObject::tr("OpenMAX High Quality",
1483  "Sample: OpenMAX High Quality");
1484  groupid = CreateProfileGroup("OpenMAX High Quality", hostname);
1485  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1486  "openmax", 4, true, "openmax", "opengl", true,
1487  "openmaxadvanced", "onefield",
1488  "");
1489  }
1490 #endif
1491 
1492  if (!profiles.contains("OpenMAX Normal")) {
1493  (void) QObject::tr("OpenMAX Normal", "Sample: OpenMAX Normal");
1494  groupid = CreateProfileGroup("OpenMAX Normal", hostname);
1495  CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
1496  "openmax", 4, true, "openmax", "softblend", false,
1497  "openmaxadvanced", "onefield",
1498  "");
1499  }
1500 #endif
1501 
1502 #ifdef USING_MEDIACODEC
1503  if (!profiles.contains("MediaCodec Normal")) {
1504  (void) QObject::tr("MediaCodec Normal",
1505  "Sample: MediaCodec Normal");
1506  groupid = CreateProfileGroup("MediaCodec Normal", hostname);
1507  CreateProfile(groupid, 1, "", "", "",
1508  "mediacodec", 4, true, "opengl",
1509  "opengl2", true,
1510  "opengldoubleratelinearblend", "opengllinearblend",
1511  "");
1512  }
1513 #endif
1514 
1515 #if defined(USING_VAAPI2) && defined(USING_OPENGL_VIDEO)
1516  if (!profiles.contains("VAAPI2 Normal")) {
1517  (void) QObject::tr("VAAPI2 Normal",
1518  "Sample: VAAPI2 Normal");
1519  groupid = CreateProfileGroup("VAAPI2 Normal", hostname);
1520  CreateProfile(groupid, 1, "", "", "",
1521  "vaapi2", 4, true, "opengl",
1522  "opengl2", true,
1523  "vaapi2doubleratedefault", "vaapi2default",
1524  "");
1525  }
1526 #endif
1527 
1528 #if defined(USING_NVDEC) && defined(USING_OPENGL_VIDEO)
1529  if (!profiles.contains("NVDEC Normal")) {
1530  (void) QObject::tr("NVDEC Normal",
1531  "Sample: NVDEC Normal");
1532  groupid = CreateProfileGroup("NVDEC Normal", hostname);
1533  CreateProfile(groupid, 1, "", "", "",
1534  "nvdec", 4, true, "opengl",
1535  "opengl2", true,
1536  "nvdecdoublerateadaptive", "nvdecadaptive",
1537  "");
1538  }
1539 #endif
1540 
1541 }
1542 
1543 QStringList VideoDisplayProfile::GetVideoRenderers(const QString &decoder)
1544 {
1545  QMutexLocker locker(&s_safe_lock);
1546  init_statics();
1547 
1548  safe_map_t::const_iterator it = s_safe_renderer.find(decoder);
1549  QStringList tmp;
1550  if (it != s_safe_renderer.end())
1551  tmp = *it;
1552  return tmp;
1553 }
1554 
1555 QString VideoDisplayProfile::GetVideoRendererHelp(const QString &renderer)
1556 {
1557  QString msg = QObject::tr("Video rendering method");
1558 
1559  if (renderer.isEmpty())
1560  return msg;
1561 
1562  if ((renderer == "null") || (renderer == "nullvaapi") ||
1563  (renderer == "nullvdpau"))
1564  msg = QObject::tr(
1565  "Render video offscreen. Used internally.");
1566 
1567  if (renderer == "xlib")
1568  msg = QObject::tr(
1569  "Use X11 pixel copy to render video. This is not recommended if "
1570  "any other option is available. The video will not be scaled to "
1571  "fit the screen. This will work with all X11 servers, local "
1572  "and remote.");
1573 
1574  if (renderer == "xshm")
1575  msg = QObject::tr(
1576  "Use X11 shared memory pixel transfer to render video. This is "
1577  "only recommended over the X11 pixel copy renderer. The video "
1578  "will not be scaled to fit the screen. This works with most "
1579  "local X11 servers.");
1580 
1581  if (renderer == "xv-blit")
1582  msg = QObject::tr(
1583  "This is the standard video renderer for X11 systems. It uses "
1584  "XVideo hardware assist for scaling, color conversion. If the "
1585  "hardware offers picture controls the renderer supports them.");
1586 
1587  if (renderer == "direct3d")
1588  msg = QObject::tr(
1589  "Windows video renderer based on Direct3D. Requires "
1590  "video card compatible with Direct3D 9. This is the preferred "
1591  "renderer for current Windows systems.");
1592 
1593  if (renderer == "opengl")
1594  {
1595  msg = QObject::tr(
1596  "Video is converted to an intermediate format by the CPU (UYVY) "
1597  "before OpenGL is used for color conversion, scaling, picture controls"
1598  " and optionally deinterlacing. Processing is balanced between the CPU"
1599  "and GPU.");
1600  }
1601 
1602  if (renderer == "opengl-lite")
1603  msg = QObject::tr(
1604  "OpenGL is used for scaling and color conversion. "
1605  "It uses faster OpenGL functionality when available but at the "
1606  "expense of picture controls and GPU based deinterlacing.");
1607 
1608  if (renderer == "opengl-yv12")
1609  {
1610  msg = QObject::tr(
1611  "OpenGL is used for all color conversion, scaling, picture "
1612  "controls and optionally deinterlacing. CPU load is low but a more "
1613  "powerful GPU is needed for deinterlacing.");
1614  }
1615 
1616  if (renderer == "opengl-hquyv")
1617  {
1618  msg = QObject::tr(
1619  "This renderer uses a higher quality CPU conversion for interlaced "
1620  "content before using OpenGL for color conversion, scaling, picture"
1621  " controls and optionally deinterlacing. CPU load is higher "
1622  "particularly on embedded systems.");
1623  }
1624 
1625  if (renderer == "opengl-rgba")
1626  {
1627  msg = QObject::tr(
1628  "All video processing is performed by the CPU. OpenGL is used "
1629  "for display only. Does not support picture controls or GPU "
1630  "deinterlacing. Requires a significantly faster CPU.");
1631  }
1632 
1633  if (renderer == "vdpau")
1634  {
1635  msg = QObject::tr(
1636  "This is the only video renderer for NVidia VDPAU decoding.");
1637  }
1638 
1639  if (renderer == "openglvaapi")
1640  {
1641  msg = QObject::tr(
1642  "This video renderer uses VAAPI for video decoding and "
1643  "OpenGL for scaling and color conversion.");
1644  }
1645 
1646  return msg;
1647 }
1648 
1649 QString VideoDisplayProfile::GetPreferredVideoRenderer(const QString &decoder)
1650 {
1651  return GetBestVideoRenderer(GetVideoRenderers(decoder));
1652 }
1653 
1655  const QString &video_renderer)
1656 {
1657  QMutexLocker locker(&s_safe_lock);
1658  init_statics();
1659 
1660  safe_map_t::const_iterator it = s_safe_deint.find(video_renderer);
1661  QStringList tmp;
1662  if (it != s_safe_deint.end())
1663  tmp = *it;
1664  return tmp;
1665 }
1666 
1667 QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint)
1668 {
1669  if (deint.isEmpty())
1670  return "";
1671 
1672  QString msg = "";
1673 
1674  QString kDoubleRateMsg =
1675  QObject::tr(
1676  "This deinterlacer requires the display to be capable "
1677  "of twice the frame rate as the source video.");
1678 
1679  QString kNoneMsg =
1680  QObject::tr("Perform no deinterlacing.") + " " +
1681  QObject::tr(
1682  "Use this with an interlaced display whose "
1683  "resolution exactly matches the video size. "
1684  "This is incompatible with MythTV zoom modes.");
1685 
1686  QString kOneFieldMsg = QObject::tr(
1687  "Shows only one of the two fields in the frame. "
1688  "This looks good when displaying a high motion "
1689  "1080i video on a 720p display.");
1690 
1691  QString kBobMsg = QObject::tr(
1692  "Shows one field of the frame followed by the "
1693  "other field displaced vertically.") + " " +
1694  kDoubleRateMsg;
1695 
1696  QString kLinearBlendMsg = QObject::tr(
1697  "Blends the odd and even fields linearly into one frame.");
1698 
1699  QString kKernelMsg = QObject::tr(
1700  "This filter disables deinterlacing when the two fields are "
1701  "similar, and performs linear deinterlacing otherwise.");
1702 
1703  QString kUsingGPU = QObject::tr("(Hardware Accelerated)");
1704 
1705  QString kUsingVA = QObject::tr("(VAAPI Hardware Accelerated)");
1706 
1707  QString kUsingNV = QObject::tr("(NVDEC Hardware Accelerated)");
1708 
1709  QString kUsingGL = QObject::tr("(OpenGL Hardware Accelerated)");
1710 
1711  QString kGreedyHMsg = QObject::tr(
1712  "This deinterlacer uses several fields to reduce motion blur. "
1713  "It has increased CPU requirements.");
1714 
1715  QString kYadifMsg = QObject::tr(
1716  "This deinterlacer uses several fields to reduce motion blur. "
1717  "It has increased CPU requirements.");
1718 
1719  QString kFieldOrderMsg = QObject::tr(
1720  "This deinterlacer attempts to synchronize with interlaced displays "
1721  "whose size and refresh rate exactly match the video source. "
1722  "It has low CPU requirements.");
1723 
1724  QString kBasicMsg = QObject::tr(
1725  "This deinterlacer uses several fields to reduce motion blur. ");
1726 
1727  QString kAdvMsg = QObject::tr(
1728  "This deinterlacer uses multiple fields to reduce motion blur "
1729  "and smooth edges. ");
1730 
1731  QString kMostAdvMsg = QObject::tr(
1732  "Use the most advanced hardware deinterlacing algorithm available. ");
1733 
1734  QString kWeaveMsg = QObject::tr(
1735  "Use the weave deinterlacing algorithm. ");
1736 
1737  QString kMAMsg = QObject::tr(
1738  "Use the motion adaptive deinterlacing algorithm. ");
1739 
1740  QString kMCMsg = QObject::tr(
1741  "Use the motion compensated deinterlacing algorithm. ");
1742 
1743  if (deint == "none")
1744  msg = kNoneMsg;
1745  else if (deint == "onefield")
1746  msg = kOneFieldMsg;
1747  else if (deint == "bobdeint")
1748  msg = kBobMsg;
1749  else if (deint == "linearblend")
1750  msg = kLinearBlendMsg;
1751  else if (deint == "kerneldeint")
1752  msg = kKernelMsg;
1753  else if (deint == "kerneldoubleprocessdeint")
1754  msg = kKernelMsg + " " + kDoubleRateMsg;
1755  else if (deint == "openglonefield")
1756  msg = kOneFieldMsg + " " + kUsingGL;
1757  else if (deint == "openglbobdeint")
1758  msg = kBobMsg + " " + kUsingGL;
1759  else if (deint == "opengllinearblend")
1760  msg = kLinearBlendMsg + " " + kUsingGL;
1761  else if (deint == "openglkerneldeint")
1762  msg = kKernelMsg + " " + kUsingGL;
1763  else if (deint == "opengldoubleratelinearblend")
1764  msg = kLinearBlendMsg + " " + kDoubleRateMsg + " " + kUsingGL;
1765  else if (deint == "opengldoubleratekerneldeint")
1766  msg = kKernelMsg + " " + kDoubleRateMsg + " " + kUsingGL;
1767  else if (deint == "opengldoubleratefieldorder")
1768  msg = kFieldOrderMsg + " " + kDoubleRateMsg + " " + kUsingGL;
1769  else if (deint == "greedyhdeint")
1770  msg = kGreedyHMsg;
1771  else if (deint == "greedyhdoubleprocessdeint")
1772  msg = kGreedyHMsg + " " + kDoubleRateMsg;
1773  else if (deint == "yadifdeint")
1774  msg = kYadifMsg;
1775  else if (deint == "yadifdoubleprocessdeint")
1776  msg = kYadifMsg + " " + kDoubleRateMsg;
1777  else if (deint == "fieldorderdoubleprocessdeint")
1778  msg = kFieldOrderMsg + " " + kDoubleRateMsg;
1779  else if (deint == "vdpauonefield")
1780  msg = kOneFieldMsg + " " + kUsingGPU;
1781  else if (deint == "vdpaubobdeint")
1782  msg = kBobMsg + " " + kUsingGPU;
1783  else if (deint == "vdpaubasic")
1784  msg = kBasicMsg + " " + kUsingGPU;
1785  else if (deint == "vdpauadvanced")
1786  msg = kAdvMsg + " " + kUsingGPU;
1787  else if (deint == "vdpaubasicdoublerate")
1788  msg = kBasicMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
1789  else if (deint == "vdpauadvanceddoublerate")
1790  msg = kAdvMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
1791  else if (deint == "vaapionefield")
1792  msg = kOneFieldMsg + " " + kUsingGPU;
1793  else if (deint == "vaapibobdeint")
1794  msg = kBobMsg + " " + kUsingGPU;
1795 
1796  else if (deint == "vaapi2default")
1797  msg = kMostAdvMsg + " " + kUsingVA;
1798  else if (deint == "vaapi2bob")
1799  msg = kBobMsg + " " + kUsingVA;
1800  else if (deint == "vaapi2weave")
1801  msg = kWeaveMsg + " " + kUsingVA;
1802  else if (deint == "vaapi2motion_adaptive")
1803  msg = kMAMsg + " " + kUsingVA;
1804  else if (deint == "vaapi2motion_compensated")
1805  msg = kMCMsg + " " + kUsingVA;
1806  else if (deint == "vaapi2doubleratedefault")
1807  msg = kMostAdvMsg + " " + kDoubleRateMsg + " " + kUsingVA;
1808  else if (deint == "vaapi2doubleratebob")
1809  msg = kBobMsg + " " + kDoubleRateMsg + " " + kUsingVA;
1810  else if (deint == "vaapi2doublerateweave")
1811  msg = kWeaveMsg + " " + kDoubleRateMsg + " " + kUsingVA;
1812  else if (deint == "vaapi2doubleratemotion_adaptive")
1813  msg = kMAMsg + " " + kDoubleRateMsg + " " + kUsingVA;
1814  else if (deint == "vaapi2doubleratemotion_compensated")
1815  msg = kMCMsg + " " + kDoubleRateMsg + " " + kUsingVA;
1816 
1817  else if (deint == "nvdecweave")
1818  msg = kWeaveMsg + " " + kUsingNV;
1819  else if (deint == "nvdecbob")
1820  msg = kBobMsg + " " + kUsingNV;
1821  else if (deint == "nvdecadaptive")
1822  msg = kMAMsg + " " + kUsingNV;
1823  else if (deint == "nvdecdoublerateweave")
1824  msg = kWeaveMsg + " " + kDoubleRateMsg + " " + kUsingNV;
1825  else if (deint == "nvdecdoubleratebob")
1826  msg = kBobMsg + " " + kDoubleRateMsg + " " + kUsingNV;
1827  else if (deint == "nvdecdoublerateadaptive")
1828  msg = kMAMsg + " " + kDoubleRateMsg + " " + kUsingNV;
1829  else
1830  msg = QObject::tr("'%1' has not been documented yet.").arg(deint);
1831 
1832  return msg;
1833 }
1834 
1835 QStringList VideoDisplayProfile::GetOSDs(const QString &video_renderer)
1836 {
1837  QMutexLocker locker(&s_safe_lock);
1838  init_statics();
1839 
1840  safe_map_t::const_iterator it = s_safe_osd.find(video_renderer);
1841  QStringList tmp;
1842  if (it != s_safe_osd.end())
1843  tmp = *it;
1844  return tmp;
1845 }
1846 
1847 QString VideoDisplayProfile::GetOSDHelp(const QString &osd)
1848 {
1849 
1850  QString msg = QObject::tr("OSD rendering method");
1851 
1852  if (osd.isEmpty())
1853  return msg;
1854 
1855  if (osd == "chromakey")
1856  msg = QObject::tr(
1857  "Render the OSD using the XVideo chromakey feature."
1858  "This renderer does not alpha blend but is the fastest "
1859  "OSD renderer for XVideo.") + "\n" +
1860  QObject::tr(
1861  "Note: nVidia hardware after the 5xxx series does not "
1862  "have XVideo chromakey support.");
1863 
1864 
1865  if (osd == "softblend")
1866  {
1867  msg = QObject::tr(
1868  "Software OSD rendering uses your CPU to alpha blend the OSD.");
1869  }
1870 
1871  if (osd.contains("opengl"))
1872  {
1873  msg = QObject::tr(
1874  "Uses OpenGL to alpha blend the OSD onto the video.");
1875  }
1876 
1877  if (osd =="threaded")
1878  {
1879  msg = QObject::tr(
1880  "Uses OpenGL in a separate thread to overlay the OSD onto the video.");
1881  }
1882 
1883 #ifdef USING_OPENMAX
1884  if (osd.contains("openmax"))
1885  {
1886  msg = QObject::tr(
1887  "Uses OpenMAX to alpha blend the OSD onto the video.");
1888  }
1889 #endif
1890 
1891  return msg;
1892 }
1893 
1894 bool VideoDisplayProfile::IsFilterAllowed(const QString &video_renderer)
1895 {
1896  QMutexLocker locker(&s_safe_lock);
1897  init_statics();
1898  return s_safe_custom.contains(video_renderer);
1899 }
1900 
1902  const QString &decoder, const QStringList &renderers)
1903 {
1904  const QStringList dec_list = GetVideoRenderers(decoder);
1905  QStringList new_list;
1906 
1907  QStringList::const_iterator it = dec_list.begin();
1908  for (; it != dec_list.end(); ++it)
1909  {
1910  if (renderers.contains(*it))
1911  new_list.push_back(*it); // deep copy not needed
1912  }
1913 
1914  return new_list;
1915 }
1916 
1917 QString VideoDisplayProfile::GetBestVideoRenderer(const QStringList &renderers)
1918 {
1919  QMutexLocker locker(&s_safe_lock);
1920  init_statics();
1921 
1922  uint top_priority = 0;
1923  QString top_renderer;
1924 
1925  QStringList::const_iterator it = renderers.begin();
1926  for (; it != renderers.end(); ++it)
1927  {
1928  priority_map_t::const_iterator p = s_safe_renderer_priority.find(*it);
1929  if ((p != s_safe_renderer_priority.end()) && (*p >= top_priority))
1930  {
1931  top_priority = *p;
1932  top_renderer = *it;
1933  }
1934  }
1935 
1936  return top_renderer;
1937 }
1938 
1940 {
1941  QString renderer = GetPreference("pref_videorenderer");
1942  QString osd = GetPreference("pref_osdrenderer");
1943  QString deint0 = GetPreference("pref_deint0");
1944  QString deint1 = GetPreference("pref_deint1");
1945  QString filter = GetPreference("pref_filters");
1946  return QString("rend(%4) osd(%5) deint(%6,%7) filt(%8)")
1947  .arg(renderer).arg(osd).arg(deint0).arg(deint1).arg(filter);
1948 }
1949 
1951 {
1952  if (s_safe_initialized)
1953  return;
1954 
1955  s_safe_initialized = true;
1956 
1957  render_opts options;
1958  options.renderers = &s_safe_custom;
1959  options.safe_renderers = &s_safe_renderer;
1960  options.deints = &s_safe_deint;
1961  options.osds = &s_safe_osd;
1964  options.decoders = &s_safe_decoders;
1965  options.equiv_decoders = &s_safe_equiv_dec;
1966 
1967  // N.B. assumes NuppelDecoder and DummyDecoder always present
1970 
1971  foreach(QString decoder, s_safe_decoders)
1972  LOG(VB_PLAYBACK, LOG_INFO, LOC +
1973  QString("decoder<->render support: %1%2")
1974  .arg(decoder, -12).arg(GetVideoRenderers(decoder).join(" ")));
1975 }
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
static safe_map_t s_safe_renderer
static uint CreateProfileGroup(const QString &profilename, const QString &hostname)
static QStringList GetDecoders(void)
void SetVideoRenderer(const QString &video_renderer)
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
static void init_statics(void)
static QString GetDeinterlacerName(const QString &short_name)
static QStringList GetOSDs(const QString &video_renderer)
static uint GetProfileGroupID(const QString &profilename, const QString &hostname)
priority_map_t * priorities
item_list_t::const_iterator FindMatch(const QSize &size, float framerate, const QString &codecName)
static void CreateProfiles(const QString &hostname)
QMap< QString, QStringList > safe_map_t
uint GetPriority(void) const
static QStringList GetDecoderNames(void)
void LoadBestPreferences(const QSize &size, float framerate, const QString &codecName)
static safe_list_t s_safe_custom
static void SetDefaultProfileName(const QString &profilename, const QString &hostname)
static void error(const char *str,...)
Definition: vbi.c:42
safe_list_t * renderers
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
QString GetDeinterlacer(void) const
bool checkRange(QString key, float fvalue, bool *ok=nullptr) const
static priority_map_t s_safe_renderer_priority
QString GetFilteredDeint(const QString &override)
static QString GetDecoderName(const QString &decoder)
safe_map_t * deints
static safe_list_t s_safe_decoders
static item_list_t LoadDB(uint groupid)
static bool IsFilterAllowed(const QString &video_renderer)
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
QString GetFallbackDeinterlacer(void) const
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static bool DeleteDB(uint groupid, const item_list_t &)
static QString GetOSDHelp(const QString &osd)
void SetOutput(float framerate)
static QString toCommaList(const QStringList &list)
static guint32 * tmp
Definition: goom_core.c:35
static safe_map_t s_safe_renderer_group
safe_map_t * render_group
QStringList safe_list_t
static QStringList GetDeinterlacers(const QString &video_renderer)
QVariant value(int i) const
Definition: mythdbcon.h:198
safe_list_t * decoders
bool IsMatch(const QSize &size, float framerate, const QString &codecName) const
safe_map_t * osds
static QString GetBestVideoRenderer(const QStringList &renderers)
#define LOC
bool CheckVideoRendererGroup(const QString &renderer)
bool IsValid(QString *reason=nullptr) const
vector< ProfileItem > item_list_t
bool operator<(const ProfileItem &other) const
QString GetDecoder(void) const
static void GetRenderOptions(render_opts &opts)
QMap< QString, QString > pref_map_t
static void GetDecoders(render_opts &opts)
bool isActive(void) const
Definition: mythdbcon.h:204
static QString GetDefaultProfileName(const QString &hostname)
static QString GetPreferredVideoRenderer(const QString &decoder)
safe_map_t * equiv_decoders
QString GetPreference(const QString &key) const
QString toString(void) const
string hostname
Definition: caa.py:17
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
void SetInput(const QSize &size, float framerate=0, const QString &codecName=QString())
virtual QStringList GetDeinterlacers(void)
static void DeleteProfiles(const QString &hostname)
QString GetActualVideoRenderer(void) const
static QStringList GetFilteredRenderers(const QString &decoder, const QStringList &renderers)
static pref_map_t s_dec_name
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
QMap< QString, uint > priority_map_t
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static safe_map_t s_safe_deint
static safe_map_t s_safe_equiv_dec
static QString GetDecoderHelp(const QString &decoder=QString())
static QString GetDeinterlacerHelp(const QString &deint)
QString GetOSDRenderer(void) const
safe_map_t * safe_renderers
static QString GetVideoRendererHelp(const QString &renderer)
static safe_map_t s_safe_osd
static bool DeleteProfileGroup(const QString &groupname, const QString &hostname)
void SetPreference(const QString &key, const QString &value)
QString GetVideoRenderer(void) const
static bool SaveDB(uint groupid, item_list_t &)
static void CreateProfile(uint groupid, uint priority, const QString &cmp0, uint width0, uint height0, const QString &cmp1, uint width1, uint height1, QString decoder, uint max_cpus, bool skiploop, QString videorenderer, QString osdrenderer, bool osdfade, QString deint0, QString deint1, QString filters)
static QStringList GetProfiles(const QString &hostname)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
QString toString(void) const
static QStringList GetVideoRenderers(const QString &decoder)
QString GetHostName(void)
bool IsDecoderCompatible(const QString &decoder)