]> git.sesse.net Git - kdenlive/commitdiff
Fix lots of issues with slowmotioned clips (bugs in move, resize, copy, load & save)
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 13 Jan 2009 09:04:00 +0000 (09:04 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 13 Jan 2009 09:04:00 +0000 (09:04 +0000)
svn path=/branches/KDE4/; revision=2908

src/abstractclipitem.cpp
src/clipitem.cpp
src/clipitem.h
src/customtrackview.cpp
src/projectlist.cpp
src/renderer.cpp
src/renderer.h

index 9a7ed808d053614109f6bcc051222fbec2387585..353fd9b9b0807438b65617accce961cadbba3b3d 100644 (file)
@@ -147,8 +147,8 @@ void AbstractClipItem::resizeEnd(int posx, double speed, bool updateKeyFrames) {
                 kDebug() << "/////////  CURRENT: " << startPos().frames(25) << "x" << endPos().frames(25) << ", RECT: " << rect() << "-" << pos();
                 kDebug() << "/////////  COLLISION: " << ((AbstractClipItem *)item)->startPos().frames(25) << "x" << ((AbstractClipItem *)item)->endPos().frames(25) << ", RECT: " << ((AbstractClipItem *)item)->rect() << "-" << item->pos();*/
                 GenTime diff = ((AbstractClipItem *)item)->startPos() - GenTime(1, m_fps) - startPos();
-                m_cropDuration = diff;
-                setRect(0, 0, m_cropDuration.frames(m_fps) - 0.02, rect().height());
+                m_cropDuration = diff * speed;
+                setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
                 break;
             }
         }
index 060327feef2ff04dfdffa570b1f1b9d1703c8c2d..b23b6296c1ccf27bd8d5253804f931e096203a74 100644 (file)
 #include "kthumb.h"
 
 
-ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, bool generateThumbs)
-        : AbstractClipItem(info, QRectF(), fps), m_clip(clip), m_resizeMode(NONE), m_grabPoint(0), m_maxTrack(0), m_hasThumbs(false), startThumbTimer(NULL), endThumbTimer(NULL), audioThumbWasDrawn(false), m_opacity(1.0), m_timeLine(0), m_startThumbRequested(false), m_endThumbRequested(false), m_startFade(0), m_endFade(0), m_hover(false), m_selectedEffect(-1), m_speed(1.0), framePixelWidth(0), m_startPix(QPixmap()), m_endPix(QPixmap()) {
+ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, bool generateThumbs)
+        : AbstractClipItem(info, QRectF(), fps), m_clip(clip), m_resizeMode(NONE), m_grabPoint(0), m_maxTrack(0), m_hasThumbs(false), startThumbTimer(NULL), endThumbTimer(NULL), audioThumbWasDrawn(false), m_opacity(1.0), m_timeLine(0), m_startThumbRequested(false), m_endThumbRequested(false), m_startFade(0), m_endFade(0), m_hover(false), m_selectedEffect(-1), m_speed(speed), framePixelWidth(0), m_startPix(QPixmap()), m_endPix(QPixmap()) {
     setZValue(1);
     setRect(0, 0, (info.endPos - info.startPos).frames(fps) - 0.02, (double)(KdenliveSettings::trackheight() - 2));
     setPos(info.startPos.frames(fps), (double)(info.track * KdenliveSettings::trackheight()) + 1);
 
-    m_clipName = clip->name();
+    if (m_speed == 1.0) m_clipName = clip->name();
+    else {
+        m_clipName = clip->name() + " - " + QString::number(m_speed * 100, 'f', 0) + "%";
+        m_cropDuration = m_cropDuration * m_speed;
+    }
     m_producer = clip->getId();
     m_clipType = clip->clipType();
     m_cropStart = info.cropStart;
@@ -108,12 +112,12 @@ ClipItem::~ClipItem() {
 }
 
 ClipItem *ClipItem::clone(ItemInfo info) const {
-    ClipItem *duplicate = new ClipItem(m_clip, info, m_fps);
+    ClipItem *duplicate = new ClipItem(m_clip, info, m_fps, m_speed);
     if (info.cropStart == cropStart()) duplicate->slotSetStartThumb(m_startPix);
     if (info.cropStart + (info.endPos - info.startPos) == m_cropStart + m_cropDuration) duplicate->slotSetEndThumb(m_endPix);
     kDebug() << "// CLoning clip: " << (info.cropStart + (info.endPos - info.startPos)).frames(m_fps) << ", CURRENT end: " << (cropStart() + duration()).frames(m_fps);
     duplicate->setEffectList(m_effectList.clone());
-    duplicate->setSpeed(m_speed);
+    //duplicate->setSpeed(m_speed);
     return duplicate;
 }
 
@@ -462,7 +466,9 @@ DocClipBase *ClipItem::baseClip() const {
 }
 
 QDomElement ClipItem::xml() const {
-    return m_clip->toXML();
+    QDomElement xml = m_clip->toXML();
+    if (m_speed != 1.0) xml.setAttribute("speed", m_speed);
+    return xml;
 }
 
 int ClipItem::clipType() const {
@@ -1046,7 +1052,7 @@ QVariant ClipItem::itemChange(GraphicsItemChange change, const QVariant &value)
                         return pos();
                     }
                     if (forwardMove) {
-                        offset = qMax(offset, (int)(newPos.x() - (static_cast < AbstractClipItem* >(items.at(i))->startPos() - m_cropDuration).frames(m_fps)));
+                        offset = qMax(offset, (int)(newPos.x() - (static_cast < AbstractClipItem* >(items.at(i))->startPos() - cropDuration()).frames(m_fps)));
                     } else {
                         offset = qMax(offset, (int)((static_cast < AbstractClipItem* >(items.at(i))->endPos().frames(m_fps)) - newPos.x()));
                     }
index 580cf3469bd5a3fe30e6a7a031b4ff98c54145c1..7aa29fec23ada183c49c04061bcc6071d4a3d781 100644 (file)
@@ -40,7 +40,7 @@ class ClipItem : public AbstractClipItem {
     Q_OBJECT
 
 public:
-    ClipItem(DocClipBase *clip, ItemInfo info, double fps, bool generateThumbs = true);
+    ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, bool generateThumbs = true);
     virtual ~ ClipItem();
     virtual void paint(QPainter *painter,
                        const QStyleOptionGraphicsItem *option,
index 93b798701f8c8eded6d91f36c0a53c80f2fd22f6..9d6d3ca710274b675ee75afae5900f4b15f19688 100644 (file)
@@ -896,7 +896,7 @@ void CustomTrackView::dragEnterEvent(QDragEnterEvent * event) {
         info.cropStart = GenTime(list.at(1).toInt(), m_document->fps());
         info.endPos = info.startPos + GenTime(list.at(2).toInt() - list.at(1).toInt(), m_document->fps());
         info.track = (int)(pos.y() / m_tracksHeight);
-        ClipItem *item = new ClipItem(clip, info, m_document->fps());
+        ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0);
         m_selectionGroup->addToGroup(item);
         //TODO: check if we do not overlap another clip when first dropping in timeline
         // if (insertPossible(m_selectionGroup, event->pos()))
@@ -916,7 +916,7 @@ void CustomTrackView::dragEnterEvent(QDragEnterEvent * event) {
             info.startPos = GenTime(pos.x(), m_document->fps());
             info.endPos = info.startPos + clip->duration();
             info.track = (int)(pos.y() / m_tracksHeight);
-            ClipItem *item = new ClipItem(clip, info, m_document->fps());
+            ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0);
             pos.setX(pos.x() + clip->duration().frames(m_document->fps()));
             m_selectionGroup->addToGroup(item);
         }
@@ -2162,17 +2162,22 @@ void CustomTrackView::changeClipSpeed() {
     }
     QUndoCommand *changeSelected = new QUndoCommand();
     changeSelected->setText("Edit clip speed");
+    int count = 0;
     for (int i = 0; i < itemList.count(); i++) {
         if (itemList.at(i)->type() == AVWIDGET) {
             ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
             ItemInfo info = item->info();
-            int percent = QInputDialog::getInteger(this, i18n("Edit Clip Speed"), i18n("New speed (percents)"), item->speed() * 100, 1, 300);
+            bool ok;
+            int percent = QInputDialog::getInteger(this, i18n("Edit Clip Speed"), i18n("New speed (percents)"), item->speed() * 100, 1, 300, 1, &ok);
             double speed = (double) percent / 100.0;
-            if (item->speed() != speed)
+            if (ok && item->speed() != speed) {
+                count++;
                 new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), true, changeSelected);
+            }
         }
     }
-    m_commandStack->push(changeSelected);
+    if (count > 0) m_commandStack->push(changeSelected);
+    else delete changeSelected;
 }
 
 void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, const QString &id) {
@@ -2208,7 +2213,7 @@ void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo i
         emit displayMessage(i18n("No clip copied"), ErrorMessage);
         return;
     }
