MythTV  0.26-pre
videodisplayprofile.cpp
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
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; // we don't use the video output rate yet
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; // already made preferences safe...
00285     }
00286 
00287     // Make preferences safe...
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 // static methods
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             // create new profileid
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 //displayprofilegroups pk(name, hostname), uk(profilegroupid)
00861 //displayprofiles      k(profilegroupid), k(profileid), value, data
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     // create new profileid
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); // deep copy not needed
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     // N.B. assumes NuppelDecoder and DummyDecoder always present
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends