|
MythTV
0.26-pre
|
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 }
1.7.6.1