Commit 40187949 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

First fixes for audio thumbs memory usage

parent 814bf013
Pipeline #1644 passed with stage
in 16 minutes and 7 seconds
......@@ -2926,8 +2926,7 @@ void Bin::slotSendAudioThumb(const QString &id)
if ((clip != nullptr) && clip->audioThumbCreated()) {
m_monitor->prepareAudioThumb(clip->audioChannels(), clip->audioFrameCache);
} else {
QVariantList list;
m_monitor->prepareAudioThumb(0, list);
m_monitor->prepareAudioThumb(0);
}
}
......
......@@ -194,13 +194,14 @@ QString ProjectClip::getXmlProperty(const QDomElement &producer, const QString &
return value;
}
void ProjectClip::updateAudioThumbnail(QVariantList audioLevels)
void ProjectClip::updateAudioThumbnail(QList <double>audioLevels)
{
std::swap(audioFrameCache, audioLevels); // avoid second copy
audioFrameCache = audioLevels;
m_audioThumbCreated = true;
if (auto ptr = m_model.lock()) {
emit std::static_pointer_cast<ProjectItemModel>(ptr)->refreshAudioThumbs(m_binId);
}
qDebug()<<" * ** * YOP AUDIO LEF CHANGED";
updateTimelineClips({TimelineModel::AudioLevelsRole});
}
......
......@@ -172,7 +172,7 @@ public:
/** Cache for every audio Frame with 10 Bytes */
/** format is frame -> channel ->bytes */
QVariantList audioFrameCache;
QList <double>audioFrameCache;
bool audioThumbCreated() const;
void setWaitingStatus(const QString &id);
......@@ -244,7 +244,7 @@ protected:
public slots:
/* @brief Store the audio thumbnails once computed. Note that the parameter is a value and not a reference, fill free to use it as a sink (use std::move to
* avoid copy). */
void updateAudioThumbnail(QVariantList audioLevels);
void updateAudioThumbnail(QList <double>audioLevels);
/** @brief Extract image thumbnails for timeline. */
void slotExtractImage(const QList<int> &frames);
/** @brief Delete the proxy file */
......
......@@ -341,6 +341,20 @@ std::shared_ptr<ProjectClip> ProjectItemModel::getClipByBinID(const QString &bin
return nullptr;
}
const QList <double>ProjectItemModel::getAudioLevelsByBinID(const QString &binId)
{
if (binId.contains(QLatin1Char('_'))) {
return getAudioLevelsByBinID(binId.section(QLatin1Char('_'), 0, 0));
}
for (const auto &clip : m_allItems) {
auto c = std::static_pointer_cast<AbstractProjectItem>(clip.second.lock());
if (c->itemType() == AbstractProjectItem::ClipItem && c->clipId() == binId) {
return std::static_pointer_cast<ProjectClip>(c)->audioFrameCache;
}
}
return QList <double>();
}
bool ProjectItemModel::hasClip(const QString &binId)
{
return getClipByBinID(binId) != nullptr;
......
......@@ -66,6 +66,8 @@ public:
/** @brief Returns a clip from the hierarchy, given its id */
std::shared_ptr<ProjectClip> getClipByBinID(const QString &binId);
/** @brief Returns audio levels for a clip from its id */
const QList <double>getAudioLevelsByBinID(const QString &binId);
/** @brief Returns a list of clips using the given url */
QStringList getClipByUrl(const QFileInfo &url) const;
......
......@@ -292,13 +292,13 @@ bool AudioThumbJob::startJob()
for (int i = 0; i < n; i++) {
QRgb p;
if ((4 * i + 3) < count) {
p = qRgba(m_audioLevels.at(4 * i).toInt(), m_audioLevels.at(4 * i + 1).toInt(), m_audioLevels.at(4 * i + 2).toInt(),
m_audioLevels.at(4 * i + 3).toInt());
p = qRgba(m_audioLevels.at(4 * i), m_audioLevels.at(4 * i + 1), m_audioLevels.at(4 * i + 2),
m_audioLevels.at(4 * i + 3));
} else {
int last = m_audioLevels.last().toInt();
int r = (4 * i + 0) < count ? m_audioLevels.at(4 * i + 0).toInt() : last;
int g = (4 * i + 1) < count ? m_audioLevels.at(4 * i + 1).toInt() : last;
int b = (4 * i + 2) < count ? m_audioLevels.at(4 * i + 2).toInt() : last;
int last = m_audioLevels.last();
int r = (4 * i + 0) < count ? m_audioLevels.at(4 * i + 0) : last;
int g = (4 * i + 1) < count ? m_audioLevels.at(4 * i + 1) : last;
int b = (4 * i + 2) < count ? m_audioLevels.at(4 * i + 2) : last;
int a = last;
p = qRgba(r, g, b, a);
}
......@@ -324,7 +324,7 @@ bool AudioThumbJob::commitResult(Fun &undo, Fun &redo)
if (!m_successful) {
return false;
}
QVariantList old = m_binClip->audioFrameCache;
QList <double>old = m_binClip->audioFrameCache;
// note that the image is moved into lambda, it won't be available from this class anymore
auto operation = [clip = m_binClip, audio = std::move(m_audioLevels)]() {
......
......@@ -68,6 +68,6 @@ private:
bool m_done{false}, m_successful{false};
int m_channels, m_frequency, m_lengthInFrames, m_audioStream;
QVariantList m_audioLevels;
QList <double>m_audioLevels;
QProcess *m_ffmpegProcess;
};
......@@ -1717,7 +1717,7 @@ void FrameRenderer::pipelineSyncToFrame(Mlt::Frame &frame)
#endif // Q_OS_WIN
}
void GLWidget::setAudioThumb(int channels, const QVariantList &audioCache)
void GLWidget::setAudioThumb(int channels, const QList <double>&audioCache)
{
if (!rootObject()) return;
......@@ -1740,9 +1740,9 @@ void GLWidget::setAudioThumb(int channels, const QVariantList &audioCache)
painter.setPen(QColor(80, 80, 150, 200));
for (int i = 0; i < img.width(); i++) {
int framePos = i / scale;
value = audioCache.at(qMin(framePos * channels, audioLevelCount)).toDouble() / 256;
value = audioCache.at(qMin(framePos * channels, audioLevelCount)) / 256;
for (int channel = 1; channel < channels; channel++) {
value = qMax(value, audioCache.at(qMin(framePos * channels + channel, audioLevelCount)).toDouble() / 256);
value = qMax(value, audioCache.at(qMin(framePos * channels + channel, audioLevelCount)) / 256);
}
painter.drawLine(i, mappedRect.bottom() - (value * channelHeight), i, mappedRect.bottom());
}
......@@ -1750,9 +1750,9 @@ void GLWidget::setAudioThumb(int channels, const QVariantList &audioCache)
QPainterPath positiveChannelPath;
positiveChannelPath.moveTo(0, mappedRect.bottom());
for (int i = 0; i < audioLevelCount / channels; i++) {
value = audioCache.at(qMin(i * channels, audioLevelCount)).toDouble() / 256;
value = audioCache.at(qMin(i * channels, audioLevelCount)) / 256;
for (int channel = 1; channel < channels; channel++) {
value = qMax(value, audioCache.at(qMin(i * channels + channel, audioLevelCount)).toDouble() / 256);
value = qMax(value, audioCache.at(qMin(i * channels + channel, audioLevelCount)) / 256);
}
positiveChannelPath.lineTo(i * scale, mappedRect.bottom() - (value * channelHeight));
}
......
......@@ -116,7 +116,7 @@ public:
void lockMonitor();
void releaseMonitor();
int realTime() const;
void setAudioThumb(int channels = 0, const QVariantList &audioCache = QList<QVariant>());
void setAudioThumb(int channels = 0, const QList <double>&audioCache = QList<double>());
int droppedFrames() const;
void resetDrops();
bool checkFrameNumber(int pos, int offset);
......
......@@ -1999,7 +1999,7 @@ void Monitor::slotEditInlineMarker()
}
}
void Monitor::prepareAudioThumb(int channels, QVariantList &audioCache)
void Monitor::prepareAudioThumb(int channels, const QList <double>&audioCache)
{
m_glMonitor->setAudioThumb(channels, audioCache);
}
......
......@@ -139,7 +139,7 @@ public:
QAction *recAction();
void refreshIcons();
/** @brief Send audio thumb data to qml for on monitor display */
void prepareAudioThumb(int channels, QVariantList &audioCache);
void prepareAudioThumb(int channels, const QList <double>&audioCache = QList <double>());
void connectAudioSpectrum(bool activate);
/** @brief Set a property on the Qml scene **/
void setQmlProperty(const QString &name, const QVariant &value);
......
......@@ -276,7 +276,8 @@ QVariant TimelineItemModel::data(const QModelIndex &index, int role) const
return clip->getProperty("mlt_service");
break;
case AudioLevelsRole:
return clip->getAudioWaveform();
// Dumb property to trigger audio thumbs reload
return true;
case AudioChannelsRole:
return clip->audioChannels();
case HasAudio:
......
......@@ -51,12 +51,12 @@ Row {
width: Math.min(waveform.innerWidth, waveform.maxWidth)
height: waveform.height
channels: clipRoot.audioChannels
binId: clipRoot.binId
isFirstChunk: index == 0
showItem: waveform.visible && (index * width) < waveform.scrollEnd && (index * width + width) > waveform.scrollStart
format: timeline.audioThumbFormat
inPoint: Math.round((clipRoot.inPoint + (index * waveform.maxWidth / clipRoot.timeScale)) * Math.abs(clipRoot.speed)) * channels
outPoint: inPoint + Math.round(width / clipRoot.timeScale * Math.abs(clipRoot.speed)) * channels
levels: clipRoot.audioLevels
fillColor: activePalette.text
}
}
......
......@@ -21,6 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "kdenlivesettings.h"
#include "core.h"
#include "bin/projectitemmodel.h"
#include <QPainter>
#include <QPainterPath>
#include <QPalette>
......@@ -76,10 +78,10 @@ private:
class TimelineWaveform : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QList<QVariant> levels MEMBER m_audioLevels NOTIFY propertyChanged)
Q_PROPERTY(QColor fillColor MEMBER m_color NOTIFY propertyChanged)
Q_PROPERTY(int inPoint MEMBER m_inPoint NOTIFY inPointChanged)
Q_PROPERTY(int channels MEMBER m_channels NOTIFY audioChannelsChanged)
Q_PROPERTY(QString binId MEMBER m_binId NOTIFY levelsChanged)
Q_PROPERTY(int outPoint MEMBER m_outPoint NOTIFY outPointChanged)
Q_PROPERTY(bool format MEMBER m_format NOTIFY propertyChanged)
Q_PROPERTY(bool showItem MEMBER m_showItem)
......@@ -94,7 +96,15 @@ public:
setRenderTarget(QQuickPaintedItem::FramebufferObject);
setMipmap(true);
setTextureSize(QSize(width(), height()));
connect(this, SIGNAL(propertyChanged()), this, SLOT(update()));
connect(this, &TimelineWaveform::levelsChanged, [&]() {
qDebug()<<"* * ** WARNING AUDIO LEVELS CHANGED for: "<<m_inPoint<<"\n\n____________________\n\n________";
m_audioLevels = pCore->projectItemModel()->getAudioLevelsByBinID(m_binId);
update();
});
connect(this, &TimelineWaveform::propertyChanged, [&]() {
update();
});
//m_audioLevels = pCore->projectItemModel()->getAudioLevelsByBinID(m_binId);
}
void paint(QPainter *painter) override
......@@ -119,9 +129,9 @@ public:
}
lastIdx = idx;
if (idx + m_channels >= m_audioLevels.length()) break;
double level = m_audioLevels.at(idx).toDouble() / 256;
double level = m_audioLevels.at(idx) / 256;
for (int j = 1; j < m_channels; j++) {
level = qMax(level, m_audioLevels.at(idx + j).toDouble() / 256);
level = qMax(level, m_audioLevels.at(idx + j) / 256);
}
path.lineTo(i, height() - level * height());
}
......@@ -158,7 +168,7 @@ public:
}
lastIdx = idx;
if (idx + channel >= m_audioLevels.length()) break;
qreal level = m_audioLevels.at(idx + channel).toReal() * channelHeight / 256;
qreal level = m_audioLevels.at(idx + channel) * channelHeight / 256;
channelPaths[channel].lineTo(i, y - level);
}
if (m_firstChunk && m_channels > 1 && m_channels < 7) {
......@@ -174,15 +184,18 @@ public:
}
signals:
void levelsChanged();
void propertyChanged();
void inPointChanged();
void outPointChanged();
void audioChannelsChanged();
private:
QList<QVariant> m_audioLevels;
bool m_levels;
QList<double> m_audioLevels;
int m_inPoint;
int m_outPoint;
QString m_binId;
QColor m_color;
bool m_format;
bool m_showItem;
......
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