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
ca7fefe9
Commit
ca7fefe9
authored
May 13, 2020
by
Jean-Baptiste Mardelle
Browse files
Some audio thumbnail optimizations
parent
211a9eae
Pipeline
#20118
passed with stage
in 9 minutes and 30 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/bin/projectclip.cpp
View file @
ca7fefe9
...
...
@@ -1551,15 +1551,15 @@ QVector <uint8_t> ProjectClip::audioFrameCache(int stream)
const
QString
cachePath
=
getAudioThumbPath
(
stream
);
// checking for cached thumbs
QImage
image
(
cachePath
);
int
channels
=
m_audioInfo
->
channels
();
if
(
!
image
.
isNull
())
{
int
channels
=
m_audioInfo
->
channels
();
int
n
=
image
.
width
()
*
image
.
height
();
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
QRgb
p
=
image
.
pixel
(
i
/
channels
,
i
%
channels
);
audioLevels
<<
qRed
(
p
);
audioLevels
<<
qGreen
(
p
);
audioLevels
<<
qBlue
(
p
);
audioLevels
<<
qAlpha
(
p
);
audioLevels
<<
(
uint8_t
)
qRed
(
p
);
audioLevels
<<
(
uint8_t
)
qGreen
(
p
);
audioLevels
<<
(
uint8_t
)
qBlue
(
p
);
audioLevels
<<
(
uint8_t
)
qAlpha
(
p
);
}
}
return
audioLevels
;
...
...
src/jobs/audiothumbjob.cpp
View file @
ca7fefe9
...
...
@@ -328,7 +328,7 @@ bool AudioThumbJob::startJob()
m_channels
=
m_binClip
->
audioInfo
()
->
channels
();
m_channels
=
m_channels
<=
0
?
2
:
m_channels
;
m_lengthInFrames
=
m_prod
->
get_length
();
m_lengthInFrames
=
m_prod
->
get_length
();
// Multiply this if we want more than 1 sample per frame
QMap
<
int
,
QString
>
streams
=
m_binClip
->
audioInfo
()
->
streams
();
if
((
m_prod
==
nullptr
)
||
!
m_prod
->
is_valid
())
{
m_errorMessage
.
append
(
i18n
(
"Audio thumbs: cannot open project file %1"
,
m_binClip
->
url
()));
...
...
src/timeline2/view/qml/ClipAudioThumbs.qml
View file @
ca7fefe9
...
...
@@ -47,8 +47,10 @@ Row {
binId
:
clipRoot
.
binId
audioStream
:
Math
.
abs
(
clipRoot
.
audioStream
)
isFirstChunk
:
index
==
0
showItem
:
waveform
.
visible
&&
(
index
*
waveform
.
maxWidth
<
(
clipRoot
.
scrollStart
+
scrollView
.
contentItem
.
width
))
&&
((
index
*
waveform
.
maxWidth
+
width
)
>
clipRoot
.
scrollStart
)
showItem
:
waveform
.
visible
&&
(
index
*
waveform
.
maxWidth
<
(
clipRoot
.
scrollStart
+
scrollView
.
width
))
&&
((
index
*
waveform
.
maxWidth
+
width
)
>
clipRoot
.
scrollStart
)
format
:
timeline
.
audioThumbFormat
drawInPoint
:
Math
.
max
(
0
,
clipRoot
.
scrollStart
-
(
index
*
waveform
.
maxWidth
))
drawOutPoint
:
(
clipRoot
.
scrollStart
+
scrollView
.
width
-
(
index
*
waveform
.
maxWidth
))
waveInPoint
:
clipRoot
.
speed
<
0
?
(
Math
.
round
(
clipRoot
.
outPoint
-
(
index
*
waveform
.
maxWidth
/
clipRoot
.
timeScale
)
*
Math
.
abs
(
clipRoot
.
speed
))
*
channels
)
:
(
Math
.
round
((
clipRoot
.
inPoint
+
(
index
*
waveform
.
maxWidth
/
clipRoot
.
timeScale
))
*
clipRoot
.
speed
)
*
channels
)
waveOutPoint
:
clipRoot
.
speed
<
0
?
(
waveInPoint
-
Math
.
ceil
(
width
/
clipRoot
.
timeScale
*
Math
.
abs
(
clipRoot
.
speed
))
*
channels
)
:
(
waveInPoint
+
Math
.
round
(
width
/
clipRoot
.
timeScale
*
clipRoot
.
speed
)
*
channels
)
fillColor
:
activePalette
.
text
...
...
src/timeline2/view/qml/ClipThumbs.qml
View file @
ca7fefe9
...
...
@@ -40,7 +40,7 @@ Row {
cache
:
enableCache
property
int
currentFrame
:
fixedThumbs
?
0
:
thumbRepeater
.
count
<
3
?
(
index
==
0
?
thumbRepeater
.
thumbStartFrame
:
thumbRepeater
.
thumbEndFrame
)
:
Math
.
floor
(
clipRoot
.
inPoint
+
Math
.
round
((
index
)
*
width
/
timeline
.
scaleFactor
)
*
clipRoot
.
speed
)
horizontalAlignment
:
thumbRepeater
.
count
<
3
?
(
index
==
0
?
Image
.
AlignLeft
:
Image
.
AlignRight
)
:
Image
.
AlignLeft
source
:
thumbRepeater
.
count
<
3
?
(
clipRoot
.
baseThumbPath
+
currentFrame
)
:
(
index
*
width
<
clipRoot
.
scrollStart
-
width
||
index
*
width
>
clipRoot
.
scrollStart
+
scrollView
.
contentItem
.
width
)
?
''
:
clipRoot
.
baseThumbPath
+
currentFrame
source
:
thumbRepeater
.
count
<
3
?
(
clipRoot
.
baseThumbPath
+
currentFrame
)
:
(
index
*
width
<
clipRoot
.
scrollStart
-
width
||
index
*
width
>
clipRoot
.
scrollStart
+
scrollView
.
width
)
?
''
:
clipRoot
.
baseThumbPath
+
currentFrame
onStatusChanged
:
{
if
(
thumbRepeater
.
count
<
3
)
{
if
(
status
===
Image
.
Ready
)
{
...
...
src/timeline2/view/qml/Track.qml
View file @
ca7fefe9
...
...
@@ -236,7 +236,7 @@ Item{
item
.
audioChannels
=
model
.
audioChannels
item
.
audioStream
=
model
.
audioStream
item
.
aStreamIndex
=
model
.
audioStreamIndex
console
.
log
(
'
loaded cl
p
i with Astream:
'
,
model
.
audioStream
)
console
.
log
(
'
loaded cli
p
with Astream:
'
,
model
.
audioStream
)
// Speed change triggers a new clip insert so no binding necessary
item
.
speed
=
model
.
speed
}
else
if
(
model
.
clipType
==
ProducerType
.
Composition
)
{
...
...
src/timeline2/view/qml/timelineitems.cpp
View file @
ca7fefe9
...
...
@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QPainter>
#include <QPainterPath>
#include <QQuickPaintedItem>
#include <QElapsedTimer>
#include <cmath>
const
QStringList
chanelNames
{
"L"
,
"R"
,
"C"
,
"LFE"
,
"BL"
,
"BR"
};
...
...
@@ -79,6 +80,8 @@ class TimelineWaveform : public QQuickPaintedItem
Q_OBJECT
Q_PROPERTY
(
QColor
fillColor
MEMBER
m_color
NOTIFY
propertyChanged
)
Q_PROPERTY
(
int
waveInPoint
MEMBER
m_inPoint
NOTIFY
propertyChanged
)
Q_PROPERTY
(
int
drawInPoint
MEMBER
m_drawInPoint
NOTIFY
propertyChanged
)
Q_PROPERTY
(
int
drawOutPoint
MEMBER
m_drawOutPoint
NOTIFY
propertyChanged
)
Q_PROPERTY
(
int
channels
MEMBER
m_channels
NOTIFY
audioChannelsChanged
)
Q_PROPERTY
(
QString
binId
MEMBER
m_binId
NOTIFY
levelsChanged
)
Q_PROPERTY
(
int
waveOutPoint
MEMBER
m_outPoint
)
...
...
@@ -94,12 +97,12 @@ public:
// setClip(true);
setEnabled
(
false
);
m_showItem
=
false
;
m_precisionFactor
=
1
;
//setRenderTarget(QQuickPaintedItem::FramebufferObject);
//setMipmap(true);
setTextureSize
(
QSize
(
1
,
1
));
connect
(
this
,
&
TimelineWaveform
::
levelsChanged
,
[
&
]()
{
if
(
!
m_binId
.
isEmpty
()
&&
m_audioLevels
.
isEmpty
()
&&
m_stream
>=
0
)
{
m_audioLevels
=
pCore
->
projectItemModel
()
->
getAudioLevelsByBinID
(
m_binId
,
m_stream
);
update
();
}
});
...
...
@@ -107,7 +110,6 @@ public:
update
();
});
}
bool
showItem
()
const
{
return
m_showItem
;
...
...
@@ -135,80 +137,115 @@ public:
return
;
}
}
qreal
indicesPrPixel
=
qreal
(
m_outPoint
-
m_inPoint
)
/
width
();
qreal
indicesPrPixel
=
qreal
(
m_outPoint
-
m_inPoint
)
/
width
()
*
m_precisionFactor
;
//qDebug()<<"== GOT DIMENSIONS FOR WAVE: "<<(m_outPoint - m_inPoint)<<", WID: "<<width();
QPen
pen
=
painter
->
pen
();
pen
.
setColor
(
m_color
);
pen
.
setWidthF
(
0
);
painter
->
setBrush
(
m_color
);
pen
.
setCapStyle
(
Qt
::
FlatCap
);
double
increment
=
qMax
(
1.
,
1.
/
qAbs
(
indicesPrPixel
));
int
h
=
height
();
double
offset
=
0
;
bool
pathDraw
=
increment
>
1.2
;
if
(
increment
>
1.
&&
!
pathDraw
)
{
pen
.
setWidth
(
ceil
(
increment
));
offset
=
pen
.
width
()
/
2.
;
}
else
if
(
pathDraw
)
{
pen
.
setWidthF
(
0
);
}
painter
->
setPen
(
pen
);
QPainterPath
path
;
if
(
!
KdenliveSettings
::
displayallchannels
())
{
// Draw merged channels
QPainterPath
path
;
path
.
moveTo
(
-
1
,
height
());
double
i
=
0
;
double
increment
=
qMax
(
1.
,
1
/
qAbs
(
indicesPrPixel
));
double
level
;
int
lastIdx
=
-
1
;
for
(;
i
<=
width
();
i
+=
increment
)
{
int
idx
=
m_inPoint
+
int
(
i
*
indicesPrPixel
);
int
j
=
0
;
if
(
m_drawInPoint
>
0
)
{
j
=
m_drawInPoint
/
increment
;
}
if
(
pathDraw
)
{
path
.
moveTo
(
j
-
1
,
height
());
}
for
(;
i
<=
width
()
&&
i
<
m_drawOutPoint
;
j
++
)
{
i
=
j
*
increment
;
int
idx
=
m_precisionFactor
*
m_inPoint
+
int
(
i
*
indicesPrPixel
);
idx
+=
idx
%
m_channels
;
i
-=
offset
;
if
(
idx
+
m_channels
>=
m_audioLevels
.
length
()
||
idx
<
0
)
{
break
;
}
if
(
lastIdx
==
idx
)
{
continue
;
}
lastIdx
=
idx
;
level
=
m_audioLevels
.
at
(
idx
)
/
255.
;
for
(
int
j
=
1
;
j
<
m_channels
;
j
++
)
{
level
=
qMax
(
level
,
m_audioLevels
.
at
(
idx
+
j
)
/
255.
);
for
(
int
k
=
1
;
k
<
m_channels
;
k
++
)
{
level
=
qMax
(
level
,
m_audioLevels
.
at
(
idx
+
k
)
/
255.
);
}
if
(
pathDraw
)
{
path
.
lineTo
(
i
,
height
()
-
level
*
height
());
}
else
{
painter
->
drawLine
(
i
,
h
,
i
,
h
-
(
h
*
level
));
}
path
.
lineTo
(
i
,
height
()
-
level
*
height
());
}
path
.
lineTo
(
i
,
height
());
painter
->
drawPath
(
path
);
if
(
pathDraw
)
{
path
.
lineTo
(
i
,
height
());
painter
->
drawPath
(
path
);
}
}
else
{
double
channelHeight
=
height
()
/
(
2
*
m_channels
);
QFont
font
=
painter
->
font
();
font
.
setPixelSize
(
channelHeight
-
1
);
painter
->
setFont
(
font
);
double
channelHeight
=
(
double
)
height
()
/
m_channels
;
// Draw separate channels
double
i
=
0
;
double
increment
=
qMax
(
1.
,
1
/
indicesPrPixel
);
double
level
;
QRectF
bgRect
(
0
,
0
,
width
(),
2
*
channelHeight
);
QVector
<
QPainterPath
>
channelPaths
(
m_channels
);
QRectF
bgRect
(
0
,
0
,
width
(),
channelHeight
);
// Path for vector drawing
//qDebug()<<"==== DRAWING FROM: "<<m_drawInPoint<<" - "<<m_drawOutPoint<<", FIRST: "<<m_firstChunk;
for
(
int
channel
=
0
;
channel
<
m_channels
;
channel
++
)
{
double
y
=
height
()
-
(
2
*
channel
*
channelHeight
)
-
channelHeight
;
channelPaths
[
channel
].
moveTo
(
-
1
,
y
);
// y is channel median pos
double
y
=
(
channel
*
channelHeight
)
+
channelHeight
/
2
;
path
.
moveTo
(
-
1
,
y
);
painter
->
setOpacity
(
0.2
);
if
(
channel
%
2
==
0
)
{
// Add dark background on odd channels
bgRect
.
moveTo
(
0
,
y
-
channelHeight
);
bgRect
.
moveTo
(
0
,
channel
*
channelHeight
);
painter
->
fillRect
(
bgRect
,
Qt
::
black
);
}
// Draw channel median line
painter
->
setOpacity
(
0.5
);
pen
.
setWidthF
(
0
);
painter
->
setPen
(
pen
);
painter
->
drawLine
(
QLineF
(
0.
,
y
,
width
(),
y
));
pen
.
setWidth
(
ceil
(
increment
));
painter
->
setPen
(
pathDraw
?
Qt
::
NoPen
:
pen
);
painter
->
setOpacity
(
1
);
int
lastIdx
=
-
1
;
for
(
i
=
0
;
i
<=
width
();
i
+=
increment
)
{
int
idx
=
m_inPoint
+
ceil
(
i
*
indicesPrPixel
);
if
(
lastIdx
==
idx
)
{
continue
;
}
lastIdx
=
idx
;
i
=
0
;
int
j
=
0
;
if
(
m_drawInPoint
>
0
)
{
j
=
m_drawInPoint
/
increment
;
}
if
(
pathDraw
)
{
path
.
moveTo
(
m_drawInPoint
-
1
,
y
);
}
for
(;
i
<=
width
()
&&
i
<
m_drawOutPoint
;
j
++
)
{
i
=
j
*
increment
;
int
idx
=
m_precisionFactor
*
m_inPoint
+
ceil
(
i
*
indicesPrPixel
);
idx
+=
idx
%
m_channels
;
i
-=
offset
;
idx
+=
channel
;
if
(
idx
>=
m_audioLevels
.
length
()
||
idx
<
0
)
break
;
level
=
m_audioLevels
.
at
(
idx
)
*
channelHeight
/
255.
;
channelPaths
[
channel
].
lineTo
(
i
,
y
-
level
);
if
(
pathDraw
)
{
level
=
m_audioLevels
.
at
(
idx
)
*
channelHeight
/
510.
;
path
.
lineTo
(
i
,
y
-
level
);
}
else
{
level
=
m_audioLevels
.
at
(
idx
)
*
channelHeight
/
510.
;
// divide height by 510 (2*255) to get height
painter
->
drawLine
(
i
,
y
-
level
,
i
,
y
+
level
);
}
}
if
(
pathDraw
)
{
path
.
lineTo
(
i
,
y
);
painter
->
drawPath
(
path
);
QTransform
tr
(
1
,
0
,
0
,
-
1
,
0
,
2
*
y
);
painter
->
drawPath
(
tr
.
map
(
path
));
}
if
(
m_firstChunk
&&
m_channels
>
1
&&
m_channels
<
7
)
{
painter
->
drawText
(
2
,
y
+
channelHeight
,
chanelNames
[
channel
]);
painter
->
drawText
(
2
,
y
+
channelHeight
/
2
,
chanelNames
[
channel
]);
}
channelPaths
[
channel
].
lineTo
(
i
,
y
);
painter
->
setPen
(
Qt
::
NoPen
);
painter
->
drawPath
(
channelPaths
.
value
(
channel
));
QTransform
tr
(
1
,
0
,
0
,
-
1
,
0
,
2
*
y
);
painter
->
drawPath
(
tr
.
map
(
channelPaths
.
value
(
channel
)));
}
}
}
...
...
@@ -224,11 +261,15 @@ private:
QVector
<
uint8_t
>
m_audioLevels
;
int
m_inPoint
;
int
m_outPoint
;
// Pixels outside the view, can be dropped
int
m_drawInPoint
;
int
m_drawOutPoint
;
QString
m_binId
;
QColor
m_color
;
bool
m_format
;
bool
m_showItem
;
int
m_channels
;
int
m_precisionFactor
;
int
m_stream
;
bool
m_firstChunk
;
};
...
...
Eugen Mohr
@emohr
·
May 13, 2020
Developer
fix crash on
#382 (closed)
fix crash on #382
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