]> git.sesse.net Git - kdenlive/commitdiff
Allow retrieval of metadata created by Magic Lantern for canon cams
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 9 Feb 2013 15:53:31 +0000 (16:53 +0100)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 9 Feb 2013 15:54:04 +0000 (16:54 +0100)
12 files changed:
data/CMakeLists.txt
data/meta_ffmpeg.png [new file with mode: 0644]
data/meta_libav.png [new file with mode: 0644]
data/meta_magiclantern.png [new file with mode: 0644]
src/clipproperties.cpp
src/docclipbase.cpp
src/docclipbase.h
src/kdenlivesettings.kcfg
src/projectlist.cpp
src/renderwidget.cpp
src/widgets/clipproperties_ui.ui
src/widgets/configmisc_ui.ui

index b593105cee9703efa8abd2e259d6b541a9181c24..77c42817dd8ec5761d6f6a8e289c758086c697a9 100644 (file)
@@ -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 (file)
index 0000000..a46ff7f
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 (file)
index 0000000..c7991da
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 (file)
index 0000000..c1b30d6
Binary files /dev/null and b/data/meta_magiclantern.png differ
index c3562a9310e595dbd0729b925e8cc9fd41f4d2d4..ea758539a16696b9678682953cd0ce27f93370ac 100644 (file)
@@ -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<QString, QString> meta = m_clip->metadata();
-    QMap<QString, QString>::const_iterator i = meta.constBegin();
+    QMap<QString, QStringList> meta = m_clip->metadata();
+    QMap<QString, QStringList>::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 <QTreeWidgetItem *> 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;
     }
 
index 8573056021d96e9fa30fd83b58dc8bafe6500966..1a2dda8ffbce1e6cae569f8bb739eeb41e2dfe72 100644 (file)
@@ -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<QString, QString> j(m_metadata);
+    QMapIterator<QString, QStringList> 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 <QString, QString> properties)
     if (refreshProducer) slotRefreshProducer();
 }
 
-void DocClipBase::setMetadata(QMap <QString, QString> properties)
+void DocClipBase::setMetadata(QMap <QString, QString> properties, QString tool)
 {
     QMapIterator<QString, QString> i(properties);
     while (i.hasNext()) {
@@ -1004,12 +1006,12 @@ void DocClipBase::setMetadata(QMap <QString, QString> 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 <QString, QString> DocClipBase::metadata() const
+QMap <QString, QStringList> DocClipBase::metadata() const
 {
     return m_metadata;
 }
index 6ac74221d2627bb9939c9c1ea6b5fcc5d1bd5647..9eb12719e073aaba24b1b5b5ac2f66f19bec4c57 100644 (file)
@@ -206,6 +206,11 @@ Q_OBJECT public:
     /** Cache for every audio Frame with 10 Bytes */
     /** format is frame -> channel ->bytes */
     QMap<int, QMap<int, QByteArray> > audioFrameCache;
+    /** Returns all current properties for this clip */
+    QMap <QString, QString> properties() const;
+    /** Return the current values for a set of properties */
+    QMap <QString, QString> currentProperties(QMap <QString, QString> props);
+    QMap <QString, QStringList> 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 <QString, QString> m_properties;
     /** Holds clip metadata like author, copyright,... */
-    QMap <QString, QString> m_metadata;
+    QMap <QString, QStringList> m_metadata;
     /** Holds clip analysis data that can be used later to create markers or keyframes */
     QMap <QString, QString> m_analysisdata;
     
@@ -275,12 +280,7 @@ public slots:
     void setClipThumbFrame(const uint &ix);
     uint getClipThumbFrame() const;
     void setProperties(QMap <QString, QString> properties);
-    void setMetadata(QMap <QString, QString> properties);
-    /** Returns all current properties for this clip */
-    QMap <QString, QString> properties() const;
-    /** Return the current values for a set of properties */
-    QMap <QString, QString> currentProperties(QMap <QString, QString> props);
-    QMap <QString, QString> metadata() const;
+    void setMetadata(QMap <QString, QString> properties, QString tool = QString());
     void slotExtractImage(QList <int> frames);
 
 signals:
index a50e3d39f3a1b64fd947a5fa184ff9550bee41a8..b00e5914a69bc4942c46d7d20431ebb648085584 100644 (file)
       <default>false</default>
     </entry>
 
+    <entry name="use_magicLantern" type="Bool">
+      <label>Get h264 metadata using exiftool.</label>
+      <default>false</default>
+    </entry>
+
     <entry name="title_duration" type="String">
       <label>Default title clip duration.</label>
       <default>00:00:05:00</default>
index 0d6c5eb58daff924ebd4ff23bb36d6c6f0c62645..6564238a1704c3470e7c0443a5f9e1ff62294d10 100644 (file)
@@ -2199,31 +2199,67 @@ void ProjectList::slotRefreshClipThumbnail(QTreeWidgetItem *it, bool update)
 void ProjectList::extractMetadata(DocClipBase *clip)
 {
     QMap <QString, QString> 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 <QString, QString> 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 <QString, QString> 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
index 1e470779d4490230039c328fbfc69b13cfda526f..c800c0437164e136bc1e59dfee0f1fabb87e25e9 100644 (file)
@@ -2116,7 +2116,6 @@ void RenderWidget::missingClips(bool hasMissing)
 void RenderWidget::errorMessage(const QString &message)
 {
     if (!message.isEmpty()) {
-       kDebug()<<"// ERROR MESS: "<<message;
 #if KDE_IS_VERSION(4,7,0)
         m_infoMessage->setMessageType(KMessageWidget::Warning);
         m_infoMessage->setText(message);
index eee6c77522264a0d660b6f5d4f401e23a6122e08..8ae184d23ca39c958dbbb1f40fca5509b56e5f9d 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>323</width>
-    <height>556</height>
+    <height>557</height>
    </rect>
   </property>
   <property name="windowTitle">
           <bool>false</bool>
          </property>
          <property name="itemsExpandable">
-          <bool>false</bool>
+          <bool>true</bool>
          </property>
          <property name="sortingEnabled">
           <bool>false</bool>
index 16987b46481abff58306ac7e96208ba0e5c467bc..166f9da68d1c92abd25f7a1c4acf298d2d35e488 100644 (file)
    <property name="topMargin">
     <number>0</number>
    </property>
-   <item row="11" column="0" colspan="3">
+   <item row="4" column="0" colspan="2">
+    <widget class="QCheckBox" name="kcfg_usekuiserver">
+     <property name="text">
+      <string>Use KDE job tracking for render jobs</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QCheckBox" name="kcfg_checkfirstprojectclip">
+     <property name="text">
+      <string>Check if first added clip matches project profile</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="3">
+    <widget class="QCheckBox" name="kcfg_crashrecovery">
+     <property name="text">
+      <string>Crash recovery (automatic backup)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="0">
+    <widget class="QCheckBox" name="kcfg_automultistreams">
+     <property name="text">
+      <string>Automatically import all streams in multi stream clips</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0">
+    <widget class="QCheckBox" name="kcfg_disable_effect_parameters">
+     <property name="text">
+      <string>Disable parameters when the effect is disabled</string>
+     </property>
+    </widget>
+   </item>
+   <item row="9" column="0">
+    <widget class="QCheckBox" name="kcfg_bypasscodeccheck">
+     <property name="text">
+      <string>Bypass codec verification</string>
+     </property>
+    </widget>
+   </item>
+   <item row="13" column="0">
+    <widget class="QCheckBox" name="kcfg_autoimagesequence">
+     <property name="text">
+      <string>Automatically import image sequences</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0">
+    <widget class="QCheckBox" name="kcfg_projectloading_avformatnovalidate">
+     <property name="text">
+      <string>Do not validate the video files when loading a project (faster)</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0">
+    <widget class="QCheckBox" name="kcfg_on_monitor_effects">
+     <property name="text">
+      <string>Use on-monitor effects</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="3">
+    <widget class="QCheckBox" name="kcfg_activatetabs">
+     <property name="text">
+      <string>Open projects in new tabs</string>
+     </property>
+    </widget>
+   </item>
+   <item row="10" column="0">
+    <widget class="QCheckBox" name="kcfg_use_exiftool">
+     <property name="text">
+      <string>Get clip metadata with exiftool</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0" colspan="3">
+    <widget class="QCheckBox" name="kcfg_openlastproject">
+     <property name="text">
+      <string>Open last project on startup</string>
+     </property>
+    </widget>
+   </item>
+   <item row="12" column="0" colspan="3">
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
       <string>Default Durations</string>
      </layout>
     </widget>
    </item>
-   <item row="9" column="0">
-    <widget class="QCheckBox" name="kcfg_bypasscodeccheck">
-     <property name="text">
-      <string>Bypass codec verification</string>
-     </property>
-    </widget>
-   </item>
-   <item row="5" column="0">
-    <widget class="QCheckBox" name="kcfg_on_monitor_effects">
-     <property name="text">
-      <string>Use on-monitor effects</string>
-     </property>
-    </widget>
-   </item>
-   <item row="2" column="0" colspan="3">
-    <widget class="QCheckBox" name="kcfg_crashrecovery">
-     <property name="text">
-      <string>Crash recovery (automatic backup)</string>
-     </property>
-    </widget>
-   </item>
-   <item row="1" column="0" colspan="2">
-    <widget class="QCheckBox" name="kcfg_checkfirstprojectclip">
-     <property name="text">
-      <string>Check if first added clip matches project profile</string>
-     </property>
-    </widget>
-   </item>
-   <item row="0" column="0" colspan="3">
-    <widget class="QCheckBox" name="kcfg_openlastproject">
-     <property name="text">
-      <string>Open last project on startup</string>
-     </property>
-    </widget>
-   </item>
-   <item row="12" column="0">
-    <widget class="QCheckBox" name="kcfg_autoimagesequence">
-     <property name="text">
-      <string>Automatically import image sequences</string>
-     </property>
-    </widget>
-   </item>
-   <item row="13" column="0">
+   <item row="14" column="0">
     <widget class="QCheckBox" name="kcfg_autoimagetransparency">
      <property name="text">
       <string>Transparent background for imported images</string>
      </property>
     </widget>
    </item>
-   <item row="14" column="0" colspan="3">
+   <item row="15" column="0" colspan="3">
     <spacer>
      <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
     </spacer>
    </item>
-   <item row="4" column="0" colspan="2">
-    <widget class="QCheckBox" name="kcfg_usekuiserver">
+   <item row="11" column="0">
+    <widget class="QCheckBox" name="kcfg_use_magicLantern">
      <property name="text">
-      <string>Use KDE job tracking for render jobs</string>
-     </property>
-    </widget>
-   </item>
-   <item row="8" column="0">
-    <widget class="QCheckBox" name="kcfg_automultistreams">
-     <property name="text">
-      <string>Automatically import all streams in multi stream clips</string>
-     </property>
-    </widget>
-   </item>
-   <item row="7" column="0">
-    <widget class="QCheckBox" name="kcfg_disable_effect_parameters">
-     <property name="text">
-      <string>Disable parameters when the effect is disabled</string>
-     </property>
-    </widget>
-   </item>
-   <item row="6" column="0">
-    <widget class="QCheckBox" name="kcfg_projectloading_avformatnovalidate">
-     <property name="text">
-      <string>Do not validate the video files when loading a project (faster)</string>
-     </property>
-    </widget>
-   </item>
-   <item row="3" column="0" colspan="3">
-    <widget class="QCheckBox" name="kcfg_activatetabs">
-     <property name="text">
-      <string>Open projects in new tabs</string>
-     </property>
-    </widget>
-   </item>
-   <item row="10" column="0">
-    <widget class="QCheckBox" name="kcfg_use_exiftool">
-     <property name="text">
-      <string>Get clip metadata with exiftool</string>
+      <string>Get clip metadata created by Magic Lantern</string>
      </property>
     </widget>
    </item>