Compare commits

...

5 Commits

Author SHA1 Message Date
Jean-Baptiste Mardelle
4fc2f242e8 Merge branch 'refactoring_timeline' into refactoring_track_producers 2019-03-11 18:31:10 +01:00
Jean-Baptiste Mardelle
fb9f6c5753 Fix comments in one producer per track branch 2019-03-11 18:30:54 +01:00
Jean-Baptiste Mardelle
b03088c3fe Update to one producer / track feature, use master instance for temporary clips, keep previous logic (1 producer / clip) for timewarp 2019-03-08 10:23:24 +01:00
Jean-Baptiste Mardelle
56060143fe Merge branch 'refactoring_timeline' into refactoring_track_producers 2019-03-08 08:54:17 +01:00
Jean-Baptiste Mardelle
e16d044b4d Use only one producer per track in timeline 2019-03-02 16:56:59 +01:00
10 changed files with 54 additions and 42 deletions

View File

@@ -534,31 +534,35 @@ void ProjectClip::createDisabledMasterProducer()
m_effectStack->addService(m_disabledProducer); m_effectStack->addService(m_disabledProducer);
} }
} }
std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, PlaylistState::ClipState state, double speed)
std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int trackId, int clipId, PlaylistState::ClipState state, double speed)
{ {
if (!m_masterProducer) { if (!m_masterProducer) {
return nullptr; return nullptr;
} }
if (qFuzzyCompare(speed, 1.0)) { if (qFuzzyCompare(speed, 1.0)) {
// we are requesting a normal speed producer // we are requesting a normal speed producer
// We can first cleen the speed producers we have for the current id if (trackId == -1) {
// Temporary copy, return clone of master
return std::shared_ptr<Mlt::Producer>(m_masterProducer->cut());
}
if (m_timewarpProducers.count(clipId) > 0) { if (m_timewarpProducers.count(clipId) > 0) {
m_effectStack->removeService(m_timewarpProducers[clipId]); m_effectStack->removeService(m_timewarpProducers[clipId]);
m_timewarpProducers.erase(clipId); m_timewarpProducers.erase(clipId);
} }
if (state == PlaylistState::AudioOnly) { if (state == PlaylistState::AudioOnly) {
// We need to get an audio producer, if none exists // We need to get an audio producer, if none exists
if (m_audioProducers.count(clipId) == 0) { if (m_audioProducers.count(trackId) == 0) {
m_audioProducers[clipId] = cloneProducer(true); m_audioProducers[trackId] = cloneProducer(true);
m_audioProducers[clipId]->set("set.test_audio", 0); m_audioProducers[trackId]->set("set.test_audio", 0);
m_audioProducers[clipId]->set("set.test_image", 1); m_audioProducers[trackId]->set("set.test_image", 1);
m_effectStack->addService(m_audioProducers[clipId]); m_effectStack->addService(m_audioProducers[trackId]);
} }
return std::shared_ptr<Mlt::Producer>(m_audioProducers[clipId]->cut()); return std::shared_ptr<Mlt::Producer>(m_audioProducers[trackId]->cut());
} }
if (m_audioProducers.count(clipId) > 0) { if (m_audioProducers.count(trackId) > 0) {
m_effectStack->removeService(m_audioProducers[clipId]); m_effectStack->removeService(m_audioProducers[trackId]);
m_audioProducers.erase(clipId); m_audioProducers.erase(trackId);
} }
if (state == PlaylistState::VideoOnly) { if (state == PlaylistState::VideoOnly) {
// we return the video producer // we return the video producer
@@ -567,18 +571,18 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
int duration = m_masterProducer->time_to_frames(m_masterProducer->get("kdenlive:duration")); int duration = m_masterProducer->time_to_frames(m_masterProducer->get("kdenlive:duration"));
return std::shared_ptr<Mlt::Producer>(m_masterProducer->cut(-1, duration > 0 ? duration : -1)); return std::shared_ptr<Mlt::Producer>(m_masterProducer->cut(-1, duration > 0 ? duration : -1));
} }
if (m_videoProducers.count(clipId) == 0) { if (m_videoProducers.count(trackId) == 0) {
m_videoProducers[clipId] = cloneProducer(true); m_videoProducers[trackId] = cloneProducer(true);
m_videoProducers[clipId]->set("set.test_audio", 1); m_videoProducers[trackId]->set("set.test_audio", 1);
m_videoProducers[clipId]->set("set.test_image", 0); m_videoProducers[trackId]->set("set.test_image", 0);
m_effectStack->addService(m_videoProducers[clipId]); m_effectStack->addService(m_videoProducers[trackId]);
} }
int duration = m_masterProducer->time_to_frames(m_masterProducer->get("kdenlive:duration")); int duration = m_masterProducer->time_to_frames(m_masterProducer->get("kdenlive:duration"));
return std::shared_ptr<Mlt::Producer>(m_videoProducers[clipId]->cut(-1, duration > 0 ? duration : -1)); return std::shared_ptr<Mlt::Producer>(m_videoProducers[trackId]->cut(-1, duration > 0 ? duration : -1));
} }
if (m_videoProducers.count(clipId) > 0) { if (m_videoProducers.count(trackId) > 0) {
m_effectStack->removeService(m_videoProducers[clipId]); m_effectStack->removeService(m_videoProducers[trackId]);
m_videoProducers.erase(clipId); m_videoProducers.erase(trackId);
} }
Q_ASSERT(state == PlaylistState::Disabled); Q_ASSERT(state == PlaylistState::Disabled);
createDisabledMasterProducer(); createDisabledMasterProducer();
@@ -586,16 +590,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int clipId, Play
return std::shared_ptr<Mlt::Producer>(m_disabledProducer->cut(-1, duration > 0 ? duration : -1)); return std::shared_ptr<Mlt::Producer>(m_disabledProducer->cut(-1, duration > 0 ? duration : -1));
} }
// in that case, we need to create a warp producer, if we don't have one // For timewarp clips, we keep one separate producer for each clip.
if (m_audioProducers.count(clipId) > 0) {
m_effectStack->removeService(m_audioProducers[clipId]);
m_audioProducers.erase(clipId);
}
if (m_videoProducers.count(clipId) > 0) {
m_effectStack->removeService(m_videoProducers[clipId]);
m_videoProducers.erase(clipId);
}
std::shared_ptr<Mlt::Producer> warpProducer; std::shared_ptr<Mlt::Producer> warpProducer;
if (m_timewarpProducers.count(clipId) > 0) { if (m_timewarpProducers.count(clipId) > 0) {
// remove in all cases, we add it unconditionally anyways // remove in all cases, we add it unconditionally anyways
@@ -656,7 +651,7 @@ std::pair<std::shared_ptr<Mlt::Producer>, bool> ProjectClip::giveMasterAndGetTim
if (state != PlaylistState::Disabled || timeWarp) { if (state != PlaylistState::Disabled || timeWarp) {
// In that case, we must create copies // In that case, we must create copies
std::shared_ptr<Mlt::Producer> prod(getTimelineProducer(clipId, state, speed)->cut(in, out)); std::shared_ptr<Mlt::Producer> prod(getTimelineProducer(-1, clipId, state, speed)->cut(in, out));
return {prod, false}; return {prod, false};
} }
if (state == PlaylistState::Disabled && !m_disabledProducer) { if (state == PlaylistState::Disabled && !m_disabledProducer) {
@@ -704,7 +699,7 @@ std::pair<std::shared_ptr<Mlt::Producer>, bool> ProjectClip::giveMasterAndGetTim
if (QString::fromUtf8(master->parent().get("mlt_service")) == QLatin1String("timewarp")) { if (QString::fromUtf8(master->parent().get("mlt_service")) == QLatin1String("timewarp")) {
speed = master->get_double("warp_speed"); speed = master->get_double("warp_speed");
} }
return {getTimelineProducer(clipId, state, speed), false}; return {getTimelineProducer(-1, clipId, state, speed), false};
} }
// we have a problem // we have a problem
return {std::shared_ptr<Mlt::Producer>(ClipController::mediaUnavailable->cut()), false}; return {std::shared_ptr<Mlt::Producer>(ClipController::mediaUnavailable->cut()), false};

View File

@@ -202,7 +202,7 @@ public:
/** @brief This function returns a cut to the master producer associated to the timeline clip with given ID. /** @brief This function returns a cut to the master producer associated to the timeline clip with given ID.
Each clip must have a different master producer (see comment of the class) Each clip must have a different master producer (see comment of the class)
*/ */
std::shared_ptr<Mlt::Producer> getTimelineProducer(int clipId, PlaylistState::ClipState st, double speed = 1.0); std::shared_ptr<Mlt::Producer> getTimelineProducer(int trackId, int clipId, PlaylistState::ClipState st, double speed = 1.0);
/* @brief This function should only be used at loading. It takes a producer that was read from mlt, and checks whether the master producer is already in /* @brief This function should only be used at loading. It takes a producer that was read from mlt, and checks whether the master producer is already in
use. If yes, then we must create a new one, because of the mixing bug. In any case, we return a cut of the master that can be used in the timeline The use. If yes, then we must create a new one, because of the mixing bug. In any case, we return a cut of the master that can be used in the timeline The

View File

@@ -75,7 +75,7 @@ int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QSt
videoAudio.first = videoAudio.first && binClip->hasVideo(); videoAudio.first = videoAudio.first && binClip->hasVideo();
videoAudio.second = videoAudio.second && binClip->hasAudio(); videoAudio.second = videoAudio.second && binClip->hasAudio();
state = stateFromBool(videoAudio); state = stateFromBool(videoAudio);
std::shared_ptr<Mlt::Producer> cutProducer = binClip->getTimelineProducer(id, state, speed); std::shared_ptr<Mlt::Producer> cutProducer = binClip->getTimelineProducer(-1, id, state, speed);
std::shared_ptr<ClipModel> clip(new ClipModel(parent, cutProducer, binClipId, id, state, speed)); std::shared_ptr<ClipModel> clip(new ClipModel(parent, cutProducer, binClipId, id, state, speed));
clip->setClipState_lambda(state)(); clip->setClipState_lambda(state)();
parent->registerClip(clip); parent->registerClip(clip);
@@ -379,7 +379,7 @@ void ClipModel::refreshProducerFromBin(PlaylistState::ClipState state, double sp
qDebug() << "changing speed" << in << out << m_speed; qDebug() << "changing speed" << in << out << m_speed;
} }
std::shared_ptr<ProjectClip> binClip = pCore->projectItemModel()->getClipByBinID(m_binClipId); std::shared_ptr<ProjectClip> binClip = pCore->projectItemModel()->getClipByBinID(m_binClipId);
std::shared_ptr<Mlt::Producer> binProducer = binClip->getTimelineProducer(m_id, state, m_speed); std::shared_ptr<Mlt::Producer> binProducer = binClip->getTimelineProducer(m_currentTrackId, m_id, state, m_speed);
m_producer = std::move(binProducer); m_producer = std::move(binProducer);
m_producer->set_in_and_out(in, out); m_producer->set_in_and_out(in, out);
// replant effect stack in updated service // replant effect stack in updated service
@@ -510,6 +510,17 @@ void ClipModel::setShowKeyframes(bool show)
service()->set("kdenlive:hide_keyframes", (int)!show); service()->set("kdenlive:hide_keyframes", (int)!show);
} }
void ClipModel::setCurrentTrackId(int tid, bool finalMove)
{
if (tid == m_currentTrackId) {
return;
}
MoveableItem::setCurrentTrackId(tid, finalMove);
if (finalMove) {
refreshProducerFromBin(m_currentState);
}
}
Fun ClipModel::setClipState_lambda(PlaylistState::ClipState state) Fun ClipModel::setClipState_lambda(PlaylistState::ClipState state)
{ {
QWriteLocker locker(&m_lock); QWriteLocker locker(&m_lock);

View File

@@ -157,6 +157,8 @@ protected:
*/ */
bool requestResize(int size, bool right, Fun &undo, Fun &redo, bool logUndo = true) override; bool requestResize(int size, bool right, Fun &undo, Fun &redo, bool logUndo = true) override;
void setCurrentTrackId(int tid, bool finalMove = true) override;
/* @brief This function change the global (timeline-wise) enabled state of the effects /* @brief This function change the global (timeline-wise) enabled state of the effects
*/ */
void setTimelineEffectsEnabled(bool enabled); void setTimelineEffectsEnabled(bool enabled);

View File

@@ -244,8 +244,9 @@ void CompositionModel::setInOut(int in, int out)
setPosition(in); setPosition(in);
} }
void CompositionModel::setCurrentTrackId(int tid) void CompositionModel::setCurrentTrackId(int tid, bool finalMove)
{ {
Q_UNUSED(finalMove);
MoveableItem::setCurrentTrackId(tid); MoveableItem::setCurrentTrackId(tid);
} }

