00001
00002 #include <algorithm>
00003 using namespace std;
00004
00005 #include "videodisplayprofile.h"
00006 #include "mythcorecontext.h"
00007 #include "mythdb.h"
00008 #include "mythlogging.h"
00009 #include "videooutbase.h"
00010 #include "avformatdecoder.h"
00011
00012 bool ProfileItem::IsMatch(const QSize &size, float rate) const
00013 {
00014 (void) rate;
00015
00016 bool match = true;
00017 QString cmp = QString::null;
00018
00019 for (uint i = 0; (i < 1000) && match; i++)
00020 {
00021 cmp = Get(QString("pref_cmp%1").arg(i));
00022 if (cmp.isEmpty())
00023 break;
00024
00025 QStringList clist = cmp.split(" ", QString::SkipEmptyParts);
00026 if (clist.size() != 3)
00027 break;
00028
00029 int width = clist[1].toInt();
00030 int height = clist[2].toInt();
00031 cmp = clist[0];
00032
00033 if (cmp == "==")
00034 match &= (size.width() == width) && (size.height() == height);
00035 else if (cmp == "!=")
00036 match &= (size.width() != width) && (size.height() != height);
00037 else if (cmp == "<=")
00038 match &= (size.width() <= width) && (size.height() <= height);
00039 else if (cmp == "<")
00040 match &= (size.width() < width) && (size.height() < height);
00041 else if (cmp == ">=")
00042 match &= (size.width() >= width) && (size.height() >= height);
00043 else if (cmp == ">")
00044 match &= (size.width() > width) || (size.height() > height);
00045 else
00046 match = false;
00047 }
00048
00049 return match;
00050 }
00051
00052 static QString toCommaList(const QStringList &list)
00053 {
00054 QString ret = "";
00055 for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
00056 ret += *it + ",";
00057
00058 if (ret.length())
00059 return ret.left(ret.length()-1);
00060
00061 return "";
00062 }
00063
00064 bool ProfileItem::IsValid(QString *reason) const
00065 {
00066 QString decoder = Get("pref_decoder");
00067 QString renderer = Get("pref_videorenderer");
00068 if (decoder.isEmpty() || renderer.isEmpty())
00069 {
00070 if (reason)
00071 *reason = "Need a decoder and renderer";
00072
00073 return false;
00074 }
00075
00076 QStringList decoders = VideoDisplayProfile::GetDecoders();
00077 if (!decoders.contains(decoder))
00078 {
00079 if (reason)
00080 {
00081 *reason = QString("decoder %1 is not supported (supported: %2)")
00082 .arg(decoder).arg(toCommaList(decoders));
00083 }
00084
00085 return false;
00086 }
00087
00088 QStringList renderers = VideoDisplayProfile::GetVideoRenderers(decoder);
00089 if (!renderers.contains(renderer))
00090 {
00091 if (reason)
00092 {
00093 *reason = QString("renderer %1 is not supported "
00094 "w/decoder %2 (supported: %3)")
00095 .arg(renderer).arg(decoder).arg(toCommaList(renderers));
00096 }
00097
00098 return false;
00099 }
00100
00101 QStringList deints = VideoDisplayProfile::GetDeinterlacers(renderer);
00102 QString deint0 = Get("pref_deint0");
00103 QString deint1 = Get("pref_deint1");
00104 if (!deint0.isEmpty() && !deints.contains(deint0))
00105 {
00106 if (reason)
00107 {
00108 *reason = QString("deinterlacer %1 is not supported "
00109 "w/renderer %2 (supported: %3)")
00110 .arg(deint0).arg(renderer).arg(toCommaList(deints));
00111 }
00112
00113 return false;
00114 }
00115
00116 if (!deint1.isEmpty() &&
00117 (!deints.contains(deint1) ||
00118 deint1.contains("bobdeint") ||
00119 deint1.contains("doublerate") ||
00120 deint1.contains("doubleprocess")))
00121 {
00122 if (reason)
00123 {
00124 if (deint1.contains("bobdeint") ||
00125 deint1.contains("doublerate") ||
00126 deint1.contains("doubleprocess"))
00127 deints.removeAll(deint1);
00128
00129 *reason = QString("deinterlacer %1 is not supported w/renderer %2 "
00130 "as second deinterlacer (supported: %3)")
00131 .arg(deint1).arg(renderer).arg(toCommaList(deints));
00132 }
00133
00134 return false;
00135 }
00136
00137 QStringList osds = VideoDisplayProfile::GetOSDs(renderer);
00138 QString osd = Get("pref_osdrenderer");
00139 if (!osds.contains(osd))
00140 {
00141 if (reason)
00142 {
00143 *reason = QString("OSD Renderer %1 is not supported "
00144 "w/renderer %2 (supported: %3)")
00145 .arg(osd).arg(renderer).arg(toCommaList(osds));
00146 }
00147
00148 return false;
00149 }
00150
00151 QString filter = Get("pref_filters");
00152 if (!filter.isEmpty() && !VideoDisplayProfile::IsFilterAllowed(renderer))
00153 {
00154 if (reason)
00155 {
00156 *reason = QString("Filter %1 is not supported w/renderer %2")
00157 .arg(filter).arg(renderer);
00158 }
00159
00160 return false;
00161 }
00162
00163 if (reason)
00164 *reason = QString::null;
00165
00166 return true;
00167 }
00168
00169 bool ProfileItem::operator< (const ProfileItem &other) const
00170 {
00171 return GetPriority() < other.GetPriority();
00172 }
00173
00174 QString ProfileItem::toString(void) const
00175 {
00176 QString cmp0 = Get("pref_cmp0");
00177 QString cmp1 = Get("pref_cmp1");
00178 QString decoder = Get("pref_decoder");
00179 uint max_cpus = Get("pref_max_cpus").toUInt();
00180 bool skiploop = Get("pref_skiploop").toInt();
00181 QString renderer = Get("pref_videorenderer");
00182 QString osd = Get("pref_osdrenderer");
00183 QString deint0 = Get("pref_deint0");
00184 QString deint1 = Get("pref_deint1");
00185 QString filter = Get("pref_filters");
00186 bool osdfade = Get("pref_osdfade").toInt();
00187
00188 QString str = QString("cmp(%1%2) dec(%3) cpus(%4) skiploop(%5) rend(%6) ")
00189 .arg(cmp0).arg(QString(cmp1.isEmpty() ? "" : ",") + cmp1)
00190 .arg(decoder).arg(max_cpus).arg((skiploop) ? "enabled" : "disabled").arg(renderer);
00191 str += QString("osd(%1) osdfade(%2) deint(%3,%4) filt(%5)")
00192 .arg(osd).arg((osdfade) ? "enabled" : "disabled")
00193 .arg(deint0).arg(deint1).arg(filter);
00194
00195 return str;
00196 }
00197
00199
00200 #define LOC QString("VDP: ")
00201
00202 QMutex VideoDisplayProfile::safe_lock(QMutex::Recursive);
00203 bool VideoDisplayProfile::safe_initialized = false;
00204 safe_map_t VideoDisplayProfile::safe_renderer;
00205 safe_map_t VideoDisplayProfile::safe_renderer_group;
00206 safe_map_t VideoDisplayProfile::safe_deint;
00207 safe_map_t VideoDisplayProfile::safe_osd;
00208 safe_map_t VideoDisplayProfile::safe_equiv_dec;
00209 safe_list_t VideoDisplayProfile::safe_custom;
00210 priority_map_t VideoDisplayProfile::safe_renderer_priority;
00211 pref_map_t VideoDisplayProfile::dec_name;
00212 safe_list_t VideoDisplayProfile::safe_decoders;
00213
00214 VideoDisplayProfile::VideoDisplayProfile()
00215 : lock(QMutex::Recursive), last_size(0,0), last_rate(0.0f),
00216 last_video_renderer(QString::null)
00217 {
00218 QMutexLocker locker(&safe_lock);
00219 init_statics();
00220
00221 QString hostname = gCoreContext->GetHostName();
00222 QString cur_profile = GetDefaultProfileName(hostname);
00223 uint groupid = GetProfileGroupID(cur_profile, hostname);
00224
00225 item_list_t items = LoadDB(groupid);
00226 item_list_t::const_iterator it;
00227 for (it = items.begin(); it != items.end(); ++it)
00228 {
00229 QString err;
00230 if (!(*it).IsValid(&err))
00231 {
00232 LOG(VB_PLAYBACK, LOG_ERR, LOC + "Rejecting: " + (*it).toString() +
00233 "\n\t\t\t" + err);
00234
00235 continue;
00236 }
00237 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Accepting: " + (*it).toString());
00238 all_pref.push_back(*it);
00239 }
00240
00241 SetInput(QSize(2048, 2048));
00242 SetOutput(60.0f);
00243 }
00244
00245 VideoDisplayProfile::~VideoDisplayProfile()
00246 {
00247 }
00248
00249 void VideoDisplayProfile::SetInput(const QSize &size)
00250 {
00251 QMutexLocker locker(&lock);
00252 if (size != last_size)
00253 {
00254 last_size = size;
00255 LoadBestPreferences(last_size, last_rate);
00256 }
00257 }
00258
00259 void VideoDisplayProfile::SetOutput(float framerate)
00260 {
00261 QMutexLocker locker(&lock);
00262 if (framerate != last_rate)
00263 {
00264 last_rate = framerate;
00265 LoadBestPreferences(last_size, last_rate);
00266 }
00267 }
00268
00269 void VideoDisplayProfile::SetVideoRenderer(const QString &video_renderer)
00270 {
00271 QMutexLocker locker(&lock);
00272
00273 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00274 QString("SetVideoRenderer(%1)").arg(video_renderer));
00275
00276 last_video_renderer = video_renderer;
00277 last_video_renderer.detach();
00278
00279 if (video_renderer == GetVideoRenderer())
00280 {
00281 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00282 QString("SetVideoRender(%1) == GetVideoRenderer()")
00283 .arg(video_renderer));
00284 return;
00285 }
00286
00287
00288
00289 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Old preferences: " + toString());
00290
00291 SetPreference("pref_videorenderer", video_renderer);
00292
00293 QStringList osds = GetOSDs(video_renderer);
00294 if (!osds.contains(GetOSDRenderer()))
00295 SetPreference("pref_osdrenderer", osds[0]);
00296
00297 QStringList deints = GetDeinterlacers(video_renderer);
00298 if (!deints.contains(GetDeinterlacer()))
00299 SetPreference("pref_deint0", deints[0]);
00300 if (!deints.contains(GetFallbackDeinterlacer()))
00301 SetPreference("pref_deint1", deints[0]);
00302 if (GetFallbackDeinterlacer().contains("bobdeint") ||
00303 GetFallbackDeinterlacer().contains("doublerate") ||
00304 GetFallbackDeinterlacer().contains("doubleprocess"))
00305 {
00306 SetPreference("pref_deint1", deints[1]);
00307 }
00308
00309 SetPreference("pref_filters", "");
00310
00311 LOG(VB_PLAYBACK, LOG_INFO, LOC + "New preferences: " + toString());
00312 }
00313
00314 bool VideoDisplayProfile::CheckVideoRendererGroup(const QString renderer)
00315 {
00316 if (last_video_renderer == renderer ||
00317 last_video_renderer == "null")
00318 return true;
00319
00320 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00321 QString("Preferred video renderer: %1 (current: %2)")
00322 .arg(renderer).arg(last_video_renderer));
00323
00324 safe_map_t::const_iterator it = safe_renderer_group.begin();
00325 for (; it != safe_renderer_group.end(); ++it)
00326 if (it->contains(last_video_renderer) &&
00327 it->contains(renderer))
00328 return true;
00329 return false;
00330 }
00331
00332 bool VideoDisplayProfile::IsDecoderCompatible(const QString &decoder)
00333 {
00334 const QString dec = GetDecoder();
00335 if (dec == decoder)
00336 return true;
00337
00338 QMutexLocker locker(&safe_lock);
00339 return (safe_equiv_dec[dec].contains(decoder));
00340 }
00341
00342 QString VideoDisplayProfile::GetFilteredDeint(const QString &override)
00343 {
00344 QString renderer = GetActualVideoRenderer();
00345 QString deint = GetDeinterlacer();
00346
00347 QMutexLocker locker(&lock);
00348
00349 if (!override.isEmpty() && GetDeinterlacers(renderer).contains(override))
00350 deint = override;
00351
00352 LOG(VB_PLAYBACK, LOG_INFO,
00353 LOC + QString("GetFilteredDeint(%1) : %2 -> '%3'")
00354 .arg(override).arg(renderer).arg(deint));
00355
00356 deint.detach();
00357 return deint;
00358 }
00359
00360 QString VideoDisplayProfile::GetPreference(const QString &key) const
00361 {
00362 QMutexLocker locker(&lock);
00363
00364 if (key.isEmpty())
00365 return QString::null;
00366
00367 pref_map_t::const_iterator it = pref.find(key);
00368 if (it == pref.end())
00369 return QString::null;
00370
00371 QString pref = *it;
00372 pref.detach();
00373 return pref;
00374 }
00375
00376 void VideoDisplayProfile::SetPreference(
00377 const QString &key, const QString &value)
00378 {
00379 QMutexLocker locker(&lock);
00380
00381 if (!key.isEmpty())
00382 {
00383 QString tmp = value;
00384 tmp.detach();
00385 pref[key] = tmp;
00386 }
00387 }
00388
00389 item_list_t::const_iterator VideoDisplayProfile::FindMatch(
00390 const QSize &size, float rate)
00391 {
00392 item_list_t::const_iterator it = all_pref.begin();
00393 for (; it != all_pref.end(); ++it)
00394 {
00395 if ((*it).IsMatch(size, rate))
00396 return it;
00397 }
00398
00399 return all_pref.end();
00400 }
00401
00402 void VideoDisplayProfile::LoadBestPreferences(const QSize &size,
00403 float framerate)
00404 {
00405 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("LoadBestPreferences(%1x%2, %3)")
00406 .arg(size.width()).arg(size.height()).arg(framerate));
00407
00408 pref.clear();
00409 item_list_t::const_iterator it = FindMatch(size, framerate);
00410 if (it != all_pref.end())
00411 pref = (*it).GetAll();
00412 }
00413
00415
00416
00417 item_list_t VideoDisplayProfile::LoadDB(uint groupid)
00418 {
00419 ProfileItem tmp;
00420 item_list_t list;
00421
00422 MSqlQuery query(MSqlQuery::InitCon());
00423 query.prepare(
00424 "SELECT profileid, value, data "
00425 "FROM displayprofiles "
00426 "WHERE profilegroupid = :GROUPID "
00427 "ORDER BY profileid");
00428 query.bindValue(":GROUPID", groupid);
00429 if (!query.exec())
00430 {
00431 MythDB::DBError("loaddb 1", query);
00432 return list;
00433 }
00434
00435 uint profileid = 0;
00436 while (query.next())
00437 {
00438 if (query.value(0).toUInt() != profileid)
00439 {
00440 if (profileid)
00441 {
00442 tmp.SetProfileID(profileid);
00443 QString error;
00444 bool valid = tmp.IsValid(&error);
00445 if (valid)
00446 list.push_back(tmp);
00447 else
00448 LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
00449 QString("Ignoring profile item %1 (%2)")
00450 .arg(profileid).arg(error));
00451 }
00452 tmp.Clear();
00453 profileid = query.value(0).toUInt();
00454 }
00455 tmp.Set(query.value(1).toString(), query.value(2).toString());
00456 }
00457 if (profileid)
00458 {
00459 tmp.SetProfileID(profileid);
00460 QString error;
00461 bool valid = tmp.IsValid(&error);
00462 if (valid)
00463 list.push_back(tmp);
00464 else
00465 LOG(VB_PLAYBACK, LOG_NOTICE, LOC +
00466 QString("Ignoring profile item %1 (%2)")
00467 .arg(profileid).arg(error));
00468 }
00469
00470 sort(list.begin(), list.end());
00471 return list;
00472 }
00473
00474 bool VideoDisplayProfile::DeleteDB(uint groupid, const item_list_t &items)
00475 {
00476 MSqlQuery query(MSqlQuery::InitCon());
00477 query.prepare(
00478 "DELETE FROM displayprofiles "
00479 "WHERE profilegroupid = :GROUPID AND "
00480 " profileid = :PROFILEID");
00481
00482 bool ok = true;
00483 item_list_t::const_iterator it = items.begin();
00484 for (; it != items.end(); ++it)
00485 {
00486 if (!(*it).GetProfileID())
00487 continue;
00488
00489 query.bindValue(":GROUPID", groupid);
00490 query.bindValue(":PROFILEID", (*it).GetProfileID());
00491 if (!query.exec())
00492 {
00493 MythDB::DBError("vdp::deletedb", query);
00494 ok = false;
00495 }
00496 }
00497
00498 return ok;
00499 }
00500
00501 bool VideoDisplayProfile::SaveDB(uint groupid, item_list_t &items)
00502 {
00503 MSqlQuery query(MSqlQuery::InitCon());
00504
00505 MSqlQuery update(MSqlQuery::InitCon());
00506 update.prepare(
00507 "UPDATE displayprofiles "
00508 "SET data = :DATA "
00509 "WHERE profilegroupid = :GROUPID AND "
00510 " profileid = :PROFILEID AND "
00511 " value = :VALUE");
00512
00513 MSqlQuery insert(MSqlQuery::InitCon());
00514 insert.prepare(
00515 "INSERT INTO displayprofiles "
00516 " ( profilegroupid, profileid, value, data) "
00517 "VALUES "
00518 " (:GROUPID, :PROFILEID, :VALUE, :DATA) ");
00519
00520
00521 bool ok = true;
00522 item_list_t::iterator it = items.begin();
00523 for (; it != items.end(); ++it)
00524 {
00525 pref_map_t list = (*it).GetAll();
00526 if (list.begin() == list.end())
00527 continue;
00528
00529 pref_map_t::const_iterator lit = list.begin();
00530
00531 if (!(*it).GetProfileID())
00532 {
00533
00534 if (!query.exec("SELECT MAX(profileid) FROM displayprofiles"))
00535 {
00536 MythDB::DBError("save_profile 1", query);
00537 ok = false;
00538 continue;
00539 }
00540 else if (query.next())
00541 {
00542 (*it).SetProfileID(query.value(0).toUInt() + 1);
00543 }
00544
00545 for (; lit != list.end(); ++lit)
00546 {
00547 if ((*lit).isEmpty())
00548 continue;
00549
00550 insert.bindValue(":GROUPID", groupid);
00551 insert.bindValue(":PROFILEID", (*it).GetProfileID());
00552 insert.bindValue(":VALUE", lit.key());
00553 insert.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
00554 if (!insert.exec())
00555 {
00556 MythDB::DBError("save_profile 2", insert);
00557 ok = false;
00558 continue;
00559 }
00560 }
00561 continue;
00562 }
00563
00564 for (; lit != list.end(); ++lit)
00565 {
00566 query.prepare(
00567 "SELECT count(*) "
00568 "FROM displayprofiles "
00569 "WHERE profilegroupid = :GROUPID AND "
00570 " profileid = :PROFILEID AND "
00571 " value = :VALUE");
00572 query.bindValue(":GROUPID", groupid);
00573 query.bindValue(":PROFILEID", (*it).GetProfileID());
00574 query.bindValue(":VALUE", lit.key());
00575
00576 if (!query.exec())
00577 {
00578 MythDB::DBError("save_profile 3", query);
00579 ok = false;
00580 continue;
00581 }
00582 else if (query.next() && (1 == query.value(0).toUInt()))
00583 {
00584 update.bindValue(":GROUPID", groupid);
00585 update.bindValue(":PROFILEID", (*it).GetProfileID());
00586 update.bindValue(":VALUE", lit.key());
00587 update.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
00588 if (!update.exec())
00589 {
00590 MythDB::DBError("save_profile 5", update);
00591 ok = false;
00592 continue;
00593 }
00594 }
00595 else
00596 {
00597 insert.bindValue(":GROUPID", groupid);
00598 insert.bindValue(":PROFILEID", (*it).GetProfileID());
00599 insert.bindValue(":VALUE", lit.key());
00600 insert.bindValue(":DATA", ((*lit).isNull()) ? "" : (*lit));
00601 if (!insert.exec())
00602 {
00603 MythDB::DBError("save_profile 4", insert);
00604 ok = false;
00605 continue;
00606 }
00607 }
00608 }
00609 }
00610
00611 return ok;
00612 }
00613
00614 QStringList VideoDisplayProfile::GetDecoders(void)
00615 {
00616 init_statics();
00617 return safe_decoders;
00618 }
00619
00620 QStringList VideoDisplayProfile::GetDecoderNames(void)
00621 {
00622 init_statics();
00623 QStringList list;
00624
00625 const QStringList decs = GetDecoders();
00626 QStringList::const_iterator it = decs.begin();
00627 for (; it != decs.end(); ++it)
00628 list += GetDecoderName(*it);
00629
00630 return list;
00631 }
00632
00633 QString VideoDisplayProfile::GetDecoderName(const QString &decoder)
00634 {
00635 if (decoder.isEmpty())
00636 return "";
00637
00638 QMutexLocker locker(&safe_lock);
00639 if (dec_name.empty())
00640 {
00641 dec_name["ffmpeg"] = QObject::tr("Standard");
00642 dec_name["macaccel"] = QObject::tr("Mac hardware acceleration");
00643 dec_name["vdpau"] = QObject::tr("NVidia VDPAU acceleration");
00644 dec_name["vaapi"] = QObject::tr("VAAPI acceleration");
00645 dec_name["dxva2"] = QObject::tr("Windows hardware acceleration");
00646 dec_name["vda"] = QObject::tr("Mac VDA hardware acceleration");
00647 }
00648
00649 QString ret = decoder;
00650 pref_map_t::const_iterator it = dec_name.find(decoder);
00651 if (it != dec_name.end())
00652 ret = *it;
00653
00654 ret.detach();
00655 return ret;
00656 }
00657
00658
00659 QString VideoDisplayProfile::GetDecoderHelp(QString decoder)
00660 {
00661 QString msg = QObject::tr("Processing method used to decode video.");
00662
00663 if (decoder.isEmpty())
00664 return msg;
00665
00666 msg += "\n";
00667
00668 if (decoder == "ffmpeg")
00669 msg += QObject::tr("Standard will use ffmpeg library.");
00670
00671 if (decoder == "macaccel")
00672 msg += QObject::tr(
00673 "Mac hardware will try to use the graphics "
00674 "processor - this may hang or crash your Mac!");
00675
00676 if (decoder == "vdpau")
00677 msg += QObject::tr(
00678 "VDPAU will attempt to use the graphics hardware to "
00679 "accelerate video decoding and playback.");
00680
00681 if (decoder == "dxva2")
00682 msg += QObject::tr(
00683 "DXVA2 will use the graphics hardware to "
00684 "accelerate video decoding and playback "
00685 "(requires Windows Vista or later).");
00686
00687 if (decoder == "vaapi")
00688 msg += QObject::tr(
00689 "VAAPI will attempt to use the graphics hardware to "
00690 "accelerate video decoding.");
00691
00692 if (decoder == "vda")
00693 msg += QObject::tr(
00694 "VDA will attempt to use the graphics hardware to "
00695 "accelerate video decoding. "
00696 "(H264 only, requires Mac OS 10.6.3)");
00697
00698 return msg;
00699 }
00700
00701 QString VideoDisplayProfile::GetDeinterlacerName(const QString short_name)
00702 {
00703 if ("none" == short_name)
00704 return QObject::tr("None");
00705 else if ("linearblend" == short_name)
00706 return QObject::tr("Linear blend");
00707 else if ("kerneldeint" == short_name)
00708 return QObject::tr("Kernel");
00709 else if ("kerneldoubleprocessdeint" == short_name)
00710 return QObject::tr("Kernel (2x)");
00711 else if ("greedyhdeint" == short_name)
00712 return QObject::tr("Greedy HighMotion");
00713 else if ("greedyhdoubleprocessdeint" == short_name)
00714 return QObject::tr("Greedy HighMotion (2x)");
00715 else if ("yadifdeint" == short_name)
00716 return QObject::tr("Yadif");
00717 else if ("yadifdoubleprocessdeint" == short_name)
00718 return QObject::tr("Yadif (2x)");
00719 else if ("bobdeint" == short_name)
00720 return QObject::tr("Bob (2x)");
00721 else if ("onefield" == short_name)
00722 return QObject::tr("One field");
00723 else if ("fieldorderdoubleprocessdeint" == short_name)
00724 return QObject::tr("Interlaced (2x)");
00725 else if ("opengllinearblend" == short_name)
00726 return QObject::tr("Linear blend (HW)");
00727 else if ("openglkerneldeint" == short_name)
00728 return QObject::tr("Kernel (HW)");
00729 else if ("openglbobdeint" == short_name)
00730 return QObject::tr("Bob (2x, HW)");
00731 else if ("openglonefield" == short_name)
00732 return QObject::tr("One field (HW)");
00733 else if ("opengldoubleratekerneldeint" == short_name)
00734 return QObject::tr("Kernel (2x, HW)");
00735 else if ("opengldoubleratelinearblend" == short_name)
00736 return QObject::tr("Linear blend (2x, HW)");
00737 else if ("opengldoubleratefieldorder" == short_name)
00738 return QObject::tr("Interlaced (2x, HW)");
00739 else if ("vdpauonefield" == short_name)
00740 return QObject::tr("One Field (1x, HW)");
00741 else if ("vdpaubobdeint" == short_name)
00742 return QObject::tr("Bob (2x, HW)");
00743 else if ("vdpaubasic" == short_name)
00744 return QObject::tr("Temporal (1x, HW)");
00745 else if ("vdpaubasicdoublerate" == short_name)
00746 return QObject::tr("Temporal (2x, HW)");
00747 else if ("vdpauadvanced" == short_name)
00748 return QObject::tr("Advanced (1x, HW)");
00749 else if ("vdpauadvanceddoublerate" == short_name)
00750 return QObject::tr("Advanced (2x, HW)");
00751 else if ("vaapionefield" == short_name)
00752 return QObject::tr("One Field (1x, HW)");
00753 else if ("vaapibobdeint" == short_name)
00754 return QObject::tr("Bob (2x, HW)");
00755
00756 return "";
00757 }
00758
00759 QStringList VideoDisplayProfile::GetProfiles(const QString &hostname)
00760 {
00761 init_statics();
00762 QStringList list;
00763 MSqlQuery query(MSqlQuery::InitCon());
00764 query.prepare(
00765 "SELECT name "
00766 "FROM displayprofilegroups "
00767 "WHERE hostname = :HOST ");
00768 query.bindValue(":HOST", hostname);
00769 if (!query.exec() || !query.isActive())
00770 MythDB::DBError("get_profiles", query);
00771 else
00772 {
00773 while (query.next())
00774 list += query.value(0).toString();
00775 }
00776 return list;
00777 }
00778
00779 QString VideoDisplayProfile::GetDefaultProfileName(const QString &hostname)
00780 {
00781 QString tmp =
00782 gCoreContext->GetSettingOnHost("DefaultVideoPlaybackProfile", hostname);
00783
00784 QStringList profiles = GetProfiles(hostname);
00785
00786 tmp = (profiles.contains(tmp)) ? tmp : QString();
00787
00788 if (tmp.isEmpty())
00789 {
00790 if (profiles.size())
00791 tmp = profiles[0];
00792
00793 tmp = (profiles.contains("Normal")) ? "Normal" : tmp;
00794
00795 if (!tmp.isEmpty())
00796 {
00797 gCoreContext->SaveSettingOnHost(
00798 "DefaultVideoPlaybackProfile", tmp, hostname);
00799 }
00800 }
00801
00802 return tmp;
00803 }
00804
00805 void VideoDisplayProfile::SetDefaultProfileName(
00806 const QString &profilename, const QString &hostname)
00807 {
00808 gCoreContext->SaveSettingOnHost(
00809 "DefaultVideoPlaybackProfile", profilename, hostname);
00810 }
00811
00812 uint VideoDisplayProfile::GetProfileGroupID(const QString &profilename,
00813 const QString &hostname)
00814 {
00815 MSqlQuery query(MSqlQuery::InitCon());
00816 query.prepare(
00817 "SELECT profilegroupid "
00818 "FROM displayprofilegroups "
00819 "WHERE name = :NAME AND "
00820 " hostname = :HOST ");
00821 query.bindValue(":NAME", profilename);
00822 query.bindValue(":HOST", hostname);
00823
00824 if (!query.exec() || !query.isActive())
00825 MythDB::DBError("get_profile_group_id", query);
00826 else if (query.next())
00827 return query.value(0).toUInt();
00828
00829 return 0;
00830 }
00831
00832 void VideoDisplayProfile::DeleteProfiles(const QString &hostname)
00833 {
00834 MSqlQuery query(MSqlQuery::InitCon());
00835 MSqlQuery query2(MSqlQuery::InitCon());
00836 query.prepare(
00837 "SELECT profilegroupid "
00838 "FROM displayprofilegroups "
00839 "WHERE hostname = :HOST ");
00840 query.bindValue(":HOST", hostname);
00841 if (!query.exec() || !query.isActive())
00842 MythDB::DBError("delete_profiles 1", query);
00843 else
00844 {
00845 while (query.next())
00846 {
00847 query2.prepare("DELETE FROM displayprofiles "
00848 "WHERE profilegroupid = :PROFID");
00849 query2.bindValue(":PROFID", query.value(0).toUInt());
00850 if (!query2.exec())
00851 MythDB::DBError("delete_profiles 2", query2);
00852 }
00853 }
00854 query.prepare("DELETE FROM displayprofilegroups WHERE hostname = :HOST");
00855 query.bindValue(":HOST", hostname);
00856 if (!query.exec() || !query.isActive())
00857 MythDB::DBError("delete_profiles 3", query);
00858 }
00859
00860
00861
00862
00863 void VideoDisplayProfile::CreateProfile(
00864 uint groupid, uint priority,
00865 QString cmp0, uint width0, uint height0,
00866 QString cmp1, uint width1, uint height1,
00867 QString decoder, uint max_cpus, bool skiploop, QString videorenderer,
00868 QString osdrenderer, bool osdfade,
00869 QString deint0, QString deint1, QString filters)
00870 {
00871 MSqlQuery query(MSqlQuery::InitCon());
00872
00873 if (cmp0.isEmpty() && cmp1.isEmpty())
00874 return;
00875
00876
00877 uint profileid = 1;
00878 if (!query.exec("SELECT MAX(profileid) FROM displayprofiles"))
00879 MythDB::DBError("create_profile 1", query);
00880 else if (query.next())
00881 profileid = query.value(0).toUInt() + 1;
00882
00883 query.prepare(
00884 "INSERT INTO displayprofiles "
00885 "VALUES (:GRPID, :PROFID, 'pref_priority', :PRIORITY)");
00886 query.bindValue(":GRPID", groupid);
00887 query.bindValue(":PROFID", profileid);
00888 query.bindValue(":PRIORITY", priority);
00889 if (!query.exec())
00890 MythDB::DBError("create_profile 2", query);
00891
00892 QStringList queryValue;
00893 QStringList queryData;
00894
00895 if (!cmp0.isEmpty())
00896 {
00897 queryValue += "pref_cmp0";
00898 queryData += QString("%1 %2 %3").arg(cmp0).arg(width0).arg(height0);
00899 }
00900
00901 if (!cmp1.isEmpty())
00902 {
00903 queryValue += QString("pref_cmp%1").arg(cmp0.isEmpty() ? 0 : 1);
00904 queryData += QString("%1 %2 %3").arg(cmp1).arg(width1).arg(height1);
00905 }
00906
00907 queryValue += "pref_decoder";
00908 queryData += decoder;
00909
00910 queryValue += "pref_max_cpus";
00911 queryData += QString::number(max_cpus);
00912
00913 queryValue += "pref_skiploop";
00914 queryData += (skiploop) ? "1" : "0";
00915
00916 queryValue += "pref_videorenderer";
00917 queryData += videorenderer;
00918
00919 queryValue += "pref_osdrenderer";
00920 queryData += osdrenderer;
00921
00922 queryValue += "pref_osdfade";
00923 queryData += (osdfade) ? "1" : "0";
00924
00925 queryValue += "pref_deint0";
00926 queryData += deint0;
00927
00928 queryValue += "pref_deint1";
00929 queryData += deint1;
00930
00931 queryValue += "pref_filters";
00932 queryData += filters;
00933
00934 QStringList::const_iterator itV = queryValue.begin();
00935 QStringList::const_iterator itD = queryData.begin();
00936 for (; itV != queryValue.end() && itD != queryData.end(); ++itV,++itD)
00937 {
00938 query.prepare(
00939 "INSERT INTO displayprofiles "
00940 "VALUES (:GRPID, :PROFID, :VALUE, :DATA)");
00941 query.bindValue(":GRPID", groupid);
00942 query.bindValue(":PROFID", profileid);
00943 query.bindValue(":VALUE", *itV);
00944 query.bindValue(":DATA", ((*itD).isNull()) ? "" : (*itD));
00945 if (!query.exec())
00946 MythDB::DBError("create_profile 3", query);
00947 }
00948 }
00949
00950 uint VideoDisplayProfile::CreateProfileGroup(
00951 const QString &profilename, const QString &hostname)
00952 {
00953 MSqlQuery query(MSqlQuery::InitCon());
00954 query.prepare(
00955 "INSERT INTO displayprofilegroups (name, hostname) "
00956 "VALUES (:NAME,:HOST)");
00957
00958 query.bindValue(":NAME", profilename);
00959 query.bindValue(":HOST", hostname);
00960
00961 if (!query.exec())
00962 {
00963 MythDB::DBError("create_profile_group", query);
00964 return 0;
00965 }
00966
00967 return GetProfileGroupID(profilename, hostname);
00968 }
00969
00970 bool VideoDisplayProfile::DeleteProfileGroup(
00971 const QString &groupname, const QString &hostname)
00972 {
00973 bool ok = true;
00974 MSqlQuery query(MSqlQuery::InitCon());
00975 MSqlQuery query2(MSqlQuery::InitCon());
00976
00977 query.prepare(
00978 "SELECT profilegroupid "
00979 "FROM displayprofilegroups "
00980 "WHERE name = :NAME AND "
00981 " hostname = :HOST ");
00982
00983 query.bindValue(":NAME", groupname);
00984 query.bindValue(":HOST", hostname);
00985
00986 if (!query.exec() || !query.isActive())
00987 {
00988 MythDB::DBError("delete_profile_group 1", query);
00989 ok = false;
00990 }
00991 else
00992 {
00993 while (query.next())
00994 {
00995 query2.prepare("DELETE FROM displayprofiles "
00996 "WHERE profilegroupid = :PROFID");
00997 query2.bindValue(":PROFID", query.value(0).toUInt());
00998 if (!query2.exec())
00999 {
01000 MythDB::DBError("delete_profile_group 2", query2);
01001 ok = false;
01002 }
01003 }
01004 }
01005
01006 query.prepare(
01007 "DELETE FROM displayprofilegroups "
01008 "WHERE name = :NAME AND "
01009 " hostname = :HOST");
01010
01011 query.bindValue(":NAME", groupname);
01012 query.bindValue(":HOST", hostname);
01013
01014 if (!query.exec())
01015 {
01016 MythDB::DBError("delete_profile_group 3", query);
01017 ok = false;
01018 }
01019
01020 return ok;
01021 }
01022
01023 void VideoDisplayProfile::CreateNewProfiles(const QString &hostname)
01024 {
01025 (void) QObject::tr("High Quality", "Sample: high quality");
01026 DeleteProfileGroup("High Quality", hostname);
01027 uint groupid = CreateProfileGroup("High Quality", hostname);
01028 CreateProfile(groupid, 1, ">=", 1920, 1080, "", 0, 0,
01029 "ffmpeg", 2, true, "xv-blit", "softblend", true,
01030 "linearblend", "linearblend", "");
01031 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01032 "ffmpeg", 1, true, "xv-blit", "softblend", true,
01033 "yadifdoubleprocessdeint", "yadifdeint", "");
01034 CreateProfile(groupid, 3, ">=", 1920, 1080, "", 0, 0,
01035 "ffmpeg", 2, true, "quartz-blit", "softblend", true,
01036 "linearblend", "linearblend", "");
01037 CreateProfile(groupid, 4, ">", 0, 0, "", 0, 0,
01038 "ffmpeg", 1, true, "quartz-blit", "softblend", true,
01039 "yadifdoubleprocessdeint", "yadifdeint", "");
01040
01041 (void) QObject::tr("Normal", "Sample: average quality");
01042 DeleteProfileGroup("Normal", hostname);
01043 groupid = CreateProfileGroup("Normal", hostname);
01044 CreateProfile(groupid, 1, ">=", 1280, 720, "", 0, 0,
01045 "ffmpeg", 1, true, "xv-blit", "softblend", false,
01046 "linearblend", "linearblend", "");
01047 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01048 "ffmpeg", 1, true, "xv-blit", "softblend", true,
01049 "greedyhdoubleprocessdeint", "kerneldeint", "");
01050 CreateProfile(groupid, 3, ">=", 1280, 720, "", 0, 0,
01051 "ffmpeg", 1, true, "quartz-blit", "softblend", false,
01052 "linearblend", "linearblend", "");
01053 CreateProfile(groupid, 4, ">", 0, 0, "", 0, 0,
01054 "ffmpeg", 1, true, "quartz-blit", "softblend", true,
01055 "greedyhdoubleprocessdeint", "kerneldeint", "");
01056
01057 (void) QObject::tr("Slim", "Sample: low CPU usage");
01058 DeleteProfileGroup("Slim", hostname);
01059 groupid = CreateProfileGroup("Slim", hostname);
01060 CreateProfile(groupid, 1, ">=", 1280, 720, "", 0, 0,
01061 "ffmpeg", 1, true, "xv-blit", "softblend", false,
01062 "onefield", "onefield", "");
01063 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01064 "ffmpeg", 1, true, "xv-blit", "softblend", false,
01065 "linearblend", "linearblend", "");
01066 CreateProfile(groupid, 3, ">=", 1280, 720, "", 0, 0,
01067 "ffmpeg", 1, true, "quartz-blit", "softblend", false,
01068 "onefield", "onefield", "");
01069 CreateProfile(groupid, 4, ">", 0, 0, "", 0, 0,
01070 "ffmpeg", 1, true, "quartz-blit", "softblend", false,
01071 "linearblend", "linearblend", "");
01072 }
01073
01074 void VideoDisplayProfile::CreateVDPAUProfiles(const QString &hostname)
01075 {
01076 (void) QObject::tr("VDPAU High Quality", "Sample: VDPAU high quality");
01077 DeleteProfileGroup("VDPAU High Quality", hostname);
01078 uint groupid = CreateProfileGroup("VDPAU High Quality", hostname);
01079 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01080 "vdpau", 1, true, "vdpau", "vdpau", true,
01081 "vdpauadvanceddoublerate", "vdpauadvanced",
01082 "vdpaucolorspace=auto");
01083
01084 (void) QObject::tr("VDPAU Normal", "Sample: VDPAU average quality");
01085 DeleteProfileGroup("VDPAU Normal", hostname);
01086 groupid = CreateProfileGroup("VDPAU Normal", hostname);
01087 CreateProfile(groupid, 1, ">=", 0, 720, "", 0, 0,
01088 "vdpau", 1, true, "vdpau", "vdpau", true,
01089 "vdpaubasicdoublerate", "vdpaubasic",
01090 "vdpaucolorspace=auto");
01091 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01092 "vdpau", 1, true, "vdpau", "vdpau", true,
01093 "vdpauadvanceddoublerate", "vdpauadvanced",
01094 "vdpaucolorspace=auto");
01095
01096 (void) QObject::tr("VDPAU Slim", "Sample: VDPAU low power GPU");
01097 DeleteProfileGroup("VDPAU Slim", hostname);
01098 groupid = CreateProfileGroup("VDPAU Slim", hostname);
01099 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01100 "vdpau", 1, true, "vdpau", "vdpau", true,
01101 "vdpaubobdeint", "vdpauonefield",
01102 "vdpauskipchroma,vdpaucolorspace=auto");
01103 }
01104
01105 void VideoDisplayProfile::CreateVDAProfiles(const QString &hostname)
01106 {
01107 (void) QObject::tr("VDA High Quality", "Sample: VDA high quality");
01108 DeleteProfileGroup("VDA High Quality", hostname);
01109 uint groupid = CreateProfileGroup("VDA High Quality", hostname);
01110 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01111 "vda", 2, true, "opengl", "opengl2", true,
01112 "greedyhdoubleprocessdeint", "greedyhdeint",
01113 "");
01114 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01115 "ffmpeg", 2, true, "opengl", "opengl2", true,
01116 "greedyhdoubleprocessdeint", "greedyhdeint",
01117 "");
01118
01119 (void) QObject::tr("VDA Normal", "Sample: VDA average quality");
01120 DeleteProfileGroup("VDA Normal", hostname);
01121 groupid = CreateProfileGroup("VDA Normal", hostname);
01122 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01123 "vda", 2, true, "opengl", "opengl2", true,
01124 "opengldoubleratekerneldeint", "openglkerneldeint",
01125 "");
01126 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01127 "ffmpeg", 2, true, "opengl", "opengl2", true,
01128 "opengldoubleratekerneldeint", "openglkerneldeint",
01129 "");
01130
01131 (void) QObject::tr("VDA Slim", "Sample: VDA low power GPU");
01132 DeleteProfileGroup("VDA Slim", hostname);
01133 groupid = CreateProfileGroup("VDA Slim", hostname);
01134 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01135 "vda", 2, true, "opengl", "opengl2", true,
01136 "opengldoubleratelinearblend", "opengllinearblend",
01137 "");
01138 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01139 "ffmpeg", 2, true, "opengl", "opengl2", true,
01140 "opengldoubleratelinearblend", "opengllinearblend",
01141 "");
01142 }
01143
01144 void VideoDisplayProfile::CreateOpenGLProfiles(const QString &hostname)
01145 {
01146 (void) QObject::tr("OpenGL High Quality", "Sample: OpenGL high quality");
01147 DeleteProfileGroup("OpenGL High Quality", hostname);
01148 uint groupid = CreateProfileGroup("OpenGL High Quality", hostname);
01149 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01150 "ffmpeg", 2, true, "opengl", "opengl2", true,
01151 "greedyhdoubleprocessdeint", "greedyhdeint",
01152 "");
01153
01154 (void) QObject::tr("OpenGL Normal", "Sample: OpenGL average quality");
01155 DeleteProfileGroup("OpenGL Normal", hostname);
01156 groupid = CreateProfileGroup("OpenGL Normal", hostname);
01157 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01158 "ffmpeg", 2, true, "opengl", "opengl2", true,
01159 "opengldoubleratekerneldeint", "openglkerneldeint",
01160 "");
01161
01162 (void) QObject::tr("OpenGL Slim", "Sample: OpenGL low power GPU");
01163 DeleteProfileGroup("OpenGL Slim", hostname);
01164 groupid = CreateProfileGroup("OpenGL Slim", hostname);
01165 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01166 "ffmpeg", 1, true, "opengl", "opengl2", true,
01167 "opengldoubleratelinearblend", "opengllinearblend",
01168 "");
01169 }
01170
01171 void VideoDisplayProfile::CreateVAAPIProfiles(const QString &hostname)
01172 {
01173 (void) QObject::tr("VAAPI Normal", "Sample: VAAPI average quality");
01174 DeleteProfileGroup("VAAPI Normal", hostname);
01175 uint groupid = CreateProfileGroup("VAAPI Normal", hostname);
01176 CreateProfile(groupid, 1, ">", 0, 0, "", 0, 0,
01177 "vaapi", 2, true, "openglvaapi", "opengl2", true,
01178 "vaapibobdeint", "vaapionefield",
01179 "");
01180 CreateProfile(groupid, 2, ">", 0, 0, "", 0, 0,
01181 "ffmpeg", 2, true, "opengl", "opengl2", true,
01182 "opengldoubleratekerneldeint", "openglkerneldeint",
01183 "");
01184 }
01185
01186 void VideoDisplayProfile::CreateProfiles(const QString &hostname)
01187 {
01188 CreateNewProfiles(hostname);
01189 }
01190
01191 QStringList VideoDisplayProfile::GetVideoRenderers(const QString &decoder)
01192 {
01193 QMutexLocker locker(&safe_lock);
01194 init_statics();
01195
01196 safe_map_t::const_iterator it = safe_renderer.find(decoder);
01197 QStringList tmp;
01198 if (it != safe_renderer.end())
01199 tmp = *it;
01200
01201 tmp.detach();
01202 return tmp;
01203 }
01204
01205 QString VideoDisplayProfile::GetVideoRendererHelp(const QString &renderer)
01206 {
01207 QString msg = QObject::tr("Video rendering method");
01208
01209 if (renderer.isEmpty())
01210 return msg;
01211
01212 if (renderer == "null")
01213 msg = QObject::tr(
01214 "Render video offscreen. Used internally.");
01215
01216 if (renderer == "xlib")
01217 msg = QObject::tr(
01218 "Use X11 pixel copy to render video. This is not recommended if "
01219 "any other option is available. The video will not be scaled to "
01220 "fit the screen. This will work with all X11 servers, local "
01221 "and remote.");
01222
01223 if (renderer == "xshm")
01224 msg = QObject::tr(
01225 "Use X11 shared memory pixel transfer to render video. This is "
01226 "only recommended over the X11 pixel copy renderer. The video "
01227 "will not be scaled to fit the screen. This works with most "
01228 "local X11 servers.");
01229
01230 if (renderer == "xv-blit")
01231 msg = QObject::tr(
01232 "This is the standard video renderer for X11 systems. It uses "
01233 "XVideo hardware assist for scaling, color conversion. If the "
01234 "hardware offers picture controls the renderer supports them.");
01235
01236 if (renderer == "direct3d")
01237 msg = QObject::tr(
01238 "Windows video renderer based on Direct3D. Requires "
01239 "video card compatible with Direct3D 9. This is the preferred "
01240 "renderer for current Windows systems.");
01241
01242 if (renderer == "quartz-blit")
01243 msg = QObject::tr(
01244 "This is the standard video render for Macintosh OS X systems.");
01245
01246 if (renderer == "quartz-accel")
01247 msg = QObject::tr(
01248 "This is the only video renderer for the MacAccel decoder.");
01249
01250 if (renderer == "opengl")
01251 {
01252 msg = QObject::tr(
01253 "This video renderer uses OpenGL for scaling and color conversion "
01254 "with full picture controls. The GPU can be used for deinterlacing. "
01255 "This requires a faster GPU than XVideo.");
01256 }
01257
01258 if (renderer == "opengl-lite")
01259 msg = QObject::tr(
01260 "This video renderer uses OpenGL for scaling and color conversion. "
01261 "It uses faster OpenGL functionality when available but at the "
01262 "expense of picture controls and GPU based deinterlacing.");
01263
01264 if (renderer == "vdpau")
01265 {
01266 msg = QObject::tr(
01267 "This is the only video renderer for NVidia VDPAU decoding.");
01268 }
01269
01270 if (renderer == "openglvaapi")
01271 {
01272 msg = QObject::tr(
01273 "This video renderer uses VAAPI for video decoding and "
01274 "OpenGL for scaling and color conversion.");
01275 }
01276
01277 return msg;
01278 }
01279
01280 QString VideoDisplayProfile::GetPreferredVideoRenderer(const QString &decoder)
01281 {
01282 return GetBestVideoRenderer(GetVideoRenderers(decoder));
01283 }
01284
01285 QStringList VideoDisplayProfile::GetDeinterlacers(
01286 const QString &video_renderer)
01287 {
01288 QMutexLocker locker(&safe_lock);
01289 init_statics();
01290
01291 safe_map_t::const_iterator it = safe_deint.find(video_renderer);
01292 QStringList tmp;
01293 if (it != safe_deint.end())
01294 tmp = *it;
01295
01296 tmp.detach();
01297 return tmp;
01298 }
01299
01300 QString VideoDisplayProfile::GetDeinterlacerHelp(const QString &deint)
01301 {
01302 if (deint.isEmpty())
01303 return "";
01304
01305 QString msg = "";
01306
01307 QString kDoubleRateMsg =
01308 QObject::tr(
01309 "This deinterlacer requires the display to be capable "
01310 "of twice the frame rate as the source video.");
01311
01312 QString kNoneMsg =
01313 QObject::tr("Perform no deinterlacing.") + " " +
01314 QObject::tr(
01315 "Use this with an interlaced display whose "
01316 "resolution exactly matches the video size. "
01317 "This is incompatible with MythTV zoom modes.");
01318
01319 QString kOneFieldMsg = QObject::tr(
01320 "Shows only one of the two fields in the frame. "
01321 "This looks good when displaying a high motion "
01322 "1080i video on a 720p display.");
01323
01324 QString kBobMsg = QObject::tr(
01325 "Shows one field of the frame followed by the "
01326 "other field displaced vertically.") + " " +
01327 kDoubleRateMsg;
01328
01329 QString kLinearBlendMsg = QObject::tr(
01330 "Blends the odd and even fields linearly into one frame.");
01331
01332 QString kKernelMsg = QObject::tr(
01333 "This filter disables deinterlacing when the two fields are "
01334 "similar, and performs linear deinterlacing otherwise.");
01335
01336 QString kUsingGPU = QObject::tr("(Hardware Accelerated)");
01337
01338 QString kGreedyHMsg = QObject::tr(
01339 "This deinterlacer uses several fields to reduce motion blur. "
01340 "It has increased CPU requirements.");
01341
01342 QString kYadifMsg = QObject::tr(
01343 "This deinterlacer uses several fields to reduce motion blur. "
01344 "It has increased CPU requirements.");
01345
01346 QString kFieldOrderMsg = QObject::tr(
01347 "This deinterlacer attempts to synchronize with interlaced displays "
01348 "whose size and refresh rate exactly match the video source. "
01349 "It has low CPU requirements.");
01350
01351 QString kBasicMsg = QObject::tr(
01352 "This deinterlacer uses several fields to reduce motion blur. ");
01353
01354 QString kAdvMsg = QObject::tr(
01355 "This deinterlacer uses multiple fields to reduce motion blur "
01356 "and smooth edges. ");
01357
01358 if (deint == "none")
01359 msg = kNoneMsg;
01360 else if (deint == "onefield")
01361 msg = kOneFieldMsg;
01362 else if (deint == "bobdeint")
01363 msg = kBobMsg;
01364 else if (deint == "linearblend")
01365 msg = kLinearBlendMsg;
01366 else if (deint == "kerneldeint")
01367 msg = kKernelMsg;
01368 else if (deint == "kerneldoubleprocessdeint")
01369 msg = kKernelMsg + " " + kDoubleRateMsg;
01370 else if (deint == "openglonefield")
01371 msg = kOneFieldMsg + " " + kUsingGPU;
01372 else if (deint == "openglbobdeint")
01373 msg = kBobMsg + " " + kUsingGPU;
01374 else if (deint == "opengllinearblend")
01375 msg = kLinearBlendMsg + " " + kUsingGPU;
01376 else if (deint == "openglkerneldeint")
01377 msg = kKernelMsg + " " + kUsingGPU;
01378 else if (deint == "opengldoubleratelinearblend")
01379 msg = kLinearBlendMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
01380 else if (deint == "opengldoubleratekerneldeint")
01381 msg = kKernelMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
01382 else if (deint == "opengldoubleratefieldorder")
01383 msg = kFieldOrderMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
01384 else if (deint == "greedyhdeint")
01385 msg = kGreedyHMsg;
01386 else if (deint == "greedyhdoubleprocessdeint")
01387 msg = kGreedyHMsg + " " + kDoubleRateMsg;
01388 else if (deint == "yadifdeint")
01389 msg = kYadifMsg;
01390 else if (deint == "yadifdoubleprocessdeint")
01391 msg = kYadifMsg + " " + kDoubleRateMsg;
01392 else if (deint == "fieldorderdoubleprocessdeint")
01393 msg = kFieldOrderMsg + " " + kDoubleRateMsg;
01394 else if (deint == "vdpauonefield")
01395 msg = kOneFieldMsg + " " + kUsingGPU;
01396 else if (deint == "vdpaubobdeint")
01397 msg = kBobMsg + " " + kUsingGPU;
01398 else if (deint == "vdpaubasic")
01399 msg = kBasicMsg + " " + kUsingGPU;
01400 else if (deint == "vdpauadvanced")
01401 msg = kAdvMsg + " " + kUsingGPU;
01402 else if (deint == "vdpaubasicdoublerate")
01403 msg = kBasicMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
01404 else if (deint == "vdpauadvanceddoublerate")
01405 msg = kAdvMsg + " " + kDoubleRateMsg + " " + kUsingGPU;
01406 else if (deint == "vaapionefield")
01407 msg = kOneFieldMsg + " " + kUsingGPU;
01408 else if (deint == "vaapibobdeint")
01409 msg = kBobMsg + " " + kUsingGPU;
01410 else
01411 msg = QObject::tr("'%1' has not been documented yet.").arg(deint);
01412
01413 return msg;
01414 }
01415
01416 QStringList VideoDisplayProfile::GetOSDs(const QString &video_renderer)
01417 {
01418 QMutexLocker locker(&safe_lock);
01419 init_statics();
01420
01421 safe_map_t::const_iterator it = safe_osd.find(video_renderer);
01422 QStringList tmp;
01423 if (it != safe_osd.end())
01424 tmp = *it;
01425
01426 tmp.detach();
01427 return tmp;
01428 }
01429
01430 QString VideoDisplayProfile::GetOSDHelp(const QString &osd)
01431 {
01432
01433 QString msg = QObject::tr("OSD rendering method");
01434
01435 if (osd.isEmpty())
01436 return msg;
01437
01438 if (osd == "chromakey")
01439 msg = QObject::tr(
01440 "Render the OSD using the XVideo chromakey feature."
01441 "This renderer does not alpha blend but is the fastest "
01442 "OSD renderer for XVideo.") + "\n" +
01443 QObject::tr(
01444 "Note: nVidia hardware after the 5xxx series does not "
01445 "have XVideo chromakey support.");
01446
01447
01448 if (osd == "softblend")
01449 {
01450 msg = QObject::tr(
01451 "Software OSD rendering uses your CPU to alpha blend the OSD.");
01452 }
01453
01454 if (osd.contains("opengl"))
01455 {
01456 msg = QObject::tr(
01457 "Uses OpenGL to alpha blend the OSD onto the video.");
01458 }
01459
01460 return msg;
01461 }
01462
01463 bool VideoDisplayProfile::IsFilterAllowed(const QString &video_renderer)
01464 {
01465 QMutexLocker locker(&safe_lock);
01466 init_statics();
01467 return safe_custom.contains(video_renderer);
01468 }
01469
01470 QStringList VideoDisplayProfile::GetFilteredRenderers(
01471 const QString &decoder, const QStringList &renderers)
01472 {
01473 const QStringList dec_list = GetVideoRenderers(decoder);
01474 QStringList new_list;
01475
01476 QStringList::const_iterator it = dec_list.begin();
01477 for (; it != dec_list.end(); ++it)
01478 {
01479 if (renderers.contains(*it))
01480 new_list.push_back(*it);
01481 }
01482
01483 return new_list;
01484 }
01485
01486 QString VideoDisplayProfile::GetBestVideoRenderer(const QStringList &renderers)
01487 {
01488 QMutexLocker locker(&safe_lock);
01489 init_statics();
01490
01491 uint top_priority = 0;
01492 QString top_renderer = QString::null;
01493
01494 QStringList::const_iterator it = renderers.begin();
01495 for (; it != renderers.end(); ++it)
01496 {
01497 priority_map_t::const_iterator p = safe_renderer_priority.find(*it);
01498 if ((p != safe_renderer_priority.end()) && (*p >= top_priority))
01499 {
01500 top_priority = *p;
01501 top_renderer = *it;
01502 }
01503 }
01504
01505 if (!top_renderer.isNull())
01506 top_renderer.detach();
01507
01508 return top_renderer;
01509 }
01510
01511 QString VideoDisplayProfile::toString(void) const
01512 {
01513 QString renderer = GetPreference("pref_videorenderer");
01514 QString osd = GetPreference("pref_osdrenderer");
01515 QString deint0 = GetPreference("pref_deint0");
01516 QString deint1 = GetPreference("pref_deint1");
01517 QString filter = GetPreference("pref_filters");
01518 return QString("rend(%4) osd(%5) deint(%6,%7) filt(%8)")
01519 .arg(renderer).arg(osd).arg(deint0).arg(deint1).arg(filter);
01520 }
01521
01522 void VideoDisplayProfile::init_statics(void)
01523 {
01524 if (safe_initialized)
01525 return;
01526
01527 safe_initialized = true;
01528
01529 render_opts options;
01530 options.renderers = &safe_custom;
01531 options.safe_renderers = &safe_renderer;
01532 options.deints = &safe_deint;
01533 options.osds = &safe_osd;
01534 options.render_group = &safe_renderer_group;
01535 options.priorities = &safe_renderer_priority;
01536 options.decoders = &safe_decoders;
01537 options.equiv_decoders = &safe_equiv_dec;
01538
01539
01540 AvFormatDecoder::GetDecoders(options);
01541 VideoOutput::GetRenderOptions(options);
01542
01543 foreach(QString decoder, safe_decoders)
01544 LOG(VB_PLAYBACK, LOG_INFO, LOC +
01545 QString("decoder<->render support: %1%2")
01546 .arg(decoder, -12).arg(GetVideoRenderers(decoder).join(" ")));
01547 }