mirror of https://github.com/procxx/kepka.git
pausing gifs that are not currently displayed
This commit is contained in:
parent
322eef660e
commit
fdb93f700d
|
@ -2441,7 +2441,7 @@ namespace App {
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopGifItems() {
|
void stopGifItems() {
|
||||||
while (!::gifItems.isEmpty()) {
|
if (!::gifItems.isEmpty()) {
|
||||||
if (HistoryItem *playing = ::gifItems.begin().value()) {
|
if (HistoryItem *playing = ::gifItems.begin().value()) {
|
||||||
if (playing->getMedia() && playing->getMedia()->type() == MediaTypeGif) {
|
if (playing->getMedia() && playing->getMedia()->type() == MediaTypeGif) {
|
||||||
static_cast<HistoryGif*>(playing->getMedia())->stop(playing);
|
static_cast<HistoryGif*>(playing->getMedia())->stop(playing);
|
||||||
|
|
|
@ -83,8 +83,9 @@ enum {
|
||||||
LocalEncryptKeySize = 256, // 2048 bit
|
LocalEncryptKeySize = 256, // 2048 bit
|
||||||
|
|
||||||
AnimationTimerDelta = 7,
|
AnimationTimerDelta = 7,
|
||||||
ClipThreadsCount = 8,
|
ClipThreadsCount = 4,
|
||||||
AverageGifSize = 320 * 240,
|
AverageGifSize = 320 * 240,
|
||||||
|
WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it
|
||||||
|
|
||||||
SaveRecentEmojisTimeout = 3000, // 3 secs
|
SaveRecentEmojisTimeout = 3000, // 3 secs
|
||||||
SaveWindowPositionTimeout = 1000, // 1 sec
|
SaveWindowPositionTimeout = 1000, // 1 sec
|
||||||
|
|
|
@ -330,6 +330,8 @@ ClipReader::ClipReader(const FileLocation &location, const QByteArray &data) : _
|
||||||
, _width(0)
|
, _width(0)
|
||||||
, _height(0)
|
, _height(0)
|
||||||
, _currentDisplayed(1)
|
, _currentDisplayed(1)
|
||||||
|
, _paused(0)
|
||||||
|
, _lastDisplayMs(getms())
|
||||||
, _private(0) {
|
, _private(0) {
|
||||||
if (_clipThreads.size() < ClipThreadsCount) {
|
if (_clipThreads.size() < ClipThreadsCount) {
|
||||||
_threadIndex = _clipThreads.size();
|
_threadIndex = _clipThreads.size();
|
||||||
|
@ -365,8 +367,15 @@ void ClipReader::start(int32 framew, int32 frameh, int32 outerw, int32 outerh, b
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap ClipReader::current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms) {
|
QPixmap ClipReader::current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms) {
|
||||||
_currentDisplayed.storeRelease(1);
|
_lastDisplayMs.set(ms);
|
||||||
_lastDisplayMs = ms;
|
_currentDisplayed.set(true);
|
||||||
|
if (_paused.get()) {
|
||||||
|
_paused.set(false);
|
||||||
|
if (_clipManagers.size() <= _threadIndex) error();
|
||||||
|
if (_state != ClipError) {
|
||||||
|
_clipManagers.at(_threadIndex)->update(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32 factor(cIntRetinaFactor());
|
int32 factor(cIntRetinaFactor());
|
||||||
QPixmap result(_current);
|
QPixmap result(_current);
|
||||||
|
@ -441,8 +450,10 @@ public:
|
||||||
, _accessed(false)
|
, _accessed(false)
|
||||||
, _buffer(_data.isEmpty() ? 0 : &_data)
|
, _buffer(_data.isEmpty() ? 0 : &_data)
|
||||||
, _reader(0)
|
, _reader(0)
|
||||||
|
, _previousMs(0)
|
||||||
, _currentMs(0)
|
, _currentMs(0)
|
||||||
, _nextUpdateMs(0) {
|
, _nextUpdateMs(0)
|
||||||
|
, _paused(false) {
|
||||||
|
|
||||||
if (_data.isEmpty() && !_location->accessEnable()) {
|
if (_data.isEmpty() && !_location->accessEnable()) {
|
||||||
error();
|
error();
|
||||||
|
@ -476,6 +487,7 @@ public:
|
||||||
if (_current.isNull()) { // first frame read, but not yet prepared
|
if (_current.isNull()) { // first frame read, but not yet prepared
|
||||||
_currentOriginal.setDevicePixelRatio(_request.factor);
|
_currentOriginal.setDevicePixelRatio(_request.factor);
|
||||||
|
|
||||||
|
_previousMs = _currentMs;
|
||||||
_currentMs = ms;
|
_currentMs = ms;
|
||||||
_current = _prepareFrame(_request, _currentOriginal, _currentCache, true);
|
_current = _prepareFrame(_request, _currentOriginal, _currentCache, true);
|
||||||
|
|
||||||
|
@ -483,7 +495,7 @@ public:
|
||||||
return error();
|
return error();
|
||||||
}
|
}
|
||||||
return ClipProcessStarted;
|
return ClipProcessStarted;
|
||||||
} else if (ms >= _nextUpdateMs) {
|
} else if (!_paused && ms >= _nextUpdateMs) {
|
||||||
swapBuffers();
|
swapBuffers();
|
||||||
return ClipProcessRedraw;
|
return ClipProcessRedraw;
|
||||||
}
|
}
|
||||||
|
@ -508,6 +520,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void swapBuffers(uint64 ms = 0) {
|
void swapBuffers(uint64 ms = 0) {
|
||||||
|
_previousMs = _currentMs;
|
||||||
_currentMs = qMax(ms, _nextUpdateMs);
|
_currentMs = qMax(ms, _nextUpdateMs);
|
||||||
qSwap(_currentOriginal, _nextOriginal);
|
qSwap(_currentOriginal, _nextOriginal);
|
||||||
qSwap(_current, _next);
|
qSwap(_current, _next);
|
||||||
|
@ -628,13 +641,15 @@ private:
|
||||||
QImage _currentOriginal, _nextOriginal, _currentCache, _nextCache;
|
QImage _currentOriginal, _nextOriginal, _currentCache, _nextCache;
|
||||||
|
|
||||||
int32 _framesLeft;
|
int32 _framesLeft;
|
||||||
uint64 _currentMs, _nextUpdateMs;
|
uint64 _previousMs, _currentMs, _nextUpdateMs;
|
||||||
|
|
||||||
|
bool _paused;
|
||||||
|
|
||||||
friend class ClipReadManager;
|
friend class ClipReadManager;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ClipReadManager::ClipReadManager(QThread *thread) : _processingInThread(0) {
|
ClipReadManager::ClipReadManager(QThread *thread) : _processingInThread(0), _needReProcess(false) {
|
||||||
moveToThread(thread);
|
moveToThread(thread);
|
||||||
connect(thread, SIGNAL(started()), this, SLOT(process()));
|
connect(thread, SIGNAL(started()), this, SLOT(process()));
|
||||||
connect(this, SIGNAL(processDelayed()), this, SLOT(process()), Qt::QueuedConnection);
|
connect(this, SIGNAL(processDelayed()), this, SLOT(process()), Qt::QueuedConnection);
|
||||||
|
@ -669,7 +684,7 @@ void ClipReadManager::stop(ClipReader *reader) {
|
||||||
emit processDelayed();
|
emit processDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result) {
|
bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms) {
|
||||||
QMutexLocker lock(&_readerPointersMutex);
|
QMutexLocker lock(&_readerPointersMutex);
|
||||||
ReaderPointers::iterator it = _readerPointers.find(reader->_interface);
|
ReaderPointers::iterator it = _readerPointers.find(reader->_interface);
|
||||||
if (result == ClipProcessError) {
|
if (result == ClipProcessError) {
|
||||||
|
@ -686,10 +701,20 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
||||||
if (result == ClipProcessStarted) {
|
if (result == ClipProcessStarted) {
|
||||||
_loadLevel.fetchAndAddRelease(reader->_currentOriginal.width() * reader->_currentOriginal.height() - AverageGifSize);
|
_loadLevel.fetchAndAddRelease(reader->_currentOriginal.width() * reader->_currentOriginal.height() - AverageGifSize);
|
||||||
}
|
}
|
||||||
|
if (!reader->_paused && (result == ClipProcessRedraw || result == ClipProcessWait)) {
|
||||||
|
if (it.key()->_lastDisplayMs.get() + WaitBeforeGifPause < qMax(reader->_previousMs, ms)) {
|
||||||
|
reader->_paused = true;
|
||||||
|
it.key()->_paused.set(true);
|
||||||
|
if (it.key()->_lastDisplayMs.get() + WaitBeforeGifPause >= qMax(reader->_previousMs, ms)) {
|
||||||
|
it.key()->_paused.set(false);
|
||||||
|
reader->_paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result == ClipProcessReinit || result == ClipProcessRedraw || result == ClipProcessStarted) {
|
if (result == ClipProcessReinit || result == ClipProcessRedraw || result == ClipProcessStarted) {
|
||||||
it.key()->_current = reader->_current;
|
it.key()->_current = reader->_current;
|
||||||
it.key()->_currentOriginal = reader->_currentOriginal;
|
it.key()->_currentOriginal = reader->_currentOriginal;
|
||||||
it.key()->_currentDisplayed.storeRelease(0);
|
it.key()->_currentDisplayed.set(false);
|
||||||
if (result == ClipProcessReinit) {
|
if (result == ClipProcessReinit) {
|
||||||
emit reinit(it.key());
|
emit reinit(it.key());
|
||||||
} else if (result == ClipProcessRedraw) {
|
} else if (result == ClipProcessRedraw) {
|
||||||
|
@ -700,7 +725,7 @@ bool ClipReadManager::handleProcessResult(ClipReaderPrivate *reader, ClipProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipReadManager::ResultHandleState ClipReadManager::handleResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms) {
|
ClipReadManager::ResultHandleState ClipReadManager::handleResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms) {
|
||||||
if (!handleProcessResult(reader, result)) {
|
if (!handleProcessResult(reader, result, ms)) {
|
||||||
_loadLevel.fetchAndAddRelease(-1 * (reader->_currentOriginal.isNull() ? AverageGifSize : reader->_currentOriginal.width() * reader->_currentOriginal.height()));
|
_loadLevel.fetchAndAddRelease(-1 * (reader->_currentOriginal.isNull() ? AverageGifSize : reader->_currentOriginal.width() * reader->_currentOriginal.height()));
|
||||||
delete reader;
|
delete reader;
|
||||||
return ResultHandleRemove;
|
return ResultHandleRemove;
|
||||||
|
@ -719,7 +744,10 @@ ClipReadManager::ResultHandleState ClipReadManager::handleResult(ClipReaderPriva
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClipReadManager::process() {
|
void ClipReadManager::process() {
|
||||||
if (_processingInThread) return;
|
if (_processingInThread) {
|
||||||
|
_needReProcess = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
_processingInThread = thread();
|
_processingInThread = thread();
|
||||||
|
@ -734,6 +762,9 @@ void ClipReadManager::process() {
|
||||||
_readers.insert(i.value(), 0);
|
_readers.insert(i.value(), 0);
|
||||||
} else {
|
} else {
|
||||||
it.value() = ms;
|
it.value() = ms;
|
||||||
|
if (it.key()->_paused && !i.key()->_paused.get()) {
|
||||||
|
it.key()->_paused = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i.value()->_request = i.key()->_request;
|
i.value()->_request = i.key()->_request;
|
||||||
i.value() = 0;
|
i.value() = 0;
|
||||||
|
@ -754,15 +785,17 @@ void ClipReadManager::process() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i.value() = i.key()->_nextUpdateMs;
|
i.value() = i.key()->_nextUpdateMs;
|
||||||
|
ms = getms();
|
||||||
}
|
}
|
||||||
if (i.value() < minms) {
|
if (!i.key()->_paused && i.value() < minms) {
|
||||||
minms = i.value();
|
minms = i.value();
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
ms = getms();
|
ms = getms();
|
||||||
if (minms <= ms) {
|
if (_needReProcess || minms <= ms) {
|
||||||
|
_needReProcess = false;
|
||||||
_timer.start(1);
|
_timer.start(1);
|
||||||
} else {
|
} else {
|
||||||
_timer.start(minms - ms);
|
_timer.start(minms - ms);
|
||||||
|
|
|
@ -493,6 +493,28 @@ struct ClipFrameRequest {
|
||||||
bool rounded;
|
bool rounded;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class Atomic {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Atomic(const Type &value = Type()) : _v(1, value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Type get() const {
|
||||||
|
QVector<Type> v(_v);
|
||||||
|
return v.at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const Type &value) {
|
||||||
|
QVector<Type> v(1, value);
|
||||||
|
_v = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<Type> _v;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class ClipReaderPrivate;
|
class ClipReaderPrivate;
|
||||||
class ClipReader {
|
class ClipReader {
|
||||||
public:
|
public:
|
||||||
|
@ -502,7 +524,7 @@ public:
|
||||||
void start(int32 framew, int32 frameh, int32 outerw, int32 outerh, bool rounded);
|
void start(int32 framew, int32 frameh, int32 outerw, int32 outerh, bool rounded);
|
||||||
QPixmap current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms);
|
QPixmap current(int32 framew, int32 frameh, int32 outerw, int32 outerh, uint64 ms);
|
||||||
bool currentDisplayed() const {
|
bool currentDisplayed() const {
|
||||||
return _currentDisplayed.loadAcquire() > 0;
|
return _currentDisplayed.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 width() const;
|
int32 width() const;
|
||||||
|
@ -529,8 +551,8 @@ private:
|
||||||
|
|
||||||
QPixmap _current;
|
QPixmap _current;
|
||||||
QImage _currentOriginal, _cacheForResize;
|
QImage _currentOriginal, _cacheForResize;
|
||||||
QAtomicInt _currentDisplayed;
|
Atomic<bool> _currentDisplayed, _paused;
|
||||||
uint64 _lastDisplayMs;
|
Atomic<uint64> _lastDisplayMs;
|
||||||
int32 _threadIndex;
|
int32 _threadIndex;
|
||||||
|
|
||||||
friend class ClipReadManager;
|
friend class ClipReadManager;
|
||||||
|
@ -580,7 +602,7 @@ private:
|
||||||
ReaderPointers _readerPointers;
|
ReaderPointers _readerPointers;
|
||||||
QMutex _readerPointersMutex;
|
QMutex _readerPointersMutex;
|
||||||
|
|
||||||
bool handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result);
|
bool handleProcessResult(ClipReaderPrivate *reader, ClipProcessResult result, uint64 ms);
|
||||||
|
|
||||||
enum ResultHandleState {
|
enum ResultHandleState {
|
||||||
ResultHandleRemove,
|
ResultHandleRemove,
|
||||||
|
@ -594,5 +616,6 @@ private:
|
||||||
|
|
||||||
QTimer _timer;
|
QTimer _timer;
|
||||||
QThread *_processingInThread;
|
QThread *_processingInThread;
|
||||||
|
bool _needReProcess;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue