]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Add non realtime preview mode to Kdenlive (available from monitor context menu)
[kdenlive] / src / renderer.cpp
index ea4b72a544fd96078f2d82df90a822833f9fb12e..affbff833fb4770f008cbe7712f7dae0cbfcb030 100644 (file)
@@ -55,7 +55,7 @@ static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr
 
 Render::Render(const QString & rendererName, int winid, int /* extid */, QWidget *parent) :
         QObject(parent),
-        m_isBlocked(true),
+        m_isBlocked(0),
         m_name(rendererName),
         m_mltConsumer(NULL),
         m_mltProducer(NULL),
@@ -84,6 +84,7 @@ Render::Render(const QString & rendererName, int winid, int /* extid */, QWidget
 
 Render::~Render()
 {
+    m_isBlocked = 1;
     closeMlt();
 }
 
@@ -223,7 +224,7 @@ void Render::seek(GenTime time)
 {
     if (!m_mltProducer)
         return;
-    m_isBlocked = false;
+    m_isBlocked = 0;
     m_mltProducer->seek((int)(time.frames(m_fps)));
     refresh();
 }
@@ -1221,7 +1222,7 @@ void Render::seekToFrame(int pos)
 void Render::askForRefresh()
 {
     // Use a Timer so that we don't refresh too much
-    m_refreshTimer->start(200);
+    m_refreshTimer->start(300);
 }
 
 void Render::doRefresh()
@@ -1240,6 +1241,17 @@ void Render::refresh()
     }
 }
 
+void Render::setDropFrames(bool show)
+{
+    if (m_mltConsumer) {
+        int dropFrames = 1;
+        if (show == false) dropFrames = 0;
+        m_mltConsumer->stop();
+        m_mltConsumer->set("play.real_time", dropFrames);
+        m_mltConsumer->start();
+    }
+}
+
 double Render::playSpeed()
 {
     if (m_mltProducer) return m_mltProducer->get_speed();
@@ -1375,6 +1387,10 @@ void Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pr
 
     Mlt::Service service(parentProd.get_service());
     Mlt::Tractor tractor(service);
+    if (info.track > tractor.count() - 1) {
+        kDebug() << "ERROR TRYING TO INSERT CLIP ON TRACK " << info.track << ", at POS: " << info.startPos.frames(25);
+        return;
+    }
     mlt_service_lock(service.get_service());
     Mlt::Producer trackProducer(tractor.track(info.track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
@@ -1507,6 +1523,7 @@ bool Render::mltRemoveClip(int track, GenTime position)
     if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
 
     Mlt::Tractor tractor(service);
+    mlt_service_lock(service.get_service());
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
     int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
@@ -1520,13 +1537,11 @@ bool Render::mltRemoveClip(int track, GenTime position)
     if (trackPlaylist.is_blank(i)) blk = "(blank)";
     kDebug()<<"CLIP "<<i<<": ("<<blankStart<<'x'<<blankStart + blankDuration<<")"<<blk;
     }*/
-
     if (trackPlaylist.is_blank(clipIndex)) {
-        kDebug() << "// WARMNING, TRYING TO REMOVE A BLANK: " << clipIndex << ", AT: " << position.frames(25);
+        kDebug() << "// WARNING, TRYING TO REMOVE A BLANK: " << position.frames(25);
         return false;
     }
     m_isBlocked = true;
-    Mlt::Producer clip(trackPlaylist.get_clip(clipIndex));
     trackPlaylist.replace_with_blank(clipIndex);
     trackPlaylist.consolidate_blanks(0);
     /*if (QString(clip.parent().get("transparency")).toInt() == 1)
@@ -1541,7 +1556,7 @@ bool Render::mltRemoveClip(int track, GenTime position)
     if (trackPlaylist.is_blank(i)) blk = "(blank)";
     kDebug()<<"CLIP "<<i<<": ("<<blankStart<<'x'<<blankStart + blankDuration<<")"<<blk;
     }*/
-
+    mlt_service_unlock(service.get_service());
     if (track != 0 && trackPlaylist.count() <= clipIndex) mltCheckLength();
     m_isBlocked = false;
     return true;
@@ -1732,16 +1747,22 @@ int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt
     int clipIndex = trackPlaylist.get_clip_index_at(startPos);
     int clipLength = trackPlaylist.clip_length(clipIndex);
 
-    Mlt::Producer clip(trackPlaylist.get_clip(clipIndex));
-    if (!clip.is_valid() || clip.is_blank()) {
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
+    if (clip == NULL) {
+        return -1;
+    }
+    if (!clip->is_valid() || clip->is_blank()) {
         // invalid clip
+        delete clip;
         return -1;
     }
-    Mlt::Producer clipparent = clip.parent();
+    Mlt::Producer clipparent = clip->parent();
     if (!clipparent.is_valid() || clipparent.is_blank()) {
         // invalid clip
+        delete clip;
         return -1;
     }
+    delete clip;
     QString serv = clipparent.get("mlt_service");
     QString id = clipparent.get("id");
     //kDebug() << "CLIP SERVICE: " << serv;
@@ -2160,9 +2181,7 @@ void Render::mltMoveEffect(int track, GenTime position, int oldPos, int newPos)
 bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration)
 {
     m_isBlocked = true;
-
     Mlt::Service service(m_mltProducer->parent().get_service());
-
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(info.track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
@@ -2182,16 +2201,22 @@ bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration)
         m_isBlocked = false;
         return false;
     }
+    mlt_service_lock(service.get_service());
     int clipIndex = trackPlaylist.get_clip_index_at((int) info.startPos.frames(m_fps));
     //kDebug() << "// SELECTED CLIP START: " << trackPlaylist.clip_start(clipIndex);
     Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
     int previousStart = clip->get_in();
     int newDuration = (int) clipDuration.frames(m_fps) - 1;
-    int diff = newDuration - trackPlaylist.clip_length(clipIndex) - 1;
+    int diff = newDuration - (trackPlaylist.clip_length(clipIndex) - 1);
     if (newDuration > clip->get_length()) {
         clip->parent().set("length", newDuration + 1);
         clip->set("length", newDuration + 1);
     }
+    if (newDuration > clip->get_out()) {
+        clip->parent().set_in_and_out(0, newDuration + 1);
+        clip->set_in_and_out(0, newDuration + 1);
+    }
+    delete clip;
     trackPlaylist.resize_clip(clipIndex, previousStart, newDuration + previousStart);
     trackPlaylist.consolidate_blanks(0);
     // skip to next clip
@@ -2213,9 +2238,8 @@ bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration)
             }
         }
     } else trackPlaylist.insert_blank(clipIndex, 0 - diff - 1);
