Commit 7c2ae67e authored by Nicolas Carion's avatar Nicolas Carion

fix timewarp and workaround Mlt's weird rounding behaviour

parent e64fca72
......@@ -487,6 +487,10 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
QString resource = QString("timewarp:%1:%2").arg(locale.toString(speed)).arg(originalProducer()->get("resource"));
warpProducer.reset(new Mlt::Producer(*originalProducer()->profile(), resource.toUtf8().constData()));
qDebug() << "new producer!";
qDebug() << "warp LENGTH before" << warpProducer->get_length();
int original_length = originalProducer()->get_length();
// this is a workaround to cope with Mlt erroneous rounding
warpProducer->set("length", double(original_length) / speed);
}
qDebug() << "warp LENGTH" << warpProducer->get_length();
......
......@@ -349,6 +349,8 @@ void ClipModel::refreshProducerFromBin(PlaylistState::ClipState state, double sp
if (!qFuzzyCompare(speed, m_speed) && speed != 0.) {
in = in * m_speed / speed;
out = in + getPlaytime() - 1;
// prevent going out of the clip's range
out = std::min(out, int(double(m_producer->get_length()) * m_speed / speed) - 1);
m_speed = speed;
qDebug() << "changing speed" << in << out << m_speed;
}
......@@ -383,8 +385,20 @@ bool ClipModel::useTimewarpProducer(double speed, int extraSpace, Fun &undo, Fun
double previousSpeed = getSpeed();
int oldDuration = getPlaytime();
int newDuration = int(double(oldDuration) * previousSpeed / speed);
int oldOut = getOut();
int oldIn = getIn();
auto operation = useTimewarpProducer_lambda(speed);
auto reverse = useTimewarpProducer_lambda(previousSpeed);
if (oldOut >= newDuration) {
// in that case, we are going to shrink the clip when changing the producer. We must undo that when reloading the old producer
reverse = [reverse, oldIn, oldOut, this]() {
bool res = reverse();
if (res) {
setInOut(oldIn, oldOut);
}
return res;
};
}
if (operation()) {
UPDATE_UNDO_REDO(operation, reverse, local_undo, local_redo);
bool res = requestResize(newDuration, true, local_undo, local_redo, true);
......@@ -395,6 +409,7 @@ bool ClipModel::useTimewarpProducer(double speed, int extraSpace, Fun &undo, Fun
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
}
qDebug() << "tw: operation fail";
return false;
}
......
......@@ -3,7 +3,6 @@
using namespace fakeit;
Mlt::Profile profile_timewarp;
TEST_CASE("Test of timewarping", "[Timewarp]")
{
auto binModel = pCore->projectItemModel();
......@@ -43,7 +42,8 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
timeline->m_allClips[cid2]->m_endlessResize = false;
timeline->m_allClips[cid3]->m_endlessResize = false;
SECTION("Timewarping orphan clip") {
SECTION("Timewarping orphan clip")
{
int originalDuration = timeline->getClipPlaytime(cid3);
REQUIRE(timeline->checkConsistency());
REQUIRE(timeline->getClipTrackId(cid3) == -1);
......@@ -72,17 +72,21 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
REQUIRE(timeline->getClipSpeed(cid3) == 0.1);
REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration / 0.1);
std::function<bool(void)> undo2 = []() { return true; };
std::function<bool(void)> redo2 = []() { return true; };
REQUIRE(timeline->requestClipTimeWarp(cid3, 100000, 1.2, undo2, redo2));
CHECK_UPDATE(TimelineModel::SpeedRole);
REQUIRE(timeline->getClipSpeed(cid3) == 1.2);
REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration / 1.2);
REQUIRE(timeline->getClipPlaytime(cid3) == int(originalDuration / 1.2));
undo2();
CHECK_UPDATE(TimelineModel::SpeedRole);
REQUIRE(timeline->getClipSpeed(cid3) == 0.1);
REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration / 0.1);
undo();
CHECK_UPDATE(TimelineModel::SpeedRole);
REQUIRE(timeline->getClipSpeed(cid3) == 1.);
REQUIRE(timeline->getClipPlaytime(cid3) == originalDuration);
......@@ -91,12 +95,13 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
int curLength = timeline->getClipPlaytime(cid3);
// This is the limit, should work
REQUIRE(timeline->requestClipTimeWarp(cid3, 100000, curLength, undo2, redo2));
REQUIRE(timeline->requestClipTimeWarp(cid3, 100000, double(curLength), undo2, redo2));
CHECK_UPDATE(TimelineModel::SpeedRole);
REQUIRE(timeline->getClipSpeed(cid3) == curLength);
REQUIRE(timeline->getClipSpeed(cid3) == double(curLength));
REQUIRE(timeline->getClipPlaytime(cid3) == 1);
REQUIRE_FALSE(true);
// This is the higher than the limit, should not work
REQUIRE_FALSE(timeline->requestClipTimeWarp(cid3, 100000, double(curLength) + 0.1, undo2, redo2));
}
}
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