Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
3c919550
Commit
3c919550
authored
Apr 22, 2021
by
Jean-Baptiste Mardelle
Browse files
Start deprecating loadjob in favor of QRunnable cliploadtask
parent
b392b15f
Changes
11
Hide whitespace changes
Inline
Side-by-side
src/bin/bin.cpp
View file @
3c919550
...
...
@@ -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
());
}
}
}
...
...
src/bin/clipcreator.cpp
View file @
3c919550
...
...
@@ -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
)
&&
!
isOnR
emovable
Device
(
pCore
->
currentDoc
()
->
projectDataFolder
())
)
{
if
(
checkRemovable
&&
isOnRemovableDevice
(
file
)
&&
!
r
emovable
Project
)
{
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.
\n
You "
...
...
@@ -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
;
...
...
src/bin/projectclip.cpp
View file @
3c919550
...
...
@@ -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
...
...
src/bin/projectclip.h
View file @
3c919550
...
...
@@ -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
...
...
src/bin/projectitemmodel.cpp
View file @
3c919550
...
...
@@ -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
;
}
...
...
src/core.cpp
View file @
3c919550
...
...
@@ -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
);
...
...
src/core.h
View file @
3c919550
...
...
@@ -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
();
...
...
src/doc/kdenlivedoc.h
View file @
3c919550
...
...
@@ -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
);
...
...
src/jobs/audiolevelstask.cpp
View file @
3c919550
...
...
@@ -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
();
}
...
...
src/jobs/cliploadtask.cpp
View file @
3c919550
...
...
@@ -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
,
1
0
);
}
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
()
<<
"=====
\n
READY 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
()
<<
"=====
\n
SEEKING 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
()
<<
"+++++
\n
INVALID 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
();
}
src/jobs/cliploadtask.h
View file @
3c919550
...
...
@@ -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
();
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment