]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Add effects XML files for frei0r facebl0r and facedetect.
[kdenlive] / src / renderer.cpp
index ca524f9ede1f4048ffad7e638b139a7c789fd0c3..3d2b2492a6901a9a8432cbb28cc6ecddedc411a0 100644 (file)
@@ -145,7 +145,6 @@ void Render::closeMlt()
                 nextservicetodisconnect = nextservice;
                 nextservice = mlt_service_producer(nextservice);
                 mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
-                nextservice = mlt_service_producer(nextservice);
                 if (nextservice == NULL) break;
                 properties = MLT_SERVICE_PROPERTIES(nextservice);
                 mlt_type = mlt_properties_get(properties, "mlt_type");
@@ -736,22 +735,35 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
             else
                 filePropertyMap["type"] = "video";
 
+            int variance;
             mlt_image_format format = mlt_image_rgb24a;
             int frame_width = width;
             int frame_height = imageHeight;
-            uint8_t *data = frame->get_image(format, frame_width, frame_height, 0);
-            QImage image((uchar *)data, frame_width, frame_height, QImage::Format_ARGB32_Premultiplied);
             QPixmap pix;
-
-            if (!image.isNull()) {
-                if (frame_width > (2 * width)) {
-                    // there was a scaling problem, do it manually
-                    QImage scaled = image.scaled(width, imageHeight);
-                    pix = QPixmap::fromImage(scaled.rgbSwapped());
-                } else pix = QPixmap::fromImage(image.rgbSwapped());
-            } else
-                pix.fill(Qt::black);
-
+            do {
+                variance = 100;
+                uint8_t *data = frame->get_image(format, frame_width, frame_height, 0);
+                QImage image((uchar *)data, frame_width, frame_height, QImage::Format_ARGB32_Premultiplied);
+
+                if (!image.isNull()) {
+                    if (frame_width > (2 * width)) {
+                        // there was a scaling problem, do it manually
+                        QImage scaled = image.scaled(width, imageHeight);
+                        pix = QPixmap::fromImage(scaled.rgbSwapped());
+                    } else pix = QPixmap::fromImage(image.rgbSwapped());
+                    variance = KThumb::imageVariance(image);
+                } else
+                    pix.fill(Qt::black);
+                
+                if (frameNumber == 0 && variance < 6) {
+                    // Thumbnail is not interesting (for example all black, seek to fetch better thumb
+                    frameNumber = 100;
+                    producer->seek(frameNumber);
+                    delete frame;
+                    frame = producer->get_frame();
+                    variance = -1;
+                }
+            } while (variance == -1);
             emit replyGetImage(clipId, pix);
 
         } else if (frame->get_int("test_audio") == 0) {
@@ -2958,6 +2970,18 @@ void Render::mltChangeTrackState(int track, bool mute, bool blind)
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(track));
 
+    // Make sure muting will not produce problems with our audio mixing transition,
+    // because audio mixing is done between each track and the lowest one
+    bool audioMixingBroken = false;
+    if (mute && trackProducer.get_int("hide") < 2 ) {
+            // We mute a track with sound
+            if (track == getLowestNonMutedAudioTrack(tractor)) audioMixingBroken = true;
+    }
+    else if (!mute && trackProducer.get_int("hide") > 1 ) {
+            // We un-mute a previously muted track
+            if (track < getLowestNonMutedAudioTrack(tractor)) audioMixingBroken = true;
+    }
+
     if (mute) {
         if (blind) trackProducer.set("hide", 3);
         else trackProducer.set("hide", 2);
@@ -2966,11 +2990,63 @@ void Render::mltChangeTrackState(int track, bool mute, bool blind)
     } else {
         trackProducer.set("hide", 0);
     }
+    if (audioMixingBroken) fixAudioMixing(tractor);
+    
     tractor.multitrack()->refresh();
     tractor.refresh();
     refresh();
 }
 
+int Render::getLowestNonMutedAudioTrack(Mlt::Tractor tractor)
+{
+    for (int i = 1; i < tractor.count(); i++) {
+        Mlt::Producer trackProducer(tractor.track(i));
+        if (trackProducer.get_int("hide") < 2) return i;
+    }
+    return tractor.count() - 1;
+}
+
+void Render::fixAudioMixing(Mlt::Tractor tractor)
+{
+    // Make sure the audio mixing transitions are applied to the lowest audible (non muted) track
+    int lowestTrack = getLowestNonMutedAudioTrack(tractor);
+
+    mlt_service serv = m_mltProducer->parent().get_service();
+    Mlt::Field *field = tractor.field();
+    mlt_service_lock(serv);
+    m_isBlocked++;
+
+    mlt_service nextservice = mlt_service_get_producer(serv);
+    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+    QString mlt_type = mlt_properties_get(properties, "mlt_type");
+    QString resource = mlt_properties_get(properties, "mlt_service");
+
+    mlt_service nextservicetodisconnect;
+     // Delete all audio mixing transitions
+    while (mlt_type == "transition") {
+        if (resource == "mix") {
+            nextservicetodisconnect = nextservice;
+            nextservice = mlt_service_producer(nextservice);
+            mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
+        }
+        else nextservice = mlt_service_producer(nextservice);
+        if (nextservice == NULL) break;
+        properties = MLT_SERVICE_PROPERTIES(nextservice);
+        mlt_type = mlt_properties_get(properties, "mlt_type");
+        resource = mlt_properties_get(properties, "mlt_service");
+    }
+
+    // Re-add correct audio transitions
+    for (int i = lowestTrack + 1; i < tractor.count(); i++) {
+        Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "mix");
+        transition->set("always_active", 1);
+        transition->set("combine", 1);
+        transition->set("internal_added", 237);
+        field->plant_transition(*transition, lowestTrack, i);
+    }
+    mlt_service_unlock(serv);
+    m_isBlocked--;    
+}
 
 bool Render::mltResizeClipCrop(ItemInfo info, GenTime diff)
 {
@@ -3510,8 +3586,8 @@ QMap<QString, QString> Render::mltGetTransitionParamsFromXml(QDomElement xml)
         if (!e.attribute("value").isEmpty()) {
             map[name] = e.attribute("value");
         }
-        if (!e.attribute("factor").isEmpty() && e.attribute("factor").toDouble() > 0) {
-            map[name] = QString::number(map[name].toDouble() / e.attribute("factor").toDouble());
+        if (e.attribute("type") != "addedgeometry" && !e.attribute("factor").isEmpty() && e.attribute("factor").toDouble() > 0) {
+            map[name] = QString::number(map.value(name).toDouble() / e.attribute("factor").toDouble());
             //map[name]=map[name].replace(".",","); //FIXME how to solve locale conversion of . ,
         }