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

Start deprecating loadjob in favor of QRunnable cliploadtask

parent b392b15f
......@@ -32,8 +32,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "jobs/audiothumbjob.hpp"
#include "jobs/transcodeclipjob.h"
#include "jobs/jobmanager.h"
#include "jobs/loadjob.hpp"
#include "jobs/thumbjob.hpp"
#include "jobs/cliploadtask.h"
#include "kdenlive_debug.h"
#include "kdenlivesettings.h"
#include "mainwindow.h"
......@@ -4054,11 +4054,12 @@ void Bin::reloadAllProducers(bool reloadThumbs)
pCore->jobManager()->slotDiscardClipJobs(clip->clipId());
clip->discardAudioThumb();
// We need to set a temporary id before all outdated producers are replaced;
int jobId = pCore->jobManager()->startJob<LoadJob>({clip->clipId()}, -1, QString(), xml);
//int jobId = pCore->jobManager()->startJob<LoadJob>({clip->clipId()}, -1, QString(), xml);
ClipLoadTask::start(clip->clipId(), xml, false, this);
if (reloadThumbs) {
ThumbnailCache::get()->invalidateThumbsForClip(clip->clipId());
}
pCore->jobManager()->startJob<ThumbJob>({clip->clipId()}, jobId, QString(), -1, true, true);
//pCore->jobManager()->startJob<ThumbJob>({clip->clipId()}, jobId, QString(), -1, true, true);
}
}
}
......@@ -4233,7 +4234,7 @@ void Bin::adjustProjectProfileToItem()
auto clip = std::static_pointer_cast<ProjectClip>(item);
if (clip) {
QDomDocument doc;
LoadJob::checkProfile(clip->clipId(), clip->toXml(doc, false), clip->originalProducer());
ClipLoadTask::checkProfile(clip->clipId(), clip->toXml(doc, false), clip->originalProducer());
}
}
}
......
......@@ -218,7 +218,7 @@ const QString ClipCreator::createClipsFromList(const QList<QUrl> &list, bool che
Fun &undo, Fun &redo, bool topLevel)
{
QString createdItem;
QScopedPointer<QProgressDialog> progressDialog;
/*QScopedPointer<QProgressDialog> progressDialog;
if (topLevel) {
progressDialog.reset(new QProgressDialog(pCore->window()));
progressDialog->setWindowTitle(i18n("Loading clips"));
......@@ -228,10 +228,11 @@ const QString ClipCreator::createClipsFromList(const QList<QUrl> &list, bool che
progressDialog->show();
progressDialog->repaint();
qApp->processEvents();
}
}*/
qDebug() << "/////////// creatclipsfromlist" << list << checkRemovable << parentFolder;
bool created = false;
QMimeDatabase db;
bool removableProject = checkRemovable ? isOnRemovableDevice(pCore->currentDoc()->projectDataFolder()) : false;
for (const QUrl &file : list) {
if (!QFile::exists(file.toLocalFile())) {
continue;
......@@ -303,7 +304,7 @@ const QString ClipCreator::createClipsFromList(const QList<QUrl> &list, bool che
}
} else {
// file is not a directory
if (checkRemovable && isOnRemovableDevice(file) && !isOnRemovableDevice(pCore->currentDoc()->projectDataFolder())) {
if (checkRemovable && isOnRemovableDevice(file) && !removableProject) {
int answer = KMessageBox::warningContinueCancel(
QApplication::activeWindow(),
i18n("Clip <b>%1</b><br /> is on a removable device, will not be available when device is unplugged or mounted at a different position.\nYou "
......@@ -318,6 +319,7 @@ const QString ClipCreator::createClipsFromList(const QList<QUrl> &list, bool che
createdItem = clipId;
}
}
//qApp->processEvents();
}
qDebug() << "/////////// creatclipsfromlist return" << created;
return createdItem == QLatin1String("-1") ? QString() : createdItem;
......
......@@ -27,11 +27,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "doc/kdenlivedoc.h"
#include "doc/kthumb.h"
#include "effects/effectstack/model/effectstackmodel.hpp"
#include "jobs/audiothumbjob.hpp"
#include "jobs/jobmanager.h"
#include "jobs/loadjob.hpp"
#include "jobs/audiolevelstask.h"
#include "jobs/thumbjob.hpp"
#include "jobs/cliploadtask.h"
#include "jobs/cachejob.hpp"
#include "kdenlivesettings.h"
#include "lib/audio/audioStreamInfo.h"
......@@ -122,6 +120,7 @@ ProjectClip::ProjectClip(const QString &id, const QIcon &thumb, const std::share
AbstractProjectItem::setRating(uint(getProducerIntProperty(QStringLiteral("kdenlive:rating"))));
connectEffectStack();
if (m_clipStatus == FileStatus::StatusProxy || m_clipStatus == FileStatus::StatusReady || m_clipStatus == FileStatus::StatusProxyOnly) {
ClipLoadTask::start(m_binId, QDomElement(), true, this);
AudioLevelsTask::start(m_binId, this, false);
}
}
......@@ -374,19 +373,22 @@ void ProjectClip::reloadProducer(bool refreshOnly, bool isProxy, bool forceAudio
{
// we find if there are some loading job on that clip
int loadjobId = -1;
pCore->jobManager()->hasPendingJob(clipId(), AbstractClipJob::LOADJOB, &loadjobId);
//pCore->jobManager()->hasPendingJob(clipId(), AbstractClipJob::LOADJOB, &loadjobId);
QMutexLocker lock(&m_thumbMutex);
if (refreshOnly) {
// In that case, we only want a new thumbnail.
// We thus set up a thumb job. We must make sure that there is no pending LOADJOB
// Clear cache first
ThumbnailCache::get()->invalidateThumbsForClip(clipId());
pCore->jobManager()->discardJobs(clipId(), AbstractClipJob::THUMBJOB);
//pCore->jobManager()->discardJobs(clipId(), AbstractClipJob::THUMBJOB);
ClipLoadTask::cancel(m_binId);
m_thumbsProducer.reset();
emit pCore->jobManager()->startJob<ThumbJob>({clipId()}, loadjobId, QString(), -1, true, true);
ClipLoadTask::start(m_binId, QDomElement(), true, this);
//emit pCore->jobManager()->startJob<ThumbJob>({clipId()}, loadjobId, QString(), -1, true, true);
} else {
// If another load job is running?
pCore->jobManager()->discardJobs(clipId());
ClipLoadTask::cancel(m_binId);
AudioLevelsTask::cancel(m_binId);
if (QFile::exists(m_path) && !hasProxy()) {
clearBackupProperties();
}
......@@ -394,7 +396,6 @@ void ProjectClip::reloadProducer(bool refreshOnly, bool isProxy, bool forceAudio
QDomElement xml = toXml(doc);
if (!xml.isNull()) {
bool hashChanged = false;
pCore->jobManager()->discardJobs(clipId(), AbstractClipJob::THUMBJOB);
m_thumbsProducer.reset();
ClipType::ProducerType type = clipType();
if (type != ClipType::Color && type != ClipType::Image && type != ClipType::SlideShow) {
......@@ -412,8 +413,9 @@ void ProjectClip::reloadProducer(bool refreshOnly, bool isProxy, bool forceAudio
}
ThumbnailCache::get()->invalidateThumbsForClip(clipId());
int loadJob = pCore->jobManager()->startJob<LoadJob>({clipId()}, loadjobId, QString(), xml);
emit pCore->jobManager()->startJob<ThumbJob>({clipId()}, loadJob, QString(), -1, true, true);
ClipLoadTask::start(m_binId, xml, false, this);
//int loadJob = pCore->jobManager()->startJob<LoadJob>({clipId()}, loadjobId, QString(), xml);
//emit pCore->jobManager()->startJob<ThumbJob>({clipId()}, loadJob, QString(), -1, true, true);
if (forceAudioReload || (!isProxy && hashChanged)) {
discardAudioThumb();
}
......@@ -530,6 +532,7 @@ bool ProjectClip::setProducer(std::shared_ptr<Mlt::Producer> producer, bool repl
getFileHash();
// set parent again (some info need to be stored in producer)
updateParent(parentItem().lock());
ClipLoadTask::start(m_binId, QDomElement(), true, this);
AudioLevelsTask::start(m_binId, this, false);
if (pCore->currentDoc()->getDocumentProperty(QStringLiteral("enableproxy")).toInt() == 1) {
......@@ -600,19 +603,20 @@ bool ProjectClip::setProducer(std::shared_ptr<Mlt::Producer> producer, bool repl
return true;
}
void ProjectClip::setThumbProducer(std::shared_ptr<Mlt::Producer>prod)
{
m_thumbsProducer = std::move(prod);
}
std::shared_ptr<Mlt::Producer> ProjectClip::thumbProducer()
{
if (m_thumbsProducer) {
return m_thumbsProducer;
}
if (clipType() == ClipType::Unknown) {
if (clipType() == ClipType::Unknown || m_masterProducer == nullptr) {
return nullptr;
}
QMutexLocker lock(&m_thumbMutex);
std::shared_ptr<Mlt::Producer> prod = originalProducer();
if (!prod->is_valid()) {
return nullptr;
}
if (KdenliveSettings::gpu_accel()) {
// TODO: when the original producer changes, we must reload this thumb producer
m_thumbsProducer = softClone(ClipController::getPassPropertiesList());
......@@ -1479,7 +1483,7 @@ void ProjectClip::discardAudioThumb()
if (!m_audioInfo) {
return;
}
pCore->jobManager()->discardJobs(clipId(), AbstractClipJob::AUDIOTHUMBJOB);
AudioLevelsTask::cancel(m_binId);
QString audioThumbPath;
QList <int> streams = m_audioInfo->streams().keys();
// Delete audio thumbnail data
......
......@@ -137,8 +137,6 @@ public:
QVariant getData(DataType type) const override;
/** @brief Sets thumbnail for this clip. */
void setThumbnail(const QImage &);
QPixmap thumbnail(int width, int height);
/** @brief Returns this clip's producer. */
......@@ -273,6 +271,10 @@ public slots:
void deleteProxy();
void audioJobProgress(int progress);
/** @brief Sets thumbnail for this clip. */
void setThumbnail(const QImage &);
void setThumbProducer(std::shared_ptr<Mlt::Producer>prod);
/**
* Imports effect from a given producer
* @param producer Producer containing the effects
......
......@@ -726,10 +726,10 @@ bool ProjectItemModel::requestAddBinClip(QString &id, const QDomElement &descrip
ProjectClip::construct(id, description, m_blankThumb, std::static_pointer_cast<ProjectItemModel>(shared_from_this()));
bool res = addItem(new_clip, parentId, undo, redo);
if (res) {
ClipLoadTask::start(id, description, this);
ClipLoadTask::start(id, description, false, this);
//int loadJob = emit pCore->jobManager()->startJob<LoadJob>({id}, -1, QString(), description, std::bind(readyCallBack, id));
int loadJob = -1;
emit pCore->jobManager()->startJob<ThumbJob>({id}, loadJob, QString(), 0, true);
//emit pCore->jobManager()->startJob<ThumbJob>({id}, loadJob, QString(), 0, true);
}
return res;
}
......@@ -762,7 +762,7 @@ bool ProjectItemModel::requestAddBinClip(QString &id, const std::shared_ptr<Mlt:
new_clip->importEffects(producer);
if (new_clip->statusReady() || new_clip->sourceExists()) {
int blocking = pCore->jobManager()->getBlockingJobId(id, AbstractClipJob::LOADJOB);
emit pCore->jobManager()->startJob<ThumbJob>({id}, blocking, QString(), -1, true);
//emit pCore->jobManager()->startJob<ThumbJob>({id}, blocking, QString(), -1, true);
}
}
return res;
......@@ -787,7 +787,7 @@ bool ProjectItemModel::requestAddBinSubClip(QString &id, int in, int out, const
bool res = addItem(new_clip, subId, undo, redo);
if (res) {
int parentJob = pCore->jobManager()->getBlockingJobId(subId, AbstractClipJob::LOADJOB);
emit pCore->jobManager()->startJob<ThumbJob>({id}, parentJob, QString(), -1, true);
//emit pCore->jobManager()->startJob<ThumbJob>({id}, parentJob, QString(), -1, true);
}
return res;
}
......
......@@ -49,7 +49,7 @@ Core::Core()
, m_thumbProfile(nullptr)
, m_capture(new MediaCapture(this))
{
clipJobPool.setMaxThreadCount(2);
clipJobPool.setMaxThreadCount(qMin(4, QThread::idealThreadCount() - 1));
}
void Core::prepareShutdown()
......@@ -692,6 +692,11 @@ void Core::displayMessage(const QString &message, MessageType type, int timeout)
}
}
void Core::loadingClips(int count)
{
m_mainWindow->displayProgressMessage(i18n("Loading clips"), MessageType::ProcessingJobMessage, count);
}
void Core::displayBinMessage(const QString &text, int type, const QList<QAction *> &actions, bool showClose, BinMessage::BinCategory messageCategory)
{
m_binWidget->doDisplayMessage(text, KMessageWidget::MessageType(type), actions, showClose, messageCategory);
......
......@@ -251,6 +251,8 @@ public:
/** @brief Display key binding info in statusbar. */
void setWidgetKeyBinding(const QString &mess = QString());
KSharedDataCache audioThumbCache;
/** @brief The number of clip load jobs changed */
void loadingClips(int);
private:
explicit Core();
......
......@@ -245,10 +245,10 @@ public slots:
void slotAutoSave(const QString &scene);
/** @brief Groups were changed, save to MLT. */
void groupsChanged(const QString &groups);
void switchProfile(std::unique_ptr<ProfileParam> &profile, const QString &id, const QDomElement &xml);
private slots:
void slotModified();
void switchProfile(std::unique_ptr<ProfileParam> &profile, const QString &id, const QDomElement &xml);
void slotSwitchProfile(const QString &profile_path, bool reloadThumbs);
/** @brief Check if we did a new action invalidating more recent undo items. */
void checkPreviewStack(int ix);
......
......@@ -90,7 +90,7 @@ void AudioLevelsTask::start(const QString cid, QObject* object, bool force)
// Otherwise, start a new audio levels generation thread.
task->m_isForce = force;
tasksList << task;
pCore->clipJobPool.start(task, 3);
pCore->clipJobPool.start(task, 1);
}
tasksListMutex.unlock();
}
......
......@@ -25,6 +25,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "bin/projectclip.h"
#include "audio/audioStreamInfo.h"
#include "kdenlivesettings.h"
#include "doc/kthumb.h"
#include "doc/kdenlivedoc.h"
#include "utils/thumbnailcache.hpp"
#include "xml/xml.hpp"
#include <QString>
......@@ -36,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QTime>
#include <QFile>
#include <QAction>
#include <QPainter>
#include <QElapsedTimer>
#include <QMimeDatabase>
#include <monitor/monitor.h>
......@@ -47,12 +51,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
static QList<ClipLoadTask*> tasksList;
static QMutex tasksListMutex;
static int maxJobs = 0;
ClipLoadTask::ClipLoadTask(const QString &clipId, const QDomElement &xml, QObject* object, std::function<void()> readyCallBack)
ClipLoadTask::ClipLoadTask(const QString &clipId, const QDomElement &xml, bool thumbOnly, QObject* object, std::function<void()> readyCallBack)
: QRunnable()
, m_cid(clipId)
, m_object(object)
, m_xml(xml)
, m_thumbOnly(thumbOnly)
, m_readyCallBack(std::move(readyCallBack))
, m_isCanceled(false)
, m_isForce(false)
......@@ -80,11 +86,12 @@ void ClipLoadTask::cancel(const QString cid)
break;
}
}
pCore->loadingClips(100 * (maxJobs - tasksList.size()) / maxJobs);
}
void ClipLoadTask::start(const QString cid, const QDomElement &xml, QObject* object, bool force, std::function<void()> readyCallBack)
void ClipLoadTask::start(const QString cid, const QDomElement &xml, bool thumbOnly, QObject* object, bool force, std::function<void()> readyCallBack)
{
ClipLoadTask* task = new ClipLoadTask(cid, xml, object, readyCallBack);
ClipLoadTask* task = new ClipLoadTask(cid, xml, thumbOnly, object, readyCallBack);
tasksListMutex.lock();
// See if there is already a task for this MLT service and resource.
foreach (ClipLoadTask* t, tasksList) {
......@@ -99,8 +106,13 @@ void ClipLoadTask::start(const QString cid, const QDomElement &xml, QObject* obj
// Otherwise, start a new audio levels generation thread.
task->m_isForce = force;
tasksList << task;
pCore->clipJobPool.start(task, 0);
pCore->clipJobPool.start(task, 10);
}
int size = tasksList.size();
if (size > maxJobs) {
maxJobs = size;
}
pCore->loadingClips(100 * (maxJobs - size) / maxJobs);
tasksListMutex.unlock();
}
......@@ -114,6 +126,7 @@ void ClipLoadTask::closeAll()
tasksList.removeFirst();
}
tasksListMutex.unlock();
pCore->loadingClips(100);
}
bool ClipLoadTask::operator==(ClipLoadTask &b)
......@@ -131,6 +144,7 @@ void ClipLoadTask::cleanup()
}
}
tasksListMutex.unlock();
pCore->loadingClips(100 * (maxJobs - tasksList.size()) / maxJobs);
}
ClipType::ProducerType ClipLoadTask::getTypeForService(const QString &id, const QString &path)
......@@ -292,6 +306,109 @@ void ClipLoadTask::processSlideShow(std::shared_ptr<Mlt::Producer> producer)
}
}
void ClipLoadTask::generateThumbnail(std::shared_ptr<ProjectClip>binClip, std::shared_ptr<Mlt::Producer> producer)
{
// Fetch thumbnail
qDebug()<<"===== \nREADY FOR THUMB\n\n=========";
int frameNumber = qMax(0, binClip->getProducerIntProperty(QStringLiteral("kdenlive:thumbnailFrame")));
if (binClip->clipType() != ClipType::Audio) {
if (ThumbnailCache::get()->hasThumbnail(m_cid, frameNumber, false)) {
// Thumbnail found in cache
QImage result = ThumbnailCache::get()->getThumbnail(m_cid, frameNumber);
qDebug()<<"=== FOUND THUMB IN CACHe";
QMetaObject::invokeMethod(binClip.get(), "setThumbnail", Qt::QueuedConnection, Q_ARG(QImage,result));
} else {
std::shared_ptr<Mlt::Producer> thumbProd = binClip->thumbProducer();
qDebug()<<"=== REGENARATING THUMB";
if (thumbProd == nullptr) {
QString mltService = producer->get("mlt_service");
const QString mltResource = producer->get("resource");
if (mltService == QLatin1String("avformat")) {
mltService = QStringLiteral("avformat-novalidate");
}
thumbProd.reset(new Mlt::Producer(*pCore->thumbProfile(), mltService.toUtf8().constData(), mltResource.toUtf8().constData()));
QMetaObject::invokeMethod(binClip.get(), "setThumbProducer", Qt::QueuedConnection, Q_ARG(std::shared_ptr<Mlt::Producer>,thumbProd));
}
//m_thumbsProducer.reset(new Mlt::Producer(*pCore->thumbProfile(), mltService.toUtf8().constData(), mltResource.toUtf8().constData()));
//std::shared_ptr<Mlt::Producer> thumbProd = binClip->thumbProducer();
if (thumbProd) {
thumbProd->set("audio_index", -1);
qDebug()<<"===== \nSEEKING THUMB PROD\n\n=========";
if (frameNumber > 0) {
thumbProd->seek(frameNumber);
}
QScopedPointer<Mlt::Frame> frame(thumbProd->get_frame());
frame->set("deinterlace_method", "onefield");
frame->set("top_field_first", -1);
frame->set("rescale.interp", "nearest");
if ((frame != nullptr) && frame->is_valid()) {
int imageHeight(pCore->thumbProfile()->height());
int imageWidth(pCore->thumbProfile()->width());
int fullWidth(int(imageHeight * pCore->getCurrentDar() + 0.5));
QImage result = KThumb::getFrame(frame.data(), imageWidth, imageHeight, fullWidth);
if (result.isNull()) {
qDebug() << "+++++\nINVALID RESULT IMAGE\n++++++++++++++";
result = QImage(fullWidth, imageHeight, QImage::Format_ARGB32_Premultiplied);
result.fill(Qt::red);
QPainter p(&result);
p.setPen(Qt::white);
p.drawText(0, 0, fullWidth, imageHeight, Qt::AlignCenter, i18n("Invalid"));
QMetaObject::invokeMethod(binClip.get(), "setThumbnail", Qt::QueuedConnection, Q_ARG(QImage,result));
} else {
QMetaObject::invokeMethod(binClip.get(), "setThumbnail", Qt::QueuedConnection, Q_ARG(QImage,result));
ThumbnailCache::get()->storeThumbnail(m_cid, frameNumber, result, true);
}
}
}
}
}
}
void ClipLoadTask::checkProfile(const QString &clipId, const QDomElement &xml, const std::shared_ptr<Mlt::Producer> &producer)
{
// Check if clip profile matches
QString service = producer->get("mlt_service");
// Check for image producer
if (service == QLatin1String("qimage") || service == QLatin1String("pixbuf")) {
// This is an image, create profile from image size
int width = producer->get_int("meta.media.width");
if (width % 2 > 0) {
width += width % 2;
}
int height = producer->get_int("meta.media.height");
height += height % 2;
if (width > 100 && height > 100) {
std::unique_ptr<ProfileParam> projectProfile(new ProfileParam(pCore->getCurrentProfile().get()));
projectProfile->m_width = width;
projectProfile->m_height = height;
projectProfile->m_sample_aspect_num = 1;
projectProfile->m_sample_aspect_den = 1;
projectProfile->m_display_aspect_num = width;
projectProfile->m_display_aspect_den = height;
projectProfile->m_description.clear();
pCore->currentDoc()->switchProfile(projectProfile, clipId, xml);
} else {
// Very small image, we probably don't want to use this as profile
}
} else if (service.contains(QStringLiteral("avformat"))) {
std::unique_ptr<Mlt::Profile> blankProfile(new Mlt::Profile());
blankProfile->set_explicit(0);
blankProfile->from_producer(*producer);
std::unique_ptr<ProfileParam> clipProfile(new ProfileParam(blankProfile.get()));
std::unique_ptr<ProfileParam> projectProfile(new ProfileParam(pCore->getCurrentProfile().get()));
clipProfile->adjustDimensions();
if (*clipProfile.get() == *projectProfile.get()) {
if (KdenliveSettings::default_profile().isEmpty()) {
// Confirm default project format
KdenliveSettings::setDefault_profile(pCore->getCurrentProfile()->path());
}
} else {
// Profiles do not match, propose profile adjustment
pCore->currentDoc()->switchProfile(clipProfile, clipId, xml);
}
}
}
void ClipLoadTask::run()
{
// 2 channels interleaved of uchar values
......@@ -299,6 +416,15 @@ void ClipLoadTask::run()
cleanup();
return;
}
//QThread::currentThread()->setPriority(QThread::HighestPriority);
if (m_thumbOnly) {
auto binClip = pCore->projectItemModel()->getClipByBinID(m_cid);
if (binClip) {
generateThumbnail(binClip, binClip->originalProducer());
}
cleanup();
return;
}
pCore->getMonitor(Kdenlive::ClipMonitor)->resetPlayOrLoopZone(m_cid);
QString resource = Xml::getXmlProperty(m_xml, QStringLiteral("resource"));
qDebug()<<"============STARTING LOAD TASK FOR: "<<resource<<"\n\n:::::::::::::::::::";
......@@ -440,9 +566,14 @@ void ClipLoadTask::run()
}
break;
}
if (m_isCanceled) {
cleanup();
return;
}
if (!producer || producer->is_blank() || !producer->is_valid()) {
qCDebug(KDENLIVE_LOG) << " / / / / / / / / ERROR / / / / // CANNOT LOAD PRODUCER: " << resource;
m_successful = false;
if (producer) {
producer.reset();
}
......@@ -571,7 +702,7 @@ void ClipLoadTask::run()
// List streams
int streams = producer->get_int("meta.media.nb_streams");
QList<int> audio_list, video_list;
for (int i = 0; i < streams; ++i) {
for (int i = 0; i < streams && !m_isCanceled; ++i) {
QByteArray propertyName = QStringLiteral("meta.media.%1.stream.type").arg(i).toLocal8Bit();
QString stype = producer->get(propertyName.data());
if (stype == QLatin1String("audio")) {
......@@ -581,13 +712,13 @@ void ClipLoadTask::run()
}
}
if (vindex > -1) {
if (vindex > -1 && !m_isCanceled) {
char property[200];
snprintf(property, sizeof(property), "meta.media.%d.stream.frame_rate", vindex);
fps = producer->get_double(property);
}
if (fps <= 0) {
if (fps <= 0 && !m_isCanceled) {
if (producer->get_double("meta.media.frame_rate_den") > 0) {
fps = producer->get_double("meta.media.frame_rate_num") / producer->get_double("meta.media.frame_rate_den");
} else {
......@@ -602,12 +733,15 @@ void ClipLoadTask::run()
vindex = -1;
}
}
auto binClip = pCore->projectItemModel()->getClipByBinID(m_cid);
if (binClip) {
QMetaObject::invokeMethod(binClip.get(), "setProducer", Qt::QueuedConnection, Q_ARG(std::shared_ptr<Mlt::Producer>,producer),
if (!m_isCanceled) {
auto binClip = pCore->projectItemModel()->getClipByBinID(m_cid);
if (binClip) {
QMetaObject::invokeMethod(binClip.get(), "setProducer", Qt::QueuedConnection, Q_ARG(std::shared_ptr<Mlt::Producer>,producer),
Q_ARG(bool , true));
//binClip->setProducer(producer, true);
//binClip->setProducer(producer, true);
}
generateThumbnail(binClip, producer);
m_readyCallBack();
}
cleanup();
}
......@@ -31,12 +31,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QObject>
#include <QList>
class ProjectClip;
class ClipLoadTask : public QRunnable
{
public:
ClipLoadTask(const QString &clipId, const QDomElement &xml, QObject* object, std::function<void()> readyCallBack);
ClipLoadTask(const QString &clipId, const QDomElement &xml, bool thumbOnly, QObject* object, std::function<void()> readyCallBack);
virtual ~ClipLoadTask();
static void start(const QString cid, const QDomElement &xml, QObject* object, bool force = false, std::function<void()> readyCallBack = []() {});
static void start(const QString cid, const QDomElement &xml, bool thumbOnly, QObject* object, bool force = false, std::function<void()> readyCallBack = []() {});
static void cancel(const QString cid);
static void closeAll();
const QString clipId() const;
......@@ -46,6 +48,8 @@ public:
std::shared_ptr<Mlt::Producer> loadPlaylist(QString &resource);
void processProducerProperties(const std::shared_ptr<Mlt::Producer> &prod, const QDomElement &xml);
void processSlideShow(std::shared_ptr<Mlt::Producer> producer);
// Do some checks on the profile
static void checkProfile(const QString &clipId, const QDomElement &xml, const std::shared_ptr<Mlt::Producer> &producer);
protected:
void run() override;
......@@ -55,11 +59,12 @@ private:
QString m_cid;
QObject* m_object;
QDomElement m_xml;
bool m_thumbOnly;
std::function<void()> m_readyCallBack;
bool m_successful;
QString m_errorMessage;
bool m_isCanceled;
bool m_isForce;
void generateThumbnail(std::shared_ptr<ProjectClip>binClip, std::shared_ptr<Mlt::Producer> producer);
void cleanup();
};
......
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