View File

@@ -99,7 +99,7 @@ public:
protected: protected:
Mlt::Transition *service() const override; Mlt::Transition *service() const override;
void setInOut(int in, int out) override; void setInOut(int in, int out) override;
void setCurrentTrackId(int tid) override; void setCurrentTrackId(int tid, bool finalMove = true) override;
int getOut() const override; int getOut() const override;
int getIn() const override; int getIn() const override;

View File

@@ -105,7 +105,7 @@ protected:
If you wish to actually change the track the item, use the slot in the timeline If you wish to actually change the track the item, use the slot in the timeline
slot. slot.
*/ */
virtual void setCurrentTrackId(int tid); virtual void setCurrentTrackId(int tid, bool finalMove = true);
/* Set in and out of service */ /* Set in and out of service */
virtual void setInOut(int in, int out); virtual void setInOut(int in, int out);

View File

@@ -81,8 +81,9 @@ template <typename Service> void MoveableItem<Service>::setPosition(int pos)
m_position = pos; m_position = pos;
} }
template <typename Service> void MoveableItem<Service>::setCurrentTrackId(int tid) template <typename Service> void MoveableItem<Service>::setCurrentTrackId(int tid, bool finalMove)
{ {
Q_UNUSED(finalMove);
QWriteLocker locker(&m_lock); QWriteLocker locker(&m_lock);
m_currentTrackId = tid; m_currentTrackId = tid;
} }

