2019-02-13 18:10:18 +00:00
|
|
|
/*
|
|
|
|
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"
|
2019-02-17 06:54:57 +00:00
|
|
|
#include "media/streaming/media_streaming_utility.h"
|
2019-02-13 18:10:18 +00:00
|
|
|
#include "media/streaming/media_streaming_reader.h"
|
2019-06-26 15:04:38 +00:00
|
|
|
#include "ffmpeg/ffmpeg_utility.h"
|
2019-02-13 18:10:18 +00:00
|
|
|
#include "base/bytes.h"
|
|
|
|
#include "base/weak_ptr.h"
|
|
|
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
namespace Data {
|
|
|
|
class Session;
|
|
|
|
} // namespace Data
|
|
|
|
|
|
|
|
namespace Media {
|
|
|
|
namespace Streaming {
|
|
|
|
|
2019-02-17 06:54:57 +00:00
|
|
|
class FileDelegate;
|
2019-02-13 18:10:18 +00:00
|
|
|
|
|
|
|
class File final {
|
|
|
|
public:
|
2019-04-10 11:26:15 +00:00
|
|
|
File(not_null<Data::Session*> owner, std::shared_ptr<Reader> reader);
|
2019-02-13 18:10:18 +00:00
|
|
|
|
|
|
|
File(const File &other) = delete;
|
|
|
|
File &operator=(const File &other) = delete;
|
|
|
|
|
2019-02-17 06:54:57 +00:00
|
|
|
void start(not_null<FileDelegate*> delegate, crl::time position);
|
|
|
|
void wake();
|
2019-04-11 10:52:49 +00:00
|
|
|
void stop(bool stillActive = false);
|
2019-02-13 18:10:18 +00:00
|
|
|
|
2019-03-05 13:56:27 +00:00
|
|
|
[[nodiscard]] bool isRemoteLoader() const;
|
2019-12-23 10:27:20 +00:00
|
|
|
void setLoaderPriority(int priority);
|
2019-03-05 13:56:27 +00:00
|
|
|
|
2019-02-13 18:10:18 +00:00
|
|
|
~File();
|
|
|
|
|
|
|
|
private:
|
|
|
|
class Context final : public base::has_weak_ptr {
|
|
|
|
public:
|
2019-02-17 06:54:57 +00:00
|
|
|
Context(not_null<FileDelegate*> delegate, not_null<Reader*> reader);
|
2019-12-19 11:13:27 +00:00
|
|
|
~Context();
|
2019-02-13 18:10:18 +00:00
|
|
|
|
2019-02-17 06:54:57 +00:00
|
|
|
void start(crl::time position);
|
2019-02-13 18:10:18 +00:00
|
|
|
void readNextPacket();
|
|
|
|
|
|
|
|
void interrupt();
|
2019-02-20 13:28:48 +00:00
|
|
|
void wake();
|
2019-02-13 18:10:18 +00:00
|
|
|
[[nodiscard]] bool interrupted() const;
|
|
|
|
[[nodiscard]] bool failed() const;
|
|
|
|
[[nodiscard]] bool finished() const;
|
|
|
|
|
2019-12-23 11:13:32 +00:00
|
|
|
void stopStreamingAsync();
|
2019-02-13 18:10:18 +00:00
|
|
|
|
|
|
|
private:
|
2019-12-19 15:14:05 +00:00
|
|
|
enum class SleepPolicy {
|
|
|
|
Allowed,
|
|
|
|
Disallowed,
|
|
|
|
};
|
2019-02-13 18:10:18 +00:00
|
|
|
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);
|
2019-06-26 15:04:38 +00:00
|
|
|
void logError(QLatin1String method, FFmpeg::AvErrorWrap error);
|
2019-02-13 18:10:18 +00:00
|
|
|
void logFatal(QLatin1String method);
|
2019-06-26 15:04:38 +00:00
|
|
|
void logFatal(QLatin1String method, FFmpeg::AvErrorWrap error);
|
2019-03-05 13:56:27 +00:00
|
|
|
void fail(Error error);
|
2019-02-13 18:10:18 +00:00
|
|
|
|
2019-03-05 13:56:27 +00:00
|
|
|
Stream initStream(
|
|
|
|
not_null<AVFormatContext *> format,
|
|
|
|
AVMediaType type);
|
|
|
|
void seekToPosition(
|
|
|
|
not_null<AVFormatContext *> format,
|
|
|
|
const Stream &stream,
|
|
|
|
crl::time position);
|
2019-02-13 18:10:18 +00:00
|
|
|
|
2019-02-17 06:54:57 +00:00
|
|
|
// TODO base::expected.
|
2019-06-26 15:04:38 +00:00
|
|
|
[[nodiscard]] auto readPacket()
|
|
|
|
-> base::variant<FFmpeg::Packet, FFmpeg::AvErrorWrap>;
|
2019-12-19 15:14:05 +00:00
|
|
|
void processQueuedPackets(SleepPolicy policy);
|
2019-02-13 18:10:18 +00:00
|
|
|
|
2019-02-17 06:54:57 +00:00
|
|
|
void handleEndOfFile();
|
2019-05-31 16:45:03 +00:00
|
|
|
void sendFullInCache(bool force = false);
|
2019-02-17 06:54:57 +00:00
|
|
|
|
|
|
|
const not_null<FileDelegate*> _delegate;
|
|
|
|
const not_null<Reader*> _reader;
|
|
|
|
|
2019-12-19 15:14:05 +00:00
|
|
|
base::flat_map<int, std::vector<FFmpeg::Packet>> _queuedPackets;
|
2019-02-13 18:10:18 +00:00
|
|
|
int _offset = 0;
|
|
|
|
int _size = 0;
|
|
|
|
bool _failed = false;
|
|
|
|
bool _readTillEnd = false;
|
2019-05-31 16:45:03 +00:00
|
|
|
std::optional<bool> _fullInCache;
|
2019-02-13 18:10:18 +00:00
|
|
|
crl::semaphore _semaphore;
|
|
|
|
std::atomic<bool> _interrupted = false;
|
|
|
|
|
2019-06-26 15:04:38 +00:00
|
|
|
FFmpeg::FormatPointer _format;
|
2019-02-13 18:10:18 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2019-02-17 06:54:57 +00:00
|
|
|
std::optional<Context> _context;
|
2019-04-10 11:26:15 +00:00
|
|
|
std::shared_ptr<Reader> _reader;
|
2019-02-17 06:54:57 +00:00
|
|
|
std::thread _thread;
|
2019-02-13 18:10:18 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Streaming
|
|
|
|
} // namespace Media
|