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
9ba6eaa9
Commit
9ba6eaa9
authored
Jul 31, 2020
by
Jean-Baptiste Mardelle
Browse files
Various fixes for audio thumb management, should slightly improve memory usage/performnace.
Related to
#102
parent
a0db1142
Pipeline
#28984
passed with stage
in 30 minutes and 41 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/bin/bin.cpp
View file @
9ba6eaa9
...
...
@@ -1510,7 +1510,7 @@ void Bin::slotReloadClip()
}
}
}
currentItem
->
reloadProducer
(
false
);
currentItem
->
reloadProducer
(
false
,
false
,
true
);
}
}
}
...
...
src/bin/projectclip.cpp
View file @
9ba6eaa9
...
...
@@ -220,8 +220,6 @@ void ProjectClip::updateAudioThumbnail()
pen
.
setColor
(
Qt
::
white
);
painter
.
setPen
(
pen
);
int
streamCount
=
0
;
qreal
indicesPrPixel
=
qreal
(
getFramePlaytime
())
/
img
.
width
();
double
increment
=
qMax
(
1.
,
1.
/
qAbs
(
indicesPrPixel
));
if
(
streams
.
count
()
>
0
)
{
double
streamHeight
=
iconHeight
/
streams
.
count
();
QMapIterator
<
int
,
QString
>
st
(
streams
);
...
...
@@ -230,17 +228,20 @@ void ProjectClip::updateAudioThumbnail()
int
channels
=
channelsList
.
value
(
st
.
key
());
double
channelHeight
=
(
double
)
streamHeight
/
channels
;
const
QVector
<
uint8_t
>
audioLevels
=
audioFrameCache
(
st
.
key
());
qreal
indicesPrPixel
=
qreal
(
audioLevels
.
length
())
/
img
.
width
();
int
idx
;
for
(
int
channel
=
0
;
channel
<
channels
;
channel
++
)
{
double
y
=
(
streamHeight
*
streamCount
)
+
(
channel
*
channelHeight
)
+
channelHeight
/
2
;
for
(
int
i
=
0
;
i
<=
img
.
width
();
i
++
)
{
double
j
=
i
*
increment
;
int
idx
=
j
*
indicesPrPixel
;
idx
=
ceil
(
i
*
indicesPrPixel
);
idx
+=
idx
%
channels
;
idx
+=
channel
;
if
(
idx
>=
audioLevels
.
length
()
||
idx
<
0
)
break
;
double
level
=
audioLevels
.
at
(
idx
)
*
channelHeight
/
510.
;
// divide height by 510 (2*255) to get height
painter
.
drawLine
(
i
,
y
-
level
,
i
,
y
+
level
);
if
(
idx
>=
audioLevels
.
length
()
||
idx
<
0
)
{
break
;
}
double
level
=
audioLevels
.
at
(
idx
)
*
channelHeight
/
510.
;
// divide height by 510 (2*255) to get height
painter
.
drawLine
(
i
,
y
-
level
,
i
,
y
+
level
);
}
}
streamCount
++
;
}
...
...
@@ -353,7 +354,7 @@ size_t ProjectClip::frameDuration() const
return
(
size_t
)
getFramePlaytime
();
}
void
ProjectClip
::
reloadProducer
(
bool
refreshOnly
,
bool
isProxy
)
void
ProjectClip
::
reloadProducer
(
bool
refreshOnly
,
bool
isProxy
,
bool
forceAudioReload
)
{
// we find if there are some loading job on that clip
int
loadjobId
=
-
1
;
...
...
@@ -399,7 +400,7 @@ void ProjectClip::reloadProducer(bool refreshOnly, bool isProxy)
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
);
if
(
!
isProxy
&&
hashChanged
)
{
if
(
forceAudioReload
||
(
!
isProxy
&&
hashChanged
)
)
{
discardAudioThumb
();
}
if
(
KdenliveSettings
::
audiothumbnails
())
{
...
...
@@ -1622,7 +1623,7 @@ void ProjectClip::setRating(uint rating)
pCore
->
currentDoc
()
->
setModified
(
true
);
}
QVector
<
uint8_t
>
ProjectClip
::
audioFrameCache
(
int
stream
)
const
QVector
<
uint8_t
>
ProjectClip
::
audioFrameCache
(
int
stream
)
{
QVector
<
uint8_t
>
audioLevels
;
if
(
stream
==
-
1
)
{
...
...
@@ -1632,12 +1633,19 @@ QVector <uint8_t> ProjectClip::audioFrameCache(int stream)
return
audioLevels
;
}
}
QString
key
=
QString
(
"%1:%2"
).
arg
(
m_binId
).
arg
(
stream
);
QByteArray
audioData
;
if
(
pCore
->
audioThumbCache
.
find
(
key
,
&
audioData
))
{
QDataStream
in
(
audioData
);
in
>>
audioLevels
;
return
audioLevels
;
}
// convert cached image
const
QString
cachePath
=
getAudioThumbPath
(
stream
);
// checking for cached thumbs
QImage
image
(
cachePath
);
if
(
!
image
.
isNull
())
{
int
channels
=
m_audioInfo
->
channels
(
);
int
channels
=
m_audioInfo
->
channels
ForStream
(
stream
);
int
n
=
image
.
width
()
*
image
.
height
();
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
QRgb
p
=
image
.
pixel
(
i
/
channels
,
i
%
channels
);
...
...
@@ -1647,6 +1655,11 @@ QVector <uint8_t> ProjectClip::audioFrameCache(int stream)
audioLevels
<<
(
uint8_t
)
qAlpha
(
p
);
}
}
// populate vector
QDataStream
st
(
&
audioData
,
QIODevice
::
WriteOnly
);
st
<<
audioLevels
;
pCore
->
audioThumbCache
.
insert
(
key
,
audioData
);
qDebug
()
<<
"=== AUDIO THUMBS TOTAL : "
<<
pCore
->
audioThumbCache
.
totalSize
()
<<
" // "
<<
pCore
->
audioThumbCache
.
freeSize
();
return
audioLevels
;
}
...
...
src/bin/projectclip.h
View file @
9ba6eaa9
...
...
@@ -81,7 +81,7 @@ protected:
public:
~
ProjectClip
()
override
;
void
reloadProducer
(
bool
refreshOnly
=
false
,
bool
isProxy
=
false
);
void
reloadProducer
(
bool
refreshOnly
=
false
,
bool
isProxy
=
false
,
bool
forceAudioReload
=
false
);
/** @brief Returns a unique hash identifier used to store clip thumbnails. */
// virtual void hash() = 0;
...
...
@@ -225,7 +225,7 @@ public:
void
getThumbFromPercent
(
int
percent
);
/** @brief Return audio cache for a stream
*/
QVector
<
uint8_t
>
audioFrameCache
(
int
stream
=
-
1
);
const
QVector
<
uint8_t
>
audioFrameCache
(
int
stream
=
-
1
);
/** @brief Return FFmpeg's audio stream index for an MLT audio stream index
*/
int
getAudioStreamFfmpegIndex
(
int
mltStream
);
...
...
@@ -288,6 +288,7 @@ private:
QFuture
<
void
>
m_thumbThread
;
QList
<
int
>
m_requestedThumbs
;
const
QString
geometryWithOffset
(
const
QString
&
data
,
int
offset
);
QMap
<
QString
,
QByteArray
>
m_audioLevels
;
// This is a helper function that creates the disabled producer. This is a clone of the original one, with audio and video disabled
void
createDisabledMasterProducer
();
...
...
src/bin/projectitemmodel.cpp
View file @
9ba6eaa9
...
...
@@ -393,9 +393,6 @@ std::shared_ptr<ProjectClip> ProjectItemModel::getClipByBinID(const QString &bin
const
QVector
<
uint8_t
>
ProjectItemModel
::
getAudioLevelsByBinID
(
const
QString
&
binId
,
int
stream
)
{
READ_LOCK
();
if
(
binId
.
contains
(
QLatin1Char
(
'_'
)))
{
return
getAudioLevelsByBinID
(
binId
.
section
(
QLatin1Char
(
'_'
),
0
,
0
),
stream
);
}
for
(
const
auto
&
clip
:
m_allItems
)
{
auto
c
=
std
::
static_pointer_cast
<
AbstractProjectItem
>
(
clip
.
second
.
lock
());
if
(
c
->
itemType
()
==
AbstractProjectItem
::
ClipItem
&&
c
->
clipId
()
==
binId
)
{
...
...
src/core.cpp
View file @
9ba6eaa9
...
...
@@ -44,7 +44,8 @@ the Free Software Foundation, either version 3 of the License, or
std
::
unique_ptr
<
Core
>
Core
::
m_self
;
Core
::
Core
()
:
m_thumbProfile
(
nullptr
)
:
audioThumbCache
(
QStringLiteral
(
"audioCache"
),
2000000
)
,
m_thumbProfile
(
nullptr
)
,
m_capture
(
new
MediaCapture
(
this
))
{
}
...
...
src/core.h
View file @
9ba6eaa9
...
...
@@ -20,6 +20,7 @@ the Free Software Foundation, either version 3 of the License, or
#include <QUrl>
#include <memory>
#include <QPoint>
#include <KSharedDataCache>
#include "timecode.h"
class
Bin
;
...
...
@@ -226,6 +227,7 @@ public:
int
audioChannels
();
/** @brief Add guides in the project. */
void
addGuides
(
QList
<
int
>
guides
);
KSharedDataCache
audioThumbCache
;
private:
explicit
Core
();
...
...
src/lib/audio/audioStreamInfo.cpp
View file @
9ba6eaa9
...
...
@@ -121,6 +121,14 @@ QMap <int, int> AudioStreamInfo::streamChannels() const
return
m_audioChannels
;
}
int
AudioStreamInfo
::
channelsForStream
(
int
stream
)
const
{
if
(
m_audioChannels
.
contains
(
stream
))
{
return
m_audioChannels
.
value
(
stream
);
}
return
m_channels
;
}
QList
<
int
>
AudioStreamInfo
::
activeStreamChannels
()
const
{
if
(
m_activeStreams
.
size
()
==
1
&&
m_activeStreams
.
contains
(
INT_MAX
))
{
...
...
src/lib/audio/audioStreamInfo.h
View file @
9ba6eaa9
...
...
@@ -32,6 +32,8 @@ public:
QMap
<
int
,
QString
>
streams
()
const
;
/** @brief returns a list of audio stream index > channels per stream */
QMap
<
int
,
int
>
streamChannels
()
const
;
/** @brief returns the channel count for a stream */
int
channelsForStream
(
int
stream
)
const
;
/** @brief returns a list of audio channels per active stream */
QList
<
int
>
activeStreamChannels
()
const
;
/** @brief returns a list of enabled audio stream indexes > stream description */
...
...
src/monitor/view/kdenliveclipmonitor.qml
View file @
9ba6eaa9
...
...
@@ -261,13 +261,15 @@ Item {
}
property
double
streamHeight
:
audioThumb
.
height
/
streamThumb
.
count
Item
{
anchors.fill
:
parent
TimelineWaveform
{
width
:
audioThumb
.
width
anchors.right
:
parent
.
right
anchors.left
:
parent
.
left
height
:
streamThumb
.
streamHeight
y
:
model
.
index
*
height
channels
:
controller
.
audioChannels
[
model
.
index
]
binId
:
controller
.
clipId
audioStream
:
controller
.
audioStreams
[
model
.
index
]
//clipRoot.audioStream
audioStream
:
controller
.
audioStreams
[
model
.
index
]
isFirstChunk
:
false
showItem
:
audioThumb
.
visible
format
:
controller
.
audioThumbFormat
...
...
src/project/projectmanager.cpp
View file @
9ba6eaa9
...
...
@@ -264,6 +264,7 @@ bool ProjectManager::closeCurrentDocument(bool saveChanges, bool quit)
break
;
}
}
pCore
->
audioThumbCache
.
clear
();
pCore
->
jobManager
()
->
slotCancelJobs
();
disconnect
(
pCore
->
window
()
->
getMainTimeline
()
->
controller
(),
&
TimelineController
::
durationChanged
,
this
,
&
ProjectManager
::
adjustProjectDuration
);
pCore
->
window
()
->
getMainTimeline
()
->
controller
()
->
clipActions
.
clear
();
...
...
src/timeline2/view/qml/timelineitems.cpp
View file @
9ba6eaa9
...
...
@@ -104,8 +104,13 @@ public:
//setMipmap(true);
setTextureSize
(
QSize
(
1
,
1
));
connect
(
this
,
&
TimelineWaveform
::
levelsChanged
,
[
&
]()
{
if
(
!
m_binId
.
isEmpty
()
&&
m_audioLevels
.
isEmpty
()
&&
m_stream
>=
0
)
{
update
();
if
(
!
m_binId
.
isEmpty
())
{
if
(
m_audioLevels
.
isEmpty
()
&&
m_stream
>=
0
)
{
update
();
}
else
{
// Clip changed, reset levels
m_audioLevels
.
clear
();
}
}
});
connect
(
this
,
&
TimelineWaveform
::
propertyChanged
,
[
&
]()
{
...
...
@@ -140,7 +145,6 @@ public:
}
}
qreal
indicesPrPixel
=
qreal
(
m_outPoint
-
m_inPoint
)
/
width
()
*
m_precisionFactor
;
//qDebug()<<"== GOT DIMENSIONS FOR WAVE: "<<m_inPoint<<"-"<<m_outPoint<<", WID: "<<width();
QPen
pen
=
painter
->
pen
();
pen
.
setColor
(
m_color
);
painter
->
setBrush
(
m_color
);
...
...
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