diff --git a/src/ui/MxcAnimatedImage.cpp b/src/ui/MxcAnimatedImage.cpp
index 90066fa0..8ecea7d9 100644
--- a/src/ui/MxcAnimatedImage.cpp
+++ b/src/ui/MxcAnimatedImage.cpp
@@ -8,7 +8,6 @@
#include <QDir>
#include <QFileInfo>
#include <QMimeDatabase>
-#include <QMovie>
#include <QQuickWindow>
#include <QSGImageNode>
#include <QStandardPaths>
@@ -35,12 +34,8 @@ MxcAnimatedImage::startDownload()
QByteArray mimeType = QString::fromStdString(mtx::accessors::mimetype(*event)).toUtf8();
- static const auto movieFormats = QMovie::supportedFormats();
- QByteArray imageFormat;
- const auto imageFormats = QImageReader::imageFormatsForMimeType(mimeType);
- if (!imageFormats.isEmpty())
- imageFormat = imageFormats.front();
- animatable_ = movieFormats.contains(imageFormat);
+ static const auto formats = QMovie::supportedFormats();
+ animatable_ = formats.contains(mimeType.split('/').back());
animatableChanged();
if (!animatable_)
@@ -71,14 +66,14 @@ MxcAnimatedImage::startDownload()
QPointer<MxcAnimatedImage> self = this;
- auto processBuffer = [this, imageFormat, encryptionInfo, self](QIODevice &device) {
+ auto processBuffer = [this, mimeType, encryptionInfo, self](QIODevice &device) {
if (!self)
return;
try {
if (buffer.isOpen()) {
- frameTimer.stop();
- movie->setDevice(nullptr);
+ movie.stop();
+ movie.setDevice(nullptr);
buffer.close();
}
@@ -97,22 +92,21 @@ MxcAnimatedImage::startDownload()
nhlog::net()->error("Failed to setup animated image buffer: {}", e.what());
}
- QTimer::singleShot(0, this, [this, imageFormat] {
+ QTimer::singleShot(0, this, [this, mimeType] {
nhlog::ui()->info(
"Playing movie with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
- movie->setFormat(imageFormat);
- movie->setDevice(&buffer);
+ movie.setFormat(mimeType);
+ movie.setDevice(&buffer);
if (height() != 0 && width() != 0)
- movie->setScaledSize(this->size().toSize());
-
- if (movie->supportsAnimation())
- frameTimer.setInterval(movie->nextImageDelay());
-
+ movie.setScaledSize(this->size().toSize());
+ if (buffer.bytesAvailable() <
+ 4LL * 1024 * 1024 * 1024) // cache images smaller than 4MB in RAM
+ movie.setCacheMode(QMovie::CacheAll);
if (play_)
- frameTimer.start();
+ movie.start();
else
- movie->jumpToImage(0);
+ movie.jumpToFrame(0);
emit loadedChanged();
update();
});
@@ -165,9 +159,9 @@ MxcAnimatedImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGe
if (newGeometry.size() != oldGeometry.size()) {
if (height() != 0 && width() != 0) {
- QSizeF r = movie->scaledSize();
+ QSizeF r = movie.scaledSize();
r.scale(newGeometry.size(), Qt::KeepAspectRatio);
- movie->setScaledSize(r.toSize());
+ movie.setScaledSize(r.toSize());
imageDirty = true;
update();
}
@@ -190,15 +184,16 @@ MxcAnimatedImage::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeD
n->setFlags(QSGNode::OwnedByParent);
}
- n->setSourceRect(currentFrame.rect());
- if (!currentFrame.isNull())
- n->setTexture(window()->createTextureFromImage(currentFrame));
+ auto img = movie.currentImage();
+ n->setSourceRect(img.rect());
+ if (!img.isNull())
+ n->setTexture(window()->createTextureFromImage(std::move(img)));
else {
delete n;
return nullptr;
}
- QSizeF r = currentFrame.size();
+ QSizeF r = img.size();
r.scale(size(), Qt::KeepAspectRatio);
n->setRect((width() - r.width()) / 2, (height() - r.height()) / 2, r.width(), r.height());
diff --git a/src/ui/MxcAnimatedImage.h b/src/ui/MxcAnimatedImage.h
index 2b067166..8891e57e 100644
--- a/src/ui/MxcAnimatedImage.h
+++ b/src/ui/MxcAnimatedImage.h
@@ -6,7 +6,7 @@
#pragma once
#include <QBuffer>
-#include <QImageReader>
+#include <QMovie>
#include <QObject>
#include <QQuickItem>
@@ -24,11 +24,10 @@ class MxcAnimatedImage : public QQuickItem
public:
MxcAnimatedImage(QQuickItem *parent = nullptr)
: QQuickItem(parent)
- , movie(new QImageReader())
{
connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload);
connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload);
- connect(&frameTimer, &QTimer::timeout, this, &MxcAnimatedImage::newFrame);
+ connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame);
setFlag(QQuickItem::ItemHasContents);
// setAcceptHoverEvents(true);
}
@@ -56,10 +55,7 @@ public:
{
if (play_ != newPlay) {
play_ = newPlay;
- if (play_)
- frameTimer.start();
- else
- frameTimer.stop();
+ movie.setPaused(!play_);
emit playChanged();
}
}
@@ -77,16 +73,10 @@ signals:
private slots:
void startDownload();
- void newFrame()
+ void newFrame(int frame)
{
- if (movie->currentImageNumber() > 0 && !movie->canRead() && movie->imageCount() > 1) {
- buffer.seek(0);
- movie.reset(new QImageReader(movie->device(), movie->format()));
- if (height() != 0 && width() != 0)
- movie->setScaledSize(this->size().toSize());
- }
- movie->read(¤tFrame);
- imageDirty = true;
+ currentFrame = frame;
+ imageDirty = true;
update();
}
@@ -96,9 +86,8 @@ private:
QString filename_;
bool animatable_ = false;
QBuffer buffer;
- std::unique_ptr<QImageReader> movie;
- bool imageDirty = true;
- bool play_ = true;
- QTimer frameTimer;
- QImage currentFrame;
+ QMovie movie;
+ int currentFrame = 0;
+ bool imageDirty = true;
+ bool play_ = true;
};
|