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

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