-
     trackPlaylist.consolidate_blanks(0);
-
+    mlt_service_unlock(service.get_service());
 
     if (info.track != 0 && clipIndex == trackPlaylist.count()) mltCheckLength();
     /*if (QString(clip->parent().get("transparency")).toInt() == 1) {
@@ -2272,6 +2296,7 @@ bool Render::mltResizeClipCrop(ItemInfo info, GenTime diff)
         return false;
     }
     int previousStart = clip->get_in();
+    delete clip;
     int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
     m_isBlocked = true;
     trackPlaylist.resize_clip(clipIndex, previousStart + frameOffset, previousStart + previousDuration + frameOffset);
@@ -2302,6 +2327,7 @@ bool Render::mltResizeClipStart(ItemInfo info, GenTime diff)
         return false;
     }
     int previousStart = clip->get_in();
+    delete clip;
     int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
     m_isBlocked = true;
     kDebug() << "RESIZE, old start: " << previousStart << ", PREV DUR: " << previousDuration << ", DIFF: " << moveFrame;
@@ -2348,7 +2374,7 @@ void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
         return;
     }
     kDebug() << "NEW PROD ID: " << prod->get("id");
-    m_mltConsumer->set("refresh", 0);
+    m_isBlocked++;
     kDebug() << "// TRYING TO UPDATE CLIP at: " << pos << ", TK: " << track;
     mlt_service_lock(m_mltConsumer->get_service());
     Mlt::Service service(m_mltProducer->parent().get_service());
@@ -2362,7 +2388,7 @@ void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
     if (clipProducer.is_blank()) {
         kDebug() << "// ERROR UPDATING CLIP PROD";
         mlt_service_unlock(m_mltConsumer->get_service());
-        m_isBlocked = false;
+        m_isBlocked--;
         return;
     }
     Mlt::Producer *clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
@@ -2383,19 +2409,18 @@ void Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
 
     trackPlaylist.insert_at(pos, clip, 1);
     mlt_service_unlock(m_mltConsumer->get_service());
-    m_isBlocked = false;
+    m_isBlocked--;
 }
 
 bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod)
 {
-    m_isBlocked = true;
+    m_isBlocked++;
 
-    m_mltConsumer->set("refresh", 0);
-    mlt_service_lock(m_mltConsumer->get_service());
     Mlt::Service service(m_mltProducer->parent().get_service());
     if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
 
     Mlt::Tractor tractor(service);
+    mlt_service_lock(service.get_service());
     Mlt::Producer trackProducer(tractor.track(startTrack));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
     int clipIndex = trackPlaylist.get_clip_index_at(moveStart + 1);
@@ -2408,8 +2433,8 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
             if (!trackPlaylist.is_blank_at(moveEnd)) trackPlaylist.insert_at(moveStart, clipProducer, 1);
             //int ix = trackPlaylist.get_clip_index_at(moveEnd);
             kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
-            mlt_service_unlock(m_mltConsumer->get_service());
-            m_isBlocked = false;
+            mlt_service_unlock(service.get_service());
+            m_isBlocked--;
             return false;
         } else {
             trackPlaylist.consolidate_blanks(0);
@@ -2425,8 +2450,8 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
         Mlt::Playlist destTrackPlaylist((mlt_playlist) destTrackProducer.get_service());
         if (!destTrackPlaylist.is_blank_at(moveEnd)) {
             // error, destination is not empty
-            mlt_service_unlock(m_mltConsumer->get_service());
-            m_isBlocked = false;
+            mlt_service_unlock(service.get_service());
+            m_isBlocked--;
             return false;
         } else {
             Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
@@ -2434,8 +2459,8 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
                 // error, destination is not empty
                 //int ix = trackPlaylist.get_clip_index_at(moveEnd);
                 kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
-                mlt_service_unlock(m_mltConsumer->get_service());
-                m_isBlocked = false;
+                mlt_service_unlock(service.get_service());
+                m_isBlocked--;
                 return false;
             }
             trackPlaylist.consolidate_blanks(0);
@@ -2480,11 +2505,11 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
             else if (newIndex + 1 == destTrackPlaylist.count()) checkLength = true;
         }
     }
-
+    mlt_service_unlock(service.get_service());
     if (checkLength) mltCheckLength();
-    mlt_service_unlock(m_mltConsumer->get_service());
-    m_isBlocked = false;
-    m_mltConsumer->set("refresh", 1);
+    m_isBlocked--;
+    //askForRefresh();
+    //m_mltConsumer->set("refresh", 1);
     return true;
 }
 
@@ -2494,14 +2519,12 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
     int new_out = (int)newOut.frames(m_fps) - 1;
     if (new_in >= new_out) return false;
 
-    Mlt::Service service(m_mltProducer->parent().get_service());
-    Mlt::Tractor tractor(service);
+    mlt_service serv = m_mltProducer->parent().get_service();
+    m_isBlocked++;
+    mlt_service_lock(serv);
+    //m_mltConsumer->set("refresh", 0);
 
-    mlt_service_lock(service.get_service());
-    m_mltConsumer->set("refresh", 0);
-    m_isBlocked = true;
 
-    mlt_service serv = m_mltProducer->parent().get_service();
     mlt_service nextservice = mlt_service_get_producer(serv);
     mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
     QString mlt_type = mlt_properties_get(properties, "mlt_type");
@@ -2517,7 +2540,7 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
         if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
             mlt_transition_set_in_and_out(tr, new_in, new_out);
             if (newTrack - startTrack != 0) {
-                kDebug() << "///// TRANSITION CHANGE TRACK. CUrrent (b): " << currentTrack << 'x' << mlt_transition_get_a_track(tr) << ", NEw: " << newTrack << 'x' << newTransitionTrack;
+                //kDebug() << "///// TRANSITION CHANGE TRACK. CUrrent (b): " << currentTrack << 'x' << mlt_transition_get_a_track(tr) << ", NEw: " << newTrack << 'x' << newTransitionTrack;
 
                 mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
                 mlt_properties_set_int(properties, "a_track", newTransitionTrack);
@@ -2532,15 +2555,15 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
         mlt_type = mlt_properties_get(properties, "mlt_type");
         resource = mlt_properties_get(properties, "mlt_service");
     }
-    m_isBlocked = false;
-    mlt_service_unlock(service.get_service());
-    m_mltConsumer->set("refresh", 1);
+    mlt_service_unlock(serv);
+    m_isBlocked--;
+    //askForRefresh();
+    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
     return true;
 }
 
 void Render::mltUpdateTransition(QString oldTag, QString tag, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml)
 {
-    // kDebug() << "update transition"  << tag << " at pos " << in.frames(25);
     if (oldTag == tag) mltUpdateTransitionParams(tag, a_track, b_track, in, out, xml);
     else {
         mltDeleteTransition(oldTag, a_track, b_track, in, out, xml, false);
@@ -2551,12 +2574,10 @@ void Render::mltUpdateTransition(QString oldTag, QString tag, int a_track, int b
 
 void Render::mltUpdateTransitionParams(QString type, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml)
 {
-    m_isBlocked = true;
-    Mlt::Service service(m_mltProducer->parent().get_service());
-    Mlt::Tractor tractor(service);
-
-    //m_mltConsumer->set("refresh", 0);
     mlt_service serv = m_mltProducer->parent().get_service();
+    mlt_service_lock(serv);
+    m_isBlocked++;
+
 
     mlt_service nextservice = mlt_service_get_producer(serv);
     mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
@@ -2601,18 +2622,23 @@ void Render::mltUpdateTransitionParams(QString type, int a_track, int b_track, G
         mlt_type = mlt_properties_get(properties, "mlt_type");
         resource = mlt_properties_get(properties, "mlt_service");
     }
-    m_isBlocked = false;
-    m_mltConsumer->set("refresh", 1);
+    mlt_service_unlock(serv);
+    m_isBlocked--;
+    //askForRefresh();
+    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
 }
 
 void Render::mltDeleteTransition(QString tag, int /*a_track*/, int b_track, GenTime in, GenTime out, QDomElement /*xml*/, bool /*do_refresh*/)
 {
-    Mlt::Service service(m_mltProducer->parent().get_service());
+    mlt_service serv = m_mltProducer->parent().get_service();
+    m_isBlocked++;
+    mlt_service_lock(serv);
+
+    Mlt::Service service(serv);
     Mlt::Tractor tractor(service);
     Mlt::Field *field = tractor.field();
 
     //if (do_refresh) m_mltConsumer->set("refresh", 0);
-    mlt_service serv = m_mltProducer->parent().get_service();
 
     mlt_service nextservice = mlt_service_get_producer(serv);
     mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
@@ -2620,6 +2646,7 @@ void Render::mltDeleteTransition(QString tag, int /*a_track*/, int b_track, GenT
     QString resource = mlt_properties_get(properties, "mlt_service");
 
     const int old_pos = (int)((in + out).frames(m_fps) / 2);
+    kDebug() << " del trans pos: " << in.frames(25) << "-" << out.frames(25);
 
     while (mlt_type == "transition") {
         mlt_transition tr = (mlt_transition) nextservice;
@@ -2638,7 +2665,10 @@ void Render::mltDeleteTransition(QString tag, int /*a_track*/, int b_track, GenT
         mlt_type = mlt_properties_get(properties, "mlt_type");
         resource = mlt_properties_get(properties, "mlt_service");
     }
-    //if (do_refresh) m_mltConsumer->set("refresh", 1);
+    mlt_service_unlock(serv);
+    m_isBlocked--;
+    //askForRefresh();
+    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
 }
 
 QMap<QString, QString> Render::mltGetTransitionParamsFromXml(QDomElement xml)
@@ -2739,7 +2769,7 @@ void Render::mltResizeTransparency(int oldStart, int newStart, int newEnd, int t
 
     mlt_service_lock(service.get_service());
     m_mltConsumer->set("refresh", 0);
-    m_isBlocked = true;
+    m_isBlocked++;
 
     mlt_service serv = m_mltProducer->parent().get_service();
     mlt_service nextservice = mlt_service_get_producer(serv);
@@ -2765,9 +2795,9 @@ void Render::mltResizeTransparency(int oldStart, int newStart, int newEnd, int t
         mlt_type = mlt_properties_get(properties, "mlt_type");
         resource = mlt_properties_get(properties, "mlt_service");
     }
-    m_isBlocked = false;
     mlt_service_unlock(service.get_service());
-    m_mltConsumer->set("refresh", 1);
+    m_isBlocked--;
+    if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
 
 }
 
@@ -2778,7 +2808,7 @@ void Render::mltMoveTransparency(int startTime, int endTime, int startTrack, int
 
     mlt_service_lock(service.get_service());
     m_mltConsumer->set("refresh", 0);
-    m_isBlocked = true;
+    m_isBlocked++;
 
     mlt_service serv = m_mltProducer->parent().get_service();
     mlt_service nextservice = mlt_service_get_producer(serv);
@@ -2811,7 +2841,7 @@ void Render::mltMoveTransparency(int startTime, int endTime, int startTrack, int
         mlt_type = mlt_properties_get(properties, "mlt_type");
         resource = mlt_properties_get(properties, "mlt_service");
     }
-    m_isBlocked = false;
+    m_isBlocked--;
     mlt_service_unlock(service.get_service());
     m_mltConsumer->set("refresh", 1);
 }
@@ -2931,11 +2961,10 @@ void Render::fillSlowMotionProducers()
 void Render::mltInsertTrack(int ix, bool videoTrack)
 {
     blockSignals(true);
-    m_isBlocked = true;
+    m_isBlocked++;
 
-    m_mltConsumer->set("refresh", 0);
-    mlt_service_lock(m_mltConsumer->get_service());
     Mlt::Service service(m_mltProducer->parent().get_service());
+    mlt_service_lock(service.get_service());
     if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
 
     Mlt::Tractor tractor(service);
@@ -2994,16 +3023,17 @@ void Render::mltInsertTrack(int ix, bool videoTrack)
     // Add audio mix transition to last track
     Mlt::Field *field = tractor.field();
     Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "mix");
-    //transition->set("mlt_service", "mix");
     transition->set("a_track", 1);
     transition->set("b_track", ct);
     transition->set("always_active", 1);
     transition->set("internal_added", 237);
     transition->set("combine", 1);
     field->plant_transition(*transition, 1, ct);
-
-    mlt_service_unlock(m_mltConsumer->get_service());
-    m_isBlocked = false;
+    //mlt_service_unlock(m_mltConsumer->get_service());
+    mlt_service_unlock(service.get_service());
+    //tractor.multitrack()->refresh();
+    //tractor.refresh();
+    m_isBlocked--;
     blockSignals(false);
 }
 
@@ -3027,12 +3057,12 @@ void Render::mltDeleteTrack(int ix)
         if (mappedProps.value("mlt_service") == "mix" && mappedProps.value("b_track").toInt() == tracksCount) {
             tractor.removeChild(transitions.at(i));
             i--;
-        } else if (mappedProps.value("mlt_service") != "mix" && mappedProps.value("b_track").toInt() >= ix) {
+        } else if (mappedProps.value("mlt_service") != "mix" && (mappedProps.value("b_track").toInt() >= ix || mappedProps.value("a_track").toInt() >= ix)) {
             // Transition needs to be moved
             int a_track = mappedProps.value("a_track").toInt();
             int b_track = mappedProps.value("b_track").toInt();
-            if (a_track > 0) a_track --;
-            if (b_track > 0) b_track --;
+            if (a_track > 0 && a_track >= ix) a_track --;
+            if (b_track > 0 && b_track >= ix) b_track --;
             for (int j = 0; j < props.count(); j++) {
                 QDomElement f = props.at(j).toElement();
                 if (f.attribute("name") == "a_track") f.firstChild().setNodeValue(QString::number(a_track));
@@ -3042,6 +3072,7 @@ void Render::mltDeleteTrack(int ix)
         }
     }
     tractor.removeChild(track);
+    //kDebug() << "/////////// RESULT SCENE: \n" << doc.toString();
     setSceneList(doc.toString(), m_framePosition);
     mltCheckLength();
 }