tdesktop/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h

96 lines
2.6 KiB
C++

/*
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 "base/observer.h"
#include "media/streaming/media_streaming_utility.h"
namespace Media {
namespace Streaming {
class AudioTrack final {
public:
// Called from some unspecified thread.
// Callbacks are assumed to be thread-safe.
AudioTrack(
const PlaybackOptions &options,
Stream &&stream,
AudioMsgId audioId,
FnMut<void(const Information &)> ready,
Fn<void(Error)> error);
// Called from the main thread.
// Must be called after 'ready' was invoked.
void pause(crl::time time);
void resume(crl::time time);
// Allow to irreversibly stop only audio track.
void stop();
// Called from the main thread.
void setSpeed(float64 speed);
[[nodiscard]] rpl::producer<> waitingForData() const;
// Called from the main thread.
// Non-const, because we subscribe to changes on the first call.
// Must be called after 'ready' was invoked.
[[nodiscard]] rpl::producer<crl::time> playPosition();
// 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.
~AudioTrack();
private:
// Called from the same unspecified thread.
[[nodiscard]] bool initialized() const;
[[nodiscard]] bool tryReadFirstFrame(FFmpeg::Packet &&packet);
[[nodiscard]] bool fillStateFromFrame();
[[nodiscard]] bool processFirstFrame();
void mixerInit();
void mixerEnqueue(gsl::span<FFmpeg::Packet> packets);
void mixerForceToBuffer();
void callReady();
PlaybackOptions _options;
// Accessed from the same unspecified thread.
Stream _stream;
const AudioMsgId _audioId;
bool _readTillEnd = false;
// Assumed to be thread-safe.
FnMut<void(const Information &)> _ready;
const Fn<void(Error)> _error;
// First set from the same unspecified thread before _ready is called.
// After that is immutable.
crl::time _startedPosition = kTimeUnknown;
// Accessed from the main thread.
base::Subscription _subscription;
rpl::event_stream<> _waitingForData;
// First set from the same unspecified thread before _ready is called.
// After that accessed from the main thread.
rpl::variable<crl::time> _playPosition;
// For initial frame skipping for an exact seek.
FFmpeg::FramePointer _initialSkippingFrame;
};
} // namespace Streaming
} // namespace Media