View File

@@ -2682,9 +2682,9 @@ void TimelineModel::requestClipReload(int clipId)
bool refreshView = oldOut > (int)binClip->frameDuration(); bool refreshView = oldOut > (int)binClip->frameDuration();
if (old_trackId != -1) { if (old_trackId != -1) {
getTrackById(old_trackId)->requestClipDeletion(clipId, refreshView, true, local_undo, local_redo); getTrackById(old_trackId)->requestClipDeletion(clipId, refreshView, true, local_undo, local_redo);
} }
m_allClips[clipId]->refreshProducerFromBin();
if (old_trackId != -1) { if (old_trackId != -1) {
m_allClips[clipId]->refreshProducerFromBin();
getTrackById(old_trackId)->requestClipInsertion(clipId, oldPos, refreshView, true, local_undo, local_redo); getTrackById(old_trackId)->requestClipInsertion(clipId, oldPos, refreshView, true, local_undo, local_redo);
} }
} }

View File

@@ -134,7 +134,7 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
m_allClips[clip->getId()] = clip; // store clip m_allClips[clip->getId()] = clip; // store clip
// update clip position and track // update clip position and track
clip->setPosition(position); clip->setPosition(position);
clip->setCurrentTrackId(m_id); clip->setCurrentTrackId(m_id, finalMove);
int new_in = clip->getPosition(); int new_in = clip->getPosition();
int new_out = new_in + clip->getPlaytime(); int new_out = new_in + clip->getPlaytime();
ptr->m_snaps->addPoint(new_in); ptr->m_snaps->addPoint(new_in);
@@ -164,6 +164,7 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
// Lock MLT playlist so that we don't end up with an invalid frame being displayed // Lock MLT playlist so that we don't end up with an invalid frame being displayed
m_playlists[0].lock(); m_playlists[0].lock();
std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId); std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId);
clip->setCurrentTrackId(m_id, finalMove);
int index = m_playlists[0].insert_at(position, *clip, 1); int index = m_playlists[0].insert_at(position, *clip, 1);
m_playlists[0].consolidate_blanks(); m_playlists[0].consolidate_blanks();
m_playlists[0].unlock(); m_playlists[0].unlock();
@@ -189,6 +190,7 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
// Lock MLT playlist so that we don't end up with an invalid frame being displayed // Lock MLT playlist so that we don't end up with an invalid frame being displayed
m_playlists[0].lock(); m_playlists[0].lock();
std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId); std::shared_ptr<ClipModel> clip = ptr->getClipPtr(clipId);
clip->setCurrentTrackId(m_id);
int index = m_playlists[0].insert_at(position, *clip, 1); int index = m_playlists[0].insert_at(position, *clip, 1);
m_playlists[0].consolidate_blanks(); m_playlists[0].consolidate_blanks();
m_playlists[0].unlock(); m_playlists[0].unlock();