From 8f0ae78b0d64b265aa0d99b37b019b2286d75b6e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Mon, 20 Sep 2010 13:34:58 +0000 Subject: [PATCH] Improve profile autodetection svn path=/trunk/kdenlive/; revision=4913 --- src/kdenlivedoc.cpp | 2 +- src/kdenlivedoc.h | 2 +- src/monitor.cpp | 34 +++++++++++------------ src/profilesdialog.cpp | 27 ++++++++++++++----- src/profilesdialog.h | 21 +++++++++++++-- src/projectlist.cpp | 61 +++++++++++++++++++++++++++--------------- 6 files changed, 99 insertions(+), 48 deletions(-) diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index c2a6e836..3e60ea7b 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -718,7 +718,7 @@ bool KdenliveDoc::setProfilePath(QString path) return (current_fps != m_fps); } -double KdenliveDoc::dar() +double KdenliveDoc::dar() const { return (double) m_profile.display_aspect_num / m_profile.display_aspect_den; } diff --git a/src/kdenlivedoc.h b/src/kdenlivedoc.h index da9e5881..a938d8d8 100644 --- a/src/kdenlivedoc.h +++ b/src/kdenlivedoc.h @@ -107,7 +107,7 @@ Q_OBJECT public: void syncGuides(QList guides); void setZoom(int horizontal, int vertical); QPoint zoom() const; - double dar(); + double dar() const; double projectDuration() const; bool saveSceneList(const QString &path, const QString &scene); int tracksCount() const; diff --git a/src/monitor.cpp b/src/monitor.cpp index f9043b5a..292623f6 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -45,19 +45,19 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget *parent) : - QWidget(parent), - render(NULL), - m_name(name), - m_monitorManager(manager), - m_currentClip(NULL), - m_ruler(new SmallRuler(m_monitorManager)), - m_overlay(NULL), - m_isActive(false), - m_scale(1), - m_length(0), - m_dragStarted(false), - m_effectScene(NULL), - m_effectView(NULL) + QWidget(parent), + render(NULL), + m_name(name), + m_monitorManager(manager), + m_currentClip(NULL), + m_ruler(new SmallRuler(m_monitorManager)), + m_overlay(NULL), + m_isActive(false), + m_scale(1), + m_length(0), + m_dragStarted(false), + m_effectScene(NULL), + m_effectView(NULL) { m_ui.setupUi(this); QVBoxLayout *layout = new QVBoxLayout; @@ -739,7 +739,7 @@ void Monitor::slotSetXml(DocClipBase *clip, QPoint zone, const int position) render->setProducer(NULL, -1); return; } - if (m_currentClip != NULL) activateMonitor(); + if (m_currentClip != NULL || clip != NULL) activateMonitor(); if (clip != m_currentClip) { m_currentClip = clip; updateMarkers(clip); @@ -871,8 +871,8 @@ bool Monitor::effectSceneDisplayed() } MonitorRefresh::MonitorRefresh(QWidget* parent) : - QWidget(parent), - m_renderer(NULL) + QWidget(parent), + m_renderer(NULL) { setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_OpaquePaintEvent); @@ -891,7 +891,7 @@ void MonitorRefresh::paintEvent(QPaintEvent *event) } Overlay::Overlay(QWidget* parent) : - QLabel(parent) + QLabel(parent) { setAttribute(Qt::WA_TransparentForMouseEvents); //setAttribute(Qt::WA_OpaquePaintEvent); diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp index 9710e12c..fca5e8ea 100644 --- a/src/profilesdialog.cpp +++ b/src/profilesdialog.cpp @@ -395,11 +395,24 @@ QMap< QString, QString > ProfilesDialog::getSettingsForProfile(const QString pro } // static -QString ProfilesDialog::getPathFromProperties(int width, int height, double fps, bool useDisplayWidth) +bool ProfilesDialog::matchProfile(int width, int height, double fps, double par, bool isImage, MltVideoProfile profile) +{ + int profileWidth; + if (isImage) { + // when using image, compare with display width + profileWidth = profile.height * profile.display_aspect_num / profile.display_aspect_den + 0.5; + } else profileWidth = profile.width; + if (width != profileWidth || height != profile.height || (fps > 0 && qAbs(profile.frame_rate_num / profile.frame_rate_den - fps) > 0.4) || (par > 0 && qAbs(profile.sample_aspect_num / profile.sample_aspect_den - par) > 0.1)) return false; + return true; +} + +// static +QMap ProfilesDialog::getProfilesFromProperties(int width, int height, double fps, double par, bool useDisplayWidth) { QStringList profilesNames; QStringList profilesFiles; QStringList profilesFilter; + QMap result; profilesFilter << "*"; // List the Mlt profiles profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files); @@ -411,8 +424,9 @@ QString ProfilesDialog::getPathFromProperties(int width, int height, double fps, else profileWidth = values.value("width").toInt(); if (profileWidth == width && values.value("height").toInt() == height) { double profile_fps = values.value("frame_rate_num").toDouble() / values.value("frame_rate_den").toDouble(); - if (fps <= 0 || qAbs(profile_fps - fps) < 0.5) - return profilesFiles.at(i); + double profile_par = values.value("sample_aspect_num").toDouble() / values.value("sample_aspect_den").toDouble(); + if ((fps <= 0 || qAbs(profile_fps - fps) < 0.5) && (par <= 0 || qAbs(profile_par - par) < 0.1)) + result.insert(profilesFiles.at(i), values.value("description")); } } @@ -428,12 +442,13 @@ QString ProfilesDialog::getPathFromProperties(int width, int height, double fps, else profileWidth = values.value("width").toInt(); if (profileWidth == width && values.value("height").toInt() == height) { double profile_fps = values.value("frame_rate_num").toDouble() / values.value("frame_rate_den").toDouble(); - if (fps <= 0 || qAbs(profile_fps - fps) < 0.5) - return customProfiles.at(i) + profiles.at(j); + double profile_par = values.value("sample_aspect_num").toDouble() / values.value("sample_aspect_den").toDouble(); + if ((fps <= 0 || qAbs(profile_fps - fps) < 0.5) && (par <= 0 || qAbs(profile_par - par) < 0.1)) + result.insert(profiles.at(j), values.value("description")); } } } - return QString(); + return result; } // static diff --git a/src/profilesdialog.h b/src/profilesdialog.h index 0ee22a5d..54d263af 100644 --- a/src/profilesdialog.h +++ b/src/profilesdialog.h @@ -42,12 +42,29 @@ public: static QString existingProfile(MltVideoProfile profile); static bool existingProfileDescription(const QString &desc); + /** @brief Check if a given profile matches passed properties: + * @param width The profile frame width + * @param height The profile frame height + * @param fps The profile fps + * @param par The sample aspect ratio + * @param isImage If true, compare width with profile's display width ( = dar * height) + * @param profile The profile to match + * @return true if properties match profile */ + static bool matchProfile(int width, int height, double fps, double par, bool isImage, MltVideoProfile profile); + /** @brief Find a profile to match parameter properties: * @param width The profile frame width * @param height The profile frame height * @param fps The profile fps - * @param useDisplayWidth If true, compare width with profile's display width ( = dar * height) */ - static QString getPathFromProperties(int width, int height, double fps, bool useDisplayWidth = false); + * @param par The sample aspect ratio + * @param useDisplayWidth If true, compare width with profile's display width ( = dar * height) + * @return A string list of the matching profiles description */ + static QMap getProfilesFromProperties(int width, int height, double fps, double par, bool useDisplayWidth = false); + + /** @brief Returns an value from a string by replacing "%width" and "%height" with given profile values: + * @param profile The profile that gives width & height + * @param eval The string to be evaluated, for example: "%width / 2" + * @return the evaluated value */ static double getStringEval(const MltVideoProfile &profile, QString eval); protected: diff --git a/src/projectlist.cpp b/src/projectlist.cpp index 8264afee..18562312 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -1473,6 +1473,7 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce int max = m_doc->clipManager()->clipsCount(); if (item && m_infoQueue.isEmpty() && m_thumbnailQueue.isEmpty()) { m_listView->setCurrentItem(item); + bool displayClipInMonitor = true; if (item->parent()) { if (item->parent()->type() == PROJECTFOLDERTYPE) static_cast (item->parent())->switchIcon(); @@ -1481,29 +1482,47 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce int width = properties.value("frame_size").section('x', 0, 0).toInt(); int height = properties.value("frame_size").section('x', -1).toInt(); double fps = properties.value("fps").toDouble(); - int renderWidth = -1; - int renderHeight = -1; - double renderFps = -1; - if (item->clipType() == IMAGE) { - renderWidth = m_doc->renderer()->renderWidth(); - renderHeight = m_doc->height(); - } else if (item->clipType() == AV || item->clipType() == VIDEO) { - renderWidth = m_doc->width(); - renderHeight = m_doc->height(); - renderFps = m_doc->fps(); - } - if ((renderWidth > 0 && width != renderWidth) || (renderHeight > 0 && height != renderHeight) || (renderFps > 0 && qAbs(fps - renderFps) > 0.5)) { - QString suggestedProfile = ProfilesDialog::getPathFromProperties(width, height, fps, item->clipType() == IMAGE); - if (!suggestedProfile.isEmpty()) { - QString description = ProfilesDialog::getSettingsFromFile(suggestedProfile).value("description"); - if (KMessageBox::questionYesNo(this, i18n("Your clip does not match current project's profile.\nDo you want to adjust the profile (clip size: %1, fps: %2)?\nSuggested profile is %3", properties.value("frame_size"), fps, description)) == KMessageBox::Yes) { - //Change project profile - emit updateProfile(suggestedProfile); - } - } else KMessageBox::information(this, i18n("Your clip does not match current project's profile.\nNo existing profile found to match the clip's properties.\nClip size: %1\nFps: %2\n", properties.value("frame_size"), fps)); + double par = properties.value("aspect_ratio").toDouble(); + if (item->clipType() == IMAGE || item->clipType() == AV || item->clipType() == VIDEO) { + if (ProfilesDialog::matchProfile(width, height, fps, par, item->clipType() == IMAGE, m_doc->mltProfile()) == false) { + // get a list of compatible profiles + QMap suggestedProfiles = ProfilesDialog::getProfilesFromProperties(width, height, fps, par, item->clipType() == IMAGE); + if (!suggestedProfiles.isEmpty()) { + KDialog *dialog = new KDialog(this); + dialog->setCaption(i18n("Change project profile")); + dialog->setButtons(KDialog::Ok | KDialog::Cancel); + + QWidget container; + QVBoxLayout *l = new QVBoxLayout; + QLabel *label = new QLabel(i18n("Your clip does not match current project's profile.\nDo you want to change the project profile?\n\nThe following profiles match the clip (size: %1, fps: %2)", properties.value("frame_size"), fps)); + l->addWidget(label); + QListWidget *list = new QListWidget; + list->setAlternatingRowColors(true); + QMapIterator i(suggestedProfiles); + while (i.hasNext()) { + i.next(); + QListWidgetItem *item = new QListWidgetItem(i.value(), list); + item->setData(Qt::UserRole, i.key()); + item->setToolTip(i.key()); + } + list->setCurrentRow(0); + l->addWidget(list); + container.setLayout(l); + dialog->setButtonText(KDialog::Ok, i18n("Update profile")); + dialog->setMainWidget(&container); + if (dialog->exec() == QDialog::Accepted) { + //Change project profile + displayClipInMonitor = false; + if (list->currentItem()) + emit updateProfile(list->currentItem()->data(Qt::UserRole).toString()); + } + delete list; + delete label; + } else KMessageBox::information(this, i18n("Your clip does not match current project's profile.\nNo existing profile found to match the clip's properties.\nClip size: %1\nFps: %2\n", properties.value("frame_size"), fps)); + } } } - emit clipSelected(item->referencedClip()); + if (displayClipInMonitor) emit clipSelected(item->referencedClip()); } else { emit displayMessage(i18n("Loading clips"), (int)(100 *(max - m_infoQueue.count()) / max)); } -- 2.39.2