1
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-04-01 00:08:02 +00:00

Optimize locked videos repainting.

This commit is contained in:
John Preston 2019-12-18 21:48:07 +03:00
parent 40d4353d05
commit 92d87f96e1
2 changed files with 75 additions and 56 deletions
Telegram/SourceFiles/history/view/media

View File

@ -47,6 +47,22 @@ int gifMaxStatusWidth(DocumentData *document) {
} // namespace
struct Gif::Streamed {
Streamed(
std::shared_ptr<::Media::Streaming::Document> shared,
Fn<void()> waitingCallback);
::Media::Streaming::Instance instance;
::Media::Streaming::FrameRequest frozenRequest;
QImage frozenFrame;
QString frozenStatusText;
};
Gif::Streamed::Streamed(
std::shared_ptr<::Media::Streaming::Document> shared,
Fn<void()> waitingCallback)
: instance(std::move(shared), std::move(waitingCallback)) {
}
Gif::Gif(
not_null<Element*> parent,
not_null<HistoryItem*> realParent,
@ -237,6 +253,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
const auto cornerDownload = downloadInCorner();
const auto canBePlayed = _data->canBePlayed();
const auto activeRoundPlaying = activeRoundStreamed();
const auto activeOwnPlaying = activeOwnStreamed();
const auto autoplay = autoplayEnabled() && canBePlayed;
const auto streamingMode = _streamed || activeRoundPlaying || autoplay;
const auto startPlayAsync = autoplay
@ -246,7 +263,9 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
if (!autoPaused) {
_parent->delegate()->elementAnimationAutoplayAsync(_parent);
}
} else if (_streamed && !_streamed->active() && !_streamed->failed()) {
} else if (_streamed
&& !_streamed->instance.active()
&& !_streamed->instance.failed()) {
startStreamedPlayer();
}
@ -259,7 +278,11 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
const auto isRound = _data->isVideoMessage();
auto displayMute = false;
const auto streamed = activeCurrentStreamed();
const auto streamed = activeRoundPlaying
? activeRoundPlaying
: activeOwnPlaying
? &activeOwnPlaying->instance
: nullptr;
if ((!streamed || item->isSending()) && displayLoading) {
ensureAnimation();
@ -314,14 +337,21 @@ 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;
if (streamed->playerLocked() && !activeRoundPlaying) {
if (_lockedFrameRequest != request || _lockedFrame.isNull()) {
_lockedFrameRequest = request;
_lockedFrame = streamed->frame(request);
if (!activeRoundPlaying && activeOwnPlaying->instance.playerLocked()) {
if (activeOwnPlaying->frozenFrame.isNull()) {
activeOwnPlaying->frozenRequest = request;
activeOwnPlaying->frozenFrame = streamed->frame(request);
activeOwnPlaying->frozenStatusText = _statusText;
} else if (activeOwnPlaying->frozenRequest != request) {
activeOwnPlaying->frozenRequest = request;
activeOwnPlaying->frozenFrame = streamed->frame(request);
}
p.drawImage(rthumb, _lockedFrame);
p.drawImage(rthumb, activeOwnPlaying->frozenFrame);
} else {
_lockedFrame = QImage();
if (activeOwnPlaying) {
activeOwnPlaying->frozenFrame = QImage();
activeOwnPlaying->frozenStatusText = QString();
}
p.drawImage(rthumb, streamed->frame(request));
if (!paused) {
streamed->markFrameShown();
@ -579,6 +609,10 @@ void Gif::drawCornerStatus(Painter &p, bool selected) const {
if (!needInfoDisplay()) {
return;
}
const auto own = activeOwnStreamed();
const auto text = (own && !own->frozenStatusText.isEmpty())
? own->frozenStatusText
: _statusText;
const auto padding = st::msgDateImgPadding;
const auto radial = _animation && _animation->radial.animating();
const auto cornerMute = _streamed && _data->isVideoFile();
@ -586,7 +620,7 @@ void Gif::drawCornerStatus(Painter &p, bool selected) const {
const auto addLeft = cornerDownload ? (st::historyVideoDownloadSize + 2 * padding.y()) : 0;
const auto addRight = cornerMute ? st::historyVideoMuteSize : 0;
const auto downloadWidth = cornerDownload ? st::normalFont->width(_downloadSize) : 0;
const auto statusW = std::max(downloadWidth, st::normalFont->width(_statusText)) + 2 * padding.x() + addLeft + addRight;
const auto statusW = std::max(downloadWidth, st::normalFont->width(text)) + 2 * padding.x() + addLeft + addRight;
const auto statusH = cornerDownload ? (st::historyVideoDownloadSize + 2 * padding.y()) : (st::normalFont->height + 2 * padding.y());
const auto statusX = st::msgDateImgDelta + padding.x();
const auto statusY = st::msgDateImgDelta + padding.y();
@ -595,7 +629,7 @@ void Gif::drawCornerStatus(Painter &p, bool selected) const {
App::roundRect(p, around, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
p.setFont(st::normalFont);
p.setPen(st::msgDateImgFg);
p.drawTextLeft(statusX + addLeft, statusTextTop, width(), _statusText, statusW - 2 * padding.x());
p.drawTextLeft(statusX + addLeft, statusTextTop, width(), text, statusW - 2 * padding.x());
if (cornerDownload) {
const auto downloadTextTop = statusY + st::normalFont->height + (2 * (statusH - 2 * st::normalFont->height) / 3) - padding.y();
p.drawTextLeft(statusX + addLeft, downloadTextTop, width(), _downloadSize, statusW - 2 * padding.x());
@ -1042,8 +1076,8 @@ void Gif::updateStatusText() const {
}
const auto round = activeRoundStreamed();
const auto own = activeOwnStreamed();
if (round || (own && _data->isVideoFile())) {
const auto streamed = round ? round : own;
if (round || (own && own->frozenFrame.isNull() && _data->isVideoFile())) {
const auto streamed = round ? round : &own->instance;
const auto state = streamed->player().prepareLegacyState();
if (state.length) {
auto position = int64(0);
@ -1098,10 +1132,10 @@ int Gif::additionalWidth(const HistoryMessageVia *via, const HistoryMessageReply
return ::Media::Player::instance()->roundVideoStreamed(_parent->data());
}
::Media::Streaming::Instance *Gif::activeOwnStreamed() const {
Gif::Streamed *Gif::activeOwnStreamed() const {
return (_streamed
&& _streamed->player().ready()
&& !_streamed->player().videoSize().isEmpty())
&& _streamed->instance.player().ready()
&& !_streamed->instance.player().videoSize().isEmpty())
? _streamed.get()
: nullptr;
}
@ -1109,8 +1143,10 @@ int Gif::additionalWidth(const HistoryMessageVia *via, const HistoryMessageReply
::Media::Streaming::Instance *Gif::activeCurrentStreamed() const {
if (const auto streamed = activeRoundStreamed()) {
return streamed;
} else if (const auto owned = activeOwnStreamed()) {
return &owned->instance;
}
return activeOwnStreamed();
return nullptr;
}
::Media::View::PlaybackProgress *Gif::videoPlayback() const {
@ -1144,19 +1180,19 @@ void Gif::createStreamedPlayer() {
if (!shared) {
return;
}
setStreamed(std::make_unique<::Media::Streaming::Instance>(
setStreamed(std::make_unique<Streamed>(
std::move(shared),
[=] { history()->owner().requestViewRepaint(_parent); }));
[=] { repaintStreamedContent(); }));
_streamed->player().updates(
_streamed->instance.player().updates(
) | rpl::start_with_next_error([=](::Media::Streaming::Update &&update) {
handleStreamingUpdate(std::move(update));
}, [=](::Media::Streaming::Error &&error) {
handleStreamingError(std::move(error));
}, _streamed->lifetime());
}, _streamed->instance.lifetime());
if (_streamed->ready()) {
streamingReady(base::duplicate(_streamed->info()));
if (_streamed->instance.ready()) {
streamingReady(base::duplicate(_streamed->instance.info()));
}
startStreamedPlayer();
}
@ -1171,10 +1207,10 @@ void Gif::startStreamedPlayer() const {
options.mode = ::Media::Streaming::Mode::Video;
options.loop = true;
//}
_streamed->play(options);
_streamed->instance.play(options);
}
void Gif::setStreamed(std::unique_ptr<::Media::Streaming::Instance> value) {
void Gif::setStreamed(std::unique_ptr<Streamed> value) {
const auto removed = (_streamed && !value);
const auto set = (!_streamed && value);
if (removed) {
@ -1192,47 +1228,29 @@ void Gif::handleStreamingUpdate(::Media::Streaming::Update &&update) {
update.data.match([&](Information &update) {
streamingReady(std::move(update));
}, [&](const PreloadedVideo &update) {
//updatePlaybackState();
}, [&](const UpdateVideo &update) {
history()->owner().requestViewRepaint(_parent);
//updatePlaybackState();
repaintStreamedContent();
}, [&](const PreloadedAudio &update) {
//_streamed->info.audio.state.receivedTill = update.till;
//updatePlaybackState();
}, [&](const UpdateAudio &update) {
//_streamed->info.audio.state.position = update.position;
//updatePlaybackState();
}, [&](const WaitingForData &update) {
//playbackWaitingChange(update.waiting);
}, [&](MutedByOther) {
}, [&](Finished) {
//updatePlaybackState();
});
}
void Gif::handleStreamingError(::Media::Streaming::Error &&error) {
//if (!_data->canBePlayed()) {
// redisplayContent();
//} else {
// playbackWaitingChange(false);
// updatePlaybackState();
//}
}
void Gif::repaintStreamedContent() {
const auto own = activeOwnStreamed();
if (own && !own->frozenFrame.isNull()) {
return;
}
history()->owner().requestViewRepaint(_parent);
}
void Gif::streamingReady(::Media::Streaming::Information &&info) {
history()->owner().requestViewResize(_parent);
//validateStreamedGoodThumbnail();
//if (videoShown()) {
// const auto contentSize = ConvertScale(videoSize());
// if (contentSize != QSize(_width, _height)) {
// update(contentRect());
// _w = contentSize.width();
// _h = contentSize.height();
// contentSizeChanged();
// }
//}
//history()->owner().requestViewRepaint(_parent);
//playbackWaitingChange(false);
}
void Gif::stopAnimation() {

View File

@ -102,6 +102,8 @@ public:
}
private:
struct Streamed;
float64 dataProgress() const override;
bool dataFinished() const override;
bool dataLoaded() const override;
@ -113,16 +115,17 @@ private:
QSize countCurrentSize(int newWidth) override;
QSize videoSize() const;
::Media::Streaming::Instance *activeRoundStreamed() const;
::Media::Streaming::Instance *activeOwnStreamed() const;
Streamed *activeOwnStreamed() const;
::Media::Streaming::Instance *activeCurrentStreamed() const;
::Media::View::PlaybackProgress *videoPlayback() const;
void createStreamedPlayer();
void startStreamedPlayer() const;
void setStreamed(std::unique_ptr<::Media::Streaming::Instance> value);
void setStreamed(std::unique_ptr<Streamed> value);
void handleStreamingUpdate(::Media::Streaming::Update &&update);
void handleStreamingError(::Media::Streaming::Error &&error);
void streamingReady(::Media::Streaming::Information &&info);
void repaintStreamedContent();
bool needInfoDisplay() const;
int additionalWidth(
@ -152,10 +155,8 @@ private:
int _thumbw = 1;
int _thumbh = 1;
Ui::Text::String _caption;
std::unique_ptr<::Media::Streaming::Instance> _streamed;
std::unique_ptr<Streamed> _streamed;
mutable ::Media::Streaming::FrameRequest _lockedFrameRequest;
mutable QImage _lockedFrame;
QString _downloadSize;
};