ItemInfo itemInfo;
itemInfo.startPos = startPos();
itemInfo.endPos = endPos();
- itemInfo.cropStart = cropStart();
+ itemInfo.cropStart = m_cropStart;
itemInfo.track = track();
return itemInfo;
}
return m_cropStart;
}
+GenTime AbstractClipItem::cropDuration() const {
+ return m_cropDuration;
+}
+
void AbstractClipItem::setCropStart(GenTime pos) {
m_cropStart = pos;
}
-void AbstractClipItem::resizeStart(int posx) {
+void AbstractClipItem::updateRectGeometry() {
+ setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
+}
+
+void AbstractClipItem::resizeStart(int posx, double speed) {
GenTime durationDiff = GenTime(posx, m_fps) - m_startPos;
if (durationDiff == GenTime()) return;
- //kDebug() << "-- RESCALE: CROP=" << m_cropStart << ", DIFF = " << durationDiff;
+ kDebug() << "-- RESCALE: CROP=" << m_cropStart.frames(25) << " - " << cropStart().frames(25);
- if (type() == AVWIDGET && m_cropStart + durationDiff < GenTime()) {
- durationDiff = GenTime() - m_cropStart;
+ if (type() == AVWIDGET && cropStart() + durationDiff < GenTime()) {
+ durationDiff = GenTime() - cropStart();
} else if (durationDiff >= m_cropDuration) {
durationDiff = m_cropDuration - GenTime(3, m_fps);
}
m_startPos += durationDiff;
- if (type() == AVWIDGET) m_cropStart += durationDiff;
- m_cropDuration = m_cropDuration - durationDiff;
+ if (type() == AVWIDGET) m_cropStart += durationDiff * speed;
+ m_cropDuration = m_cropDuration - durationDiff * speed;
- setRect(0, 0, m_cropDuration.frames(m_fps) - 0.02, rect().height());
+ setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
setPos((qreal) m_startPos.frames(m_fps), pos().y());
//setRect((double) m_startPos.frames(m_fps) * scale, rect().y(), (double) m_cropDuration.frames(m_fps) * scale, rect().height());
if (durationDiff < GenTime()) {
}
}
-void AbstractClipItem::resizeEnd(int posx, bool updateKeyFrames) {
+void AbstractClipItem::resizeEnd(int posx, double speed, bool updateKeyFrames) {
GenTime durationDiff = GenTime(posx, m_fps) - endPos();
if (durationDiff == GenTime()) return;
//kDebug() << "-- RESCALE: CROP=" << m_cropStart << ", DIFF = " << durationDiff;
- if (m_cropDuration + durationDiff <= GenTime()) {
- durationDiff = GenTime() - (m_cropDuration - GenTime(3, m_fps));
- } else if (m_cropStart + m_cropDuration + durationDiff >= maxDuration()) {
- durationDiff = maxDuration() - m_cropDuration - m_cropStart;
+ kDebug() << "// DUR DIFF1:" << durationDiff.frames(25) << ", ADJUSTED: " << durationDiff.frames(25) * speed << ", SPED:" << speed;
+ if (cropDuration() + durationDiff <= GenTime()) {
+ durationDiff = GenTime() - (cropDuration() - GenTime(3, m_fps));
+ } else if (cropStart() + cropDuration() + durationDiff >= maxDuration()) {
+ kDebug() << "// MAX OVERLOAD:" << cropDuration().frames(25) << " + " << durationDiff.frames(25) << ", MAX:" << maxDuration().frames(25);
+ durationDiff = maxDuration() - cropDuration() - cropStart();
}
- m_cropDuration += durationDiff;
- setRect(0, 0, m_cropDuration.frames(m_fps) - 0.02, rect().height());
+ kDebug() << "// DUR DIFF2:" << durationDiff.frames(25) << ", ADJUSTED: " << durationDiff.frames(25) * speed << ", SPED:" << speed;
+ m_cropDuration += durationDiff * speed;
+ setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
if (durationDiff > GenTime()) {
QList <QGraphicsItem *> collisionList = collidingItems(Qt::IntersectsItemBoundingRect);
for (int i = 0; i < collisionList.size(); ++i) {
double keyFrameFactor() const;
ItemInfo info() const;
CustomTrackScene* projectScene();
+ void updateRectGeometry();
virtual OPERATIONTYPE operationMode(QPointF pos) = 0;
virtual GenTime startPos() const ;
virtual GenTime endPos() const ;
virtual int track() const ;
virtual GenTime cropStart() const ;
- virtual void resizeStart(int posx);
- virtual void resizeEnd(int posx, bool updateKeyFrames = true);
+ virtual GenTime cropDuration() const ;
+ virtual void resizeStart(int posx, double speed = 1.0);
+ virtual void resizeEnd(int posx, double speed = 1.0, bool updateKeyFrames = true);
virtual GenTime duration() const;
virtual double fps() const;
virtual GenTime maxDuration() const;
// virtual
void ChangeSpeedCommand::undo() {
- m_view->doChangeClipSpeed(m_clipInfo, m_old_speed, m_clipId);
+ m_view->doChangeClipSpeed(m_clipInfo, m_old_speed, m_new_speed, m_clipId);
}
// virtual
void ChangeSpeedCommand::redo() {
if (m_doIt) {
- m_view->doChangeClipSpeed(m_clipInfo, m_new_speed, m_clipId);
+ m_view->doChangeClipSpeed(m_clipInfo, m_new_speed, m_old_speed, m_clipId);
}
m_doIt = true;
}
if (m_endPix.isNull() && m_startPix.isNull()) {
m_startThumbRequested = true;
m_endThumbRequested = true;
- emit getThumb((int)m_cropStart.frames(m_fps), (int)(m_cropStart + m_cropDuration).frames(m_fps) - 1);
+ emit getThumb((int)cropStart().frames(m_fps), (int)(cropStart() + cropDuration()).frames(m_fps) - 1);
} else {
if (m_endPix.isNull()) {
slotGetEndThumb();
void ClipItem::slotGetStartThumb() {
m_startThumbRequested = true;
- emit getThumb((int)m_cropStart.frames(m_fps), -1);
+ emit getThumb((int)cropStart().frames(m_fps), -1);
//videoThumbProducer.setThumbFrames(m_clip->producer(), (int)m_cropStart.frames(m_fps), - 1);
//videoThumbProducer.start(QThread::LowestPriority);
}
void ClipItem::slotGetEndThumb() {
m_endThumbRequested = true;
- emit getThumb(-1, (int)(m_cropStart + m_cropDuration).frames(m_fps) - 1);
+ emit getThumb(-1, (int)(cropStart() + cropDuration()).frames(m_fps) - 1);
//videoThumbProducer.setThumbFrames(m_clip->producer(), -1, (int)(m_cropStart + m_cropDuration).frames(m_fps) - 1);
//videoThumbProducer.start(QThread::LowestPriority);
}
if (scene() == NULL) return;
QRectF r = sceneBoundingRect();
double width = m_startPix.width() / projectScene()->scale();
- if (m_startThumbRequested && frame == m_cropStart.frames(m_fps)) {
+ if (m_startThumbRequested && frame == cropStart().frames(m_fps)) {
m_startPix = pix;
m_startThumbRequested = false;
double height = r.height();
update(r.x(), r.y(), width, height);
- } else if (m_endThumbRequested && frame == (m_cropStart + m_cropDuration).frames(m_fps) - 1) {
+ } else if (m_endThumbRequested && frame == (cropStart() + cropDuration()).frames(m_fps) - 1) {
m_endPix = pix;
m_endThumbRequested = false;
double height = r.height();
}
// draw audio thumbnails
- if (KdenliveSettings::audiothumbnails() && ((m_clipType == AV && exposed.bottom() > (itemHeight / 2)) || m_clipType == AUDIO) && audioThumbReady) {
+ if (KdenliveSettings::audiothumbnails() && m_speed == 1.0 && ((m_clipType == AV && exposed.bottom() > (itemHeight / 2)) || m_clipType == AUDIO) && audioThumbReady) {
double startpixel = exposed.left();
if (startpixel < 0)
update(r.right() - width, r.y() + height, width, height);
}
-void ClipItem::resizeStart(int posx) {
+void ClipItem::resizeStart(int posx, double speed) {
const int min = (startPos() - cropStart()).frames(m_fps);
if (posx < min) posx = min;
if (posx == startPos().frames(m_fps)) return;
const int previous = cropStart().frames(m_fps);
- AbstractClipItem::resizeStart(posx);
+ AbstractClipItem::resizeStart(posx, m_speed);
checkEffectsKeyframesPos(previous, cropStart().frames(m_fps), true);
if (m_hasThumbs && KdenliveSettings::videothumbnails()) {
/*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/
}
}
-void ClipItem::resizeEnd(int posx, bool updateKeyFrames) {
+void ClipItem::resizeEnd(int posx, double speed, bool updateKeyFrames) {
const int max = (startPos() - cropStart() + maxDuration()).frames(m_fps) + 1;
if (posx > max) posx = max;
if (posx == endPos().frames(m_fps)) return;
+ kDebug() << "// NEW POS: " << posx << ", OLD END: " << endPos().frames(m_fps);
const int previous = (cropStart() + duration()).frames(m_fps);
- AbstractClipItem::resizeEnd(posx);
+ AbstractClipItem::resizeEnd(posx, m_speed);
if (updateKeyFrames) checkEffectsKeyframesPos(previous, (cropStart() + duration()).frames(m_fps), false);
if (m_hasThumbs && KdenliveSettings::videothumbnails()) {
/*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/
m_speed = speed;
if (m_speed == 1.0) m_clipName = baseClip()->name();
else m_clipName = baseClip()->name() + " - " + QString::number(speed * 100, 'f', 0) + "%";
- update();
+ //update();
}
GenTime ClipItem::maxDuration() const {
return m_maxDuration / m_speed;
}
+GenTime ClipItem::cropStart() const {
+ return m_cropStart / m_speed;
+}
+
+GenTime ClipItem::cropDuration() const {
+ return m_cropDuration / m_speed;
+}
+
+GenTime ClipItem::endPos() const {
+ return m_startPos + cropDuration();
+}
+
//virtual
void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event) {
QString effects = QString(event->mimeData()->data("kdenlive/effectslist"));
const QStyleOptionGraphicsItem *option,
QWidget *);
virtual int type() const;
- void resizeStart(int posx);
- void resizeEnd(int posx, bool updateKeyFrames = true);
+ void resizeStart(int posx, double speed = 1.0);
+ void resizeEnd(int posx, double speed = 1.0, bool updateKeyFrames = true);
OPERATIONTYPE operationMode(QPointF pos);
const QString &clipProducer() const;
int clipType() const;
void setSpeed(const double speed);
double speed() const;
GenTime maxDuration() const;
+ GenTime cropStart() const;
+ GenTime endPos() const;
+ GenTime cropDuration() const;
int hasEffect(const QString &tag, const QString &id) const;
bool checkKeyFrames();
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)"), 100, 1, 300);
+ int percent = QInputDialog::getInteger(this, i18n("Edit Clip Speed"), i18n("New speed (percents)"), item->speed() * 100, 1, 300);
double speed = (double) percent / 100.0;
if (item->speed() != speed)
new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), true, changeSelected);
m_commandStack->push(changeSelected);
}
-void CustomTrackView::doChangeClipSpeed(ItemInfo info, double speed, const QString &id) {
+void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, const QString &id) {
+
DocClipBase *baseclip = m_document->clipManager()->getClipById(id);
ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()) + 1, info.track);
info.track = m_scene->m_tracksList.count() - item->track();
- m_document->renderer()->mltChangeClipSpeed(info, speed, baseclip->producer());
+ int endPos = m_document->renderer()->mltChangeClipSpeed(info, speed, oldspeed, baseclip->producer());
+ kDebug() << "//CH CLIP SPEED: " << speed << "x" << oldspeed << ", END POS: " << endPos;
item->setSpeed(speed);
- GenTime maxDuration = item->maxDuration();
- if (maxDuration < item->duration()) {
- info = item->info();
- ItemInfo endInfo = info;
- endInfo.endPos = info.startPos + maxDuration;
- ResizeClipCommand *command = new ResizeClipCommand(this, info, endInfo, true);
- m_commandStack->push(command);
- }
+ item->updateRectGeometry();
+ kDebug() << "// SPD CHG: " << item->cropDuration().frames(m_document->fps()) << " - " << endPos;
+ if (item->cropDuration().frames(m_document->fps()) > endPos)
+ item->AbstractClipItem::resizeEnd(info.startPos.frames(m_document->fps()) + endPos, speed);
}
void CustomTrackView::cutSelectedClips() {
void clipStart();
void clipEnd();
void changeClipSpeed();
- void doChangeClipSpeed(ItemInfo info, double speed, const QString &id);
+ void doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, const QString &id);
void setDocumentModified();
void setInPoint();
void setOutPoint();
return true;
}
-int Render::mltChangeClipSpeed(ItemInfo info, double speed, Mlt::Producer *prod) {
+int Render::mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt::Producer *prod) {
m_isBlocked = true;
int newLength = 0;
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());
- int clipIndex = trackPlaylist.get_clip_index_at((int) info.startPos.frames(m_fps));
+ int startPos = info.startPos.frames(m_fps);
+ int clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ int clipLength = trackPlaylist.clip_length(clipIndex);
+
Mlt::Producer clip(trackPlaylist.get_clip(clipIndex));
QString serv = clip.parent().get("mlt_service");
QString id = clip.parent().get("id");
delete[] tmp;
m_slowmotionProducers.insert(url, slowprod);
}
- Mlt::Producer *cut = slowprod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps) - 1);
- newLength = cut->get_length();
trackPlaylist.replace_with_blank(clipIndex);
trackPlaylist.consolidate_blanks(0);
- trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *cut, 1);
+ // Check that the blank space is long enough for our new duration
+ clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ int blankEnd = trackPlaylist.clip_start(clipIndex) + trackPlaylist.clip_length(clipIndex);
+ Mlt::Producer *cut;
+ if (clipIndex + 1 < trackPlaylist.count() && (startPos + clipLength / speed > blankEnd)) {
+ GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
+ cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)(info.cropStart.frames(m_fps) / speed + maxLength.frames(m_fps) - 1));
+ } else cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)((info.cropStart.frames(m_fps) + clipLength) / speed - 1));
+ trackPlaylist.insert_at(startPos, *cut, 1);
+ clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ newLength = trackPlaylist.clip_length(clipIndex);
mlt_service_unlock(service.get_service());
} else if (speed == 1.0) {
mlt_service_lock(service.get_service());
- Mlt::Producer *cut = prod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps) - 1);
+
trackPlaylist.replace_with_blank(clipIndex);
- newLength = cut->get_length();
trackPlaylist.consolidate_blanks(0);
- trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *cut, 1);
+
+ // Check that the blank space is long enough for our new duration
+ clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ int blankEnd = trackPlaylist.clip_start(clipIndex) + trackPlaylist.clip_length(clipIndex);
+
+ Mlt::Producer *cut;
+ GenTime oldDuration = GenTime(clipLength, m_fps);
+ GenTime newDuration = oldDuration * oldspeed;
+ if (clipIndex + 1 < trackPlaylist.count() && (info.startPos + newDuration).frames(m_fps) > blankEnd) {
+ GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
+ cut = prod->cut((int)(info.cropStart.frames(m_fps)), (int)(info.cropStart.frames(m_fps) + maxLength.frames(m_fps) - 1));
+ } else cut = prod->cut((int)(info.cropStart.frames(m_fps)), (int)((info.cropStart + newDuration).frames(m_fps)) - 1);
+ trackPlaylist.insert_at(startPos, *cut, 1);
+ clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ newLength = trackPlaylist.clip_length(clipIndex);
mlt_service_unlock(service.get_service());
+
} else if (serv == "framebuffer") {
mlt_service_lock(service.get_service());
QString url = clip.parent().get("resource");
delete[] tmp;
m_slowmotionProducers.insert(url, slowprod);
}
- Mlt::Producer *cut = slowprod->cut(info.cropStart.frames(m_fps), (info.endPos - info.startPos).frames(m_fps) - 1);
- newLength = cut->get_length();
trackPlaylist.replace_with_blank(clipIndex);
trackPlaylist.consolidate_blanks(0);
- trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *cut, 1);
+
+ GenTime oldDuration = GenTime(clipLength, m_fps);
+ GenTime newDuration = oldDuration * oldspeed / speed;
+
+ // Check that the blank space is long enough for our new duration
+ clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ int blankEnd = trackPlaylist.clip_start(clipIndex) + trackPlaylist.clip_length(clipIndex);
+
+ Mlt::Producer *cut;
+ if (clipIndex + 1 < trackPlaylist.count() && (info.startPos + newDuration).frames(m_fps) > blankEnd) {
+ GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
+ cut = slowprod->cut((int)(info.cropStart.frames(m_fps)), (int)(info.cropStart.frames(m_fps) + maxLength.frames(m_fps) - 1));
+ } else cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)((info.cropStart / speed + newDuration).frames(m_fps) - 1));
+
+ trackPlaylist.insert_at(startPos, *cut, 1);
+ clipIndex = trackPlaylist.get_clip_index_at(startPos);
+ newLength = trackPlaylist.clip_length(clipIndex);
+
mlt_service_unlock(service.get_service());
- kDebug() << "AVFORMAT CLIP!!!:";
}
-
+ if (clipIndex + 1 == trackPlaylist.count()) mltCheckLength();
m_isBlocked = false;
return newLength;
}
to the clip and 0.6 is the speed in percents. The newly created producer will have it's
"id" parameter set to: "slowmotion:parentid:speed", where parentid is the id of the original clip
in the ClipManager list and speed is the current speed */
- int mltChangeClipSpeed(ItemInfo info, double speed, Mlt::Producer *prod);
+ int mltChangeClipSpeed(ItemInfo info, double speed, double oldspeed, Mlt::Producer *prod);
QList <Mlt::Producer *> producersList();