11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
32PROMEKI_NAMESPACE_BEGIN
47struct RtmpConnectOptions {
59 String type =
"nonprivate";
61 int objectEncoding = 0;
63 int capabilities = 239;
65 int audioCodecs = 0x0FFF;
67 int videoCodecs = 0x00FF;
69 int videoFunction = 1;
80 List<FourCC> fourCcList = { FourCC(
"hvc1") };
138class RtmpSession :
public ObjectBase {
139 PROMEKI_OBJECT(RtmpSession, ObjectBase)
142 static constexpr int DefaultPostConnectChunkSize = 60000;
151 explicit RtmpSession(RtmpRole role, ObjectBase *parent =
nullptr);
154 ~RtmpSession()
override;
163 Error attach(IODevice *device);
166 IODevice *device()
const {
return _device; }
169 RtmpChunkStream *chunkStream() {
return _chunk.get(); }
177 Error performHandshake(
unsigned int timeoutMs = 10000);
193 Error connect(
const RtmpConnectOptions &opts,
unsigned int timeoutMs = 10000);
199 Result<uint32_t> createStream(
unsigned int timeoutMs = 5000);
209 Error publish(uint32_t streamId,
const String &streamKey,
210 const String &mode =
"live",
unsigned int timeoutMs = 5000);
224 Error play(uint32_t streamId,
const String &streamKey,
225 double start = -2.0,
double duration = -1.0,
226 unsigned int timeoutMs = 5000);
233 Error deleteStream(uint32_t streamId);
243 Error releaseStream(
const String &streamKey);
250 Error fcPublish(
const String &streamKey);
256 Error fcUnpublish(
const String &streamKey);
263 Error fcSubscribe(
const String &streamKey);
272 Error sendMessage(
const RtmpMessage &m);
286 Result<RtmpMessage> readMessage(
unsigned int timeoutMs = 0);
297 static Error onStatusToError(
const String &code);
302 PROMEKI_SIGNAL(handshakeComplete);
305 PROMEKI_SIGNAL(connected);
312 PROMEKI_SIGNAL(connectionFailed, Error);
319 PROMEKI_SIGNAL(streamCreated, uint32_t);
326 PROMEKI_SIGNAL(publishStarted, uint32_t);
333 PROMEKI_SIGNAL(playStarted, uint32_t);
343 PROMEKI_SIGNAL(onStatus, Amf0Value);
351 PROMEKI_SIGNAL(onMetaData, Metadata);
358 PROMEKI_SIGNAL(audioMessageReceived, RtmpMessage);
365 PROMEKI_SIGNAL(videoMessageReceived, RtmpMessage);
368 PROMEKI_SIGNAL(disconnected);
372 struct PendingTransaction {
373 Error result = Error::Timeout;
374 bool completed =
false;
375 Amf0Value commandObject;
391 uint32_t expectedMsid = 0;
402 Error sendCommand(uint32_t csid, uint32_t msid,
403 const String &command,
double txnId,
404 const Amf0Value::List &args);
405 Error awaitTransaction(
double txnId,
unsigned int timeoutMs,
406 PendingTransaction *outTxn =
nullptr);
407 Error handleInboundCommand(
const RtmpMessage &msg);
408 Error handleInboundUserControl(
const RtmpMessage &msg);
409 Error handleInboundData(
const RtmpMessage &msg);
410 void applyConnectFlowDefaults();
417 Error pumpUntilTransaction(
double txnId,
unsigned int timeoutMs,
418 PendingTransaction *outTxn);
421 double nextTransactionId();
423 IODevice *_device =
nullptr;
425 RtmpHandshake _handshake;
426 UniquePtr<RtmpChunkStream> _chunk;
428 Atomic<double> _nextTxnId{1.0};
431 HashMap<double, PendingTransaction *> _pending;
433 bool _connected =
false;