From: Jean-Baptiste Mardelle Date: Sat, 9 Feb 2013 15:53:31 +0000 (+0100) Subject: Allow retrieval of metadata created by Magic Lantern for canon cams X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=efa3eb3a43aeaee3a66956e5fe791260739b8aaf;p=kdenlive Allow retrieval of metadata created by Magic Lantern for canon cams --- diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index b593105c..77c42817 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,4 +1,4 @@ -install(FILES banner.png timeline_nothumbs.png timeline_athumbs.png timeline_vthumbs.png timeline_avthumbs.png metadata.properties blacklisted_effects.txt blacklisted_transitions.txt encodingprofiles.rc DESTINATION ${DATA_INSTALL_DIR}/kdenlive ) +install(FILES banner.png timeline_nothumbs.png timeline_athumbs.png timeline_vthumbs.png timeline_avthumbs.png metadata.properties blacklisted_effects.txt blacklisted_transitions.txt encodingprofiles.rc meta_ffmpeg.png meta_libav.png meta_magiclantern.png DESTINATION ${DATA_INSTALL_DIR}/kdenlive ) install( FILES kdenliveeffectscategory.rc DESTINATION ${CONFIG_INSTALL_DIR} ) install (FILES kdenlive.xpm DESTINATION share/pixmaps) install (FILES kdenlive.menu DESTINATION share/menu RENAME kdenlive) diff --git a/data/meta_ffmpeg.png b/data/meta_ffmpeg.png new file mode 100644 index 00000000..a46ff7fa Binary files /dev/null and b/data/meta_ffmpeg.png differ diff --git a/data/meta_libav.png b/data/meta_libav.png new file mode 100644 index 00000000..c7991da0 Binary files /dev/null and b/data/meta_libav.png differ diff --git a/data/meta_magiclantern.png b/data/meta_magiclantern.png new file mode 100644 index 00000000..c1b30d66 Binary files /dev/null and b/data/meta_magiclantern.png differ diff --git a/src/clipproperties.cpp b/src/clipproperties.cpp index c3562a93..ea758539 100644 --- a/src/clipproperties.cpp +++ b/src/clipproperties.cpp @@ -196,12 +196,42 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg connect(m_view.clip_full_luma, SIGNAL(toggled(bool)), this, SLOT(slotModified())); // Check for Metadata - QMap meta = m_clip->metadata(); - QMap::const_iterator i = meta.constBegin(); + QMap meta = m_clip->metadata(); + QMap::const_iterator i = meta.constBegin(); while (i != meta.constEnd()) { - QTreeWidgetItem *metaitem = new QTreeWidgetItem(m_view.metadata_list); + QStringList values = i.value(); + QString parentName; + QString iconName; + if (values.count() > 1 && !values.at(1).isEmpty()) parentName = values.at(1); + else { + if (KdenliveSettings::ffmpegpath().endsWith("avconv")) { + parentName = i18n("Libav"); + iconName = "meta_libav.png"; + } + else { + parentName = i18n("FFmpeg"); + iconName = "meta_ffmpeg.png"; + } + } + QTreeWidgetItem *parent = NULL; + QList matches = m_view.metadata_list->findItems(parentName, Qt::MatchExactly); + if (!matches.isEmpty()) parent = matches.at(0); + else { + if (parentName == "Magic Lantern") iconName = "meta_magiclantern.png"; + parent = new QTreeWidgetItem(m_view.metadata_list, QStringList() << parentName); + if (!iconName.isEmpty()) { + KIcon icon(KStandardDirs::locate("appdata", iconName)); + parent->setIcon(0, icon); + } + } + QTreeWidgetItem *metaitem = NULL; + if (parent) { + metaitem = new QTreeWidgetItem(parent); + parent->setExpanded(true); + } + else metaitem = new QTreeWidgetItem(m_view.metadata_list); metaitem->setText(0, i.key()); //i18n(i.key().section('.', 2, 3).toUtf8().data())); - metaitem->setText(1, i.value()); + metaitem->setText(1, values.at(0)); ++i; } diff --git a/src/docclipbase.cpp b/src/docclipbase.cpp index 85730560..1a2dda8f 100644 --- a/src/docclipbase.cpp +++ b/src/docclipbase.cpp @@ -64,14 +64,14 @@ DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QStrin for (int i = 0; i < attributes.count(); i++) { QString name = attributes.item(i).nodeName(); if (name.startsWith("meta.attr.")) { - m_metadata.insert(name.section('.', 2), attributes.item(i).nodeValue()); + m_metadata.insert(name.section('.', 2), QStringList() << attributes.item(i).nodeValue()); } else m_properties.insert(name, attributes.item(i).nodeValue()); } QDomNodeList metas = xml.elementsByTagName("metaproperty"); for (int i = 0; i < metas.count(); i++) { QDomElement e = metas.item(i).toElement(); if (!e.isNull()) { - m_metadata.insert(e.attribute("name").section('.', 2), e.firstChild().nodeValue()); + m_metadata.insert(e.attribute("name").section('.', 2), QStringList() << e.firstChild().nodeValue() << e.attribute("tool")); } } @@ -263,14 +263,16 @@ QDomElement DocClipBase::toXML(bool hideTemporaryProperties) const if (!i.value().isEmpty()) clip.setAttribute(i.key(), i.value()); } - QMapIterator j(m_metadata); + QMapIterator j(m_metadata); // Metadata name can have special chars so we cannot pass it as simple attribute while (j.hasNext()) { j.next(); if (!j.value().isEmpty()) { QDomElement property = doc.createElement("metaproperty"); property.setAttribute("name", "meta.attr." + j.key()); - QDomText value = doc.createTextNode(j.value()); + QStringList values = j.value(); + QDomText value = doc.createTextNode(values.at(0)); + if (values.count() > 1) property.setAttribute("tool", values.at(1)); property.appendChild(value); clip.appendChild(property); } @@ -996,7 +998,7 @@ void DocClipBase::setProperties(QMap properties) if (refreshProducer) slotRefreshProducer(); } -void DocClipBase::setMetadata(QMap properties) +void DocClipBase::setMetadata(QMap properties, QString tool) { QMapIterator i(properties); while (i.hasNext()) { @@ -1004,12 +1006,12 @@ void DocClipBase::setMetadata(QMap properties) if (i.value().isEmpty() && m_metadata.contains(i.key())) { m_metadata.remove(i.key()); } else { - m_metadata.insert(i.key(), i.value()); + m_metadata.insert(i.key(), QStringList() << i.value() << tool); } } } -QMap DocClipBase::metadata() const +QMap DocClipBase::metadata() const { return m_metadata; } diff --git a/src/docclipbase.h b/src/docclipbase.h index 6ac74221..9eb12719 100644 --- a/src/docclipbase.h +++ b/src/docclipbase.h @@ -206,6 +206,11 @@ Q_OBJECT public: /** Cache for every audio Frame with 10 Bytes */ /** format is frame -> channel ->bytes */ QMap > audioFrameCache; + /** Returns all current properties for this clip */ + QMap properties() const; + /** Return the current values for a set of properties */ + QMap currentProperties(QMap props); + QMap metadata() const; private: // Private attributes /** The number of times this clip is used in the project - the number of references to this clip @@ -236,7 +241,7 @@ private: // Private attributes /** Holds clip infos like fps, size,... */ QMap m_properties; /** Holds clip metadata like author, copyright,... */ - QMap m_metadata; + QMap m_metadata; /** Holds clip analysis data that can be used later to create markers or keyframes */ QMap m_analysisdata; @@ -275,12 +280,7 @@ public slots: void setClipThumbFrame(const uint &ix); uint getClipThumbFrame() const; void setProperties(QMap properties); - void setMetadata(QMap properties); - /** Returns all current properties for this clip */ - QMap properties() const; - /** Return the current values for a set of properties */ - QMap currentProperties(QMap props); - QMap metadata() const; + void setMetadata(QMap properties, QString tool = QString()); void slotExtractImage(QList frames); signals: diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index a50e3d39..b00e5914 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -70,6 +70,11 @@ false + + + false + + 00:00:05:00 diff --git a/src/projectlist.cpp b/src/projectlist.cpp index 0d6c5eb5..6564238a 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -2199,31 +2199,67 @@ void ProjectList::slotRefreshClipThumbnail(QTreeWidgetItem *it, bool update) void ProjectList::extractMetadata(DocClipBase *clip) { QMap props = clip->properties(); - if (props.contains("exiftool")) { - // metadata was already extracted - return; + if (KdenliveSettings::use_exiftool() && !props.contains("exiftool")) { + QString codecid = props.value("videocodecid").simplified(); + if (codecid == "h264") { + QProcess p; + QStringList args; + args << "-g" << "-args" << clip->fileURL().encodedPathAndQuery(); + p.start("exiftool", args); + p.waitForFinished(); + QString res = p.readAllStandardOutput(); + QStringList list = res.split("\n"); + QMap meta; + foreach(QString tagline, list) { + if (!tagline.startsWith("-H264")) continue; + QString tag = tagline.section(':', 1); + if (tag.startsWith("ImageWidth") || tag.startsWith("ImageHeight")) continue; + meta.insert(tag.section('=', 0, 0), tag.section('=', 1)); + } + clip->setProperty("exiftool", "1"); + if (!meta.isEmpty()) { + clip->setMetadata(meta, "ExifTool"); + //checkCamcorderFilters(clip, meta); + } + } } - QString codecid = props.value("videocodecid").simplified(); - if (codecid == "h264") { - QProcess p; - QStringList args; - args << "-g" << "-args" << clip->fileURL().encodedPathAndQuery(); - p.start("exiftool", args); - p.waitForFinished(); - QString res = p.readAllStandardOutput(); - QStringList list = res.split("\n"); + if (KdenliveSettings::use_magicLantern() && !props.contains("magiclantern")) { QMap meta; - foreach(QString tagline, list) { - if (!tagline.startsWith("-H264")) continue; - QString tag = tagline.section(':', 1); - if (tag.startsWith("ImageWidth") || tag.startsWith("ImageHeight")) continue; - meta.insert(tag.section('=', 0, 0), tag.section('=', 1)); + QString url = clip->fileURL().path(); + url = url.section('.', 0, -2) + ".LOG"; + if (QFile::exists(url)) { + QFile file(url); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + while (!file.atEnd()) { + QString line = file.readLine().simplified(); + if (line.startsWith('#') || line.isEmpty() || !line.contains(':')) continue; + if (line.startsWith("CSV data")) break; + meta.insert(line.section(':', 0, 0).simplified(), line.section(':', 1).simplified()); + } + } } - clip->setProperty("exiftool", "1"); - if (!meta.isEmpty()) { - clip->setMetadata(meta); - //checkCamcorderFilters(clip, meta); + url = url.section('.', 0, -2) + ".THM"; + if (QFile::exists(url) && KdenliveSettings::use_exiftool()) { + // Read the exif metadata embeded in the THM file + QProcess p; + QStringList args; + args << "-g" << "-args" << url; + p.start("exiftool", args); + p.waitForFinished(); + QString res = p.readAllStandardOutput(); + QStringList list = res.split("\n"); + foreach(QString tagline, list) { + if (tagline.startsWith("-File") || tagline.startsWith("-ExifTool")) continue; + QString tag = tagline.section(':', 1).simplified(); + if (tag.startsWith("ImageWidth") || tag.startsWith("ImageHeight")) continue; + if (!tag.section('=', 0, 0).isEmpty() && !tag.section('=', 1).simplified().isEmpty()) + meta.insert(tag.section('=', 0, 0), tag.section('=', 1).simplified()); + } } + + if (!meta.isEmpty()) + clip->setMetadata(meta, "Magic Lantern"); + clip->setProperty("magiclantern", "1"); } } @@ -2245,7 +2281,7 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce } item->setProperties(properties, metadata); clip->setProducer(producer, replace); - if (KdenliveSettings::use_exiftool()) extractMetadata(clip); + extractMetadata(clip); m_render->processingDone(clipId); // Proxy stuff diff --git a/src/renderwidget.cpp b/src/renderwidget.cpp index 1e470779..c800c043 100644 --- a/src/renderwidget.cpp +++ b/src/renderwidget.cpp @@ -2116,7 +2116,6 @@ void RenderWidget::missingClips(bool hasMissing) void RenderWidget::errorMessage(const QString &message) { if (!message.isEmpty()) { - kDebug()<<"// ERROR MESS: "<setMessageType(KMessageWidget::Warning); m_infoMessage->setText(message); diff --git a/src/widgets/clipproperties_ui.ui b/src/widgets/clipproperties_ui.ui index eee6c775..8ae184d2 100644 --- a/src/widgets/clipproperties_ui.ui +++ b/src/widgets/clipproperties_ui.ui @@ -7,7 +7,7 @@ 0 0 323 - 556 + 557 @@ -528,7 +528,7 @@ false - false + true false diff --git a/src/widgets/configmisc_ui.ui b/src/widgets/configmisc_ui.ui index 16987b46..166f9da6 100644 --- a/src/widgets/configmisc_ui.ui +++ b/src/widgets/configmisc_ui.ui @@ -17,7 +17,91 @@ 0 - + + + + Use KDE job tracking for render jobs + + + + + + + Check if first added clip matches project profile + + + + + + + Crash recovery (automatic backup) + + + + + + + Automatically import all streams in multi stream clips + + + + + + + Disable parameters when the effect is disabled + + + + + + + Bypass codec verification + + + + + + + Automatically import image sequences + + + + + + + Do not validate the video files when loading a project (faster) + + + + + + + Use on-monitor effects + + + + + + + Open projects in new tabs + + + + + + + Get clip metadata with exiftool + + + + + + + Open last project on startup + + + + Default Durations @@ -85,56 +169,14 @@ - - - - Bypass codec verification - - - - - - - Use on-monitor effects - - - - - - - Crash recovery (automatic backup) - - - - - - - Check if first added clip matches project profile - - - - - - - Open last project on startup - - - - - - - Automatically import image sequences - - - - + Transparent background for imported images - + Qt::Vertical @@ -147,45 +189,10 @@ - - + + - Use KDE job tracking for render jobs - - - - - - - Automatically import all streams in multi stream clips - - - - - - - Disable parameters when the effect is disabled - - - - - - - Do not validate the video files when loading a project (faster) - - - - - - - Open projects in new tabs - - - - - - - Get clip metadata with exiftool + Get clip metadata created by Magic Lantern