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

Ensure jobs for timeline clips/tracks are properly canceled when the...

Ensure jobs for timeline clips/tracks are properly canceled when the clip/track is deleted, fix crash on audio align deleted clip
parent 48a34b5f
Pipeline #46262 canceled with stage
......@@ -115,6 +115,7 @@ ButtonParamWidget::ButtonParamWidget(std::shared_ptr<AssetParameterModel> model,
} else if (owner.first == ObjectType::TimelineTrack || owner.first == ObjectType::Master) {
in = 0;
out = pCore->getItemDuration(owner);
binId = QStringLiteral("-1");
}
std::unordered_map<QString, QVariant> fParams;
std::unordered_map<QString, QString> fData;
......
......@@ -393,6 +393,7 @@ QDomDocument KdenliveDoc::createEmptyDocument(const QList<TrackInfo> &tracks)
tr.set("b_track", i);
tr.set("always_active", 1);
tr.set("sum", 1);
tr.set("accepts_blanks", 1);
tr.set("internal_added", 237);
field->plant_transition(tr, 0, i);
}
......
......@@ -22,12 +22,13 @@
#include "doc/kdenlivedoc.h"
#include "kdenlivesettings.h"
AbstractClipJob::AbstractClipJob(JOBTYPE type, QString id, QObject *parent)
AbstractClipJob::AbstractClipJob(JOBTYPE type, QString id, const ObjectId &owner, QObject *parent)
: QObject(parent)
, m_clipId(std::move(id))
, m_jobType(type)
, m_inPoint(-1)
, m_outPoint(-1)
, m_owner(owner)
{
if (m_clipId.count(QStringLiteral("/")) == 2) {
m_inPoint = m_clipId.section(QLatin1Char('/'), 1, 1).toInt();
......@@ -64,3 +65,8 @@ AbstractClipJob::JOBTYPE AbstractClipJob::jobType() const
return m_jobType;
}
const ObjectId AbstractClipJob::owner()
{
return m_owner;
}
......@@ -53,7 +53,7 @@ public:
SPEEDJOB = 10,
CACHEJOB = 11
};
AbstractClipJob(JOBTYPE type, QString id, QObject *parent = nullptr);
AbstractClipJob(JOBTYPE type, QString id, const ObjectId &owner, QObject *parent = nullptr);
~AbstractClipJob() override;
template <typename T, typename... Args> static std::shared_ptr<T> make(const QString &binId, Args &&... args)
......@@ -82,6 +82,9 @@ public:
/* @brief return the type of this job */
JOBTYPE jobType() const;
/* @brief return the owner of this job */
const ObjectId owner();
protected:
QString m_clipId;
QString m_errorMessage;
......@@ -90,6 +93,7 @@ protected:
JOBTYPE m_jobType;
int m_inPoint;
int m_outPoint;
const ObjectId m_owner;
bool m_resultConsumed{false};
signals:
......
......@@ -38,7 +38,7 @@
#include <mlt++/MltProducer.h>
AudioThumbJob::AudioThumbJob(const QString &binId)
: AbstractClipJob(AUDIOTHUMBJOB, binId)
: AbstractClipJob(AUDIOTHUMBJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_ffmpegProcess(nullptr)
{
}
......
......@@ -38,7 +38,7 @@
#include <QtConcurrent>
CacheJob::CacheJob(const QString &binId, int thumbsCount, int inPoint, int outPoint)
: AbstractClipJob(CACHEJOB, binId)
: AbstractClipJob(CACHEJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_fullWidth(qFuzzyCompare(pCore->getCurrentSar(), 1.0) ? 0 : pCore->thumbProfile()->height() * pCore->getCurrentDar() + 0.5)
, m_semaphore(1)
, m_done(false)
......
......@@ -41,7 +41,7 @@
#include <QPointer>
CutClipJob::CutClipJob(const QString &binId, const QString sourcePath, GenTime inTime, GenTime outTime, const QString destPath, QStringList encodingParams)
: AbstractClipJob(CUTJOB, binId)
: AbstractClipJob(CUTJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_sourceUrl(sourcePath)
, m_destUrl(destPath)
, m_done(false)
......
......@@ -32,14 +32,13 @@
#include <klocalizedstring.h>
FilterClipJob::FilterClipJob(const QString &binId, const ObjectId &owner, std::weak_ptr<AssetParameterModel> model, const QString &assetId, int in, int out, const QString &filterName, std::unordered_map<QString, QVariant> filterParams, std::unordered_map<QString, QString> filterData, const QStringList consumerArgs)
: MeltJob(binId, FILTERCLIPJOB, false, in, out)
: MeltJob(binId, owner, FILTERCLIPJOB, false, in, out)
, m_model(model)
, m_filterName(filterName)
, m_assetId(assetId)
, m_filterParams(std::move(filterParams))
, m_filterData(std::move(filterData))
, m_consumerArgs(consumerArgs)
, m_owner(owner)
{
m_timelineClipId = -1;
if (owner.first == ObjectType::TimelineClip) {
......
......@@ -57,7 +57,6 @@ protected:
std::unordered_map<QString, QVariant> m_filterParams;
std::unordered_map<QString, QString> m_filterData;
QStringList m_consumerArgs;
ObjectId m_owner;
};
#endif
......@@ -181,16 +181,23 @@ void JobManager::prepareJobs(const QList<ProjectClip *> &clips, double fps, Abst
}
*/
void JobManager::slotDiscardClipJobs(const QString &binId)
void JobManager::slotDiscardClipJobs(const QString &binId, const ObjectId &owner)
{
QWriteLocker locker(&m_lock);
if (m_jobsByClip.count(binId) > 0) {
for (int jobId : m_jobsByClip.at(binId)) {
Q_ASSERT(m_jobs.count(jobId) > 0);
bool abortJob = true;
for (const std::shared_ptr<AbstractClipJob> &job : m_jobs.at(jobId)->m_job) {
if (owner.first != ObjectType::NoItem && job->owner() != owner) {
abortJob = false;
break;
}
emit job->jobCanceled();
}
m_jobs[jobId]->m_future.cancel();
if (abortJob) {
m_jobs[jobId]->m_future.cancel();
}
}
}
}
......
......@@ -143,7 +143,7 @@ protected:
public slots:
/** @brief Discard jobs running on a given clip */
void slotDiscardClipJobs(const QString &binId);
void slotDiscardClipJobs(const QString &binId, const ObjectId &owner = {ObjectType::NoItem,-1});
/** @brief Discard all running jobs. */
void slotCancelJobs();
/** @brief Discard all pending jobs. */
......
......@@ -43,7 +43,7 @@
#include <mlt++/MltProfile.h>
LoadJob::LoadJob(const QString &binId, const QDomElement &xml, const std::function<void()> &readyCallBack)
: AbstractClipJob(LOADJOB, binId)
: AbstractClipJob(LOADJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_xml(xml)
, m_readyCallBack(readyCallBack)
{
......
......@@ -37,8 +37,8 @@ static void consumer_frame_render(mlt_consumer, MeltJob *self, mlt_frame frame_p
emit self->jobProgress((int)(100 * mlt_frame_get_position(frame_ptr) / self->length));
}
MeltJob::MeltJob(const QString &binId, JOBTYPE type, bool useProducerProfile, int in, int out)
: AbstractClipJob(type, binId)
MeltJob::MeltJob(const QString &binId, const ObjectId &owner, JOBTYPE type, bool useProducerProfile, int in, int out)
: AbstractClipJob(type, binId, owner)
, m_useProducerProfile(useProducerProfile)
, m_in(in)
, m_out(out)
......@@ -208,6 +208,7 @@ bool MeltJob::startJob()
if (m_filter) {
m_producer->attach(*m_filter.get());
}
qDebug()<<"=== FILTER READY TO PROCESS; LENGTH: "<<length;
m_showFrameEvent.reset(m_consumer->listen("consumer-frame-show", this, (mlt_listener)consumer_frame_render));
connect(this, &MeltJob::jobCanceled, [&] () {
m_showFrameEvent.reset();
......
......@@ -50,7 +50,7 @@ public:
if useProducerProfile == true, the profile used will be the one of the producer
in and out represent the portion of the clip we deal with. Leave to -1 for default (whole clip)
*/
MeltJob(const QString &binId, JOBTYPE type, bool useProducerProfile = false, int in = -1, int out = -1);
MeltJob(const QString &binId, const ObjectId &owner, JOBTYPE type, bool useProducerProfile = false, int in = -1, int out = -1);
bool startJob() override;
int length;
......
......@@ -35,7 +35,7 @@
#include <klocalizedstring.h>
ProxyJob::ProxyJob(const QString &binId)
: AbstractClipJob(PROXYJOB, binId)
: AbstractClipJob(PROXYJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_jobDuration(0)
, m_isFfmpegJob(true)
, m_jobProcess(nullptr)
......
......@@ -38,7 +38,7 @@
#include <mlt++/Mlt.h>
SceneSplitJob::SceneSplitJob(const QString &binId, bool subClips, int markersType, int minInterval)
: MeltJob(binId, STABILIZEJOB, true, -1, -1)
: MeltJob(binId, {ObjectType::BinClip, binId.toInt()}, STABILIZEJOB, true, -1, -1)
, m_subClips(subClips)
, m_markersType(markersType)
, m_minInterval(minInterval)
......
......@@ -44,7 +44,7 @@
#include <mlt++/Mlt.h>
SpeedJob::SpeedJob(const QString &binId, double speed, bool warp_pitch, QString destUrl)
: MeltJob(binId, SPEEDJOB, false, -1, -1)
: MeltJob(binId, {ObjectType::BinClip, binId.toInt()}, SPEEDJOB, false, -1, -1)
, m_speed(speed)
, m_warp_pitch(warp_pitch)
, m_destUrl(std::move(destUrl))
......
......@@ -36,7 +36,7 @@
#include <memory>
#include <mlt++/Mlt.h>
StabilizeJob::StabilizeJob(const QString &binId, const QString &filterName, QString destUrl, std::unordered_map<QString, QString> filterParams)
: MeltJob(binId, STABILIZEJOB, false, -1, -1)
: MeltJob(binId, {ObjectType::BinClip, binId.toInt()}, STABILIZEJOB, false, -1, -1)
, m_filterName(filterName)
, m_destUrl(std::move(destUrl))
, m_filterParams(std::move(filterParams))
......
......@@ -33,7 +33,7 @@
#include <mlt++/MltProducer.h>
ThumbJob::ThumbJob(const QString &binId, int frameNumber, bool persistent, bool reloadAllThumbs)
: AbstractClipJob(THUMBJOB, binId)
: AbstractClipJob(THUMBJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_frameNumber(frameNumber)
, m_imageHeight(pCore->thumbProfile()->height())
, m_imageWidth(pCore->thumbProfile()->width())
......
......@@ -35,7 +35,7 @@
#include <klocalizedstring.h>
TranscodeJob::TranscodeJob(const QString &binId, QString params)
: AbstractClipJob(TRANSCODEJOB, binId)
: AbstractClipJob(TRANSCODEJOB, binId, {ObjectType::BinClip, binId.toInt()})
, m_jobDuration(0)
, m_isFfmpegJob(true)
, m_jobProcess(nullptr)
......
......@@ -1219,6 +1219,7 @@ void TimelineFunctions::saveTimelineSelection(const std::shared_ptr<TimelineItem
Mlt::Transition t(*newTractor.profile(), isAudio ? "mix" : composite.toUtf8().constData());
if (isAudio) {
t.set("sum", 1);
t.set("accepts_blanks", 1);
}
t.set("always_active", 1);
t.set("internal_added", 237);
......
......@@ -672,6 +672,7 @@ void TimelineItemModel::buildTrackCompositing(bool rebuild)
std::unique_ptr<Mlt::Transition> transition = TransitionsRepository::get()->getTransition(QStringLiteral("mix"));
transition->set("internal_added", 237);
transition->set("always_active", 1);
transition->set("accepts_blanks", 1);
transition->set("sum", 1);
transition->set_tracks(0, trackPos);
field->plant_transition(*transition.get(), 0, trackPos);
......
......@@ -30,6 +30,7 @@
#include "effects/effectsrepository.hpp"
#include "bin/model/subtitlemodel.hpp"
#include "effects/effectstack/model/effectstackmodel.hpp"
#include "jobs/jobmanager.h"
#include "groupsmodel.hpp"
#include "kdenlivesettings.h"
#include "logger.hpp"
......@@ -3435,6 +3436,9 @@ bool TimelineModel::requestTrackDeletion(int trackId, Fun &undo, Fun &redo)
pCore->displayMessage(i18n("Cannot delete last track in timeline"), InformationMessage, 500);
return false;
}
// Discard running jobs
pCore->jobManager()->slotDiscardClipJobs(QStringLiteral("-1"), {ObjectType::TimelineTrack,trackId});
std::vector<int> clips_to_delete;
for (const auto &it : getTrackById(trackId)->m_allClips) {
clips_to_delete.push_back(it.first);
......
......@@ -28,6 +28,7 @@
#include "kdenlivesettings.h"
#include "logger.hpp"
#include "snapmodel.hpp"
#include "jobs/jobmanager.h"
#include "timelinemodel.hpp"
#include <QDebug>
#include <QModelIndex>
......@@ -430,6 +431,9 @@ bool TrackModel::requestClipDeletion(int clipId, bool updateView, bool finalMove
int old_position = old_clip->getPosition();
// qDebug() << "/// REQUESTOING CLIP DELETION_: " << updateView;
int duration = trackDuration();
if (finalDeletion) {
pCore->jobManager()->slotDiscardClipJobs(m_allClips[clipId]->binId(), {ObjectType::TimelineClip,clipId});
}
auto operation = requestClipDeletion_lambda(clipId, updateView, finalMove, groupMove, finalDeletion);
if (operation()) {
if (finalMove && duration != trackDuration()) {
......
......@@ -2489,6 +2489,9 @@ void TimelineController::setAudioRef(int clipId)
if (!result) {
pCore->displayMessage(i18n("Cannot move clip to frame %1.", (pos + shift)), InformationMessage, 500);
}
} else {
// Clip was deleted, discard audio reference
m_audioRef = -1;
}
});
connect(m_audioCorrelator.get(), &AudioCorrelation::displayMessage, pCore.get(), &Core::displayMessage);
......@@ -2504,7 +2507,7 @@ void TimelineController::alignAudio(int clipId)
return;
}
}
if (m_audioRef == -1 || m_audioRef == clipId) {
if (m_audioRef == -1 || m_audioRef == clipId || !m_model->isClip(m_audioRef)) {
pCore->displayMessage(i18n("Set audio reference before attempting to align"), InformationMessage, 500);
return;
}
......
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