| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*
- 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_utility.h"
- #include <crl/crl_object_on_queue.h>
- namespace Media {
- namespace Streaming {
- constexpr auto kFrameDisplayTimeAlreadyDone
- = std::numeric_limits<crl::time>::max();
- class VideoTrackObject;
- class Instance;
- class VideoTrack final {
- public:
- // Called from some unspecified thread.
- // Callbacks are assumed to be thread-safe.
- VideoTrack(
- const PlaybackOptions &options,
- Stream &&stream,
- const AudioMsgId &audioId,
- FnMut<void(const Information &)> ready,
- Fn<void(Error)> error);
- // Thread-safe.
- [[nodiscard]] int streamIndex() const;
- [[nodiscard]] AVRational streamTimeBase() const;
- [[nodiscard]] crl::time streamDuration() const;
- // Called from the same unspecified thread.
- void process(std::vector<FFmpeg::Packet> &&packets);
- void waitForData();
- // Called from the main thread.
- // Must be called after 'ready' was invoked.
- void pause(crl::time time);
- void resume(crl::time time);
- // Called from the main thread.
- void setSpeed(float64 speed);
- void setWaitForMarkAsShown(bool wait);
- // Called from the main thread.
- // Returns the position of the displayed frame.
- [[nodiscard]] crl::time markFrameDisplayed(crl::time now);
- void addTimelineDelay(crl::time delayed);
- bool markFrameShown();
- [[nodiscard]] crl::time nextFrameDisplayTime() const;
- [[nodiscard]] QImage frame(
- const FrameRequest &request,
- const Instance *instance);
- [[nodiscard]] FrameWithInfo frameWithInfo(
- const FrameRequest &request,
- const Instance *instance);
- [[nodiscard]] FrameWithInfo frameWithInfo(const Instance *instance);
- [[nodiscard]] QImage currentFrameImage();
- void unregisterInstance(not_null<const Instance*> instance);
- [[nodiscard]] rpl::producer<> checkNextFrame() const;
- [[nodiscard]] rpl::producer<> waitingForData() const;
- // Called from the main thread.
- ~VideoTrack();
- private:
- friend class VideoTrackObject;
- struct Prepared {
- Prepared(const FrameRequest &request) : request(request) {
- }
- FrameRequest request = FrameRequest::NonStrict();
- QImage image;
- };
- struct Frame {
- FFmpeg::FramePointer decoded = FFmpeg::MakeFramePointer();
- FFmpeg::FramePointer transferred;
- QImage original;
- FrameYUV yuv;
- crl::time position = kTimeUnknown;
- crl::time displayed = kTimeUnknown;
- crl::time display = kTimeUnknown;
- FrameFormat format = FrameFormat::None;
- base::flat_map<const Instance*, Prepared> prepared;
- int index = 0;
- bool alpha = false;
- };
- struct FrameWithIndex {
- not_null<Frame*> frame;
- int index = -1;
- };
- class Shared {
- public:
- using PrepareFrame = not_null<Frame*>;
- using PrepareNextCheck = crl::time;
- using PrepareState = std::variant<
- v::null_t,
- PrepareFrame,
- PrepareNextCheck>;
- struct PresentFrame {
- crl::time displayPosition = kTimeUnknown;
- crl::time nextCheckDelay = 0;
- crl::time addedWorldTimeDelay = 0;
- };
- // Called from the wrapped object queue.
- void init(QImage &&cover, bool hasAlpha, crl::time position);
- [[nodiscard]] bool initialized() const;
- [[nodiscard]] PrepareState prepareState(
- crl::time trackTime,
- bool dropStaleFrames);
- [[nodiscard]] PresentFrame presentFrame(
- not_null<VideoTrackObject*> object,
- TimePoint trackTime,
- float64 playbackSpeed,
- bool dropStaleFrames);
- [[nodiscard]] bool firstPresentHappened() const;
- // Called from the main thread.
- // Returns the position of the displayed frame.
- [[nodiscard]] crl::time markFrameDisplayed(crl::time now);
- void addTimelineDelay(crl::time delayed);
- bool markFrameShown();
- [[nodiscard]] crl::time nextFrameDisplayTime() const;
- [[nodiscard]] not_null<Frame*> frameForPaint();
- [[nodiscard]] FrameWithIndex frameForPaintWithIndex();
- private:
- [[nodiscard]] not_null<Frame*> getFrame(int index);
- [[nodiscard]] not_null<const Frame*> getFrame(int index) const;
- [[nodiscard]] int counter() const;
- static constexpr auto kCounterUninitialized = -1;
- std::atomic<int> _counter = kCounterUninitialized;
- static constexpr auto kFramesCount = 4;
- std::array<Frame, kFramesCount> _frames;
- // (_counter % 2) == 1 main thread can write _delay.
- // (_counter % 2) == 0 crl::queue can read _delay.
- crl::time _delay = kTimeUnknown;
- };
- static void PrepareFrameByRequests(
- not_null<Frame*> frame,
- const AVRational &aspect,
- int rotation);
- [[nodiscard]] static bool IsDecoded(not_null<const Frame*> frame);
- [[nodiscard]] static bool IsRasterized(not_null<const Frame*> frame);
- [[nodiscard]] static bool IsStale(
- not_null<const Frame*> frame,
- crl::time trackTime);
- [[nodiscard]] QImage frameImage(
- not_null<Frame*> frame,
- const FrameRequest &request,
- const Instance *instance);
- const int _streamIndex = 0;
- const AVRational _streamTimeBase;
- const crl::time _streamDuration = 0;
- const int _streamRotation = 0;
- const AVRational _streamAspect = FFmpeg::kNormalAspect;
- std::unique_ptr<Shared> _shared;
- using Implementation = VideoTrackObject;
- crl::object_on_queue<Implementation> _wrapped;
- };
- } // namespace Streaming
- } // namespace Media
|