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
d0a5fb9c
Commit
d0a5fb9c
authored
Jan 12, 2022
by
Jean-Baptiste Mardelle
Browse files
Speedup loading of projects with timeline preview.
Related to
#1266
parent
e3b71237
Changes
10
Hide whitespace changes
Inline
Side-by-side
src/core.cpp
View file @
d0a5fb9c
...
...
@@ -1195,3 +1195,8 @@ void Core::addBin(const QString &id)
const
QString
folderName
=
bin
->
setDocument
(
pCore
->
currentDoc
(),
id
);
m_mainWindow
->
addBin
(
bin
,
folderName
);
}
void
Core
::
loadTimelinePreview
(
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enablePreview
,
Mlt
::
Playlist
&
playlist
)
{
pCore
->
window
()
->
getMainTimeline
()
->
controller
()
->
loadPreview
(
chunks
,
dirty
,
documentDate
,
enablePreview
,
playlist
);
}
src/core.h
View file @
d0a5fb9c
...
...
@@ -22,7 +22,8 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include <unordered_set>
#include "timecode.h"
#include "mlt++/MltProfile.h"
#include <mlt++/MltProfile.h>
#include <mlt++/MltPlaylist.h>
class
Bin
;
class
DocUndoStack
;
...
...
@@ -271,6 +272,7 @@ public:
int
getNewStuff
(
const
QString
&
configFile
);
/** @brief Get the frame size of the clip above a composition */
const
QSize
getCompositionSizeOnTrack
(
const
ObjectId
&
id
);
void
loadTimelinePreview
(
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enablePreview
,
Mlt
::
Playlist
&
playlist
);
private:
explicit
Core
();
...
...
src/project/projectmanager.cpp
View file @
d0a5fb9c
...
...
@@ -222,7 +222,7 @@ void ProjectManager::newFile(QString profileName, bool showProjectSettings)
pCore
->
bin
()
->
setDocument
(
doc
);
m_project
=
doc
;
pCore
->
monitorManager
()
->
activateMonitor
(
Kdenlive
::
ProjectMonitor
);
updateTimeline
(
0
);
updateTimeline
(
0
,
QString
(),
QString
(),
QDateTime
(),
0
);
pCore
->
window
()
->
connectDocument
();
pCore
->
mixer
()
->
setModel
(
m_mainTimelineModel
);
bool
disabled
=
m_project
->
getDocumentProperty
(
QStringLiteral
(
"disabletimelineeffects"
))
==
QLatin1String
(
"1"
);
...
...
@@ -615,19 +615,15 @@ void ProjectManager::doOpenFile(const QUrl &url, KAutoSaveFile *stale)
// Set default target tracks to upper audio / lower video tracks
m_project
=
doc
;
doc
->
loadDocumentGuides
();
if
(
!
updateTimeline
(
m_project
->
getDocumentProperty
(
QStringLiteral
(
"position"
)).
toInt
()))
{
m_project
->
loadDocumentGuides
();
QDateTime
documentDate
=
QFileInfo
(
m_project
->
url
().
toLocalFile
()).
lastModified
();
if
(
!
updateTimeline
(
m_project
->
getDocumentProperty
(
QStringLiteral
(
"position"
)).
toInt
(),
m_project
->
getDocumentProperty
(
QStringLiteral
(
"previewchunks"
)),
m_project
->
getDocumentProperty
(
QStringLiteral
(
"dirtypreviewchunks"
)),
documentDate
,
m_project
->
getDocumentProperty
(
QStringLiteral
(
"disablepreview"
)).
toInt
()))
{
delete
m_progressDialog
;
m_progressDialog
=
nullptr
;
return
;
}
pCore
->
window
()
->
connectDocument
();
pCore
->
mixer
()
->
setModel
(
m_mainTimelineModel
);
QDateTime
documentDate
=
QFileInfo
(
m_project
->
url
().
toLocalFile
()).
lastModified
();
pCore
->
window
()
->
getMainTimeline
()
->
controller
()
->
loadPreview
(
m_project
->
getDocumentProperty
(
QStringLiteral
(
"previewchunks"
)),
m_project
->
getDocumentProperty
(
QStringLiteral
(
"dirtypreviewchunks"
)),
documentDate
,
m_project
->
getDocumentProperty
(
QStringLiteral
(
"disablepreview"
)).
toInt
());
emit
docOpened
(
m_project
);
pCore
->
displayMessage
(
QString
(),
OperationCompletedMessage
,
100
);
if
(
openBackup
)
{
...
...
@@ -929,7 +925,7 @@ void ProjectManager::slotMoveFinished(KJob *job)
}
}
bool
ProjectManager
::
updateTimeline
(
int
pos
)
bool
ProjectManager
::
updateTimeline
(
int
pos
,
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enablePreview
)
{
pCore
->
taskManager
.
slotCancelJobs
();
pCore
->
window
()
->
getMainTimeline
()
->
loading
=
true
;
...
...
@@ -960,7 +956,7 @@ bool ProjectManager::updateTimeline(int pos)
m_mainTimelineModel
->
addSnap
(
0
);
pCore
->
window
()
->
getMainTimeline
()
->
setModel
(
m_mainTimelineModel
,
pCore
->
monitorManager
()
->
projectMonitor
()
->
getControllerProxy
());
bool
projectErrors
=
false
;
if
(
!
constructTimelineFromMelt
(
m_mainTimelineModel
,
tractor
,
m_progressDialog
,
m_project
->
modifiedDecimalPoint
(),
&
projectErrors
))
{
if
(
!
constructTimelineFromMelt
(
m_mainTimelineModel
,
tractor
,
m_progressDialog
,
m_project
->
modifiedDecimalPoint
(),
chunks
,
dirty
,
documentDate
,
enablePreview
,
&
projectErrors
))
{
//TODO: act on project load failure
qDebug
()
<<
"// Project failed to load!!"
;
}
...
...
src/project/projectmanager.h
View file @
d0a5fb9c
...
...
@@ -185,7 +185,7 @@ signals:
protected:
/** @brief Update the timeline according to the MLT XML */
bool
updateTimeline
(
int
pos
);
bool
updateTimeline
(
int
pos
,
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enablePreview
);
private:
/** @brief checks if autoback files exists, recovers from it if user says yes, returns true if files were recovered. */
...
...
src/timeline2/model/builders/meltBuilder.cpp
View file @
d0a5fb9c
...
...
@@ -36,7 +36,7 @@ bool constructTrackFromMelt(const std::shared_ptr<TimelineItemModel> &timeline,
bool
constructTrackFromMelt
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
tid
,
Mlt
::
Playlist
&
track
,
const
std
::
unordered_map
<
QString
,
QString
>
&
binIdCorresp
,
Fun
&
undo
,
Fun
&
redo
,
bool
audioTrack
,
QString
originalDecimalPoint
,
int
playlist
,
QList
<
Mlt
::
Transition
*>
compositions
,
QProgressDialog
*
progressDialog
=
nullptr
);
bool
constructTimelineFromMelt
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
Mlt
::
Tractor
tractor
,
QProgressDialog
*
progressDialog
,
QString
originalDecimalPoint
,
bool
*
projectErrors
)
bool
constructTimelineFromMelt
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
Mlt
::
Tractor
tractor
,
QProgressDialog
*
progressDialog
,
const
QString
&
originalDecimalPoint
,
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enablePreview
,
bool
*
projectErrors
)
{
Fun
undo
=
[]()
{
return
true
;
};
Fun
redo
=
[]()
{
return
true
;
};
...
...
@@ -72,6 +72,10 @@ bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timelin
std
::
unique_ptr
<
Mlt
::
Producer
>
track
(
tractor
.
track
(
i
));
QString
playlist_name
=
track
->
get
(
"id"
);
if
(
reserved_names
.
contains
(
playlist_name
))
{
if
(
playlist_name
==
QLatin1String
(
"timeline_preview"
))
{
Mlt
::
Playlist
local_playlist
(
*
track
);
pCore
->
loadTimelinePreview
(
chunks
,
dirty
,
documentDate
,
enablePreview
,
local_playlist
);
}
continue
;
}
switch
(
track
->
type
())
{
...
...
src/timeline2/model/builders/meltBuilder.hpp
View file @
d0a5fb9c
...
...
@@ -8,12 +8,13 @@
#include <memory>
#include <mlt++/MltTractor.h>
#include <QtCore/QString>
#include <QDateTime>
class
TimelineItemModel
;
class
QProgressDialog
;
/** @brief This function can be used to construct a TimelineModel object from a Mlt object hierarchy
*/
bool
constructTimelineFromMelt
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
Mlt
::
Tractor
mlt_timeline
,
QProgressDialog
*
progressDialog
=
nullptr
,
QString
originalDecimalPoint
=
QString
(),
bool
*
projectErrors
=
nullptr
);
bool
constructTimelineFromMelt
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
Mlt
::
Tractor
mlt_timeline
,
QProgressDialog
*
progressDialog
=
nullptr
,
const
QString
&
originalDecimalPoint
=
QString
(),
const
QString
&
chunks
=
QString
(),
const
QString
&
dirty
=
QString
(),
const
QDateTime
&
documentDate
=
QDateTime
(),
int
enablePreview
=
0
,
bool
*
projectErrors
=
nullptr
);
#endif
src/timeline2/view/previewmanager.cpp
View file @
d0a5fb9c
...
...
@@ -127,7 +127,7 @@ bool PreviewManager::buildPreviewTrack()
return
true
;
}
void
PreviewManager
::
loadChunks
(
QVariantList
previewChunks
,
QVariantList
dirtyChunks
,
const
QDateTime
&
documentDate
)
void
PreviewManager
::
loadChunks
(
QVariantList
previewChunks
,
QVariantList
dirtyChunks
,
const
QDateTime
&
documentDate
,
Mlt
::
Playlist
&
playlist
)
{
if
(
previewChunks
.
isEmpty
())
{
previewChunks
=
m_renderedChunks
;
...
...
@@ -135,21 +135,39 @@ void PreviewManager::loadChunks(QVariantList previewChunks, QVariantList dirtyCh
if
(
dirtyChunks
.
isEmpty
())
{
dirtyChunks
=
m_dirtyChunks
;
}
for
(
const
auto
&
frame
:
qAsConst
(
previewChunks
))
{
const
QString
fileName
=
m_cacheDir
.
absoluteFilePath
(
QStringLiteral
(
"%1.%2"
).
arg
(
frame
.
toInt
()).
arg
(
m_extension
));
QFile
file
(
fileNa
me
);
if
(
file
.
exists
()
)
{
if
(
!
documentDate
.
isNull
()
&&
QFileInfo
(
file
)
.
lastModified
()
>
documentDate
)
{
// Timeline preview file was created after document,
invalid
ate
file
.
remove
(
);
dirtyChunks
<<
fr
ame
;
}
else
{
gotPreviewRender
(
frame
.
toInt
(),
fileName
,
1000
);
}
// First chech if there are invalid chunks (created after document date)
QFile
InfoList
chunksList
=
m_cacheDir
.
entryInfoList
({
QString
(
"*.%1"
).
arg
(
m_extension
)},
QDir
::
Files
,
QDir
::
Ti
me
);
for
(
auto
&
chunkFile
:
chunksList
)
{
if
(
chunkFile
.
lastModified
()
>
documentDate
)
{
// This chunk is
invalid
QString
chunkName
=
chunkFile
.
fileName
().
section
(
QLatin1Char
(
'.'
),
0
,
0
);
previewChunks
.
removeAll
(
chunkN
ame
)
;
dirtyChunks
<<
chunkName
;
// Physically remove chunk file
m_cacheDir
.
remove
(
chunkFile
.
fileName
());
}
else
{
dirtyChunks
<<
frame
;
// Done
break
;
}
}
int
max
=
playlist
.
count
();
std
::
shared_ptr
<
Mlt
::
Producer
>
clip
;
m_tractor
->
lock
();
for
(
int
i
=
0
;
i
<
max
;
i
++
)
{
if
(
playlist
.
is_blank
(
i
))
{
continue
;
}
int
position
=
playlist
.
clip_start
(
i
);
if
(
previewChunks
.
contains
(
QString
::
number
(
position
)))
{
clip
.
reset
(
playlist
.
get_clip
(
i
));
m_renderedChunks
<<
position
;
m_previewTrack
->
insert_at
(
position
,
clip
.
get
(),
1
);
}
}
m_previewTrack
->
consolidate_blanks
();
m_tractor
->
unlock
();
if
(
!
previewChunks
.
isEmpty
())
{
emit
m_controller
->
renderedChunksChanged
();
}
...
...
src/timeline2/view/previewmanager.h
View file @
d0a5fb9c
...
...
@@ -65,7 +65,7 @@ public:
/** @brief: Returns directory currently used to store the preview files. */
const
QDir
getCacheDir
()
const
;
/** @brief: Load existing ruler chunks. */
void
loadChunks
(
QVariantList
previewChunks
,
QVariantList
dirtyChunks
,
const
QDateTime
&
documentDate
);
void
loadChunks
(
QVariantList
previewChunks
,
QVariantList
dirtyChunks
,
const
QDateTime
&
documentDate
,
Mlt
::
Playlist
&
playlist
);
int
setOverlayTrack
(
Mlt
::
Playlist
*
overlay
);
/** @brief Remove the effect compare overlay track */
void
removeOverlayTrack
();
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
d0a5fb9c
...
...
@@ -2412,7 +2412,8 @@ void TimelineController::disablePreview(bool disable)
m_timelinePreview
->
reconnectTrack
();
m_model
->
m_tractor
->
unlock
();
}
m_timelinePreview
->
loadChunks
(
QVariantList
(),
QVariantList
(),
QDateTime
());
Mlt
::
Playlist
playlist
;
m_timelinePreview
->
loadChunks
(
QVariantList
(),
QVariantList
(),
QDateTime
(),
playlist
);
m_usePreview
=
true
;
}
}
...
...
@@ -2452,7 +2453,7 @@ void TimelineController::resetPreview()
}
}
void
TimelineController
::
loadPreview
(
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enable
)
void
TimelineController
::
loadPreview
(
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enable
,
Mlt
::
Playlist
&
playlist
)
{
if
(
chunks
.
isEmpty
()
&&
dirty
.
isEmpty
())
{
return
;
...
...
@@ -2490,7 +2491,7 @@ void TimelineController::loadPreview(const QString &chunks, const QString &dirty
m_usePreview
=
true
;
m_model
->
m_overlayTrackCount
=
m_timelinePreview
->
addedTracks
();
}
m_timelinePreview
->
loadChunks
(
renderedChunks
,
dirtyChunks
,
documentDate
);
m_timelinePreview
->
loadChunks
(
renderedChunks
,
dirtyChunks
,
documentDate
,
playlist
);
}
}
...
...
src/timeline2/view/timelinecontroller.h
View file @
d0a5fb9c
...
...
@@ -559,7 +559,7 @@ public:
/** @brief Load timeline preview from saved doc
*/
void
loadPreview
(
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enable
);
void
loadPreview
(
const
QString
&
chunks
,
const
QString
&
dirty
,
const
QDateTime
&
documentDate
,
int
enable
,
Mlt
::
Playlist
&
playlist
);
/** @brief Return document properties with added settings from timeline
*/
QMap
<
QString
,
QString
>
documentProperties
();
...
...
Write
Preview
Supports
Markdown
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