]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Try to fix timecode error:
[kdenlive] / src / renderer.cpp
index 6759eadd9994f78a1b08633cf7dfb1341228aac9..26791b5beae82497ee564a2f44ac87a28175b112 100644 (file)
@@ -230,6 +230,8 @@ void Render::buildConsumer(const QString profileName)
         delete[] tmp;
     }
 
+    int volume = KdenliveSettings::volume();
+    m_mltConsumer->set("volume", (float)volume / 100);
 
     m_mltConsumer->set("progressive", 1);
     m_mltConsumer->set("audio_buffer", 1024);
@@ -257,7 +259,11 @@ int Render::resetProfile(const QString profileName)
         QString videoDriver = KdenliveSettings::videodrivername();
         QString currentDriver = m_mltConsumer->get("video_driver");
         if (getenv("SDL_VIDEO_YUV_HWACCEL") != NULL && currentDriver == "x11") currentDriver = "x11_noaccel";
-        if (m_activeProfile == profileName && currentDriver == videoDriver) {
+        QString background = KdenliveSettings::window_background().name();
+        QString currentBackground = m_mltConsumer->get("window_background");
+        int volume = KdenliveSettings::volume();
+        int currentVolume = (int)(QString(m_mltConsumer->get("volume")).toDouble() * 100.0);
+        if (m_activeProfile == profileName && currentDriver == videoDriver && volume == currentVolume && background == currentBackground) {
             kDebug() << "reset to same profile, nothing to do";
             return 1;
         }
@@ -744,10 +750,14 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
             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);
-            QPixmap pix(frame_width, frame_height);
+            QPixmap pix;
 
             if (!image.isNull()) {
-                pix = QPixmap::fromImage(image.rgbSwapped());
+                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);
 
@@ -917,7 +927,7 @@ int Render::setProducer(Mlt::Producer *producer, int position)
     if (position != -1) {
         m_mltProducer->seek(position);
         emit rendererPosition(position);
-    }
+    } else emit rendererPosition((int) m_mltProducer->position());
     m_isBlocked = false;
     return error;
 }
@@ -1430,9 +1440,12 @@ const QString & Render::rendererName() const
 
 void Render::emitFrameNumber(double position)
 {
+    if (position == m_framePosition) {
+        emit frameUpdated((int) position);
+        return;
+    }
     m_framePosition = position;
     emit rendererPosition((int) position);
-    //if (qApp->activeWindow()) QApplication::postEvent(qApp->activeWindow(), new PositionChangeEvent( GenTime((int) position, m_fps), m_monitorId));
 }
 
 void Render::emitConsumerStopped()
@@ -1645,7 +1658,6 @@ int Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pro
 
 void Render::mltCutClip(int track, GenTime position)
 {
-
     m_isBlocked = true;
 
     Mlt::Service service(m_mltProducer->parent().get_service());
@@ -2229,14 +2241,23 @@ bool Render::mltRemoveEffect(int track, GenTime position, QString index, bool up
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
-    //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
-    Mlt::Producer *clip = trackPlaylist.get_clip_at((int) position.frames(m_fps));
+
+    int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
     if (!clip) {
         kDebug() << " / / / CANNOT FIND CLIP TO REMOVE EFFECT";
-        return success;
+        return false;
     }
+
     Mlt::Service clipService(clip->get_service());
+    int duration = clip->get_playtime();
+    if (doRefresh) {
+        // Check if clip is visible in monitor
+        int diff = trackPlaylist.clip_start(clipIndex) + duration - m_mltProducer->position();
+        if (diff < 0 || diff > duration) doRefresh = false;
+    }
     delete clip;
+
 //    if (tag.startsWith("ladspa")) tag = "ladspa";
     m_isBlocked = true;
     int ct = 0;
@@ -2267,14 +2288,21 @@ bool Render::mltAddEffect(int track, GenTime position, EffectsParameterList para
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
 
-    Mlt::Producer *clip = trackPlaylist.get_clip_at((int) position.frames(m_fps));
+    int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
     if (!clip) {
         return false;
     }
+
     Mlt::Service clipService(clip->get_service());
     m_isBlocked = true;
     int duration = clip->get_playtime();
     bool updateIndex = false;
+    if (doRefresh) {
+        // Check if clip is visible in monitor
+        int diff = trackPlaylist.clip_start(clipIndex) + duration - m_mltProducer->position();
+        if (diff < 0 || diff > duration) doRefresh = false;
+    }
     delete clip;
 
     const int filter_ix = params.paramValue("kdenlive_ix").toInt();
@@ -2383,11 +2411,16 @@ bool Render::mltAddEffect(int track, GenTime position, EffectsParameterList para
         if (filter && filter->is_valid()) {
             filter->set("kdenlive_id", filterId);
             if (!region.isEmpty()) {
-                char *filterResource = decodedString(region);
-                filter->set("resource", filterResource);
+                char *tmp = decodedString(region);
+                filter->set("resource", tmp);
+                tmp = decodedString(params.paramValue("kdenlive_ix"));
+                filter->set("kdenlive_ix", tmp);
                 filter->set("filter0", filterTag);
                 prefix = "filter0.";
-                delete[] filterResource;
+                delete[] tmp;
+                params.removeParam("id");
+                params.removeParam("region");
+                params.removeParam("kdenlive_ix");
             }
         } else {
             kDebug() << "filter is NULL";
@@ -2445,9 +2478,8 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
 {
     QString index = params.paramValue("kdenlive_ix");
     QString tag =  params.paramValue("tag");
-    QString region =  params.paramValue("region");
 
-    if (!params.paramValue("keyframes").isEmpty() || /*it.key().startsWith("#") || */tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle" || !region.isEmpty()) {
+    if (!params.paramValue("keyframes").isEmpty() || /*it.key().startsWith("#") || */tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle" || params.hasParam("region")) {
         // This is a keyframe effect, to edit it, we remove it and re-add it.
         mltRemoveEffect(track, position, index, false);
         bool success = mltAddEffect(track, position, params);
@@ -2456,17 +2488,23 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
 
     // find filter
     Mlt::Service service(m_mltProducer->parent().get_service());
-
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
-    //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
-    Mlt::Producer *clip = trackPlaylist.get_clip_at((int) position.frames(m_fps));
+
+    int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
     if (!clip) {
         kDebug() << "WARINIG, CANNOT FIND CLIP ON track: " << track << ", AT POS: " << position.frames(m_fps);
         return false;
     }
+
     Mlt::Service clipService(clip->get_service());
+    int duration = clip->get_playtime();
+    bool doRefresh = true;
+    // Check if clip is visible in monitor
+    int diff = trackPlaylist.clip_start(clipIndex) + duration - m_mltProducer->position();
+    if (diff < 0 || diff > duration) doRefresh = false;
     delete clip;
     m_isBlocked = true;
     int ct = 0;
@@ -2498,9 +2536,12 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
         m_isBlocked = false;
         return success;
     }
+    QString prefix;
+    QString ser = filter->get("mlt_service");
+    if (ser == "region") prefix = "filter0.";
     mlt_service_lock(service.get_service());
     for (int j = 0; j < params.count(); j++) {
-        char *name = decodedString(params.at(j).name());
+        char *name = decodedString(prefix + params.at(j).name());
         char *value = decodedString(params.at(j).value());
         filter->set(name, value);
         delete[] name;
@@ -2509,7 +2550,7 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
     mlt_service_unlock(service.get_service());
 
     m_isBlocked = false;
-    refresh();
+    if (doRefresh) refresh();
     return true;
 }
 
@@ -2522,14 +2563,22 @@ void Render::mltUpdateEffectPosition(int track, GenTime position, int oldPos, in
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
-    //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
-    Mlt::Producer *clip = trackPlaylist.get_clip_at((int) position.frames(m_fps));
+
+    int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
     if (!clip) {
         kDebug() << "WARINIG, CANNOT FIND CLIP ON track: " << track << ", AT POS: " << position.frames(m_fps);
         return;
     }
+
     Mlt::Service clipService(clip->get_service());
+    int duration = clip->get_playtime();
+    bool doRefresh = true;
+    // Check if clip is visible in monitor
+    int diff = trackPlaylist.clip_start(clipIndex) + duration - m_mltProducer->position();
+    if (diff < 0 || diff > duration) doRefresh = false;
     delete clip;
+
     m_isBlocked = true;
     int ct = 0;
     Mlt::Filter *filter = clipService.filter(ct);
@@ -2542,7 +2591,7 @@ void Render::mltUpdateEffectPosition(int track, GenTime position, int oldPos, in
     }
 
     m_isBlocked = false;
-    refresh();
+    if (doRefresh) refresh();
 }
 
 void Render::mltMoveEffect(int track, GenTime position, int oldPos, int newPos)
@@ -2554,14 +2603,22 @@ void Render::mltMoveEffect(int track, GenTime position, int oldPos, int newPos)
     Mlt::Tractor tractor(service);
     Mlt::Producer trackProducer(tractor.track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
-    //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
-    Mlt::Producer *clip = trackPlaylist.get_clip_at((int) position.frames(m_fps));
+
+    int clipIndex = trackPlaylist.get_clip_index_at((int) position.frames(m_fps));
+    Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
     if (!clip) {
         kDebug() << "WARINIG, CANNOT FIND CLIP ON track: " << track << ", AT POS: " << position.frames(m_fps);
         return;
     }
+
     Mlt::Service clipService(clip->get_service());
+    int duration = clip->get_playtime();
+    bool doRefresh = true;
+    // Check if clip is visible in monitor
+    int diff = trackPlaylist.clip_start(clipIndex) + duration - m_mltProducer->position();
+    if (diff < 0 || diff > duration) doRefresh = false;
     delete clip;
+
     m_isBlocked = true;
     int ct = 0;
     QList <Mlt::Filter *> filtersList;
@@ -2615,7 +2672,7 @@ void Render::mltMoveEffect(int track, GenTime position, int oldPos, int newPos)
     }
 
     m_isBlocked = false;
-    refresh();
+    if (doRefresh) refresh();
 }
 
 bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration)
@@ -2751,7 +2808,7 @@ bool Render::mltResizeClipCrop(ItemInfo info, GenTime diff)
 
 bool Render::mltResizeClipStart(ItemInfo info, GenTime diff)
 {
-    // kDebug() << "////////  RSIZING CLIP from: "<<info.startPos.frames(25)<<" to "<<diff.frames(25);
+    //kDebug() << "////////  RSIZING CLIP from: "<<info.startPos.frames(25)<<" to "<<diff.frames(25);
     Mlt::Service service(m_mltProducer->parent().get_service());
     int moveFrame = (int) diff.frames(m_fps);
     Mlt::Tractor tractor(service);
@@ -2773,14 +2830,20 @@ bool Render::mltResizeClipStart(ItemInfo info, GenTime diff)
     int previousOut = clip->get_out();
     delete clip;
     m_isBlocked = true;
-    //kDebug() << "RESIZE, old start: " << previousStart + moveFrame << ", " << previousStart + previousOut;
-    trackPlaylist.resize_clip(clipIndex, previousStart + moveFrame, previousStart + previousOut);
+    previousStart += moveFrame;
+    if (previousStart < 0) {
+        // special case, in point becoming negative (resizing images)
+        previousOut -= previousStart;
+        previousStart = 0;
+    }
+    // kDebug() << "RESIZE, new start: " << previousStart << ", " << previousOut;
+    trackPlaylist.resize_clip(clipIndex, previousStart, previousOut);
     if (moveFrame > 0) trackPlaylist.insert_blank(clipIndex, moveFrame - 1);
     else {
         //int midpos = info.startPos.frames(m_fps) + moveFrame - 1;
         int blankIndex = clipIndex - 1;
         int blankLength = trackPlaylist.clip_length(blankIndex);
-        kDebug() << " + resizing blank length " <<  blankLength << ", SIZE DIFF: " << moveFrame;
+        // kDebug() << " + resizing blank length " <<  blankLength << ", SIZE DIFF: " << moveFrame;
         if (! trackPlaylist.is_blank(blankIndex)) {
             kDebug() << "WARNING, CLIP TO RESIZE IS NOT BLANK";
         }
@@ -3004,11 +3067,22 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
     int new_in = (int)newIn.frames(m_fps);
     int new_out = (int)newOut.frames(m_fps) - 1;
     if (new_in >= new_out) return false;
+    int old_in = (int)oldIn.frames(m_fps);
+    int old_out = (int)oldOut.frames(m_fps) - 1;
 
     Mlt::Service service(m_mltProducer->parent().get_service());
     Mlt::Tractor tractor(service);
     Mlt::Field *field = tractor.field();
 
+    bool doRefresh = true;
+    // Check if clip is visible in monitor
+    int diff = old_out - m_mltProducer->position();
+    if (diff < 0 || diff > old_out - old_in) doRefresh = false;
+    if (doRefresh) {
+        diff = new_out - m_mltProducer->position();
+        if (diff < 0 || diff > new_out - new_in) doRefresh = false;
+    }
+
     m_isBlocked++;
     mlt_service_lock(service.get_service());
 
@@ -3016,7 +3090,7 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
     mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
     QString mlt_type = mlt_properties_get(properties, "mlt_type");
     QString resource = mlt_properties_get(properties, "mlt_service");
-    int old_pos = (int)(oldIn.frames(m_fps) + oldOut.frames(m_fps)) / 2;
+    int old_pos = (int)(old_in + old_out) / 2;
     bool found = false;
 
     while (mlt_type == "transition") {
@@ -3049,7 +3123,7 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
     }
     mlt_service_unlock(service.get_service());
     m_isBlocked--;
-    refresh();
+    if (doRefresh) refresh();
     //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
     return found;
 }
@@ -3102,8 +3176,8 @@ void Render::mltUpdateTransition(QString oldTag, QString tag, int a_track, int b
         mltDeleteTransition(oldTag, a_track, b_track, in, out, xml, false);
         mltAddTransition(tag, a_track, b_track, in, out, xml, false);
     }
-    refresh();
-    //mltSavePlaylist();
+
+    if (m_mltProducer->position() > in.frames(m_fps) && m_mltProducer->position() < out.frames(m_fps)) refresh();
 }
 
 void Render::mltUpdateTransitionParams(QString type, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml)
@@ -3133,14 +3207,32 @@ void Render::mltUpdateTransitionParams(QString type, int a_track, int b_track, G
             QMap<QString, QString>::Iterator it;
             QString key;
             mlt_properties transproperties = MLT_TRANSITION_PROPERTIES(tr);
+
+            QString currentId = mlt_properties_get(transproperties, "kdenlive_id");
+            if (currentId != xml.attribute("id")) {
+                // The transition ID is not the same, so reset all properties
+                char *tmp = decodedString(xml.attribute("id"));
+                mlt_properties_set(transproperties, "kdenlive_id", tmp);
+                delete[] tmp;
+                // Cleanup previous properties
+                QStringList permanentProps;
+                permanentProps << "factory" << "kdenlive_id" << "mlt_service" << "mlt_type" << "in";
+                permanentProps << "out" << "a_track" << "b_track";
+                for (int i = 0; i < mlt_properties_count(transproperties); i++) {
+                    QString propName = mlt_properties_get_name(transproperties, i);
+                    if (!propName.startsWith('_') && ! permanentProps.contains(propName)) {
+                        tmp = decodedString(propName);
+                        mlt_properties_set(transproperties, tmp, "");
+                        delete[] tmp;
+                    }
+                }
+            }
+
             mlt_properties_set_int(transproperties, "force_track", xml.attribute("force_track").toInt());
             mlt_properties_set_int(transproperties, "automatic", xml.attribute("automatic", "0").toInt());
-            // update the transition id in case it uses the same MLT service but different Kdenlive id
-            char *tmp = decodedString(xml.attribute("id"));
-            mlt_properties_set(transproperties, "kdenlive_id", tmp);
-            delete[] tmp;
+
             if (currentBTrack != a_track) {
-                mlt_properties_set_int(properties, "a_track", a_track);
+                mlt_properties_set_int(transproperties, "a_track", a_track);
             }
             for (it = map.begin(); it != map.end(); ++it) {
                 key = it.key();
@@ -3398,6 +3490,8 @@ bool Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in,
     Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, transId);
     if (out != GenTime())
         transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps) - 1);
+
+    if (do_refresh && (m_mltProducer->position() < in.frames(m_fps) || m_mltProducer->position() > out.frames(m_fps))) do_refresh = false;
     QMap<QString, QString>::Iterator it;
     QString key;
     if (xml.attribute("automatic") == "1") transition->set("automatic", 1);