11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
36PROMEKI_NAMESPACE_BEGIN
88class RtmpClient :
public ObjectBase {
89 PROMEKI_OBJECT(RtmpClient, ObjectBase)
92 static constexpr int DefaultSendQueueDepth = 64;
95 static constexpr int DefaultReadQueueDepth = 64;
98 static constexpr unsigned int DefaultConnectTimeoutMs = 10000;
106 explicit RtmpClient(ObjectBase *parent =
nullptr);
109 ~RtmpClient()
override;
111#if PROMEKI_ENABLE_TLS
126 void setSslContext(SslContext ctx) { _sslContext = std::move(ctx); }
139 Error open(
const Url &url,
140 const RtmpConnectOptions &opts = {},
141 unsigned int timeoutMs = DefaultConnectTimeoutMs);
153 Error publish(
const String &streamKey = String(),
154 const String &mode =
"live",
155 unsigned int timeoutMs = 5000);
163 Error play(
const String &streamKey = String(),
164 unsigned int timeoutMs = 5000,
165 bool useFcSubscribe =
false);
175 Error sendVideo(
const FlvVideoTag &tag, uint32_t timestampMs);
182 Error sendAudio(
const FlvAudioTag &tag, uint32_t timestampMs);
195 Error sendMetadata(
const Metadata &meta, uint32_t timestampMs = 0);
205 Result<FlvVideoTag> takeVideo(
unsigned int timeoutMs);
211 Result<FlvAudioTag> takeAudio(
unsigned int timeoutMs);
217 Result<Metadata> takeMetadata(
unsigned int timeoutMs);
227 const Url &url()
const {
return _url; }
230 const String &app()
const {
return _app; }
233 const String &streamKey()
const {
return _streamKey; }
236 uint32_t streamId()
const {
return _streamId.value(); }
239 bool isOpen()
const {
return _open.value(); }
242 RtmpSession *session() {
return _session.get(); }
247 int64_t bytesSent()
const {
return _bytesSent.value(); }
250 int64_t bytesReceived()
const {
return _bytesReceived.value(); }
253 int64_t videoMessagesSent()
const {
return _videoMessagesSent.value(); }
256 int64_t audioMessagesSent()
const {
return _audioMessagesSent.value(); }
259 int64_t videoMessagesReceived()
const {
return _videoMessagesReceived.value(); }
262 int64_t audioMessagesReceived()
const {
return _audioMessagesReceived.value(); }
274 Duration rttEstimate()
const {
return Duration(); }
279 PROMEKI_SIGNAL(connected);
282 PROMEKI_SIGNAL(disconnected, Error);
285 PROMEKI_SIGNAL(metadataReceived, Metadata);
305 static void splitPath(
const Url &url, String &app, String &streamKey);
311 void teardown(Error reason);
312 void startMediaThreads();
317 Atomic<uint32_t> _streamId{0};
318 Atomic<bool> _open{
false};
319 Atomic<bool> _stopping{
false};
321 UniquePtr<TcpSocket> _socket;
322 UniquePtr<RtmpSession> _session;
323 UniquePtr<WriterThread> _writer;
324 UniquePtr<ReaderThread> _reader;
326#if PROMEKI_ENABLE_TLS
327 SslContext _sslContext;
331 Queue<RtmpMessage> _writeQueue;
332 Queue<FlvVideoTag> _videoRxQueue;
333 Queue<FlvAudioTag> _audioRxQueue;
334 Queue<Metadata> _metadataRxQueue;
336 Atomic<int64_t> _bytesSent{0};
337 Atomic<int64_t> _bytesReceived{0};
338 Atomic<int64_t> _videoMessagesSent{0};
339 Atomic<int64_t> _audioMessagesSent{0};
340 Atomic<int64_t> _videoMessagesReceived{0};
341 Atomic<int64_t> _audioMessagesReceived{0};