diff options
author | John Preston <johnprestonmail@gmail.com> | 2020-10-13 19:43:18 +0300 |
---|---|---|
committer | John Preston <johnprestonmail@gmail.com> | 2020-10-30 18:32:18 +0300 |
commit | 8b96f4c214d119b1665d9c66083512385d243ac8 (patch) | |
tree | a3d2669619927a67cc7b38b3292cfe77e155be68 | |
parent | 05eb549a3db6e7222688c3a6f39b69ac7802d9d1 (diff) |
Move Media::Clip::Reader and FileLocation to td_ui.
47 files changed, 636 insertions, 746 deletions
diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index d6fdb2a4db..94741dda35 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -692,14 +692,6 @@ PRIVATE media/audio/media_child_ffmpeg_loader.h media/audio/media_openal_functions.cpp media/audio/media_openal_functions.h - media/clip/media_clip_check_streaming.cpp - media/clip/media_clip_check_streaming.h - media/clip/media_clip_ffmpeg.cpp - media/clip/media_clip_ffmpeg.h - media/clip/media_clip_implementation.cpp - media/clip/media_clip_implementation.h - media/clip/media_clip_reader.cpp - media/clip/media_clip_reader.h media/player/media_player_button.cpp media/player/media_player_button.h media/player/media_player_float.cpp diff --git a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp index baca58e7bc..083778c9e3 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp @@ -110,7 +110,7 @@ void DicePack::tryGenerateLocalZero() { const auto document = _session->data().processDocument( result->document, Images::FromImageInMemory(result->thumb, "PNG")); - document->setLocation(FileLocation(path)); + document->setLocation(Core::FileLocation(path)); _map.emplace(0, document); diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 5bc8f9c47b..f9b9f496de 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -21,13 +21,8 @@ enum { LocalEncryptSaltSize = 32, // 256 bit AnimationTimerDelta = 7, - ClipThreadsCount = 8, - AverageGifSize = 320 * 240, - WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it RecentInlineBotsLimit = 10, - AVBlockSize = 4096, // 4Kb for ffmpeg blocksize - AutoSearchTimeout = 900, // 0.9 secs SearchPerPage = 50, SearchManyPerPage = 100, diff --git a/Telegram/SourceFiles/core/file_location.cpp b/Telegram/SourceFiles/core/file_location.cpp new file mode 100644 index 0000000000..641bf0ea0c --- /dev/null +++ b/Telegram/SourceFiles/core/file_location.cpp @@ -0,0 +1,121 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "core/file_location.h" + +#include "platform/platform_file_bookmark.h" +#include "logs.h" + +#include <QtCore/QFileInfo> + +namespace Core { +namespace { + +const auto kInMediaCacheLocation = u"*media_cache*"_q; + +} // namespace + +ReadAccessEnabler::ReadAccessEnabler(const Platform::FileBookmark *bookmark) +: _bookmark(bookmark) +, _failed(_bookmark ? !_bookmark->enable() : false) { +} + +ReadAccessEnabler::ReadAccessEnabler( + const std::shared_ptr<Platform::FileBookmark> &bookmark) +: _bookmark(bookmark.get()) +, _failed(_bookmark ? !_bookmark->enable() : false) { +} + +ReadAccessEnabler::~ReadAccessEnabler() { + if (_bookmark && !_failed) _bookmark->disable(); +} + +FileLocation::FileLocation(const QString &name) : fname(name) { + if (fname.isEmpty() || fname == kInMediaCacheLocation) { + size = 0; + } else { + setBookmark(Platform::PathBookmark(name)); + + QFileInfo f(name); + if (f.exists()) { + qint64 s = f.size(); + if (s > INT_MAX) { + fname = QString(); + _bookmark = nullptr; + size = 0; + } else { + modified = f.lastModified(); + size = qint32(s); + } + } else { + fname = QString(); + _bookmark = nullptr; + size = 0; + } + } +} + +FileLocation FileLocation::InMediaCacheLocation() { + return FileLocation(kInMediaCacheLocation); +} + +bool FileLocation::check() const { + if (fname.isEmpty() || fname == kInMediaCacheLocation) { + return false; + } + + ReadAccessEnabler enabler(_bookmark); + if (enabler.failed()) { + const_cast<FileLocation*>(this)->_bookmark = nullptr; + } + + QFileInfo f(name()); + if (!f.isReadable()) return false; + + quint64 s = f.size(); + if (s > INT_MAX) { + DEBUG_LOG(("File location check: Wrong size %1").arg(s)); + return false; + } + + if (qint32(s) != size) { + DEBUG_LOG(("File location check: Wrong size %1 when should be %2").arg(s).arg(size)); + return false; + } + auto realModified = f.lastModified(); + if (realModified != modified) { + DEBUG_LOG(("File location check: Wrong last modified time %1 when should be %2").arg(realModified.toMSecsSinceEpoch()).arg(modified.toMSecsSinceEpoch())); + return false; + } + return true; +} + +const QString &FileLocation::name() const { + return _bookmark ? _bookmark->name(fname) : fname; +} + +QByteArray FileLocation::bookmark() const { + return _bookmark ? _bookmark->bookmark() : QByteArray(); +} + +bool FileLocation::inMediaCache() const { + return (fname == kInMediaCacheLocation); +} + +void FileLocation::setBookmark(const QByteArray &bm) { + _bookmark.reset(bm.isEmpty() ? nullptr : new Platform::FileBookmark(bm)); +} + +bool FileLocation::accessEnable() const { + return isEmpty() ? false : (_bookmark ? _bookmark->enable() : true); +} + +void FileLocation::accessDisable() const { + return _bookmark ? _bookmark->disable() : (void)0; +} + +} // namespace Core diff --git a/Telegram/SourceFiles/core/file_location.h b/Telegram/SourceFiles/core/file_location.h new file mode 100644 index 0000000000..16db6fce3e --- /dev/null +++ b/Telegram/SourceFiles/core/file_location.h @@ -0,0 +1,72 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include <QtCore/QDateTime> + +namespace Platform { +class FileBookmark; +} // namespace Platform + +namespace Core { + +class ReadAccessEnabler { +public: + ReadAccessEnabler(const Platform::FileBookmark *bookmark); + ReadAccessEnabler( + const std::shared_ptr<Platform::FileBookmark> &bookmark); + bool failed() const { + return _failed; + } + ~ReadAccessEnabler(); + +private: + const Platform::FileBookmark *_bookmark = nullptr; + bool _failed; + +}; + +class FileLocation { +public: + FileLocation() = default; + explicit FileLocation(const QString &name); + + static FileLocation InMediaCacheLocation(); + + [[nodiscard]] bool check() const; + [[nodiscard]] const QString &name() const; + void setBookmark(const QByteArray &bookmark); + QByteArray bookmark() const; + [[nodiscard]] bool isEmpty() const { + return name().isEmpty(); + } + [[nodiscard]] bool inMediaCache() const; + + bool accessEnable() const; + void accessDisable() const; + + QString fname; + QDateTime modified; + qint32 size; + +private: + std::shared_ptr<Platform::FileBookmark> _bookmark; + +}; + +inline bool operator==(const FileLocation &a, const FileLocation &b) { + return (a.name() == b.name()) + && (a.modified == b.modified) + && (a.size == b.size); +} + +inline bool operator!=(const FileLocation &a, const FileLocation &b) { + return !(a == b); +} + +} // namespace Core diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 9d9dbf3e15..a4784561b2 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -849,7 +849,7 @@ void DocumentData::finishLoad() { _flags |= Flag::DownloadCancelled; return; } - setLocation(FileLocation(_loader->fileName())); + setLocation(Core::FileLocation(_loader->fileName())); setGoodThumbnailDataReady(); if (const auto media = activeMediaView()) { media->setBytes(_loader->bytes()); @@ -917,7 +917,7 @@ void DocumentData::setLoadedInMediaCache(bool loaded) { if (loadedInMediaCache()) { session().local().writeFileLocation( mediaKey(), - FileLocation::InMediaCacheLocation()); + Core::FileLocation::InMediaCacheLocation()); } else { session().local().removeFileLocation(mediaKey()); } @@ -926,7 +926,7 @@ void DocumentData::setLoadedInMediaCache(bool loaded) { } void DocumentData::setLoadedInMediaCacheLocation() { - _location = FileLocation(); + _location = Core::FileLocation(); _flags |= Flag::LoadedInMediaCache; } @@ -954,10 +954,10 @@ void DocumentData::save( f.write(media->bytes()); f.close(); - setLocation(FileLocation(toFile)); + setLocation(Core::FileLocation(toFile)); session().local().writeFileLocation( mediaKey(), - FileLocation(toFile)); + Core::FileLocation(toFile)); } else if (l.accessEnable()) { const auto &alreadyName = l.name(); if (alreadyName != toFile) { @@ -1151,7 +1151,7 @@ QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) { return result; } -const FileLocation &DocumentData::location(bool check) const { +const Core::FileLocation &DocumentData::location(bool check) const { if (check && !_location.check()) { const auto location = session().local().readFileLocation(mediaKey()); const auto that = const_cast<DocumentData*>(this); @@ -1164,7 +1164,7 @@ const FileLocation &DocumentData::location(bool check) const { return _location; } -void DocumentData::setLocation(const FileLocation &loc) { +void DocumentData::setLocation(const Core::FileLocation &loc) { if (loc.inMediaCache()) { setLoadedInMediaCacheLocation(); } else if (loc.check()) { @@ -1207,7 +1207,7 @@ bool DocumentData::saveFromDataChecked() { return false; } file.close(); - _location = FileLocation(path); + _location = Core::FileLocation(path); session().local().writeFileLocation(mediaKey(), _location); return true; } @@ -1585,7 +1585,7 @@ void DocumentData::setRemoteLocation( } else if (_location.isEmpty() && loadedInMediaCache()) { session().local().writeFileLocation( mediaKey(), - FileLocation::InMediaCacheLocation()); + Core::FileLocation::InMediaCacheLocation()); } } } diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index a31dd63701..35b998d12d 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/binary_guard.h" #include "data/data_types.h" #include "data/data_cloud_file.h" +#include "core/file_location.h" #include "ui/image/image.h" class mtpFileLoader; @@ -114,8 +115,8 @@ public: void setWaitingForAlbum(); [[nodiscard]] bool waitingForAlbum() const; - [[nodiscard]] const FileLocation &location(bool check = false) const; - void setLocation(const FileLocation &loc); + [[nodiscard]] const Core::FileLocation &location(bool check = false) const; + void setLocation(const Core::FileLocation &loc); bool saveFromData(); bool saveFromDataSilent(); @@ -315,7 +316,7 @@ private: std::weak_ptr<Data::DocumentMedia> _media; PhotoData *_goodThumbnailPhoto = nullptr; - FileLocation _location; + Core::FileLocation _location; std::unique_ptr<DocumentAdditionalData> _additional; int32 _duration = -1; mutable Flags _flags = kStreamingSupportedUnknown; diff --git a/Telegram/SourceFiles/data/data_document_media.cpp b/Telegram/SourceFiles/data/data_document_media.cpp index 28916e511f..4a1267e6ec 100644 --- a/Telegram/SourceFiles/data/data_document_media.cpp +++ b/Telegram/SourceFiles/data/data_document_media.cpp @@ -111,8 +111,8 @@ void VideoPreviewState::automaticLoad(Data::FileOrigin origin) const { _media->videoThumbnailContent(), std::move(callback)) : ::Media::Clip::MakeReader( - _media, - FullMsgId(), + _media->owner()->location(), + _media->bytes(), std::move(callback)); } @@ -386,7 +386,7 @@ void DocumentMedia::GenerateGoodThumbnail( : FileType::Video; auto location = document->location().isEmpty() ? nullptr - : std::make_unique<FileLocation>(document->location()); + : std::make_unique<Core::FileLocation>(document->location()); if (data.isEmpty() && !location) { document->setGoodThumbnailChecked(false); return; diff --git a/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.h b/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.h index de7db7a219..4be81913c5 100644 --- a/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.h +++ b/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.h @@ -25,6 +25,7 @@ class QImage; namespace FFmpeg { inline constexpr auto kPixelBytesSize = 4; +inline constexpr auto kAVBlockSize = 4096; // 4Kb for ffmpeg blocksize constexpr auto kUniversalTimeBase = AVRational{ 1, AV_TIME_BASE }; constexpr auto kNormalAspect = AVRational{ 1, 1 }; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index 4810cbc4aa..c36ac5937f 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -1373,9 +1373,10 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con bool loaded = _documentMedia->loaded(), loading = document->loading(), displayLoading = document->displayLoading(); if (loaded && !_gif && !_gif.isBad()) { auto that = const_cast<Game*>(this); - that->_gif = Media::Clip::MakeReader(_documentMedia.get(), FullMsgId(), [that](Media::Clip::Notification notification) { - that->clipCallback(notification); - }); + that->_gif = Media::Clip::MakeReader( + _documentMedia->owner()->location(), + _documentMedia->bytes(), + [=](Media::Clip::Notification notification) { that->clipCallback(notification); }); } bool animating = (_gif && _gif->started()); diff --git a/Telegram/SourceFiles/media/audio/media_audio.cpp b/Telegram/SourceFiles/media/audio/media_audio.cpp index e429ee774d..02dcffd79f 100644 --- a/Telegram/SourceFiles/media/audio/media_audio.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio.cpp @@ -430,7 +430,7 @@ void Mixer::Track::clear() { detach(); state = TrackState(); - file = FileLocation(); + file = Core::FileLocation(); data = QByteArray(); bufferedPosition = 0; bufferedLength = 0; @@ -1519,7 +1519,7 @@ void DetachFromDevice(not_null<Audio::Instance*> instance) { class FFMpegAttributesReader : public AbstractFFMpegLoader { public: - FFMpegAttributesReader(const FileLocation &file, const QByteArray &data) + FFMpegAttributesReader(const Core::FileLocation &file, const QByteArray &data) : AbstractFFMpegLoader(file, data, bytes::vector()) { } @@ -1632,7 +1632,7 @@ namespace Player { Ui::PreparedFileInformation::Song PrepareForSending(const QString &fname, const QByteArray &data) { auto result = Ui::PreparedFileInformation::Song(); - FFMpegAttributesReader reader(FileLocation(fname), data); + FFMpegAttributesReader reader(Core::FileLocation(fname), data); const auto positionMs = crl::time(0); if (reader.open(positionMs) && reader.samplesCount() > 0) { result.duration = reader.samplesCount() / reader.samplesFrequency(); @@ -1647,7 +1647,7 @@ Ui::PreparedFileInformation::Song PrepareForSending(const QString &fname, const class FFMpegWaveformCounter : public FFMpegLoader { public: - FFMpegWaveformCounter(const FileLocation &file, const QByteArray &data) : FFMpegLoader(file, data, bytes::vector()) { + FFMpegWaveformCounter(const Core::FileLocation &file, const QByteArray &data) : FFMpegLoader(file, data, bytes::vector()) { } bool open(crl::time positionMs) override { @@ -1732,7 +1732,7 @@ private: } // namespace Media VoiceWaveform audioCountWaveform( - const FileLocation &file, + const Core::FileLocation &file, const QByteArray &data) { Media::FFMpegWaveformCounter counter(file, data); const auto positionMs = crl::time(0); diff --git a/Telegram/SourceFiles/media/audio/media_audio.h b/Telegram/SourceFiles/media/audio/media_audio.h index 962017073b..890570cdb6 100644 --- a/Telegram/SourceFiles/media/audio/media_audio.h +++ b/Telegram/SourceFiles/media/audio/media_audio.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animation_value.h" #include "ui/chat/attach/attach_prepare.h" +#include "core/file_location.h" #include "base/bytes.h" #include <QtCore/QTimer> @@ -221,7 +222,7 @@ private: TrackState state; - FileLocation file; + Core::FileLocation file; QByteArray data; int64 bufferedPosition = 0; int64 bufferedLength = 0; @@ -368,7 +369,7 @@ bool audioCheckError(); } // namespace Player } // namespace Media -VoiceWaveform audioCountWaveform(const FileLocation &file, const QByteArray &data); +VoiceWaveform audioCountWaveform(const Core::FileLocation &file, const QByteArray &data); namespace Media { namespace Audio { diff --git a/Telegram/SourceFiles/media/audio/media_audio_capture.cpp b/Telegram/SourceFiles/media/audio/media_audio_capture.cpp index 224bd7ffb6..580a8f8bc9 100644 --- a/Telegram/SourceFiles/media/audio/media_audio_capture.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio_capture.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/audio/media_audio_capture.h" #include "media/audio/media_audio_ffmpeg_loader.h" +#include "ffmpeg/ffmpeg_utility.h" #include "base/timer.h" #include <al.h> @@ -247,9 +248,9 @@ void Instance::Inner::start(Fn<void(Update)> updated, Fn<void()> error) { // Create encoding context - d->ioBuffer = (uchar*)av_malloc(AVBlockSize); + d->ioBuffer = (uchar*)av_malloc(FFmpeg::kAVBlockSize); - d->ioContext = avio_alloc_context(d->ioBuffer, AVBlockSize, 1, static_cast<void*>(d.get()), &Private::_read_data, &Private::_write_data, &Private::_seek_data); + d->ioContext = avio_alloc_context(d->ioBuffer, FFmpeg::kAVBlockSize, 1, static_cast<void*>(d.get()), &Private::_read_data, &Private::_write_data, &Private::_seek_data); int res = 0; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; AVOutputFormat *fmt = 0; diff --git a/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.cpp b/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.cpp index 258e46a415..24c8bac2a6 100644 --- a/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "media/audio/media_audio_ffmpeg_loader.h" +#include "core/file_location.h" +#include "ffmpeg/ffmpeg_utility.h" #include "base/bytes.h" namespace Media { @@ -34,13 +36,13 @@ bool AbstractFFMpegLoader::open(crl::time positionMs) { int res = 0; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; - ioBuffer = (uchar *)av_malloc(AVBlockSize); + ioBuffer = (uchar *)av_malloc(FFmpeg::kAVBlockSize); if (!_data.isEmpty()) { - ioContext = avio_alloc_context(ioBuffer, AVBlockSize, 0, reinterpret_cast<void *>(this), &AbstractFFMpegLoader::_read_data, 0, &AbstractFFMpegLoader::_seek_data); + ioContext = avio_alloc_context(ioBuffer, FFmpeg::kAVBlockSize, 0, reinterpret_cast<void *>(this), &AbstractFFMpegLoader::_read_data, 0, &AbstractFFMpegLoader::_seek_data); } else if (!_bytes.empty()) { - ioContext = avio_alloc_context(ioBuffer, AVBlockSize, 0, reinterpret_cast<void *>(this), &AbstractFFMpegLoader::_read_bytes, 0, &AbstractFFMpegLoader::_seek_bytes); + ioContext = avio_alloc_context(ioBuffer, FFmpeg::kAVBlockSize, 0, reinterpret_cast<void *>(this), &AbstractFFMpegLoader::_read_bytes, 0, &AbstractFFMpegLoader::_seek_bytes); } else { - ioContext = avio_alloc_context(ioBuffer, AVBlockSize, 0, reinterpret_cast<void *>(this), &AbstractFFMpegLoader::_read_file, 0, &AbstractFFMpegLoader::_seek_file); + ioContext = avio_alloc_context(ioBuffer, FFmpeg::kAVBlockSize, 0, reinterpret_cast<void *>(this), &AbstractFFMpegLoader::_read_file, 0, &AbstractFFMpegLoader::_seek_file); } fmtContext = avformat_alloc_context(); if (!fmtContext) { @@ -187,7 +189,7 @@ int64_t AbstractFFMpegLoader::_seek_file(void *opaque, int64_t offset, int whenc } AbstractAudioFFMpegLoader::AbstractAudioFFMpegLoader( - const FileLocation &file, + const Core::FileLocation &file, const QByteArray &data, bytes::vector &&buffer) : AbstractFFMpegLoader(file, data, std::move(buffer)) @@ -389,7 +391,7 @@ bool AbstractAudioFFMpegLoader::ensureResampleSpaceAvailable(int samples) { return true; } const auto allocate = std::max(samples, int(av_rescale_rnd( - AVBlockSize / _outputSampleSize, + FFmpeg::kAVBlockSize / _outputSampleSize, _swrDstRate, _swrSrcRate, AV_ROUND_UP))); @@ -501,7 +503,7 @@ AbstractAudioFFMpegLoader::~AbstractAudioFFMpegLoader() { } FFMpegLoader::FFMpegLoader( - const FileLocation & file, + const Core::FileLocation & file, const QByteArray & data, bytes::vector && buffer) : AbstractAudioFFMpegLoader(file, data, std::move(buffer)) { diff --git a/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.h b/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.h index c0c5f32ca4..83de13bad2 100644 --- a/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.h +++ b/Telegram/SourceFiles/media/audio/media_audio_ffmpeg_loader.h @@ -20,12 +20,16 @@ extern "C" { #include <al.h> +namespace Core { +class FileLocation; +} // namespace Core + namespace Media { class AbstractFFMpegLoader : public AudioPlayerLoader { public: AbstractFFMpegLoader( - |