/* 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 "media/streaming/media_streaming_common.h" #include "media/streaming/media_streaming_utility.h" #include "media/streaming/media_streaming_reader.h" #include "ffmpeg/ffmpeg_utility.h" #include "base/bytes.h" #include "base/weak_ptr.h" #include namespace Media { namespace Streaming { class FileDelegate; struct StartOptions { crl::time position = 0; crl::time durationOverride = 0; bool seekable = true; bool hwAllow = false; }; class File final { public: explicit File(std::shared_ptr reader); File(const File &other) = delete; File &operator=(const File &other) = delete; void start(not_null delegate, StartOptions options); void wake(); void stop(bool stillActive = false); [[nodiscard]] bool isRemoteLoader() const; void setLoaderPriority(int priority); ~File(); private: class Context final : public base::has_weak_ptr { public: Context(not_null delegate, not_null reader); ~Context(); void start(StartOptions options); void readNextPacket(); void interrupt(); void wake(); [[nodiscard]] bool interrupted() const; [[nodiscard]] bool failed() const; [[nodiscard]] bool finished() const; void stopStreamingAsync(); private: enum class SleepPolicy { Allowed, Disallowed, }; static int Read(void *opaque, uint8_t *buffer, int bufferSize); static int64_t Seek(void *opaque, int64_t offset, int whence); [[nodiscard]] int read(bytes::span buffer); [[nodiscard]] int64_t seek(int64_t offset, int whence); [[nodiscard]] bool unroll() const; void logError(QLatin1String method); void logError(QLatin1String method, FFmpeg::AvErrorWrap error); void logFatal(QLatin1String method); void logFatal(QLatin1String method, FFmpeg::AvErrorWrap error); void fail(Error error); [[nodiscard]] Stream initStream( not_null format, AVMediaType type, Mode mode, StartOptions options); void seekToPosition( not_null format, const Stream &stream, crl::time position); // TODO base::expected. [[nodiscard]] auto readPacket() -> std::variant; void processQueuedPackets(SleepPolicy policy); void handleEndOfFile(); void sendFullInCache(bool force = false); const not_null _delegate; const not_null _reader; base::flat_map> _queuedPackets; int64 _offset = 0; int64 _size = 0; bool _failed = false; bool _readTillEnd = false; std::optional _fullInCache; crl::semaphore _semaphore; std::atomic _interrupted = false; FFmpeg::FormatPointer _format; }; std::optional _context; std::shared_ptr _reader; std::thread _thread; }; } // namespace Streaming } // namespace Media