Fix huge memory consumption and inefficiency of audio thumbnails causing freeze on high zoom

parent 56815a21
......@@ -71,6 +71,7 @@ Rectangle {
property bool forceReloadThumb
property bool isComposition: false
property var groupTrimData
property int scrollStart: scrollView.flickableItem.contentX - clipRoot.modelStart * timeline.scaleFactor
width : clipDuration * timeScale;
opacity: dragProxyArea.drag.active && dragProxy.draggedItem == clipId ? 0.8 : 1.0
......@@ -164,9 +165,6 @@ Rectangle {
x = modelStart * timeScale;
width = clipDuration * timeScale;
labelRect.x = scrollX > modelStart * timeScale ? scrollX - modelStart * timeScale : 0
if (parentTrack && parentTrack.isAudio && thumbsLoader.item) {
thumbsLoader.item.reload();
}
}
onScrollXChanged: {
labelRect.x = scrollX > modelStart * timeScale ? scrollX - modelStart * timeScale : 0
......
......@@ -8,12 +8,8 @@ Row {
id: waveform
visible: clipStatus != ClipState.VideoOnly && parentTrack.isAudio && !parentTrack.isMute
opacity: clipStatus == ClipState.Disabled ? 0.2 : 1
property int maxWidth: 1000
property int maxWidth: 500 + 100 * timeline.scaleFactor
anchors.fill: parent
property int scrollStart: scrollView.flickableItem.contentX - clipRoot.modelStart * timeline.scaleFactor
property int scrollEnd: scrollStart + scrollView.viewport.width
property int scrollMin: scrollView.flickableItem.contentX / timeline.scaleFactor
property int scrollMax: scrollMin + scrollView.viewport.width / timeline.scaleFactor
Timer {
id: waveTimer
......@@ -21,18 +17,17 @@ Row {
onTriggered: processReload()
}
onScrollStartChanged: {
waveTimer.start()
}
function reload() {
waveTimer.start()
}
onMaxWidthChanged: {
waveTimer.start();
}
function processReload() {
// This is needed to make the model have the correct count.
// Model as a property expression is not working in all cases.
if (!waveform.visible || !timeline.showAudioThumbnails || (waveform.scrollMin > clipRoot.modelStart + clipRoot.clipDuration) || (clipRoot.modelStart > waveform.scrollMax)) {
if (!waveform.visible || !timeline.showAudioThumbnails) {
return;
}
var chunks = Math.ceil(waveform.width / waveform.maxWidth)
......@@ -49,16 +44,11 @@ Row {
channels: clipRoot.audioChannels
binId: clipRoot.binId
isFirstChunk: index == 0
showItem: waveform.visible && (index * width) < waveform.scrollEnd && (index * width + width) > waveform.scrollStart
showItem: waveform.visible && (index * waveform.maxWidth < clipRoot.scrollStart + scrollView.viewport.width) && (index * waveform.maxWidth + width > clipRoot.scrollStart)
format: timeline.audioThumbFormat
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
onShowItemChanged: {
if (showItem) {
update();
}
}
}
}
}
......@@ -10,8 +10,6 @@ Row {
visible: !isAudio
opacity: parentTrack.isAudio || parentTrack.isHidden || clipStatus == ClipState.Disabled ? 0.2 : 1
property int thumbWidth: container.height * 16.0/9.0
property int scrollStart: scrollView.flickableItem.contentX - clipRoot.modelStart * timeline.scaleFactor
property int scrollEnd: scrollStart + scrollView.viewport.width
property bool enableCache: clipRoot.itemType == ProducerType.Video || clipRoot.itemType == ProducerType.AV
function reload() {
......@@ -41,7 +39,7 @@ Row {
cache: enableCache
property int currentFrame: 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 ? (index == 0 ? clipRoot.baseThumbPath + thumbRepeater.thumbStartFrame : clipRoot.baseThumbPath + thumbRepeater.thumbEndFrame) : (index * width < thumbRow.scrollStart - width || index * width > thumbRow.scrollEnd) ? '' : clipRoot.baseThumbPath + currentFrame
source: thumbRepeater.count < 3 ? (index == 0 ? clipRoot.baseThumbPath + thumbRepeater.thumbStartFrame : clipRoot.baseThumbPath + thumbRepeater.thumbEndFrame) : (index * width < clipRoot.scrollStart - width || index * width > clipRoot.scrollStart + scrollView.viewport.width) ? '' : clipRoot.baseThumbPath + currentFrame
}
}
}
......@@ -249,7 +249,8 @@ Rectangle {
property int wheelAccumulatedDelta: 0
readonly property int defaultDeltasPerStep: 120
property bool seekingFinished : proxy.seekFinished
property int scrollMin: scrollView.flickableItem.contentX / timeline.scaleFactor
property int scrollMax: scrollMin + scrollView.viewport.width / timeline.scaleFactor
onSeekingFinishedChanged : {
playhead.opacity = seekingFinished ? 1 : 0.5
......
......@@ -83,7 +83,7 @@ class TimelineWaveform : public QQuickPaintedItem
Q_PROPERTY(QString binId MEMBER m_binId NOTIFY levelsChanged)
Q_PROPERTY(int waveOutPoint MEMBER m_outPoint)
Q_PROPERTY(bool format MEMBER m_format NOTIFY propertyChanged)
Q_PROPERTY(bool showItem MEMBER m_showItem NOTIFY showItemChanged)
Q_PROPERTY(bool showItem READ showItem WRITE setShowItem NOTIFY showItemChanged)
Q_PROPERTY(bool isFirstChunk MEMBER m_firstChunk)
public:
......@@ -92,9 +92,10 @@ public:
setAntialiasing(false);
// setClip(true);
setEnabled(false);
setRenderTarget(QQuickPaintedItem::FramebufferObject);
setMipmap(true);
setTextureSize(QSize(width(), height()));
m_showItem = false;
//setRenderTarget(QQuickPaintedItem::FramebufferObject);
//setMipmap(true);
setTextureSize(QSize(1, 1));
connect(this, &TimelineWaveform::levelsChanged, [&]() {
if (!m_binId.isEmpty() && m_audioLevels.isEmpty()) {
m_audioLevels = pCore->projectItemModel()->getAudioLevelsByBinID(m_binId);
......@@ -106,6 +107,22 @@ public:
});
}
bool showItem() const
{
return m_showItem;
}
void setShowItem(bool show)
{
m_showItem = show;
if (show) {
setTextureSize(QSize(width(), height()));
update();
} else {
// Free memory
setTextureSize(QSize(1, 1));
}
}
void paint(QPainter *painter) override
{
if (!m_showItem || m_binId.isEmpty()) {
......
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