shotcut: update to 26.2.26

This commit is contained in:
zlice
2026-03-17 00:16:27 +01:00
committed by Duncan Overbruck
parent 725ad105d7
commit 2c552a03de
2 changed files with 2 additions and 169 deletions
@@ -1,167 +0,0 @@
From 9c022acb7356c92f73280a9c17f424b4b3945a4e Mon Sep 17 00:00:00 2001
From: Dan Dennedy <dan@dennedy.org>
Date: Thu, 12 Feb 2026 18:45:22 -0800
Subject: [PATCH] Fix #1786 timeline waveform crash on long video
This is not an obvious direct fix. After reproduciung it, I looked for a way to make the existing code more efficient and then the problem went away. Maybe the old approach was having a problem with a QVariantList on Qt 6.10.1. A vector of uchar is more efficient by less data, less conversions, and less copies during conversion.
---
src/models/audiolevelstask.cpp | 38 +++++++++++++++++-----------------
src/models/multitrackmodel.cpp | 4 ++--
src/qmltypes/timelineitems.cpp | 11 +++++-----
3 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/src/models/audiolevelstask.cpp b/src/models/audiolevelstask.cpp
index b88da67a94..f57adf7d78 100644
--- a/src/models/audiolevelstask.cpp
+++ b/src/models/audiolevelstask.cpp
@@ -32,14 +32,14 @@
#include <QString>
#include <QThreadPool>
#include <QTime>
-#include <QVariantList>
+#include <QVector>
static QList<AudioLevelsTask *> tasksList;
static QMutex tasksListMutex;
-static void deleteQVariantList(QVariantList *list)
+static void deleteAudioLevels(QVector<uchar> *levels)
{
- delete list;
+ delete levels;
}
AudioLevelsTask::AudioLevelsTask(Mlt::Producer &producer, QObject *object, const QModelIndex &index)
@@ -172,7 +172,7 @@ QString AudioLevelsTask::cacheKey()
void AudioLevelsTask::run()
{
// 2 channels interleaved of uchar values
- QVariantList levels;
+ QVector<uchar> levels;
QImage image = DB.getThumbnail(cacheKey());
if (image.isNull() || m_isForce) {
const char *key[2] = {"meta.media.audio_level.0", "meta.media.audio_level.1"};
@@ -203,9 +203,9 @@ void AudioLevelsTask::run()
frame->get_audio(format, frequency, channels, samples);
// for each channel
for (int channel = 0; channel < channels; channel++)
- // Convert real to uint for caching as image.
+ // Convert real to uchar for caching as image.
// Scale by 0.9 because values may exceed 1.0 to indicate clipping.
- levels << 256 * qMin(frame->get_double(key[channel]) * 0.9, 1.0);
+ levels << uchar(qBound(0.0, 256.0 * frame->get_double(key[channel]) * 0.9, 255.0));
} else if (!levels.isEmpty()) {
for (int channel = 0; channel < channels; channel++)
levels << levels.last();
@@ -216,12 +216,12 @@ void AudioLevelsTask::run()
if (updateTime.elapsed() > 3 * 1000 && !m_isCanceled) {
updateTime.restart();
foreach (ProducerAndIndex p, m_producers) {
- QVariantList *levelsCopy = new QVariantList(levels);
+ QVector<uchar> *levelsCopy = new QVector<uchar>(levels);
p.first->lock();
p.first->set(kAudioLevelsProperty,
levelsCopy,
0,
- (mlt_destructor) deleteQVariantList);
+ (mlt_destructor) deleteAudioLevels);
p.first->unlock();
if (-1
!= m_object->metaObject()->indexOfMethod(
@@ -240,16 +240,16 @@ void AudioLevelsTask::run()
for (int i = 0; i < n; i++) {
QRgb p;
if ((4 * i + 3) < count) {
- p = qRgba(levels.at(4 * i).toInt(),
- levels.at(4 * i + 1).toInt(),
- levels.at(4 * i + 2).toInt(),
- levels.at(4 * i + 3).toInt());
+ p = qRgba(levels.at(4 * i),
+ levels.at(4 * i + 1),
+ levels.at(4 * i + 2),
+ levels.at(4 * i + 3));
} else {
- int last = levels.last().toInt();
- int r = (4 * i + 0) < count ? levels.at(4 * i + 0).toInt() : last;
- int g = (4 * i + 1) < count ? levels.at(4 * i + 1).toInt() : last;
- int b = (4 * i + 2) < count ? levels.at(4 * i + 2).toInt() : last;
- int a = last;
+ uchar last = levels.last();
+ uchar r = (4 * i + 0) < count ? levels.at(4 * i + 0) : last;
+ uchar g = (4 * i + 1) < count ? levels.at(4 * i + 1) : last;
+ uchar b = (4 * i + 2) < count ? levels.at(4 * i + 2) : last;
+ uchar a = last;
p = qRgba(r, g, b, a);
}
image.setPixel(i / 2, i % channels, p);
@@ -294,9 +294,9 @@ void AudioLevelsTask::run()
if (levels.size() > 0 && !m_isCanceled) {
foreach (ProducerAndIndex p, m_producers) {
- QVariantList *levelsCopy = new QVariantList(levels);
+ QVector<uchar> *levelsCopy = new QVector<uchar>(levels);
p.first->lock();
- p.first->set(kAudioLevelsProperty, levelsCopy, 0, (mlt_destructor) deleteQVariantList);
+ p.first->set(kAudioLevelsProperty, levelsCopy, 0, (mlt_destructor) deleteAudioLevels);
p.first->unlock();
if (-1
!= m_object->metaObject()->indexOfMethod("audioLevelsReady(QPersistentModelIndex)"))
diff --git a/src/models/multitrackmodel.cpp b/src/models/multitrackmodel.cpp
index 1b50e38b07..a5518ec087 100644
--- a/src/models/multitrackmodel.cpp
+++ b/src/models/multitrackmodel.cpp
@@ -155,8 +155,8 @@ QVariant MultitrackModel::data(const QModelIndex &index, int role) const
if (info->producer && info->producer->is_valid()) {
info->producer->lock();
if (info->producer->get_data(kAudioLevelsProperty)) {
- result = QVariant::fromValue(
- *((QVariantList *) info->producer->get_data(kAudioLevelsProperty)));
+ result = QVariant::fromValue(*(
+ (QVector<uchar> *) info->producer->get_data(kAudioLevelsProperty)));
}
info->producer->unlock();
}
diff --git a/src/qmltypes/timelineitems.cpp b/src/qmltypes/timelineitems.cpp
index 960b7e306d..e47194db12 100644
--- a/src/qmltypes/timelineitems.cpp
+++ b/src/qmltypes/timelineitems.cpp
@@ -92,7 +92,7 @@ class TimelineTriangle : public QQuickPaintedItem
class TimelineWaveform : public QQuickPaintedItem
{
Q_OBJECT
- Q_PROPERTY(QVariant levels MEMBER m_audioLevels NOTIFY propertyChanged)
+ Q_PROPERTY(QVector<uchar> 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 outPoint MEMBER m_outPoint NOTIFY outPointChanged)
@@ -112,8 +112,7 @@ class TimelineWaveform : public QQuickPaintedItem
{
if (!m_isActive)
return;
- QVariantList data = m_audioLevels.toList();
- if (data.isEmpty())
+ if (m_audioLevels.isEmpty())
return;
// In and out points are # frames at current fps,
@@ -130,9 +129,9 @@ class TimelineWaveform : public QQuickPaintedItem
int i = 0;
for (; i < width(); ++i) {
int idx = inPoint + int(i * indicesPrPixel);
- if ((idx < 0) || (idx + 2 >= data.length()))
+ if ((idx < 0) || (idx + 2 >= m_audioLevels.size()))
break;
- qreal level = qMax(data.at(idx).toReal(), data.at(idx + 1).toReal()) / 256;
+ qreal level = qMax(m_audioLevels[idx], m_audioLevels[idx + 1]) / 256.0;
path.lineTo(i, height() - level * height());
}
path.lineTo(i, height());
@@ -149,7 +148,7 @@ class TimelineWaveform : public QQuickPaintedItem
void outPointChanged();
private:
- QVariant m_audioLevels;
+ QVector<uchar> m_audioLevels;
int m_inPoint;
int m_outPoint;
QColor m_color;
+2 -2
View File
@@ -1,6 +1,6 @@
# Template file for 'shotcut'
pkgname=shotcut
version=26.1.30
version=26.2.26
revision=1
build_style=cmake
configure_args="-DSHOTCUT_VERSION=${version}"
@@ -15,6 +15,6 @@ license="GPL-3.0-or-later"
homepage="https://www.shotcut.org"
changelog="https://github.com/mltframework/shotcut/releases"
distfiles="https://github.com/mltframework/shotcut/archive/v${version}.tar.gz"
checksum=921c3c927033fe85bbe0cf28ce62fd62b01b56d6a2926093643291928a7b76cc
checksum=b5c840a459eaf4ad9e0ad7a02d782678207f9102cfce7f129f413fe2c0cb3ca8
CXXFLAGS="-DHAVE_LOCALE_H=1 -DSHOTCUT_NOUPGRADE"