Commit 1e271eb8 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Fix timewarp

parent 5f57fdd8
......@@ -480,12 +480,14 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
std::shared_ptr<Mlt::Producer> warpProducer;
if (m_timewarpProducers.count(clipId) > 0) {
// remove in all cases, we add it unconditionally anyways
m_effectStack->removeService(m_timewarpProducers[clipId]);
if (qFuzzyCompare(m_timewarpProducers[clipId]->get_double("warp_speed"), speed)) {
// the producer we have is good, use it !
warpProducer = m_timewarpProducers[clipId];
} else {
m_timewarpProducers.erase(clipId);
}
// remove in all cases, we add it unconditionally anyways
m_effectStack->removeService(m_timewarpProducers[clipId]);
}
if (!warpProducer) {
QString resource = QString("timewarp:%1:%2").arg(speed).arg(originalProducer()->get("resource"));
......@@ -502,7 +504,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
}
m_timewarpProducers[clipId] = warpProducer;
m_effectStack->addService(m_timewarpProducers[clipId]);
return warpProducer;
return std::shared_ptr<Mlt::Producer>(warpProducer->cut());
}
std::pair<std::shared_ptr<Mlt::Producer>, bool> ProjectClip::giveMasterAndGetTimelineProducer(int clipId, std::shared_ptr<Mlt::Producer> master,
......
......@@ -122,9 +122,9 @@ void ClipModel::deregisterClipToBin()
ClipModel::~ClipModel() {}
bool ClipModel::requestResize(int size, bool right, Fun &undo, Fun &redo, bool logUndo)
{
qDebug() << "++++++++++ PERFORMAING CLIP RESIZE==: "<<size;
QWriteLocker locker(&m_lock);
//qDebug() << "RESIZE CLIP" << m_id << "target size=" << size << "right=" << right << "endless=" << m_endlessResize << "total length" <<
//m_producer->get_length() << "current length" << getPlaytime();
......@@ -136,13 +136,7 @@ bool ClipModel::requestResize(int size, bool right, Fun &undo, Fun &redo, bool l
if (delta == 0) {
return true;
}
int in = m_producer->get_in();
int out = m_producer->get_out();
if (!m_endlessResize && (size <= 0 || size > m_producer->get_length())) {
return false;
}
return requestResize(in, out, oldDuration, delta, right, undo, redo, logUndo);
return requestResize(m_producer->get_in(), m_producer->get_out(), oldDuration, delta, right, undo, redo, logUndo);
}
......@@ -369,7 +363,7 @@ void ClipModel::refreshProducerFromBin()
bool ClipModel::useTimewarpProducer(double speed, int extraSpace, Fun &undo, Fun &redo)
{
if (m_endlessResize) {
if (m_endlessResize || qFuzzyCompare(speed, m_speed)) {
// no timewarp for endless producers
return false;
}
......@@ -378,28 +372,60 @@ bool ClipModel::useTimewarpProducer(double speed, int extraSpace, Fun &undo, Fun
double previousSpeed = getSpeed();
int old_in = getIn();
int old_out = getOut();
int oldDuration = getPlaytime();
int new_in = int(double(old_in) * previousSpeed / speed);
int new_out = int(double(old_out) * previousSpeed / speed);
int delta = oldDuration - (new_out - new_in);
if (extraSpace > 0 && (new_out - old_out >= extraSpace)) {
delta = -extraSpace;
}
int oldDuration = old_out - old_in;
int newIn = old_in * previousSpeed / speed;
auto operation = useTimewarpProducer_lambda(speed);
if (operation()) {
auto reverse = useTimewarpProducer_lambda(previousSpeed);
UPDATE_UNDO_REDO(operation, reverse, local_undo, local_redo);
// timewarp can change the clip out, so we need to
bool res = requestResize(old_in, old_out, oldDuration, delta, true, local_undo, local_redo, true);
if (!res) {
bool undone = local_undo();
Q_ASSERT(undone);
return false;
}
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
Fun newInOperation = [this, newIn]() {
int duration = m_producer->get_playtime() - 1;
m_producer->set_in_and_out(newIn, newIn + duration);
return true;
};
Fun oldInOperation = [this, old_in]() {
int duration = m_producer->get_playtime() - 1;
m_producer->set_in_and_out(old_in, old_in + duration);
return true;
};
int newDuration = int(double(oldDuration) * previousSpeed / speed);
int delta = oldDuration - newDuration;
if (extraSpace > 0 && (newDuration >= extraSpace)) {
newDuration = extraSpace;
}
return false;
auto reverse = useTimewarpProducer_lambda(previousSpeed);
bool res = false;
// We have 2 different cases here to have a working undo. If the speed is slowed (<1), duration will be increased
// So the new out point might be outside current clip. So we perform the producer change, then resize
if (speed < previousSpeed) {
// Update to timewarp producer, duration is longer.
res = operation();
if (res) {
UPDATE_UNDO_REDO(operation, reverse, local_undo, local_redo);
// Adjust length
res = requestResize(old_in, old_out, oldDuration, oldDuration - newDuration, true, local_undo, local_redo, true);
if (res) {
// Set the new in point
newInOperation();
UPDATE_UNDO_REDO(newInOperation, oldInOperation, local_undo, local_redo);
}
}
} else {
// Speed is increased (>1), duration will be shortened
// So we first resize to the new duration, then change the producer
// Resize to shortened length
// Switch to timewarp producer
res = requestResize(old_in, old_out, oldDuration, oldDuration - newDuration, true, local_undo, local_redo, true);
if (res) {
UPDATE_UNDO_REDO(newInOperation, oldInOperation, local_undo, local_redo);
UPDATE_UNDO_REDO(operation, reverse, local_undo, local_redo);
// Update in point
newInOperation();
res = operation();
}
}
if (!res) {
return false;
}
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
}
Fun ClipModel::useTimewarpProducer_lambda(double speed)
......
......@@ -2082,41 +2082,6 @@ bool TimelineModel::checkConsistency()
return true;
}
bool TimelineModel::requestItemResizeToPos(int itemId, int position, bool right)
{
QWriteLocker locker(&m_lock);
Q_ASSERT(isClip(itemId) || isComposition(itemId));
int in, out;
if (isClip(itemId)) {
in = getClipPosition(itemId);
out = in + getClipPlaytime(itemId) - 1;
} else {
in = getCompositionPosition(itemId);
out = in + getCompositionPlaytime(itemId) - 1;
}
int size = 0;
if (!right) {
if (position < out) {
size = out - position;
}
} else {
if (position > in) {
size = position - in;
}
}
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool result = requestItemResize(itemId, size, right, true, undo, redo);
if (result) {
if (isClip(itemId)) {
PUSH_UNDO(undo, redo, i18n("Resize clip"));
} else {
PUSH_UNDO(undo, redo, i18n("Resize composition"));
}
}
return result;
}
void TimelineModel::setTimelineEffectsEnabled(bool enabled)
{
m_timelineEffectsEnabled = enabled;
......@@ -2232,10 +2197,10 @@ bool TimelineModel::requestClipTimeWarp(int clipId, int trackId, int blankSpace,
}
if (success) {
success = getTrackById(trackId)->requestClipInsertion(clipId, oldPos, true, true, local_undo, local_redo);
if (!success) {
local_undo();
return false;
}
}
if (!success) {
local_undo();
return false;
}
PUSH_LAMBDA(local_undo, undo);
PUSH_LAMBDA(local_redo, redo);
......@@ -2269,6 +2234,9 @@ bool TimelineModel::changeItemSpeed(int clipId, int speed)
}
if (result) {
result = requestClipTimeWarp(clipId, trackId, blankSpace, speed / 100.0, undo, redo);
} else {
pCore->displayMessage(i18n("Change speed failed"), ErrorMessage);
undo();
}
} else {
m_allClips[clipId]->useTimewarpProducer(speed, -1, undo, redo);
......
......@@ -372,14 +372,6 @@ public:
@param snap if set to true, the resize order will be coerced to use the snapping grid
*/
Q_INVOKABLE int requestItemResize(int itemId, int size, bool right, bool logUndo = true, int snapDistance = -1, bool allowSingleResize = false);
/* @brief Change the duration of an item (clip or composition)
This action is undoable
Returns true on success. If it fails, nothing is modified.
@param itemId is the ID of the item
@param position is the requested start or end position
@param resizeStart is true if we want to resize clip start, false to resize clip end
*/
bool requestItemResizeToPos(int itemId, int position, bool right);
/* Same function, but accumulates undo and redo and doesn't deal with snapping*/
bool requestItemResize(int itemId, int size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo = false);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment