1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include "media/streaming/media_streaming_utility.h" 11 12 namespace Media { 13 namespace Streaming { 14 15 class AudioTrack final { 16 public: 17 // Called from some unspecified thread. 18 // Callbacks are assumed to be thread-safe. 19 AudioTrack( 20 const PlaybackOptions &options, 21 Stream &&stream, 22 AudioMsgId audioId, 23 FnMut<void(const Information &)> ready, 24 Fn<void(Error)> error); 25 26 // Called from the main thread. 27 // Must be called after 'ready' was invoked. 28 void pause(crl::time time); 29 void resume(crl::time time); 30 31 // Allow to irreversibly stop only audio track. 32 void stop(); 33 34 // Called from the main thread. 35 void setSpeed(float64 speed); 36 [[nodiscard]] rpl::producer<> waitingForData() const; 37 38 // Called from the main thread. 39 // Non-const, because we subscribe to changes on the first call. 40 // Must be called after 'ready' was invoked. 41 [[nodiscard]] rpl::producer<crl::time> playPosition(); 42 43 // Thread-safe. 44 [[nodiscard]] int streamIndex() const; 45 [[nodiscard]] AVRational streamTimeBase() const; 46 [[nodiscard]] crl::time streamDuration() const; 47 48 // Called from the same unspecified thread. 49 void process(std::vector<FFmpeg::Packet> &&packets); 50 void waitForData(); 51 52 // Called from the main thread. 53 ~AudioTrack(); 54 55 private: 56 // Called from the same unspecified thread. 57 [[nodiscard]] bool initialized() const; 58 [[nodiscard]] bool tryReadFirstFrame(FFmpeg::Packet &&packet); 59 [[nodiscard]] bool fillStateFromFrame(); 60 [[nodiscard]] bool processFirstFrame(); 61 void mixerInit(); 62 void mixerEnqueue(gsl::span<FFmpeg::Packet> packets); 63 void mixerForceToBuffer(); 64 void callReady(); 65 66 PlaybackOptions _options; 67 68 // Accessed from the same unspecified thread. 69 Stream _stream; 70 const AudioMsgId _audioId; 71 bool _readTillEnd = false; 72 73 // Assumed to be thread-safe. 74 FnMut<void(const Information &)> _ready; 75 const Fn<void(Error)> _error; 76 77 // First set from the same unspecified thread before _ready is called. 78 // After that is immutable. 79 crl::time _startedPosition = kTimeUnknown; 80 81 // Accessed from the main thread. 82 base::Subscription _subscription; 83 rpl::event_stream<> _waitingForData; 84 // First set from the same unspecified thread before _ready is called. 85 // After that accessed from the main thread. 86 rpl::variable<crl::time> _playPosition; 87 88 // For initial frame skipping for an exact seek. 89 FFmpeg::FramePointer _initialSkippingFrame; 90 91 }; 92 93 } // namespace Streaming 94 } // namespace Media 95