From 8704f6efd0a210d15364979a623b9d180106318e Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 12 Apr 2019 12:00:06 +0400 Subject: [PATCH] Use simple loader for non-streamable file types. --- Telegram/SourceFiles/data/data_document.cpp | 15 +++++++--- Telegram/SourceFiles/data/data_document.h | 1 + .../streaming/media_streaming_reader.cpp | 15 +++++++--- .../media/streaming/media_streaming_reader.h | 1 + .../storage/streamed_file_downloader.cpp | 30 +++++++++++-------- .../storage/streamed_file_downloader.h | 3 ++ 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index f130f2c62..9b691f9d9 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -1196,6 +1196,13 @@ bool DocumentData::hasRemoteLocation() const { return (_dc != 0 && _access != 0); } +bool DocumentData::useStreamingLoader() const { + return isAnimation() + || isVideoFile() + || isAudioFile() + || isVoiceMessage(); +} + bool DocumentData::canBeStreamed() const { // For now video messages are not streamed. return hasRemoteLocation() && supportsStreaming() && !isVideoMessage(); @@ -1203,10 +1210,7 @@ bool DocumentData::canBeStreamed() const { bool DocumentData::canBePlayed() const { return !_inappPlaybackFailed - && (isAnimation() - || isVideoFile() - || isAudioFile() - || isVoiceMessage()) + && useStreamingLoader() && (loaded() || canBeStreamed()); } @@ -1220,6 +1224,9 @@ bool DocumentData::inappPlaybackFailed() const { auto DocumentData::createStreamingLoader(Data::FileOrigin origin) const -> std::unique_ptr { + if (!useStreamingLoader()) { + return nullptr; + } const auto &location = this->location(true); if (!data().isEmpty()) { return Media::Streaming::MakeBytesLoader(data()); diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index e8836d92d..6d91f126b 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -249,6 +249,7 @@ private: void destroyLoader(FileLoader *newValue = nullptr) const; + [[nodiscard]] bool useStreamingLoader() const; [[nodiscard]] bool thumbnailEnoughForSticker() const; // Two types of location: from MTProto by dc+access or from web by url diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp index 7e2099a24..50507d444 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp @@ -473,7 +473,7 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult { if (_headerMode != HeaderMode::NoCache && !(_header.flags & Flag::LoadedFromCache)) { // Waiting for initial cache query. - Assert(_header.flags & Flag::LoadingFromCache); + Assert(waitingForHeaderCache()); return {}; } else if (isFullInHeader()) { return fillFromHeader(offset, buffer); @@ -587,16 +587,20 @@ QByteArray Reader::Slices::partForDownloader(int offset) const { return (i != end(slice.parts)) ? i->second : QByteArray(); } +bool Reader::Slices::waitingForHeaderCache() const { + return (_header.flags & Slice::Flag::LoadingFromCache); +} + std::optional Reader::Slices::readCacheRequiredFor(int offset) { Expects(offset < _size); + Expects(!waitingForHeaderCache()); - using Flag = Slice::Flag; - if ((_header.flags & Flag::LoadingFromCache) || isFullInHeader()) { + if (isFullInHeader()) { return std::nullopt; } const auto index = offset / kInSlice; auto &slice = _data[index]; - return (slice.flags & Flag::LoadedFromCache) + return (slice.flags & Slice::Flag::LoadedFromCache) ? std::nullopt : std::make_optional(index + 1); } @@ -923,6 +927,9 @@ void Reader::processDownloaderRequests() { } bool Reader::downloaderWaitForCachedSlice(int offset) { + if (_slices.waitingForHeaderCache()) { + return true; + } const auto sliceNumber = _slices.readCacheRequiredFor(offset); if (sliceNumber.value_or(0) != _downloaderSliceNumber) { _downloaderSliceNumber = sliceNumber.value_or(0); diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h index a2a5e9626..0918b8eb5 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h @@ -131,6 +131,7 @@ private: [[nodiscard]] bool headerModeUnknown() const; [[nodiscard]] bool isFullInHeader() const; [[nodiscard]] bool isGoodHeader() const; + [[nodiscard]] bool waitingForHeaderCache() const; void processCacheResult(int sliceNumber, PartsMap &&result); void processPart(int offset, QByteArray &&bytes); diff --git a/Telegram/SourceFiles/storage/streamed_file_downloader.cpp b/Telegram/SourceFiles/storage/streamed_file_downloader.cpp index f9783fed9..0c9e2d4ea 100644 --- a/Telegram/SourceFiles/storage/streamed_file_downloader.cpp +++ b/Telegram/SourceFiles/storage/streamed_file_downloader.cpp @@ -47,8 +47,9 @@ StreamedFileDownloader::StreamedFileDownloader( , _origin(origin) , _cacheKey(cacheKey) , _fileLocationKey(fileLocationKey) -, _reader(std::move(reader)) { - _partIsSaved.resize((size + kPartSize - 1) / kPartSize, false); +, _reader(std::move(reader)) +, _partsCount((size + kPartSize - 1) / kPartSize) { + _partIsSaved.resize(_partsCount, false); _reader->partsForDownloader( ) | rpl::start_with_next([=](const LoadedPart &part) { @@ -87,18 +88,19 @@ std::optional StreamedFileDownloader::fileLocationKey() const { } void StreamedFileDownloader::cancelRequests() { - const auto requests = std::count( - begin(_partIsSaved), - begin(_partIsSaved) + _nextPartIndex, - false); - _queue->queriesCount -= requests; + //_partsRequested == std::count( + // begin(_partIsSaved), + // begin(_partIsSaved) + _nextPartIndex, + // false); + _queue->queriesCount -= _partsRequested; + _partsRequested = 0; _nextPartIndex = 0; _reader->cancelForDownloader(); } bool StreamedFileDownloader::loadPart() { - if (_finished || _nextPartIndex >= size(_partIsSaved)) { + if (_finished || _nextPartIndex >= _partsCount) { return false; } const auto index = std::find( @@ -106,17 +108,19 @@ bool StreamedFileDownloader::loadPart() { end(_partIsSaved), false ) - begin(_partIsSaved); - if (index == size(_partIsSaved)) { - _nextPartIndex = index; + if (index == _partsCount) { + _nextPartIndex = _partsCount; return false; } _nextPartIndex = index + 1; _reader->loadForDownloader(index * kPartSize); + AssertIsDebug(); //_downloader->requestedAmountIncrement( // requestData.dcId, // requestData.dcIndex, // kPartSize); + ++_partsRequested; ++_queue->queriesCount; return true; @@ -132,11 +136,12 @@ void StreamedFileDownloader::savePart(const LoadedPart &part) { const auto offset = part.offset; const auto index = offset / kPartSize; - Assert(index >= 0 && index < _partIsSaved.size()); + Assert(index >= 0 && index < _partsCount); if (_partIsSaved[index]) { return; } _partIsSaved[index] = true; + ++_partsSaved; if (index < _nextPartIndex) { AssertIsDebug(); @@ -144,12 +149,13 @@ void StreamedFileDownloader::savePart(const LoadedPart &part) { // requestData.dcId, // requestData.dcIndex, // -kPartSize); + --_partsRequested; --_queue->queriesCount; } if (!writeResultPart(offset, bytes::make_span(part.bytes))) { return; } - if (ranges::find(_partIsSaved, false) == end(_partIsSaved)) { + if (_partsSaved == _partsCount) { if (!finalizeResult()) { return; } diff --git a/Telegram/SourceFiles/storage/streamed_file_downloader.h b/Telegram/SourceFiles/storage/streamed_file_downloader.h index dfc9827f0..14e899b6c 100644 --- a/Telegram/SourceFiles/storage/streamed_file_downloader.h +++ b/Telegram/SourceFiles/storage/streamed_file_downloader.h @@ -59,6 +59,9 @@ private: std::vector _partIsSaved; // vector :D int _nextPartIndex = 0; + int _partsCount = 0; + int _partsRequested = 0; + int _partsSaved = 0; rpl::lifetime _lifetime;