-    ClipItem *item = new ClipItem(baseclip, info, m_document->fps());
+    ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble());
     item->setEffectList(effects);
     scene()->addItem(item);
     if (item->baseClip()->isTransparent()) {
index 38f1556ec7b3735cfaa7595c552212e80a406385..c4bf7dc3f213670e8cd912c895d24a285e288d06 100644 (file)
@@ -375,7 +375,7 @@ void ProjectList::slotProcessNextClipInQueue() {
 
 void ProjectList::slotUpdateClip(const QString &id) {
     ProjectItem *item = getItemById(id);
-    item->setData(1, UsageRole, QString::number(item->numReferences()));
+    if (item) item->setData(1, UsageRole, QString::number(item->numReferences()));
 }
 
 void ProjectList::updateAllClips() {
index d31b98ffe7d4658a92f83dd5f6537526738a7b71..b42ef96ff24279bdf9e2c0e63d7a39bd343568f4 100644 (file)
@@ -753,6 +753,7 @@ void Render::setSceneList(QDomDocument list, int position) {
 void Render::setSceneList(QString playlist, int position) {
     if (m_winid == -1) return;
     m_isBlocked = true;
+    m_slowmotionProducers.clear();
 
     //kWarning() << "//////  RENDER, SET SCENE LIST: " << playlist;
 
@@ -811,6 +812,7 @@ void Render::setSceneList(QString playlist, int position) {
     m_fps = m_mltProducer->get_fps();
     kDebug() << "// NEW SCENE LIST DURATION SET TO: " << m_mltProducer->get_playtime();
     connectPlaylist();
+    fillSlowMotionProducers();
     if (position != 0) {
         //TODO: seek to correct place after opening project.
         //  Needs to be done from another place since it crashes here.
@@ -1294,6 +1296,28 @@ void Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pr
     Mlt::Producer trackProducer(tractor.track(info.track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
     //kDebug()<<"/// INSERT cLIP: "<<info.cropStart.frames(m_fps)<<", "<<info.startPos.frames(m_fps)<<"-"<<info.endPos.frames(m_fps);
+
+    if (element.attribute("speed", "1.0").toDouble() != 1.0) {
+        // We want a slowmotion producer
+        double speed = element.attribute("speed", "1.0").toDouble();
+        QString url = prod->get("resource");
+        url.append("?" + QString::number(speed));
+        Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
+        if (!slowprod || slowprod->get_producer() == NULL) {
+            char *tmp = decodedString(url);
+            slowprod = new Mlt::Producer(*m_mltProfile, "framebuffer", tmp);
+            delete[] tmp;
+            QString id = prod->get("id");
+            if (id.contains('_')) id = id.section('_', 0, 0);
+            QString producerid = "slowmotion:" + id + ":" + QString::number(speed);
+            tmp = decodedString(producerid);
+            slowprod->set("id", tmp);
+            delete[] tmp;
+            m_slowmotionProducers.insert(url, slowprod);
+        }
+        prod = slowprod;
+    }
+
     Mlt::Producer *clip = prod->cut((int) info.cropStart.frames(m_fps), (int)(info.endPos - info.startPos + info.cropStart).frames(m_fps) - 1);
     int newIndex = trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *clip, 1);
 
@@ -2684,6 +2708,32 @@ QList <Mlt::Producer *> Render::producersList() {
     return prods;
 }
 
+void Render::fillSlowMotionProducers() {
+    Mlt::Service service(m_mltProducer->parent().get_service());
+    Mlt::Tractor tractor(service);
+
+    int trackNb = tractor.count();
+    for (int t = 1; t < trackNb; t++) {
+        Mlt::Producer trackProducer(tractor.track(t));
+        Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
+        int clipNb = trackPlaylist.count();
+        for (int i = 0; i < clipNb; i++) {
+            Mlt::Producer *prod = trackPlaylist.get_clip(i);
+            Mlt::Producer *nprod = new Mlt::Producer(prod->get_parent());
+            if (nprod && !nprod->is_blank()) {
+                QString id = nprod->get("id");
+                if (id.startsWith("slowmotion:")) {
+                    // this is a slowmotion producer, add it to the list
+                    QString url = nprod->get("resource");
+                    if (!m_slowmotionProducers.contains(url)) {
+                        m_slowmotionProducers.insert(url, nprod);
+                    }
+                }
+            }
+        }
+    }
+}
+
 void Render::mltInsertTrack(int ix, bool videoTrack) {
     blockSignals(true);
     m_isBlocked = true;
index 3940b943ef4b7df6f2b14f783d098e43ad751563..d13bf11166ca9e930ff37010eeed7bf0e5eafc89 100644 (file)
@@ -224,6 +224,7 @@ private:   // Private attributes & methods
     QMap<QString, Mlt::Producer *> m_slowmotionProducers;
     void buildConsumer();
     void resetZoneMode();
+    void fillSlowMotionProducers();
 
 private slots:  // Private slots
     /** refresh monitor display */