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