From 10c810ff0395c2789a2a36c13e592d9f55829e61 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 17 Dec 2019 17:30:14 +0300 Subject: [PATCH] Lock inline HistoryView::Gif when playing fullscreen. --- .../history/view/media/history_view_gif.cpp | 15 ++++++++--- .../history/view/media/history_view_gif.h | 4 ++- .../streaming/media_streaming_instance.cpp | 27 +++++++++++++++++++ .../streaming/media_streaming_instance.h | 5 ++++ .../streaming/media_streaming_player.cpp | 14 ++++++++++ .../media/streaming/media_streaming_player.h | 6 +++++ .../media/view/media_view_overlay_widget.cpp | 2 ++ 7 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 9590068c7..01318a9d2 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -314,9 +314,18 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms request.resize = QSize(_thumbw, _thumbh) * cIntRetinaFactor(); request.corners = roundCorners; request.radius = roundRadius; - p.drawImage(rthumb, streamed->frame(request)); - if (!paused) { - streamed->markFrameShown(); + if (streamed->playerLocked() && !activeRoundPlaying) { + if (_lockedFrameRequest != request || _lockedFrame.isNull()) { + _lockedFrameRequest = request; + _lockedFrame = streamed->frame(request); + } + p.drawImage(rthumb, _lockedFrame); + } else { + _lockedFrame = QImage(); + p.drawImage(rthumb, streamed->frame(request)); + if (!paused) { + streamed->markFrameShown(); + } } if (const auto playback = videoPlayback()) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.h b/Telegram/SourceFiles/history/view/media/history_view_gif.h index f0e95945a..20deba96e 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.h +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.h @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "history/view/media/history_view_file.h" -#include "media/clip/media_clip_reader.h" +#include "media/streaming/media_streaming_common.h" struct HistoryMessageVia; struct HistoryMessageReply; @@ -154,6 +154,8 @@ private: Ui::Text::String _caption; std::unique_ptr<::Media::Streaming::Instance> _streamed; + mutable ::Media::Streaming::FrameRequest _lockedFrameRequest; + mutable QImage _lockedFrame; QString _downloadSize; }; diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_instance.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_instance.cpp index e958db5e0..d51a4eb4c 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_instance.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_instance.cpp @@ -36,6 +36,7 @@ Instance::Instance( Instance::~Instance() { if (_shared) { + unlockPlayer(); _shared->unregisterInstance(this); } } @@ -147,9 +148,35 @@ QImage Instance::frame(const FrameRequest &request) const { } bool Instance::markFrameShown() { + Expects(_shared != nullptr); + return _shared->player().markFrameShown(); } +void Instance::lockPlayer() { + Expects(_shared != nullptr); + + if (!_playerLocked) { + _playerLocked = true; + _shared->player().lock(); + } +} + +void Instance::unlockPlayer() { + Expects(_shared != nullptr); + + if (_playerLocked) { + _playerLocked = false; + _shared->player().unlock(); + } +} + +bool Instance::playerLocked() const { + Expects(_shared != nullptr); + + return _shared->player().locked(); +} + rpl::lifetime &Instance::lifetime() { return _lifetime; } diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_instance.h b/Telegram/SourceFiles/media/streaming/media_streaming_instance.h index 747a54b64..2948c41b1 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_instance.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_instance.h @@ -63,11 +63,16 @@ public: [[nodiscard]] QImage frame(const FrameRequest &request) const; bool markFrameShown(); + void lockPlayer(); + void unlockPlayer(); + [[nodiscard]] bool playerLocked() const; + [[nodiscard]] rpl::lifetime &lifetime(); private: const std::shared_ptr _shared; Fn _waitingCallback; + bool _playerLocked = false; rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp index d343f8125..19bf593f0 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp @@ -883,6 +883,20 @@ crl::time Player::getCurrentReceivedTill(crl::time duration) const { : result; } +void Player::lock() { + ++_locks; +} + +void Player::unlock() { + Expects(_locks > 0); + + --_locks; +} + +bool Player::locked() const { + return (_locks > 0); +} + rpl::lifetime &Player::lifetime() { return _lifetime; } diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.h b/Telegram/SourceFiles/media/streaming/media_streaming_player.h index e5df3cd6e..fb40322b2 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_player.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.h @@ -69,6 +69,10 @@ public: [[nodiscard]] Media::Player::TrackState prepareLegacyState() const; + void lock(); + void unlock(); + [[nodiscard]] bool locked() const; + [[nodiscard]] rpl::lifetime &lifetime(); ~Player(); @@ -194,6 +198,8 @@ private: int _durationByLastAudioPacket = 0; int _durationByLastVideoPacket = 0; + int _locks = 0; + rpl::lifetime _lifetime; rpl::lifetime _sessionLifetime; diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 12771628f..b1011aaf4 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -436,6 +436,7 @@ void OverlayWidget::clearStreaming() { _fullScreenVideo = false; if (_streamed) { _streamed->instance.stop(); + _streamed->instance.unlockPlayer(); _streamed = nullptr; } } @@ -2077,6 +2078,7 @@ void OverlayWidget::createStreamingObjects() { this, static_cast(this), [=] { waitingAnimationCallback(); }); + _streamed->instance.lockPlayer(); _streamed->withSound = _doc->isAudioFile() || _doc->isVideoFile() || _doc->isVoiceMessage()