init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
223
Telegram/SourceFiles/media/streaming/media_streaming_player.h
Normal file
223
Telegram/SourceFiles/media/streaming/media_streaming_player.h
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
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_file_delegate.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace Media {
|
||||
namespace Player {
|
||||
struct TrackState;
|
||||
} // namespace Player
|
||||
} // namespace Media
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
|
||||
class Reader;
|
||||
class File;
|
||||
class AudioTrack;
|
||||
class VideoTrack;
|
||||
class Instance;
|
||||
|
||||
class Player final : private FileDelegate {
|
||||
public:
|
||||
// Public interfaces is used from the main thread.
|
||||
explicit Player(std::shared_ptr<Reader> reader);
|
||||
|
||||
// Because we remember 'this' in calls to crl::on_main.
|
||||
Player(const Player &other) = delete;
|
||||
Player &operator=(const Player &other) = delete;
|
||||
|
||||
void play(const PlaybackOptions &options);
|
||||
void pause();
|
||||
void resume();
|
||||
void stop();
|
||||
|
||||
// Allow to irreversibly stop only audio track.
|
||||
void stopAudio();
|
||||
|
||||
[[nodiscard]] bool active() const;
|
||||
[[nodiscard]] bool ready() const;
|
||||
|
||||
[[nodiscard]] float64 speed() const;
|
||||
void setSpeed(float64 speed);
|
||||
void setWaitForMarkAsShown(bool wait);
|
||||
|
||||
[[nodiscard]] bool playing() const;
|
||||
[[nodiscard]] bool buffering() const;
|
||||
[[nodiscard]] bool paused() const;
|
||||
[[nodiscard]] std::optional<Error> failed() const;
|
||||
[[nodiscard]] bool finished() const;
|
||||
|
||||
[[nodiscard]] rpl::producer<Update, Error> updates() const;
|
||||
[[nodiscard]] rpl::producer<bool> fullInCache() const;
|
||||
|
||||
[[nodiscard]] int64 fileSize() const;
|
||||
[[nodiscard]] QSize videoSize() const;
|
||||
[[nodiscard]] QImage frame(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance = nullptr) const;
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(
|
||||
const FrameRequest &request,
|
||||
const Instance *instance = nullptr) const;
|
||||
[[nodiscard]] FrameWithInfo frameWithInfo(
|
||||
const Instance *instance = nullptr) const; // !requireARGB32
|
||||
|
||||
[[nodiscard]] QImage currentFrameImage() const; // Converts if needed.
|
||||
|
||||
void unregisterInstance(not_null<const Instance*> instance);
|
||||
bool markFrameShown();
|
||||
|
||||
void setLoaderPriority(int priority);
|
||||
|
||||
[[nodiscard]] Media::Player::TrackState prepareLegacyState() const;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
[[nodiscard]] bool locked() const;
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
~Player();
|
||||
|
||||
private:
|
||||
enum class Stage {
|
||||
Uninitialized,
|
||||
Initializing,
|
||||
Ready,
|
||||
Started,
|
||||
};
|
||||
|
||||
// Thread-safe.
|
||||
not_null<FileDelegate*> delegate();
|
||||
|
||||
// FileDelegate methods are called only from the File thread.
|
||||
Mode fileOpenMode() override;
|
||||
bool fileReady(int headerSize, Stream &&video, Stream &&audio) override;
|
||||
void fileError(Error error) override;
|
||||
void fileWaitingForData() override;
|
||||
void fileFullInCache(bool fullInCache) override;
|
||||
bool fileProcessPackets(
|
||||
base::flat_map<int, std::vector<FFmpeg::Packet>> &packets) override;
|
||||
void fileProcessEndOfFile() override;
|
||||
bool fileReadMore() override;
|
||||
|
||||
// Called from the main thread.
|
||||
void streamReady(Information &&information);
|
||||
void streamFailed(Error error);
|
||||
void start();
|
||||
void stop(bool stillActive);
|
||||
void provideStartInformation();
|
||||
void fail(Error error);
|
||||
void checkVideoStep();
|
||||
void checkNextFrameRender();
|
||||
void checkNextFrameAvailability();
|
||||
void renderFrame(crl::time now);
|
||||
void audioReceivedTill(crl::time position);
|
||||
void audioPlayedTill(crl::time position);
|
||||
void videoReceivedTill(crl::time position);
|
||||
void videoPlayedTill(crl::time position);
|
||||
|
||||
void updatePausedState();
|
||||
[[nodiscard]] bool trackReceivedEnough(
|
||||
const TrackState &state,
|
||||
crl::time amount) const;
|
||||
[[nodiscard]] bool bothReceivedEnough(crl::time amount) const;
|
||||
[[nodiscard]] bool receivedTillEnd() const;
|
||||
void checkResumeFromWaitingForData();
|
||||
[[nodiscard]] crl::time getCurrentReceivedTill(crl::time duration) const;
|
||||
void savePreviousReceivedTill(
|
||||
const PlaybackOptions &options,
|
||||
crl::time previousReceivedTill);
|
||||
[[nodiscard]] crl::time loadInAdvanceFor() const;
|
||||
|
||||
template <typename Track>
|
||||
int durationByPacket(const Track &track, const FFmpeg::Packet &packet);
|
||||
|
||||
// Valid after fileReady call ends. Thread-safe.
|
||||
[[nodiscard]] crl::time computeAudioDuration() const;
|
||||
[[nodiscard]] crl::time computeVideoDuration() const;
|
||||
[[nodiscard]] crl::time computeTotalDuration() const;
|
||||
void setDurationByPackets();
|
||||
|
||||
template <typename Track>
|
||||
void trackReceivedTill(
|
||||
const Track &track,
|
||||
TrackState &state,
|
||||
crl::time position);
|
||||
|
||||
template <typename Track>
|
||||
void trackSendReceivedTill(
|
||||
const Track &track,
|
||||
TrackState &state);
|
||||
|
||||
template <typename Track>
|
||||
void trackPlayedTill(
|
||||
const Track &track,
|
||||
TrackState &state,
|
||||
crl::time position);
|
||||
|
||||
const std::unique_ptr<File> _file;
|
||||
|
||||
// Immutable while File is active after it is ready.
|
||||
AudioMsgId _audioId;
|
||||
std::unique_ptr<AudioTrack> _audio;
|
||||
std::unique_ptr<VideoTrack> _video;
|
||||
|
||||
// Immutable while File is active.
|
||||
base::has_weak_ptr _sessionGuard;
|
||||
|
||||
// Immutable while File is active except '.speed'.
|
||||
// '.speed' is changed from the main thread.
|
||||
PlaybackOptions _options;
|
||||
|
||||
// Belongs to the File thread while File is active.
|
||||
bool _readTillEnd = false;
|
||||
bool _waitingForData = false;
|
||||
|
||||
std::atomic<bool> _pauseReading = false;
|
||||
|
||||
// Belongs to the main thread.
|
||||
Information _information;
|
||||
Stage _stage = Stage::Uninitialized;
|
||||
std::optional<Error> _lastFailure;
|
||||
bool _pausedByUser = false;
|
||||
bool _pausedByWaitingForData = false;
|
||||
bool _paused = false;
|
||||
bool _audioFinished = false;
|
||||
bool _videoFinished = false;
|
||||
bool _remoteLoader = false;
|
||||
|
||||
crl::time _startedTime = kTimeUnknown;
|
||||
crl::time _pausedTime = kTimeUnknown;
|
||||
crl::time _currentFrameTime = kTimeUnknown;
|
||||
crl::time _nextFrameTime = kTimeUnknown;
|
||||
base::Timer _renderFrameTimer;
|
||||
rpl::event_stream<Update, Error> _updates;
|
||||
rpl::event_stream<bool> _fullInCache;
|
||||
std::optional<bool> _fullInCacheSinceStart;
|
||||
|
||||
crl::time _totalDuration = kTimeUnknown;
|
||||
crl::time _loopingShift = 0;
|
||||
crl::time _previousReceivedTill = kTimeUnknown;
|
||||
std::atomic<int> _durationByPackets = 0;
|
||||
int _durationByLastAudioPacket = 0;
|
||||
int _durationByLastVideoPacket = 0;
|
||||
|
||||
int _locks = 0;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
rpl::lifetime _sessionLifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Streaming
|
||||
} // namespace Media
|
||||
Reference in New Issue
Block a user