P2P - Libdatachannel/RTC Library Files

This commit is contained in:
2026-09-30 11:34:07 -07:00
parent 23f7abd778
commit 0d5ca59a8e
49 changed files with 4458 additions and 0 deletions

21
libdatachannel/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 RandomityGuy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,57 @@
/**
* Copyright (c) 2023 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_AV1_RTP_PACKETIZER_H
#define RTC_AV1_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "nalunit.hpp"
#include "rtppacketizer.hpp"
namespace rtc {
// RTP packetization of AV1 payload
class RTC_CPP_EXPORT AV1RtpPacketizer final : public RtpPacketizer {
public:
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;
// Define how OBUs are seperated in a AV1 Sample
enum class Packetization {
Obu = RTC_OBU_PACKETIZED_OBU,
TemporalUnit = RTC_OBU_PACKETIZED_TEMPORAL_UNIT,
};
// Constructs AV1 payload packetizer with given RTP configuration.
// @note RTP configuration is used in packetization process which may change some configuration
// properties such as sequence number.
AV1RtpPacketizer(Packetization packetization, shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
private:
static std::vector<binary> extractTemporalUnitObus(const binary &data);
std::vector<binary> fragment(binary data) override;
std::vector<binary> fragmentObu(const binary &data);
const Packetization mPacketization;
const size_t mMaxFragmentSize;
std::unique_ptr<binary> mSequenceHeader;
};
// For backward compatibility, do not use
using AV1PacketizationHandler [[deprecated("Add AV1RtpPacketizer directly")]] = PacketizationHandler;
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_AV1_RTP_PACKETIZER_H */

View File

@ -0,0 +1,77 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_CANDIDATE_H
#define RTC_CANDIDATE_H
#include "common.hpp"
#include <string>
namespace rtc {
class RTC_CPP_EXPORT Candidate {
public:
enum class Family { Unresolved, Ipv4, Ipv6 };
enum class Type { Unknown, Host, ServerReflexive, PeerReflexive, Relayed };
enum class TransportType { Unknown, Udp, TcpActive, TcpPassive, TcpSo, TcpUnknown };
Candidate();
Candidate(string candidate);
Candidate(string candidate, string mid);
void hintMid(string mid);
void changeAddress(string addr);
void changeAddress(string addr, uint16_t port);
void changeAddress(string addr, string service);
enum class ResolveMode { Simple, Lookup };
bool resolve(ResolveMode mode = ResolveMode::Simple);
Type type() const;
TransportType transportType() const;
uint32_t priority() const;
string candidate() const;
string mid() const;
operator string() const;
bool operator==(const Candidate &other) const;
bool operator!=(const Candidate &other) const;
bool isResolved() const;
Family family() const;
optional<string> address() const;
optional<uint16_t> port() const;
private:
void parse(string candidate);
string mFoundation;
uint32_t mComponent, mPriority;
string mTypeString, mTransportString;
Type mType;
TransportType mTransportType;
string mNode, mService;
string mTail;
optional<string> mMid;
// Extracted on resolution
Family mFamily;
string mAddress;
uint16_t mPort;
};
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const Candidate &candidate);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const Candidate::Type &type);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out,
const Candidate::TransportType &transportType);
} // namespace rtc
#endif

View File

@ -0,0 +1,61 @@
/**
* Copyright (c) 2019-2021 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_CHANNEL_H
#define RTC_CHANNEL_H
#include "common.hpp"
#include <atomic>
#include <functional>
namespace rtc {
namespace impl {
struct Channel;
}
class RTC_CPP_EXPORT Channel : private CheshireCat<impl::Channel> {
public:
virtual ~Channel();
virtual void close() = 0;
virtual bool send(message_variant data) = 0; // returns false if buffered
virtual bool send(const byte *data, size_t size) = 0;
virtual bool isOpen() const = 0;
virtual bool isClosed() const = 0;
virtual size_t maxMessageSize() const; // max message size in a call to send
virtual size_t bufferedAmount() const; // total size buffered to send
void onOpen(std::function<void()> callback);
void onClosed(std::function<void()> callback);
void onError(std::function<void(string error)> callback);
void onMessage(std::function<void(message_variant data)> callback);
void onMessage(std::function<void(binary data)> binaryCallback,
std::function<void(string data)> stringCallback);
void onBufferedAmountLow(std::function<void()> callback);
void setBufferedAmountLowThreshold(size_t amount);
void resetCallbacks();
// Extended API
optional<message_variant> receive(); // only if onMessage unset
optional<message_variant> peek(); // only if onMessage unset
size_t availableAmount() const; // total size available to receive
void onAvailable(std::function<void()> callback);
protected:
Channel(impl_ptr<impl::Channel> impl);
};
} // namespace rtc
#endif // RTC_CHANNEL_H

View File

@ -0,0 +1,85 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_COMMON_H
#define RTC_COMMON_H
#ifdef RTC_STATIC
#define RTC_CPP_EXPORT
#else // dynamic library
#ifdef _WIN32
#ifdef RTC_EXPORTS
#define RTC_CPP_EXPORT __declspec(dllexport) // building the library
#else
#define RTC_CPP_EXPORT __declspec(dllimport) // using the library
#endif
#else // not WIN32
#define RTC_CPP_EXPORT
#endif
#endif
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0602 // Windows 8
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4251) // disable "X needs to have dll-interface..."
#endif
#endif
#ifndef RTC_ENABLE_WEBSOCKET
#define RTC_ENABLE_WEBSOCKET 1
#endif
#ifndef RTC_ENABLE_MEDIA
#define RTC_ENABLE_MEDIA 1
#endif
#include "rtc.h" // for C API defines
#include "utils.hpp"
#include <cstddef>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
namespace rtc {
using std::byte;
using std::nullopt;
using std::optional;
using std::shared_ptr;
using std::string;
using std::string_view;
using std::unique_ptr;
using std::variant;
using std::weak_ptr;
using binary = std::vector<byte>;
using message_variant = variant<binary, string>;
using std::int16_t;
using std::int32_t;
using std::int64_t;
using std::int8_t;
using std::ptrdiff_t;
using std::size_t;
using std::uint16_t;
using std::uint32_t;
using std::uint64_t;
using std::uint8_t;
} // namespace rtc
#endif

View File

@ -0,0 +1,130 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_ICE_CONFIGURATION_H
#define RTC_ICE_CONFIGURATION_H
#include "common.hpp"
#include <vector>
namespace rtc {
struct RTC_CPP_EXPORT IceServer {
enum class Type { Stun, Turn };
enum class RelayType { TurnUdp, TurnTcp, TurnTls };
// Any type
IceServer(const string &url);
// STUN
IceServer(string hostname_, uint16_t port_);
IceServer(string hostname_, string service_);
// TURN
IceServer(string hostname_, uint16_t port, string username_, string password_,
RelayType relayType_ = RelayType::TurnUdp);
IceServer(string hostname_, string service_, string username_, string password_,
RelayType relayType_ = RelayType::TurnUdp);
string hostname;
uint16_t port;
Type type;
string username;
string password;
RelayType relayType;
};
struct RTC_CPP_EXPORT ProxyServer {
enum class Type { Http, Socks5 };
ProxyServer(const string &url);
ProxyServer(Type type_, string hostname_, uint16_t port_);
ProxyServer(Type type_, string hostname_, uint16_t port_, string username_, string password_);
Type type;
string hostname;
uint16_t port;
optional<string> username;
optional<string> password;
};
enum class CertificateType {
Default = RTC_CERTIFICATE_DEFAULT, // ECDSA
Ecdsa = RTC_CERTIFICATE_ECDSA,
Rsa = RTC_CERTIFICATE_RSA
};
enum class TransportPolicy { All = RTC_TRANSPORT_POLICY_ALL, Relay = RTC_TRANSPORT_POLICY_RELAY };
struct RTC_CPP_EXPORT Configuration {
// ICE settings
std::vector<IceServer> iceServers;
optional<ProxyServer> proxyServer; // libnice only
optional<string> bindAddress; // libjuice only, default any
// Options
CertificateType certificateType = CertificateType::Default;
TransportPolicy iceTransportPolicy = TransportPolicy::All;
bool enableIceTcp = false;
bool enableIceUdpMux = false; // libjuice only
bool disableAutoNegotiation = false;
bool disableAutoGathering = false;
bool forceMediaTransport = false;
bool disableFingerprintVerification = false;
// Port range
uint16_t portRangeBegin = 1024;
uint16_t portRangeEnd = 65535;
// Network MTU
optional<size_t> mtu;
// Local maximum message size for Data Channels
optional<size_t> maxMessageSize;
// Certificates and private keys
optional<string> certificatePemFile;
optional<string> keyPemFile;
optional<string> keyPemPass;
};
#ifdef RTC_ENABLE_WEBSOCKET
struct WebSocketConfiguration {
bool disableTlsVerification = false; // if true, don't verify the TLS certificate
optional<ProxyServer> proxyServer; // only non-authenticated http supported for now
std::vector<string> protocols;
optional<std::chrono::milliseconds> tcpConnectionTimeout; // zero to disable
optional<std::chrono::milliseconds> connectionTimeout; // zero to disable
optional<std::chrono::milliseconds> pingInterval; // zero to disable
optional<int> maxOutstandingPings;
optional<string> caCertificatePemFile;
optional<string> certificatePemFile;
optional<string> keyPemFile;
optional<string> keyPemPass;
optional<size_t> maxMessageSize;
};
struct WebSocketServerConfiguration {
uint16_t port = 8080;
bool enableTls = false;
optional<string> certificatePemFile;
optional<string> keyPemFile;
optional<string> keyPemPass;
optional<string> bindAddress;
optional<std::chrono::milliseconds> connectionTimeout;
optional<size_t> maxMessageSize;
};
#endif
} // namespace rtc
#endif

View File

@ -0,0 +1,80 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_DATA_CHANNEL_H
#define RTC_DATA_CHANNEL_H
#include "channel.hpp"
#include "common.hpp"
#include "reliability.hpp"
#include <type_traits>
namespace rtc {
namespace impl {
struct DataChannel;
struct PeerConnection;
} // namespace impl
class RTC_CPP_EXPORT DataChannel final : private CheshireCat<impl::DataChannel>, public Channel {
public:
DataChannel(impl_ptr<impl::DataChannel> impl);
~DataChannel() override;
optional<uint16_t> stream() const;
optional<uint16_t> id() const;
string label() const;
string protocol() const;
Reliability reliability() const;
bool isOpen(void) const override;
bool isClosed(void) const override;
size_t maxMessageSize() const override;
void close(void) override;
bool send(message_variant data) override;
bool send(const byte *data, size_t size) override;
template <typename Buffer> bool sendBuffer(const Buffer &buf);
template <typename Iterator> bool sendBuffer(Iterator first, Iterator last);
private:
using CheshireCat<impl::DataChannel>::impl;
};
template <typename Buffer> std::pair<const byte *, size_t> to_bytes(const Buffer &buf) {
using T = typename std::remove_pointer<decltype(buf.data())>::type;
using E = typename std::conditional<std::is_void<T>::value, byte, T>::type;
return std::make_pair(static_cast<const byte *>(static_cast<const void *>(buf.data())),
buf.size() * sizeof(E));
}
template <typename Buffer> bool DataChannel::sendBuffer(const Buffer &buf) {
auto [bytes, size] = to_bytes(buf);
return send(bytes, size);
}
template <typename Iterator> bool DataChannel::sendBuffer(Iterator first, Iterator last) {
size_t size = 0;
for (Iterator it = first; it != last; ++it)
size += it->size();
binary buffer(size);
byte *pos = buffer.data();
for (Iterator it = first; it != last; ++it) {
auto [bytes, len] = to_bytes(*it);
pos = std::copy(bytes, bytes + len, pos);
}
return send(std::move(buffer));
}
} // namespace rtc
#endif

View File

@ -0,0 +1,107 @@
/**
* Copyright (c) 2024 Shigemasa Watanabe (Wandbox)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_DEPENDENCY_DESCRIPTOR_H
#define RTC_DEPENDENCY_DESCRIPTOR_H
#include "common.hpp"
#include <bitset>
namespace rtc {
struct BitWriter {
static BitWriter fromSizeBits(byte *buf, size_t offsetBits, size_t sizeBits);
static BitWriter fromNull();
size_t getWrittenBits() const;
bool write(uint64_t v, size_t bits);
// Write non-symmetric unsigned encoded integer
// ref: https://aomediacodec.github.io/av1-rtp-spec/#a82-syntax
bool writeNonSymmetric(uint64_t v, uint64_t n);
private:
size_t writePartialByte(uint8_t *p, size_t offset, uint64_t v, size_t bits);
private:
byte *mBuf = nullptr;
size_t mInitialOffset = 0;
size_t mOffset = 0;
size_t mSize = 0;
};
enum class DecodeTargetIndication {
NotPresent = 0,
Discardable = 1,
Switch = 2,
Required = 3,
};
struct RenderResolution {
int width = 0;
int height = 0;
};
struct FrameDependencyTemplate {
int spatialId = 0;
int temporalId = 0;
std::vector<DecodeTargetIndication> decodeTargetIndications;
std::vector<int> frameDiffs;
std::vector<int> chainDiffs;
};
struct FrameDependencyStructure {
int templateIdOffset = 0;
int decodeTargetCount = 0;
int chainCount = 0;
std::vector<int> decodeTargetProtectedBy;
std::vector<RenderResolution> resolutions;
std::vector<FrameDependencyTemplate> templates;
};
struct DependencyDescriptor {
bool startOfFrame = true;
bool endOfFrame = true;
int frameNumber = 0;
FrameDependencyTemplate dependencyTemplate;
std::optional<RenderResolution> resolution;
std::optional<uint32_t> activeDecodeTargetsBitmask;
bool structureAttached;
};
struct DependencyDescriptorContext {
DependencyDescriptor descriptor;
std::bitset<32> activeChains;
FrameDependencyStructure structure;
};
// Write dependency descriptor to RTP Header Extension
// Dependency descriptor specification is here:
// https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension
class DependencyDescriptorWriter {
public:
explicit DependencyDescriptorWriter(const DependencyDescriptorContext& context);
size_t getSizeBits() const;
size_t getSize() const;
void writeTo(byte *buf, size_t sizeBytes) const;
private:
void doWriteTo(BitWriter &writer) const;
void writeBits(BitWriter &writer, uint64_t v, size_t bits) const;
void writeNonSymmetric(BitWriter &writer, uint64_t v, uint64_t n) const;
private:
const FrameDependencyStructure &mStructure;
std::bitset<32> mActiveChains;
const DependencyDescriptor &mDescriptor;
};
} // namespace rtc
#endif

View File

@ -0,0 +1,401 @@
/**
* Copyright (c) 2019-2020 Paul-Louis Ageneau
* Copyright (c) 2020 Staz Modrzynski
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_DESCRIPTION_H
#define RTC_DESCRIPTION_H
#include "candidate.hpp"
#include "common.hpp"
#include "rtp.hpp"
#include <iostream>
#include <map>
#include <vector>
namespace rtc {
const string DEFAULT_OPUS_AUDIO_PROFILE =
"minptime=10;maxaveragebitrate=96000;stereo=1;sprop-stereo=1;useinbandfec=1";
// Use Constrained Baseline profile Level 3.1 (necessary for Firefox)
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#Supported_video_codecs
// TODO: Should be 42E0 but 42C0 appears to be more compatible. Investigate this.
const string DEFAULT_H264_VIDEO_PROFILE =
"profile-level-id=42e01f;packetization-mode=1;level-asymmetry-allowed=1";
struct CertificateFingerprint {
enum class Algorithm { Sha1, Sha224, Sha256, Sha384, Sha512 };
static string AlgorithmIdentifier(Algorithm algorithm);
static size_t AlgorithmSize(Algorithm algorithm);
bool isValid() const;
Algorithm algorithm;
string value;
};
class RTC_CPP_EXPORT Description {
public:
enum class Type { Unspec, Offer, Answer, Pranswer, Rollback };
enum class Role { ActPass, Passive, Active };
enum class Direction {
SendOnly = RTC_DIRECTION_SENDONLY,
RecvOnly = RTC_DIRECTION_RECVONLY,
SendRecv = RTC_DIRECTION_SENDRECV,
Inactive = RTC_DIRECTION_INACTIVE,
Unknown = RTC_DIRECTION_UNKNOWN
};
Description(const string &sdp, Type type = Type::Unspec, Role role = Role::ActPass);
Description(const string &sdp, string typeString);
Type type() const;
string typeString() const;
Role role() const;
string bundleMid() const;
std::vector<string> iceOptions() const;
optional<string> iceUfrag() const;
optional<string> icePwd() const;
optional<CertificateFingerprint> fingerprint() const;
bool ended() const;
void hintType(Type type);
void addIceOption(string option);
void removeIceOption(const string &option);
void setIceAttribute(string ufrag, string pwd);
void setFingerprint(CertificateFingerprint f);
std::vector<string> attributes() const;
void addAttribute(string attr);
void removeAttribute(const string &attr);
std::vector<Candidate> candidates() const;
std::vector<Candidate> extractCandidates();
bool hasCandidate(const Candidate &candidate) const;
void addCandidate(Candidate candidate);
void addCandidates(std::vector<Candidate> candidates);
void endCandidates();
operator string() const;
string generateSdp(string_view eol = "\r\n") const;
string generateApplicationSdp(string_view eol = "\r\n") const;
class RTC_CPP_EXPORT RidAttribute {
public:
RidAttribute(string name, string value);
[[nodiscard]] const string &name() const;
[[nodiscard]] const string &value() const;
void value(string value);
private:
string mName;
string mValue;
};
class RTC_CPP_EXPORT Rid {
public:
explicit Rid(string rid);
Rid(string rid, std::vector<RidAttribute> attributes);
[[nodiscard]] const string &rid() const;
[[nodiscard]] const std::vector<RidAttribute> &attributes() const;
private:
string mRid;
std::vector<RidAttribute> mAttributes;
};
class RTC_CPP_EXPORT RidBuilder {
public:
explicit RidBuilder(string rid);
// https://datatracker.ietf.org/doc/html/rfc8851#name-arid-restrictions
RidBuilder& max_width(uint32_t value);
RidBuilder& max_height(uint32_t value);
RidBuilder& max_fps(uint32_t value);
RidBuilder& max_br(uint32_t value);
RidBuilder& custom(string key, string value);
// One time use only
[[nodiscard]] Rid build();
private:
string mRid;
std::vector<RidAttribute> mAttributes;
RidBuilder& saveAttribute(string key, string value);
};
class RTC_CPP_EXPORT Entry {
public:
virtual ~Entry() = default;
virtual string type() const;
virtual string protocol() const;
virtual string description() const;
virtual string mid() const;
Direction direction() const;
void setDirection(Direction dir);
bool isRemoved() const;
void markRemoved();
std::vector<string> attributes() const;
void addAttribute(string attr);
void removeAttribute(const string &attr);
void addRid(string rid); // Just the name
void addRid(Rid rid); // With RFC 8851 attributes
std::vector<Rid> rids() const;
struct RTC_CPP_EXPORT ExtMap {
static int parseId(string_view description);
ExtMap(int id, string uri, Direction direction = Direction::Unknown);
ExtMap(string_view description);
void setDescription(string_view description);
int id;
string uri;
string attributes;
Direction direction = Direction::Unknown;
};
std::vector<int> extIds();
ExtMap *extMap(int id);
const ExtMap *extMap(int id) const;
void addExtMap(ExtMap map);
void removeExtMap(int id);
operator string() const;
string generateSdp(string_view eol = "\r\n", string_view addr = "0.0.0.0",
uint16_t port = 9) const;
virtual void parseSdpLine(string_view line);
protected:
Entry(const string &mline, string mid, Direction dir = Direction::Unknown);
virtual string generateSdpLines(string_view eol) const;
std::vector<string> mAttributes;
std::map<int, ExtMap> mExtMaps;
private:
string mType;
string mProtocol;
string mDescription;
string mMid;
std::vector<Rid> mRids;
Direction mDirection;
bool mIsRemoved;
};
struct RTC_CPP_EXPORT Application : public Entry {
public:
Application(string mid = "data");
Application(const string &mline, string mid);
virtual ~Application() = default;
Application reciprocate() const;
void setSctpPort(uint16_t port);
void hintSctpPort(uint16_t port);
void setMaxMessageSize(size_t size);
optional<uint16_t> sctpPort() const;
optional<size_t> maxMessageSize() const;
virtual void parseSdpLine(string_view line) override;
private:
virtual string generateSdpLines(string_view eol) const override;
optional<uint16_t> mSctpPort;
optional<size_t> mMaxMessageSize;
};
// Media (non-data)
class RTC_CPP_EXPORT Media : public Entry {
public:
Media(const string &mline, string mid, Direction dir = Direction::SendOnly);
Media(const string &sdp);
virtual ~Media() = default;
string description() const override;
Media reciprocate() const;
void addSSRC(uint32_t ssrc, optional<string> name, optional<string> msid = nullopt,
optional<string> trackId = nullopt);
void removeSSRC(uint32_t ssrc);
void replaceSSRC(uint32_t old, uint32_t ssrc, optional<string> name,
optional<string> msid = nullopt, optional<string> trackID = nullopt);
bool hasSSRC(uint32_t ssrc) const;
void clearSSRCs();
std::vector<uint32_t> getSSRCs() const;
optional<std::string> getCNameForSsrc(uint32_t ssrc) const;
void addRtxSSRC(SSRC primarySsrc, SSRC rtxSsrc, optional<string> cname = nullopt);
void removeRtxSSRC(SSRC primarySsrc);
optional<SSRC> getRtxSsrcForSsrc(SSRC primarySsrc) const;
optional<SSRC> getSsrcForRtxSsrc(SSRC rtxSsrc) const;
int bitrate() const;
void setBitrate(int bitrate);
struct RTC_CPP_EXPORT RtpMap {
static int parsePayloadType(string_view description);
explicit RtpMap(int payloadType);
RtpMap(string_view description);
void setDescription(string_view description);
void addFeedback(string fb);
void removeFeedback(const string &str);
bool hasFeedback(const string &str) const;
void addParameter(string p);
void removeParameter(const string &str);
int payloadType;
string format;
int clockRate;
string encParams;
std::vector<string> rtcpFbs;
std::vector<string> fmtps;
};
bool hasPayloadType(int payloadType) const;
std::vector<int> payloadTypes() const;
RtpMap *rtpMap(int payloadType);
const RtpMap *rtpMap(int payloadType) const;
void addRtpMap(RtpMap map);
void removeRtpMap(int payloadType);
void removeFormat(const string &format);
void addRtxCodec(int payloadType, int origPayloadType, unsigned int clockRate);
optional<int> getRtxPayloadType(int primaryPayloadType) const;
bool isRtxEnabled() const;
void disableRtx();
virtual void parseSdpLine(string_view line) override;
private:
virtual string generateSdpLines(string_view eol) const override;
int mBas = -1;
std::vector<int> mOrderedPayloadTypes;
std::map<int, RtpMap> mRtpMaps;
std::vector<uint32_t> mSsrcs;
std::map<uint32_t, string> mCNameMap;
std::map<SSRC, SSRC> mSsrcToRtxSsrc; // primary_ssrc -> rtx_ssrc
};
class RTC_CPP_EXPORT Audio : public Media {
public:
Audio(string mid = "audio", Direction dir = Direction::SendOnly);
void addAudioCodec(int payloadType, string codec, optional<string> profile = std::nullopt);
void addOpusCodec(int payloadType, optional<string> profile = DEFAULT_OPUS_AUDIO_PROFILE);
void addPCMACodec(int payloadType, optional<string> profile = std::nullopt);
void addPCMUCodec(int payloadType, optional<string> profile = std::nullopt);
void addAACCodec(int payloadType, optional<string> profile = std::nullopt);
void addG722Codec(int payloadType, optional<string> profile = std::nullopt);
[[deprecated("Use addAACCodec")]] inline void
addAacCodec(int payloadType, optional<string> profile = std::nullopt) {
addAACCodec(payloadType, std::move(profile));
};
};
class RTC_CPP_EXPORT Video : public Media {
public:
Video(string mid = "video", Direction dir = Direction::SendOnly);
void addVideoCodec(int payloadType, string codec, optional<string> profile = std::nullopt);
void addH264Codec(int payloadType, optional<string> profile = DEFAULT_H264_VIDEO_PROFILE);
void addH265Codec(int payloadType, optional<string> profile = std::nullopt);
void addVP8Codec(int payloadType, optional<string> profile = std::nullopt);
void addVP9Codec(int payloadType, optional<string> profile = std::nullopt);
void addAV1Codec(int payloadType, optional<string> profile = std::nullopt);
};
// Adds RTX payload type mappings for SDP negotiation (codec level only).
// For per-stream RTX, also call Media::addRtxSSRC() once SSRCs are known.
// Set audio=true to also apply RTX to audio media streams.
void addRtx(optional<unsigned int> clockRate = nullopt, bool audio = false);
bool hasApplication() const;
bool hasAudioOrVideo() const;
bool hasMid(string_view mid) const;
int addMedia(Media media);
int addMedia(Application application);
int addApplication(string mid = "data");
int addVideo(string mid = "video", Direction dir = Direction::SendOnly);
int addAudio(string mid = "audio", Direction dir = Direction::SendOnly);
void clearMedia();
variant<Media *, Application *> media(int index);
variant<const Media *, const Application *> media(int index) const;
int mediaCount() const;
const Application *application() const;
Application *application();
static Type stringToType(const string &typeString);
static string typeToString(Type type);
string sessionId() const;
private:
optional<Candidate> defaultCandidate() const;
shared_ptr<Entry> createEntry(string mline, string mid, Direction dir);
void removeApplication();
Type mType;
// Session-level attributes
Role mRole;
string mUsername;
string mSessionId;
std::vector<string> mIceOptions;
optional<string> mIceUfrag, mIcePwd;
optional<CertificateFingerprint> mFingerprint;
std::vector<string> mAttributes; // other attributes
// Entries
std::vector<shared_ptr<Entry>> mEntries;
shared_ptr<Application> mApplication;
// Candidates
std::vector<Candidate> mCandidates;
bool mEnded = false;
};
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const Description &description);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, Description::Type type);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, Description::Role role);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, const Description::Direction &direction);
} // namespace rtc
#endif

View File

@ -0,0 +1,44 @@
/**
* Copyright (c) 2019-2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_FRAMEINFO_H
#define RTC_FRAMEINFO_H
#include "common.hpp"
#include <chrono>
namespace rtc {
struct RTC_CPP_EXPORT FrameInfo {
FrameInfo(uint32_t timestamp) : timestamp(timestamp) {};
template<typename Period = std::ratio<1>> FrameInfo(std::chrono::duration<double, Period> timestamp) : timestampSeconds(timestamp) {}
[[deprecated]] FrameInfo(uint8_t payloadType, uint32_t timestamp) : timestamp(timestamp), payloadType(payloadType) {};
uint32_t timestamp = 0;
uint8_t payloadType = 0;
optional<std::chrono::duration<double>> timestampSeconds;
bool isKeyFrame = false; // Set by the application
/// Absolute capture timestamp in NTP-format (high 32 bits seconds since
/// the NTP epoch 1900-01-01 UTC; low 32 bits fractional seconds). When
/// set alongside an RtpPacketizationConfig with absCaptureTimeId > 0,
/// the RtpPacketizer writes the 8-byte form of the abs-capture-time RTP
/// header extension on every packet of this frame. Receivers use this
/// to recover the source's capture wallclock and compute glass-to-glass
/// latency.
/// https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/abs-capture-time
optional<uint64_t> absCaptureTimeNtp;
};
} // namespace rtc
#endif // RTC_FRAMEINFO_H

View File

@ -0,0 +1,66 @@
/**
* Copyright (c) 2020-2021 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_GLOBAL_H
#define RTC_GLOBAL_H
#include "common.hpp"
#include <chrono>
#include <future>
#include <iostream>
namespace rtc {
#ifdef None
#undef None
#endif
enum class LogLevel { // Don't change, it must match plog severity
None = 0,
Fatal = 1,
Error = 2,
Warning = 3,
Info = 4,
Debug = 5,
Verbose = 6
};
typedef std::function<void(LogLevel level, string message)> LogCallback;
RTC_CPP_EXPORT void InitLogger(LogLevel level, LogCallback callback = nullptr);
RTC_CPP_EXPORT void SetThreadPoolSize(unsigned int count); // 0: hardware concurrency
struct SctpSettings {
// For the following settings, not set means optimized default
optional<size_t> recvBufferSize; // in bytes
optional<size_t> sendBufferSize; // in bytes
optional<size_t> maxChunksOnQueue; // in chunks
optional<size_t> initialCongestionWindow; // in MTUs
optional<size_t> maxBurst; // in MTUs
optional<unsigned int> congestionControlModule; // 0: RFC2581, 1: HSTCP, 2: H-TCP, 3: RTCC
optional<std::chrono::milliseconds> delayedSackTime;
optional<std::chrono::milliseconds> minRetransmitTimeout;
optional<std::chrono::milliseconds> maxRetransmitTimeout;
optional<std::chrono::milliseconds> initialRetransmitTimeout;
optional<unsigned int> maxRetransmitAttempts;
optional<std::chrono::milliseconds> heartbeatInterval;
};
RTC_CPP_EXPORT void SetSctpSettings(SctpSettings s);
// Optional global preload and cleanup
RTC_CPP_EXPORT bool Preload();
RTC_CPP_EXPORT std::shared_future<void> Cleanup();
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, LogLevel level);
} // namespace rtc
#endif

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2020 Staz Modrzynski
* Copyright (c) 2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_H264_RTP_DEPACKETIZER_H
#define RTC_H264_RTP_DEPACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include "message.hpp"
#include "nalunit.hpp"
#include "rtp.hpp"
#include "rtpdepacketizer.hpp"
namespace rtc {
/// RTP depacketization for H264
class RTC_CPP_EXPORT H264RtpDepacketizer final : public VideoRtpDepacketizer {
public:
using Separator = NalUnit::Separator;
H264RtpDepacketizer(Separator separator = Separator::StartSequence);
~H264RtpDepacketizer();
private:
message_ptr reassemble(message_buffer &buffer) override;
void addSeparator(binary &frame);
const NalUnit::Separator mSeparator;
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif /* RTC_H264_RTP_DEPACKETIZER_H */

View File

@ -0,0 +1,57 @@
/**
* Copyright (c) 2020 Filip Klembara (in2core)
* Copyright (c) 2023 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_H264_RTP_PACKETIZER_H
#define RTC_H264_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "nalunit.hpp"
#include "rtppacketizer.hpp"
namespace rtc {
/// RTP packetization for H264
class RTC_CPP_EXPORT H264RtpPacketizer final : public RtpPacketizer {
public:
using Separator = NalUnit::Separator;
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;
/// Constructs h264 payload packetizer with given RTP configuration.
/// @note RTP configuration is used in packetization process which may change some configuration
/// properties such as sequence number.
/// @param separator NAL unit separator
/// @param rtpConfig RTP configuration
/// @param maxFragmentSize maximum size of one NALU fragment
H264RtpPacketizer(Separator separator, shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
// For backward compatibility, do not use
[[deprecated]] H264RtpPacketizer(
shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
private:
std::vector<binary> fragment(binary data) override;
std::vector<NalUnit> splitFrame(const binary &frame);
const Separator mSeparator;
const size_t mMaxFragmentSize;
};
// For backward compatibility, do not use
using H264PacketizationHandler [[deprecated("Add H264RtpPacketizer directly")]] = PacketizationHandler;
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_H264_RTP_PACKETIZER_H */

View File

@ -0,0 +1,194 @@
/**
* Copyright (c) 2023 Zita Liao (Dolby)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_H265_NAL_UNIT_H
#define RTC_H265_NAL_UNIT_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include "nalunit.hpp"
#include <cassert>
#include <vector>
namespace rtc {
#pragma pack(push, 1)
#define H265_FU_HEADER_SIZE 1
/// Nalu header
struct RTC_CPP_EXPORT H265NalUnitHeader {
/*
* nal_unit_header( ) {
* forbidden_zero_bit f(1)
* nal_unit_type u(6)
* nuh_layer_id u(6)
* nuh_temporal_id_plus1 u(3)
}
*/
uint8_t _first = 0; // high byte of header
uint8_t _second = 0; // low byte of header
bool forbiddenBit() const { return _first >> 7; }
uint8_t unitType() const { return (_first & 0b0111'1110) >> 1; }
uint8_t nuhLayerId() const { return ((_first & 0x1) << 5) | ((_second & 0b1111'1000) >> 3); }
uint8_t nuhTempIdPlus1() const { return _second & 0b111; }
void setForbiddenBit(bool isSet) { _first = (_first & 0x7F) | (isSet << 7); }
void setUnitType(uint8_t type) { _first = (_first & 0b1000'0001) | ((type & 0b11'1111) << 1); }
void setNuhLayerId(uint8_t nuhLayerId) {
_first = (_first & 0b1111'1110) | ((nuhLayerId & 0b10'0000) >> 5);
_second = (_second & 0b0000'0111) | ((nuhLayerId & 0b01'1111) << 3);
}
void setNuhTempIdPlus1(uint8_t nuhTempIdPlus1) {
_second = (_second & 0b1111'1000) | (nuhTempIdPlus1 & 0b111);
}
};
/// Nalu fragment header
struct RTC_CPP_EXPORT H265NalUnitFragmentHeader {
/*
* +---------------+
* |0|1|2|3|4|5|6|7|
* +-+-+-+-+-+-+-+-+
* |S|E| FuType |
* +---------------+
*/
uint8_t _first = 0;
bool isStart() const { return _first >> 7; }
bool isEnd() const { return (_first >> 6) & 0x01; }
uint8_t unitType() const { return _first & 0b11'1111; }
void setStart(bool isSet) { _first = (_first & 0x7F) | (isSet << 7); }
void setEnd(bool isSet) { _first = (_first & 0b1011'1111) | (isSet << 6); }
void setUnitType(uint8_t type) { _first = (_first & 0b1100'0000) | (type & 0b11'1111); }
};
#pragma pack(pop)
struct H265NalUnitFragment;
/// NAL unit
struct RTC_CPP_EXPORT H265NalUnit : NalUnit {
static std::vector<binary> GenerateFragments(const std::vector<H265NalUnit> &nalus,
size_t maxFragmentSize);
H265NalUnit(const H265NalUnit &unit) = default;
H265NalUnit(size_t size, bool includingHeader = true)
: NalUnit(size, includingHeader, NalUnit::Type::H265) {}
H265NalUnit(binary &&data) : NalUnit(std::move(data)) {}
H265NalUnit() : NalUnit(NalUnit::Type::H265) {}
template <typename Iterator>
H265NalUnit(Iterator begin_, Iterator end_) : NalUnit(begin_, end_) {}
bool forbiddenBit() const { return header()->forbiddenBit(); }
uint8_t unitType() const { return header()->unitType(); }
uint8_t nuhLayerId() const { return header()->nuhLayerId(); }
uint8_t nuhTempIdPlus1() const { return header()->nuhTempIdPlus1(); }
binary payload() const {
assert(size() >= H265_NAL_HEADER_SIZE);
return {begin() + H265_NAL_HEADER_SIZE, end()};
}
void setForbiddenBit(bool isSet) { header()->setForbiddenBit(isSet); }
void setUnitType(uint8_t type) { header()->setUnitType(type); }
void setNuhLayerId(uint8_t nuhLayerId) { header()->setNuhLayerId(nuhLayerId); }
void setNuhTempIdPlus1(uint8_t nuhTempIdPlus1) { header()->setNuhTempIdPlus1(nuhTempIdPlus1); }
void setPayload(binary payload) {
assert(size() >= H265_NAL_HEADER_SIZE);
erase(begin() + H265_NAL_HEADER_SIZE, end());
insert(end(), payload.begin(), payload.end());
}
std::vector<H265NalUnitFragment> generateFragments(size_t maxFragmentSize) const;
protected:
const H265NalUnitHeader *header() const {
assert(size() >= H265_NAL_HEADER_SIZE);
return reinterpret_cast<const H265NalUnitHeader *>(data());
}
H265NalUnitHeader *header() {
assert(size() >= H265_NAL_HEADER_SIZE);
return reinterpret_cast<H265NalUnitHeader *>(data());
}
};
/// NAL unit fragment
struct RTC_CPP_EXPORT H265NalUnitFragment : H265NalUnit {
[[deprecated]] static std::vector<shared_ptr<H265NalUnitFragment>> fragmentsFrom(shared_ptr<H265NalUnit> nalu,
uint16_t maxFragmentSize);
enum class FragmentType { Start, Middle, End };
H265NalUnitFragment(FragmentType type, bool forbiddenBit, uint8_t nuhLayerId,
uint8_t nuhTempIdPlus1, uint8_t unitType, binary data);
uint8_t unitType() const { return fragmentHeader()->unitType(); }
binary payload() const {
assert(size() >= H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE);
return {begin() + H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE, end()};
}
FragmentType type() const {
if (fragmentHeader()->isStart()) {
return FragmentType::Start;
} else if (fragmentHeader()->isEnd()) {
return FragmentType::End;
} else {
return FragmentType::Middle;
}
}
void setUnitType(uint8_t type) { fragmentHeader()->setUnitType(type); }
void setPayload(binary payload) {
assert(size() >= H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE);
erase(begin() + H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE, end());
insert(end(), payload.begin(), payload.end());
}
void setFragmentType(FragmentType type);
protected:
const uint8_t nal_type_fu = 49;
H265NalUnitHeader *fragmentIndicator() { return reinterpret_cast<H265NalUnitHeader *>(data()); }
const H265NalUnitHeader *fragmentIndicator() const {
return reinterpret_cast<const H265NalUnitHeader *>(data());
}
H265NalUnitFragmentHeader *fragmentHeader() {
return reinterpret_cast<H265NalUnitFragmentHeader *>(data() + H265_NAL_HEADER_SIZE);
}
const H265NalUnitFragmentHeader *fragmentHeader() const {
return reinterpret_cast<const H265NalUnitFragmentHeader *>(data() + H265_NAL_HEADER_SIZE);
}
};
class [[deprecated]] RTC_CPP_EXPORT H265NalUnits : public std::vector<shared_ptr<H265NalUnit>> {
public:
static const uint16_t defaultMaximumFragmentSize =
uint16_t(RTC_DEFAULT_MTU - 12 - 8 - 40); // SRTP/UDP/IPv6
std::vector<shared_ptr<binary>> generateFragments(uint16_t maxFragmentSize);
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_NAL_UNIT_H */

View File

@ -0,0 +1,45 @@
/**
* Copyright (c) 2020 Staz Modrzynski
* Copyright (c) 2020-2024 Paul-Louis Ageneau
* Copyright (c) 2024 Robert Edmonds
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_H265_RTP_DEPACKETIZER_H
#define RTC_H265_RTP_DEPACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include "h265nalunit.hpp"
#include "message.hpp"
#include "rtp.hpp"
#include "rtpdepacketizer.hpp"
#include <set>
namespace rtc {
/// RTP depacketization for H265
class RTC_CPP_EXPORT H265RtpDepacketizer final : public VideoRtpDepacketizer {
public:
using Separator = NalUnit::Separator;
H265RtpDepacketizer(Separator separator = Separator::StartSequence);
~H265RtpDepacketizer();
private:
message_ptr reassemble(message_buffer &buffer);
void addSeparator(binary &frame);
const NalUnit::Separator mSeparator;
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif // RTC_H265_RTP_DEPACKETIZER_H

View File

@ -0,0 +1,55 @@
/**
* Copyright (c) 2023 Zita Liao (Dolby)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_H265_RTP_PACKETIZER_H
#define RTC_H265_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "h265nalunit.hpp"
#include "rtppacketizer.hpp"
namespace rtc {
// RTP packetization for H265
class RTC_CPP_EXPORT H265RtpPacketizer final : public RtpPacketizer {
public:
using Separator = NalUnit::Separator;
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;
// Constructs h265 payload packetizer with given RTP configuration.
// @note RTP configuration is used in packetization process which may change some configuration
// properties such as sequence number.
// @param separator NAL unit separator
// @param rtpConfig RTP configuration
// @param maxFragmentSize maximum size of one NALU fragment
H265RtpPacketizer(Separator separator, shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
// For backward compatibility, do not use
[[deprecated]] H265RtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
private:
std::vector<binary> fragment(binary data) override;
std::vector<H265NalUnit> splitFrame(const binary &frame);
const NalUnit::Separator mSeparator;
const size_t mMaxFragmentSize;
};
// For backward compatibility, do not use
using H265PacketizationHandler [[deprecated("Add H265RtpPacketizer directly")]] = PacketizationHandler;
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_H265_RTP_PACKETIZER_H */

View File

@ -0,0 +1,47 @@
/**
* Copyright (c) 2025 Alex Potsides
* Copyright (c) 2025 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_ICE_UDP_MUX_LISTENER_H
#define RTC_ICE_UDP_MUX_LISTENER_H
#include "common.hpp"
namespace rtc {
namespace impl {
struct IceUdpMuxListener;
} // namespace impl
struct IceUdpMuxRequest { // TODO change name
string localUfrag;
string remoteUfrag;
string remoteAddress;
uint16_t remotePort;
};
class RTC_CPP_EXPORT IceUdpMuxListener final : private CheshireCat<impl::IceUdpMuxListener> {
public:
IceUdpMuxListener(uint16_t port, optional<string> bindAddress = nullopt);
~IceUdpMuxListener();
void stop();
uint16_t port() const;
void OnUnhandledStunRequest(std::function<void(IceUdpMuxRequest)> callback);
private:
using CheshireCat<impl::IceUdpMuxListener>::impl;
};
} // namespace rtc
#endif

View File

@ -0,0 +1,60 @@
/**
* Copyright (c) 2020 Staz Modrzynski
* Copyright (c) 2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_MEDIA_HANDLER_H
#define RTC_MEDIA_HANDLER_H
#include "common.hpp"
#include "description.hpp"
#include "message.hpp"
#include <vector>
namespace rtc {
class RTC_CPP_EXPORT MediaHandler : public std::enable_shared_from_this<MediaHandler> {
public:
MediaHandler();
virtual ~MediaHandler();
/// Called when a media is added or updated
/// @param desc Description of the media
virtual void media([[maybe_unused]] const Description::Media &desc) {}
/// Called when there is traffic coming from the peer
/// @param messages Incoming messages from the peer, can be modified by the handler
/// @param send Send callback to send messages back to the peer
virtual void incoming([[maybe_unused]] message_vector &messages, [[maybe_unused]] const message_callback &send) {}
/// Called when there is traffic that needs to be sent to the peer
/// @param messages Outgoing messages to the peer, can be modified by the handler
/// @param send Send callback to send messages back to the peer
virtual void outgoing([[maybe_unused]] message_vector &messages, [[maybe_unused]] const message_callback &send) {}
virtual bool requestKeyframe(const std::vector<SSRC>& targetSSRCs, bool retransmit, const message_callback &send);
virtual bool requestBitrate(unsigned int bitrate, const message_callback &send);
void addToChain(shared_ptr<MediaHandler> handler);
void setNext(shared_ptr<MediaHandler> handler);
shared_ptr<MediaHandler> next();
shared_ptr<const MediaHandler> next() const;
shared_ptr<MediaHandler> last(); // never null
shared_ptr<const MediaHandler> last() const; // never null
void mediaChain(const Description::Media &desc);
void incomingChain(message_vector &messages, const message_callback &send);
void outgoingChain(message_vector &messages, const message_callback &send);
private:
shared_ptr<MediaHandler> mNext;
};
} // namespace rtc
#endif // RTC_MEDIA_HANDLER_H

View File

@ -0,0 +1,100 @@
/**
* Copyright (c) 2019-2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_MESSAGE_H
#define RTC_MESSAGE_H
#include "common.hpp"
#include "frameinfo.hpp"
#include "reliability.hpp"
#include <functional>
namespace rtc {
struct RTC_CPP_EXPORT Message : binary {
enum Type { Binary, String, Control, Reset };
Message(const Message &message) = default;
Message(size_t size, Type type_ = Binary) : binary(size), type(type_) {}
template <typename Iterator>
Message(Iterator begin_, Iterator end_, Type type_ = Binary)
: binary(begin_, end_), type(type_) {}
Message(binary &&data, Type type_ = Binary) : binary(std::move(data)), type(type_) {}
Type type;
unsigned int stream = 0; // Stream id (SCTP stream or SSRC)
unsigned int dscp = 0; // Differentiated Services Code Point
shared_ptr<Reliability> reliability;
shared_ptr<FrameInfo> frameInfo;
};
using message_ptr = shared_ptr<Message>;
using message_callback = std::function<void(message_ptr message)>;
using message_vector = std::vector<message_ptr>;
inline size_t message_size_func(const message_ptr &m) {
return m->type == Message::Binary || m->type == Message::String ? m->size() : 0;
}
template <typename Iterator>
message_ptr make_message(Iterator begin, Iterator end, Message::Type type = Message::Binary,
unsigned int stream = 0, shared_ptr<Reliability> reliability = nullptr) {
auto message = std::make_shared<Message>(begin, end, type);
message->stream = stream;
message->reliability = reliability;
return message;
}
template <typename Iterator>
message_ptr make_message(Iterator begin, Iterator end, shared_ptr<FrameInfo> frameInfo) {
auto message = std::make_shared<Message>(begin, end);
message->frameInfo = frameInfo;
return message;
}
// For backward compatibiity, do not use
template <typename Iterator>
[[deprecated]] message_ptr make_message(Iterator begin, Iterator end, Message::Type type,
unsigned int stream, shared_ptr<FrameInfo> frameInfo) {
auto message = std::make_shared<Message>(begin, end, type);
message->stream = stream;
message->frameInfo = frameInfo;
return message;
}
RTC_CPP_EXPORT message_ptr make_message(size_t size, Message::Type type = Message::Binary,
unsigned int stream = 0,
shared_ptr<Reliability> reliability = nullptr);
RTC_CPP_EXPORT message_ptr make_message(binary &&data, Message::Type type = Message::Binary,
unsigned int stream = 0,
shared_ptr<Reliability> reliability = nullptr);
RTC_CPP_EXPORT message_ptr make_message(binary &&data, shared_ptr<FrameInfo> frameInfo);
RTC_CPP_EXPORT message_ptr make_message(size_t size, message_ptr orig);
RTC_CPP_EXPORT message_ptr make_message(message_variant data);
#if RTC_ENABLE_MEDIA
// Reconstructs a message_ptr from an opaque rtcMessage pointer that
// was allocated by rtcCreateOpaqueMessage().
message_ptr make_message_from_opaque_ptr(rtcMessage *&&message);
#endif
RTC_CPP_EXPORT message_variant to_variant(Message &&message);
RTC_CPP_EXPORT message_variant to_variant(const Message &message);
} // namespace rtc
#endif

View File

@ -0,0 +1,197 @@
/**
* Copyright (c) 2020 Filip Klembara (in2core)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_NAL_UNIT_H
#define RTC_NAL_UNIT_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include <vector>
#include <cassert>
namespace rtc {
#pragma pack(push, 1)
/// Nalu header
struct RTC_CPP_EXPORT NalUnitHeader {
uint8_t _first = 0;
bool forbiddenBit() const { return _first >> 7; }
uint8_t nri() const { return _first >> 5 & 0x03; }
uint8_t idc() const { return _first & 0x60; }
uint8_t unitType() const { return _first & 0x1F; }
void setForbiddenBit(bool isSet) { _first = (_first & 0x7F) | (isSet << 7); }
void setNRI(uint8_t nri) { _first = (_first & 0x9F) | ((nri & 0x03) << 5); }
void setUnitType(uint8_t type) { _first = (_first & 0xE0) | (type & 0x1F); }
};
/// Nalu fragment header
struct RTC_CPP_EXPORT NalUnitFragmentHeader {
uint8_t _first = 0;
bool isStart() const { return _first >> 7; }
bool reservedBit6() const { return (_first >> 5) & 0x01; }
bool isEnd() const { return (_first >> 6) & 0x01; }
uint8_t unitType() const { return _first & 0x1F; }
void setStart(bool isSet) { _first = (_first & 0x7F) | (isSet << 7); }
void setEnd(bool isSet) { _first = (_first & 0xBF) | (isSet << 6); }
void setReservedBit6(bool isSet) { _first = (_first & 0xDF) | (isSet << 5); }
void setUnitType(uint8_t type) { _first = (_first & 0xE0) | (type & 0x1F); }
};
#pragma pack(pop)
enum NalUnitStartSequenceMatch {
NUSM_noMatch,
NUSM_firstZero,
NUSM_secondZero,
NUSM_thirdZero,
NUSM_shortMatch,
NUSM_longMatch
};
static const size_t H264_NAL_HEADER_SIZE = 1;
static const size_t H265_NAL_HEADER_SIZE = 2;
struct NalUnitFragmentA;
/// NAL unit
struct RTC_CPP_EXPORT NalUnit : binary {
static std::vector<binary> GenerateFragments(const std::vector<NalUnit> &nalus,
size_t maxFragmentSize);
enum class Separator {
Length = RTC_NAL_SEPARATOR_LENGTH, // first 4 bytes are NAL unit length
LongStartSequence = RTC_NAL_SEPARATOR_LONG_START_SEQUENCE, // 0x00, 0x00, 0x00, 0x01
ShortStartSequence = RTC_NAL_SEPARATOR_SHORT_START_SEQUENCE, // 0x00, 0x00, 0x01
StartSequence = RTC_NAL_SEPARATOR_START_SEQUENCE, // LongStartSequence or ShortStartSequence
};
static NalUnitStartSequenceMatch StartSequenceMatchSucc(NalUnitStartSequenceMatch match,
std::byte _byte, Separator separator);
enum class Type { H264, H265 };
NalUnit(const NalUnit &unit) = default;
NalUnit(size_t size, bool includingHeader = true, Type type = Type::H264)
: binary(size + (includingHeader ? 0
: (type == Type::H264 ? H264_NAL_HEADER_SIZE
: H265_NAL_HEADER_SIZE))) {}
NalUnit(binary &&data) : binary(std::move(data)) {}
NalUnit(Type type = Type::H264)
: binary(type == Type::H264 ? H264_NAL_HEADER_SIZE : H265_NAL_HEADER_SIZE) {}
template <typename Iterator> NalUnit(Iterator begin_, Iterator end_) : binary(begin_, end_) {}
bool forbiddenBit() const { return header()->forbiddenBit(); }
uint8_t nri() const { return header()->nri(); }
uint8_t unitType() const { return header()->unitType(); }
binary payload() const {
assert(size() >= 1);
return {begin() + 1, end()};
}
void setForbiddenBit(bool isSet) { header()->setForbiddenBit(isSet); }
void setNRI(uint8_t nri) { header()->setNRI(nri); }
void setUnitType(uint8_t type) { header()->setUnitType(type); }
void setPayload(binary payload) {
assert(size() >= 1);
erase(begin() + 1, end());
insert(end(), payload.begin(), payload.end());
}
std::vector<NalUnitFragmentA> generateFragments(size_t maxFragmentSize) const;
protected:
const NalUnitHeader *header() const {
assert(size() >= 1);
return reinterpret_cast<const NalUnitHeader *>(data());
}
NalUnitHeader *header() {
assert(size() >= 1);
return reinterpret_cast<NalUnitHeader *>(data());
}
};
/// Nal unit fragment A
struct RTC_CPP_EXPORT NalUnitFragmentA : NalUnit {
// For backward compatibility, do not use
[[deprecated]] static std::vector<shared_ptr<NalUnitFragmentA>>
fragmentsFrom(shared_ptr<NalUnit> nalu, uint16_t maxFragmentSize);
enum class FragmentType { Start, Middle, End };
NalUnitFragmentA(FragmentType type, bool forbiddenBit, uint8_t nri, uint8_t unitType,
binary data);
uint8_t unitType() const { return fragmentHeader()->unitType(); }
binary payload() const {
assert(size() >= 2);
return {begin() + 2, end()};
}
FragmentType type() const {
if (fragmentHeader()->isStart()) {
return FragmentType::Start;
} else if (fragmentHeader()->isEnd()) {
return FragmentType::End;
} else {
return FragmentType::Middle;
}
}
void setUnitType(uint8_t type) { fragmentHeader()->setUnitType(type); }
void setPayload(binary payload) {
assert(size() >= 2);
erase(begin() + 2, end());
insert(end(), payload.begin(), payload.end());
}
void setFragmentType(FragmentType type);
protected:
const uint8_t nal_type_fu_A = 28;
NalUnitHeader *fragmentIndicator() { return reinterpret_cast<NalUnitHeader *>(data()); }
const NalUnitHeader *fragmentIndicator() const {
return reinterpret_cast<const NalUnitHeader *>(data());
}
NalUnitFragmentHeader *fragmentHeader() {
return reinterpret_cast<NalUnitFragmentHeader *>(fragmentIndicator() + 1);
}
const NalUnitFragmentHeader *fragmentHeader() const {
return reinterpret_cast<const NalUnitFragmentHeader *>(fragmentIndicator() + 1);
}
};
// For backward compatibility, do not use
class [[deprecated]] RTC_CPP_EXPORT NalUnits : public std::vector<shared_ptr<NalUnit>> {
public:
static const uint16_t defaultMaximumFragmentSize =
uint16_t(RTC_DEFAULT_MTU - 12 - 8 - 40); // SRTP/UDP/IPv6
std::vector<shared_ptr<binary>> generateFragments(uint16_t maxFragmentSize);
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_NAL_UNIT_H */

View File

@ -0,0 +1,61 @@
/**
* Copyright (c) 2024 Sean DuBois <sean@siobud.com>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_PACING_HANDLER_H
#define RTC_PACING_HANDLER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "utils.hpp"
#include <atomic>
#include <queue>
namespace rtc {
// Paced sending of RTP packets. It takes a stream of RTP packets that can have an uneven bitrate
// and delivers them in a smoother manner by sending a fixed size of them on an interval
class RTC_CPP_EXPORT PacingHandler : public MediaHandler {
public:
PacingHandler(double bitsPerSecond, std::chrono::milliseconds sendInterval, size_t maxQueueSize=0);
void setBitrate(double bitsPerSecond);
void setMaxQueueAmount(size_t maxQueueAmount);
void onOverflow(std::function<void()> callback);
void outgoing(message_vector &messages, const message_callback &send) override;
private:
std::atomic<bool> mHaveScheduled = false;
double mBytesPerSecond;
double mBudget;
std::chrono::milliseconds mSendInterval;
std::chrono::time_point<std::chrono::high_resolution_clock> mLastRun;
size_t mMaxQueueAmount;
std::mutex mParamsMutex;
std::mutex mMutex;
std::queue<message_ptr> mRtpBuffer;
synchronized_callback<> mOverflowCallback;
void schedule(const message_callback &send, std::chrono::milliseconds scheduleInterval);
void run(const message_callback &send);
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif // RTC_PACING_HANDLER_H

View File

@ -0,0 +1,142 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_PEER_CONNECTION_H
#define RTC_PEER_CONNECTION_H
#include "candidate.hpp"
#include "common.hpp"
#include "configuration.hpp"
#include "datachannel.hpp"
#include "description.hpp"
#include "reliability.hpp"
#include "track.hpp"
#include <chrono>
#include <functional>
namespace rtc {
namespace impl {
struct PeerConnection;
}
struct RTC_CPP_EXPORT DataChannelInit {
Reliability reliability = {};
bool negotiated = false;
optional<uint16_t> id = nullopt;
string protocol = "";
};
struct RTC_CPP_EXPORT LocalDescriptionInit {
optional<string> iceUfrag;
optional<string> icePwd;
};
class RTC_CPP_EXPORT PeerConnection final : CheshireCat<impl::PeerConnection> {
public:
enum class State : int {
New = RTC_NEW,
Connecting = RTC_CONNECTING,
Connected = RTC_CONNECTED,
Disconnected = RTC_DISCONNECTED,
Failed = RTC_FAILED,
Closed = RTC_CLOSED
};
enum class IceState : int {
New = RTC_ICE_NEW,
Checking = RTC_ICE_CHECKING,
Connected = RTC_ICE_CONNECTED,
Completed = RTC_ICE_COMPLETED,
Failed = RTC_ICE_FAILED,
Disconnected = RTC_ICE_DISCONNECTED,
Closed = RTC_ICE_CLOSED
};
enum class GatheringState : int {
New = RTC_GATHERING_NEW,
InProgress = RTC_GATHERING_INPROGRESS,
Complete = RTC_GATHERING_COMPLETE
};
enum class SignalingState : int {
Stable = RTC_SIGNALING_STABLE,
HaveLocalOffer = RTC_SIGNALING_HAVE_LOCAL_OFFER,
HaveRemoteOffer = RTC_SIGNALING_HAVE_REMOTE_OFFER,
HaveLocalPranswer = RTC_SIGNALING_HAVE_LOCAL_PRANSWER,
HaveRemotePranswer = RTC_SIGNALING_HAVE_REMOTE_PRANSWER,
};
PeerConnection();
PeerConnection(Configuration config);
~PeerConnection();
void close();
const Configuration *config() const;
State state() const;
IceState iceState() const;
GatheringState gatheringState() const;
SignalingState signalingState() const;
bool negotiationNeeded() const;
bool hasMedia() const;
optional<Description> localDescription() const;
optional<Description> remoteDescription() const;
size_t remoteMaxMessageSize() const;
optional<string> localAddress() const;
optional<string> remoteAddress() const;
uint16_t maxDataChannelId() const;
bool getSelectedCandidatePair(Candidate *local, Candidate *remote);
void setLocalDescription(Description::Type type = Description::Type::Unspec, LocalDescriptionInit init = {});
void gatherLocalCandidates(std::vector<IceServer> additionalIceServers = {});
void setRemoteDescription(Description description);
void addRemoteCandidate(Candidate candidate);
// For specific use cases only
Description createOffer();
Description createAnswer();
void setMediaHandler(shared_ptr<MediaHandler> handler);
shared_ptr<MediaHandler> getMediaHandler();
[[nodiscard]] shared_ptr<DataChannel> createDataChannel(string label,
DataChannelInit init = {});
void onDataChannel(std::function<void(std::shared_ptr<DataChannel> dataChannel)> callback);
[[nodiscard]] shared_ptr<Track> addTrack(Description::Media description);
void onTrack(std::function<void(std::shared_ptr<Track> track)> callback);
void onLocalDescription(std::function<void(Description description)> callback);
void onLocalCandidate(std::function<void(Candidate candidate)> callback);
void onStateChange(std::function<void(State state)> callback);
void onIceStateChange(std::function<void(IceState state)> callback);
void onGatheringStateChange(std::function<void(GatheringState state)> callback);
void onSignalingStateChange(std::function<void(SignalingState state)> callback);
void resetCallbacks();
CertificateFingerprint remoteFingerprint();
// Stats
void clearStats();
size_t bytesSent();
size_t bytesReceived();
optional<std::chrono::milliseconds> rtt();
};
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, PeerConnection::State state);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, PeerConnection::IceState state);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, PeerConnection::GatheringState state);
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, PeerConnection::SignalingState state);
} // namespace rtc
#endif

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2023 Arda Cinar
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_PLI_RESPONDER_H
#define RTC_PLI_RESPONDER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "utils.hpp"
#include <unordered_map>
namespace rtc {
/// Responds to PLI and FIR messages sent by the receiver. The sender should respond to these
/// messages by sending an intra.
class RTC_CPP_EXPORT PliHandler final : public MediaHandler {
rtc::synchronized_callback<> mOnPli;
public:
/// Constructs the PLIResponder object to notify whenever a new intra frame is requested
/// @param onPli The callback that gets called whenever an intra frame is requested by the receiver
PliHandler(std::function<void(void)> onPli);
void incoming(message_vector &messages, const message_callback &send) override;
protected:
std::unordered_map<uint64_t, uint8_t> mFirSSRCSeqNumberMap;
};
}
#endif // RTC_ENABLE_MEDIA
#endif // RTC_PLI_RESPONDER_H

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RELIABILITY_H
#define RTC_RELIABILITY_H
#include "common.hpp"
#include <chrono>
namespace rtc {
struct Reliability {
// It true, the channel does not enforce message ordering and out-of-order delivery is allowed
bool unordered = false;
// If both maxPacketLifeTime or maxRetransmits are unset, the channel is reliable.
// If either maxPacketLifeTime or maxRetransmits is set, the channel is unreliable.
// (The settings are exclusive so both maxPacketLifetime and maxRetransmits must not be set.)
// Time window during which transmissions and retransmissions may occur
optional<std::chrono::milliseconds> maxPacketLifeTime;
// Maximum number of retransmissions that are attempted
optional<unsigned int> maxRetransmits;
// For backward compatibility, do not use
enum class Type { Reliable = 0, Rexmit, Timed };
union {
Type typeDeprecated = Type::Reliable;
[[deprecated("Use maxPacketLifeTime or maxRetransmits")]] Type type;
};
variant<int, std::chrono::milliseconds> rexmit = 0;
};
} // namespace rtc
#endif

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) 2024 Vladimir Voronin
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_REMB_RESPONDER_H
#define RTC_REMB_RESPONDER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "utils.hpp"
namespace rtc {
/// Responds to REMB messages sent by the receiver.
class RTC_CPP_EXPORT RembHandler final : public MediaHandler {
rtc::synchronized_callback<unsigned int> mOnRemb;
public:
/// Constructs the RembResponder object to notify whenever a bitrate
/// @param onRemb The callback that gets called whenever a bitrate by the receiver
RembHandler(std::function<void(unsigned int)> onRemb);
void incoming(message_vector &messages, const message_callback &send) override;
};
}
#endif // RTC_ENABLE_MEDIA
#endif // RTC_REMB_RESPONDER_H

View File

@ -0,0 +1,581 @@
/**
* Copyright (c) 2019-2021 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_C_API
#define RTC_C_API
#include "version.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#ifdef RTC_STATIC
#define RTC_C_EXPORT
#else // dynamic library
#ifdef _WIN32
#ifdef RTC_EXPORTS
#define RTC_C_EXPORT __declspec(dllexport) // building the library
#else
#define RTC_C_EXPORT __declspec(dllimport) // using the library
#endif
#else // not WIN32
#define RTC_C_EXPORT
#endif
#endif
#ifndef RTC_ENABLE_WEBSOCKET
#define RTC_ENABLE_WEBSOCKET 1
#endif
#ifndef RTC_ENABLE_MEDIA
#define RTC_ENABLE_MEDIA 1
#endif
#define RTC_DEFAULT_MTU 1280 // IPv6 minimum guaranteed MTU
#if RTC_ENABLE_MEDIA
#define RTC_DEFAULT_MAX_FRAGMENT_SIZE ((uint16_t)(RTC_DEFAULT_MTU - 12 - 8 - 40)) // SRTP/UDP/IPv6
#define RTC_DEFAULT_MAX_STORED_PACKET_COUNT 512
// Deprecated, do not use
#define RTC_DEFAULT_MAXIMUM_FRAGMENT_SIZE RTC_DEFAULT_MAX_FRAGMENT_SIZE
#define RTC_DEFAULT_MAXIMUM_PACKET_COUNT_FOR_NACK_CACHE RTC_DEFAULT_MAX_STORED_PACKET_COUNT
#endif
#ifdef _WIN32
#ifdef CAPI_STDCALL
#define RTC_API __stdcall
#else
#define RTC_API
#endif
#else // not WIN32
#define RTC_API
#endif
#if defined(__GNUC__) || defined(__clang__)
#define RTC_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define RTC_DEPRECATED __declspec(deprecated)
#else
#define DEPRECATED
#endif
// libdatachannel C API
typedef enum {
RTC_NEW = 0,
RTC_CONNECTING = 1,
RTC_CONNECTED = 2,
RTC_DISCONNECTED = 3,
RTC_FAILED = 4,
RTC_CLOSED = 5
} rtcState;
typedef enum {
RTC_ICE_NEW = 0,
RTC_ICE_CHECKING = 1,
RTC_ICE_CONNECTED = 2,
RTC_ICE_COMPLETED = 3,
RTC_ICE_FAILED = 4,
RTC_ICE_DISCONNECTED = 5,
RTC_ICE_CLOSED = 6
} rtcIceState;
typedef enum {
RTC_GATHERING_NEW = 0,
RTC_GATHERING_INPROGRESS = 1,
RTC_GATHERING_COMPLETE = 2
} rtcGatheringState;
typedef enum {
RTC_SIGNALING_STABLE = 0,
RTC_SIGNALING_HAVE_LOCAL_OFFER = 1,
RTC_SIGNALING_HAVE_REMOTE_OFFER = 2,
RTC_SIGNALING_HAVE_LOCAL_PRANSWER = 3,
RTC_SIGNALING_HAVE_REMOTE_PRANSWER = 4,
} rtcSignalingState;
typedef enum { // Don't change, it must match plog severity
RTC_LOG_NONE = 0,
RTC_LOG_FATAL = 1,
RTC_LOG_ERROR = 2,
RTC_LOG_WARNING = 3,
RTC_LOG_INFO = 4,
RTC_LOG_DEBUG = 5,
RTC_LOG_VERBOSE = 6
} rtcLogLevel;
typedef enum {
RTC_CERTIFICATE_DEFAULT = 0, // ECDSA
RTC_CERTIFICATE_ECDSA = 1,
RTC_CERTIFICATE_RSA = 2,
} rtcCertificateType;
typedef enum {
// video
RTC_CODEC_H264 = 0,
RTC_CODEC_VP8 = 1,
RTC_CODEC_VP9 = 2,
RTC_CODEC_H265 = 3,
RTC_CODEC_AV1 = 4,
// audio
RTC_CODEC_OPUS = 128,
RTC_CODEC_PCMU = 129,
RTC_CODEC_PCMA = 130,
RTC_CODEC_AAC = 131,
RTC_CODEC_G722 = 132,
} rtcCodec;
typedef enum {
RTC_DIRECTION_UNKNOWN = 0,
RTC_DIRECTION_SENDONLY = 1,
RTC_DIRECTION_RECVONLY = 2,
RTC_DIRECTION_SENDRECV = 3,
RTC_DIRECTION_INACTIVE = 4
} rtcDirection;
typedef enum { RTC_TRANSPORT_POLICY_ALL = 0, RTC_TRANSPORT_POLICY_RELAY = 1 } rtcTransportPolicy;
#define RTC_ERR_SUCCESS 0
#define RTC_ERR_INVALID -1 // invalid argument
#define RTC_ERR_FAILURE -2 // runtime error
#define RTC_ERR_NOT_AVAIL -3 // element not available
#define RTC_ERR_TOO_SMALL -4 // buffer too small
typedef void(RTC_API *rtcLogCallbackFunc)(rtcLogLevel level, const char *message);
typedef void(RTC_API *rtcDescriptionCallbackFunc)(int pc, const char *sdp, const char *type,
void *ptr);
typedef void(RTC_API *rtcCandidateCallbackFunc)(int pc, const char *cand, const char *mid,
void *ptr);
typedef void(RTC_API *rtcStateChangeCallbackFunc)(int pc, rtcState state, void *ptr);
typedef void(RTC_API *rtcIceStateChangeCallbackFunc)(int pc, rtcIceState state, void *ptr);
typedef void(RTC_API *rtcGatheringStateCallbackFunc)(int pc, rtcGatheringState state, void *ptr);
typedef void(RTC_API *rtcSignalingStateCallbackFunc)(int pc, rtcSignalingState state, void *ptr);
typedef void(RTC_API *rtcDataChannelCallbackFunc)(int pc, int dc, void *ptr);
typedef void(RTC_API *rtcTrackCallbackFunc)(int pc, int tr, void *ptr);
typedef void(RTC_API *rtcOpenCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcClosedCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcErrorCallbackFunc)(int id, const char *error, void *ptr);
typedef void(RTC_API *rtcMessageCallbackFunc)(int id, const char *message, int size, void *ptr);
typedef void *(RTC_API *rtcInterceptorCallbackFunc)(int pc, const char *message, int size,
void *ptr);
typedef void(RTC_API *rtcBufferedAmountLowCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcAvailableCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcPliHandlerCallbackFunc)(int tr, void *ptr);
typedef void(RTC_API *rtcRembHandlerCallbackFunc)(int tr, unsigned int bitrate, void *ptr);
typedef struct {
uint32_t timestamp;
uint8_t payloadType;
double timestampSeconds; // negative means not available
} rtcFrameInfo;
typedef void(RTC_API *rtcFrameCallbackFunc)(int tr, const char *data, int size,
const rtcFrameInfo *info, void *ptr);
// Log
// NULL cb on the first call will log to stdout
RTC_C_EXPORT void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb);
// User pointer
RTC_C_EXPORT void rtcSetUserPointer(int id, void *ptr);
RTC_C_EXPORT void *rtcGetUserPointer(int i);
// PeerConnection
typedef struct {
const char **iceServers;
int iceServersCount;
const char *proxyServer; // libnice only
const char *bindAddress; // libjuice only, NULL means any
rtcCertificateType certificateType;
const char *certificatePemFile; // NULL for autogenerated certificate
const char *keyPemFile; // NULL for autogenerated certificate
const char *keyPemPass; // NULL if no pass
rtcTransportPolicy iceTransportPolicy;
bool enableIceTcp;
bool enableIceUdpMux; // libjuice only
bool disableAutoNegotiation;
bool forceMediaTransport;
uint16_t portRangeBegin; // 0 means automatic
uint16_t portRangeEnd; // 0 means automatic
int mtu; // <= 0 means automatic
int maxMessageSize; // <= 0 means default
} rtcConfiguration;
RTC_C_EXPORT int rtcCreatePeerConnection(const rtcConfiguration *config); // returns pc id
RTC_C_EXPORT int rtcClosePeerConnection(int pc);
RTC_C_EXPORT int rtcDeletePeerConnection(int pc);
RTC_C_EXPORT int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb);
RTC_C_EXPORT int rtcSetLocalCandidateCallback(int pc, rtcCandidateCallbackFunc cb);
RTC_C_EXPORT int rtcSetStateChangeCallback(int pc, rtcStateChangeCallbackFunc cb);
RTC_C_EXPORT int rtcSetIceStateChangeCallback(int pc, rtcIceStateChangeCallbackFunc cb);
RTC_C_EXPORT int rtcSetGatheringStateChangeCallback(int pc, rtcGatheringStateCallbackFunc cb);
RTC_C_EXPORT int rtcSetSignalingStateChangeCallback(int pc, rtcSignalingStateCallbackFunc cb);
RTC_C_EXPORT int rtcSetLocalDescription(int pc, const char *type); // type may be NULL
RTC_C_EXPORT int rtcSetRemoteDescription(int pc, const char *sdp, const char *type);
RTC_C_EXPORT int rtcAddRemoteCandidate(int pc, const char *cand, const char *mid);
RTC_C_EXPORT int rtcGetLocalDescription(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetRemoteDescription(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetLocalDescriptionType(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetRemoteDescriptionType(int pc, char *buffer, int size);
// For specific use cases only
RTC_C_EXPORT int rtcCreateOffer(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcCreateAnswer(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetLocalAddress(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetRemoteAddress(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, char *remote,
int remoteSize);
RTC_C_EXPORT bool rtcIsNegotiationNeeded(int pc);
RTC_C_EXPORT int rtcGetMaxDataChannelStream(int pc);
RTC_C_EXPORT int rtcGetRemoteMaxMessageSize(int pc);
// DataChannel, Track, and WebSocket common API
RTC_C_EXPORT int rtcSetOpenCallback(int id, rtcOpenCallbackFunc cb);
RTC_C_EXPORT int rtcSetClosedCallback(int id, rtcClosedCallbackFunc cb);
RTC_C_EXPORT int rtcSetErrorCallback(int id, rtcErrorCallbackFunc cb);
RTC_C_EXPORT int rtcSetMessageCallback(int id, rtcMessageCallbackFunc cb);
RTC_C_EXPORT int rtcSendMessage(int id, const char *data, int size);
RTC_C_EXPORT int rtcClose(int id);
RTC_C_EXPORT int rtcDelete(int id);
RTC_C_EXPORT bool rtcIsOpen(int id);
RTC_C_EXPORT bool rtcIsClosed(int id);
RTC_C_EXPORT int rtcMaxMessageSize(int id);
RTC_C_EXPORT int rtcGetBufferedAmount(int id); // total size buffered to send
RTC_C_EXPORT int rtcSetBufferedAmountLowThreshold(int id, int amount);
RTC_C_EXPORT int rtcSetBufferedAmountLowCallback(int id, rtcBufferedAmountLowCallbackFunc cb);
// DataChannel, Track, and WebSocket common extended API
RTC_C_EXPORT int rtcGetAvailableAmount(int id); // total size available to receive
RTC_C_EXPORT int rtcSetAvailableCallback(int id, rtcAvailableCallbackFunc cb);
RTC_C_EXPORT int rtcReceiveMessage(int id, char *buffer, int *size);
// DataChannel
typedef struct {
bool unordered;
bool unreliable;
unsigned int maxPacketLifeTime; // ignored if reliable
unsigned int maxRetransmits; // ignored if reliable
} rtcReliability;
typedef struct {
rtcReliability reliability;
const char *protocol; // empty string if NULL
bool negotiated;
bool manualStream;
uint16_t stream; // numeric ID 0-65534, ignored if manualStream is false
} rtcDataChannelInit;
RTC_C_EXPORT int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb);
RTC_C_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
RTC_C_EXPORT int rtcCreateDataChannelEx(int pc, const char *label,
const rtcDataChannelInit *init); // returns dc id
RTC_C_EXPORT int rtcDeleteDataChannel(int dc);
RTC_C_EXPORT int rtcGetDataChannelStream(int dc);
RTC_C_EXPORT int rtcGetDataChannelLabel(int dc, char *buffer, int size);
RTC_C_EXPORT int rtcGetDataChannelProtocol(int dc, char *buffer, int size);
RTC_C_EXPORT int rtcGetDataChannelReliability(int dc, rtcReliability *reliability);
// Track
typedef struct {
rtcDirection direction;
rtcCodec codec;
int payloadType;
uint32_t ssrc;
const char *mid;
const char *name; // optional
const char *msid; // optional
const char *trackId; // optional, track ID used in MSID
const char *profile; // optional, codec profile
} rtcTrackInit;
RTC_C_EXPORT int rtcSetTrackCallback(int pc, rtcTrackCallbackFunc cb);
RTC_C_EXPORT int rtcAddTrack(int pc, const char *mediaDescriptionSdp); // returns tr id
RTC_C_EXPORT int rtcAddTrackEx(int pc, const rtcTrackInit *init); // returns tr id
RTC_C_EXPORT int rtcDeleteTrack(int tr);
RTC_C_EXPORT int rtcGetTrackDescription(int tr, char *buffer, int size);
RTC_C_EXPORT int rtcGetTrackMid(int tr, char *buffer, int size);
RTC_C_EXPORT int rtcGetTrackDirection(int tr, rtcDirection *direction);
RTC_C_EXPORT int rtcRequestKeyframe(int tr);
RTC_C_EXPORT int rtcRequestBitrate(int tr, unsigned int bitrate);
RTC_C_EXPORT int rtcSetFrameCallback(int tr, rtcFrameCallbackFunc cb);
#if RTC_ENABLE_MEDIA
// Media
// Define how OBUs are packetizied in a AV1 Sample
typedef enum {
RTC_OBU_PACKETIZED_OBU = 0,
RTC_OBU_PACKETIZED_TEMPORAL_UNIT = 1,
} rtcObuPacketization;
// Define how NAL units are separated in a H264/H265 sample
typedef enum {
RTC_NAL_SEPARATOR_LENGTH = 0, // first 4 bytes are NAL unit length
RTC_NAL_SEPARATOR_LONG_START_SEQUENCE = 1, // 0x00, 0x00, 0x00, 0x01
RTC_NAL_SEPARATOR_SHORT_START_SEQUENCE = 2, // 0x00, 0x00, 0x01
RTC_NAL_SEPARATOR_START_SEQUENCE = 3, // long or short start sequence
} rtcNalUnitSeparator;
typedef struct {
uint32_t ssrc;
const char *cname;
uint8_t payloadType;
uint32_t clockRate;
uint16_t sequenceNumber;
uint32_t timestamp;
// H264, H265, AV1
uint16_t maxFragmentSize; // Maximum fragment size, 0 means default
// H264/H265 only
rtcNalUnitSeparator nalSeparator; // NAL unit separator
// AV1 only
rtcObuPacketization obuPacketization; // OBU paketization for AV1 samples
uint8_t playoutDelayId;
uint16_t playoutDelayMin;
uint16_t playoutDelayMax;
uint8_t colorSpaceId;
uint8_t colorChromaSitingHorz;
uint8_t colorChromaSitingVert;
uint8_t colorRange;
uint8_t colorPrimaries;
uint8_t colorTransfer;
uint8_t colorMatrix;
} rtcPacketizerInit;
// Deprecated, do not use
typedef rtcPacketizerInit rtcPacketizationHandlerInit;
typedef struct {
uint32_t ssrc;
const char *name; // optional
const char *msid; // optional
const char *trackId; // optional, track ID used in MSID
} rtcSsrcForTypeInit;
// Opaque type used (via rtcMessage*) to reference an rtc::Message
typedef void *rtcMessage;
// Allocate a new opaque message.
// Must be explicitly freed by rtcDeleteOpaqueMessage() unless
// explicitly returned by a media interceptor callback;
RTC_C_EXPORT rtcMessage *rtcCreateOpaqueMessage(void *data, int size);
RTC_C_EXPORT void rtcDeleteOpaqueMessage(rtcMessage *msg);
// Set MediaInterceptor on peer connection
RTC_C_EXPORT int rtcSetMediaInterceptorCallback(int id, rtcInterceptorCallbackFunc cb);
// Set a packetizer on track
RTC_C_EXPORT int rtcSetH264Packetizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetH265Packetizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetAV1Packetizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetVP8Packetizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetVP9Packetizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetOpusPacketizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetAACPacketizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetPCMUPacketizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetPCMAPacketizer(int tr, const rtcPacketizerInit *init);
RTC_C_EXPORT int rtcSetG722Packetizer(int tr, const rtcPacketizerInit *init);
// Set a depacketizer on track
RTC_C_EXPORT int rtcSetH264Depacketizer(int tr, rtcNalUnitSeparator nalSeparator);
RTC_C_EXPORT int rtcSetH265Depacketizer(int tr, rtcNalUnitSeparator nalSeparator);
RTC_C_EXPORT int rtcSetVP8Depacketizer(int tr);
RTC_C_EXPORT int rtcSetVP9Depacketizer(int tr);
RTC_C_EXPORT int rtcSetOpusDepacketizer(int tr);
RTC_C_EXPORT int rtcSetAACDepacketizer(int tr);
RTC_C_EXPORT int rtcSetPCMUDepacketizer(int tr);
RTC_C_EXPORT int rtcSetPCMADepacketizer(int tr);
RTC_C_EXPORT int rtcSetG722Depacketizer(int tr);
// Deprecated, do not use
RTC_DEPRECATED static inline int
rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return rtcSetH264Packetizer(tr, init);
}
RTC_DEPRECATED static inline int
rtcSetH265PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return rtcSetH265Packetizer(tr, init);
}
RTC_DEPRECATED static inline int
rtcSetAV1PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return rtcSetAV1Packetizer(tr, init);
}
RTC_DEPRECATED static inline int
rtcSetOpusPacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return rtcSetOpusPacketizer(tr, init);
}
RTC_DEPRECATED static inline int
rtcSetAACPacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return rtcSetAACPacketizer(tr, init);
}
// Chain RtcpReceivingSession on track
RTC_C_EXPORT int rtcChainRtcpReceivingSession(int tr);
// Chain RtcpSrReporter on track
RTC_C_EXPORT int rtcChainRtcpSrReporter(int tr);
// Chain RtcpNackResponder on track
RTC_C_EXPORT int rtcChainRtcpNackResponder(int tr, unsigned int maxStoredPacketsCount);
// Chain PliHandler on track
RTC_C_EXPORT int rtcChainPliHandler(int tr, rtcPliHandlerCallbackFunc cb);
// Chain RembHandler on track
RTC_C_EXPORT int rtcChainRembHandler(int tr, rtcRembHandlerCallbackFunc cb);
// Chain PacingHandler on track
RTC_C_EXPORT int rtcChainPacingHandler(int tr, double bitsPerSecond, int sendIntervalMs);
// Transform seconds to timestamp using track's clock rate, result is written to timestamp
RTC_C_EXPORT int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp);
// Transform timestamp to seconds using track's clock rate, result is written to seconds
RTC_C_EXPORT int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds);
// Get current timestamp, result is written to timestamp
RTC_C_EXPORT int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp);
// Set RTP timestamp for track identified by given id
RTC_C_EXPORT int rtcSetTrackRtpTimestamp(int id, uint32_t timestamp);
// Get timestamp of last RTCP SR, result is written to timestamp
RTC_C_EXPORT int rtcGetLastTrackSenderReportTimestamp(int id, uint32_t *timestamp);
// Get sync timestamps from receiving RTCP session
RTC_C_EXPORT int rtcGetTrackRtcpSyncTimestamps(int tr, uint64_t *rtpTimestamp, uint64_t *ntpTimestamp);
// Get all available payload types for given codec and stores them in buffer, does nothing if
// buffer is NULL
RTC_C_EXPORT int rtcGetTrackPayloadTypesForCodec(int tr, const char *ccodec, int *buffer, int size);
// Get all SSRCs for given track
RTC_C_EXPORT int rtcGetSsrcsForTrack(int tr, uint32_t *buffer, int count);
// Get CName for SSRC
RTC_C_EXPORT int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char *cname, int cnameSize);
// Get all SSRCs for given media type in given SDP
RTC_C_EXPORT int rtcGetSsrcsForType(const char *mediaType, const char *sdp, uint32_t *buffer, int bufferSize);
// Set SSRC for given media type in given SDP
RTC_C_EXPORT int rtcSetSsrcForType(const char *mediaType, const char *sdp, char *buffer, const int bufferSize,
rtcSsrcForTypeInit *init);
// For backward compatibility, do not use
RTC_C_EXPORT RTC_DEPRECATED int rtcSetNeedsToSendRtcpSr(int id);
#endif // RTC_ENABLE_MEDIA
#if RTC_ENABLE_WEBSOCKET
// WebSocket
typedef struct {
bool disableTlsVerification; // if true, don't verify the TLS certificate
const char *proxyServer; // only non-authenticated http supported for now
const char **protocols;
int protocolsCount;
int tcpConnectionTimeoutMs; // in milliseconds, 0 means default, < 0 means disabled
int connectionTimeoutMs; // in milliseconds, 0 means default, < 0 means disabled
int pingIntervalMs; // in milliseconds, 0 means default, < 0 means disabled
int maxOutstandingPings; // 0 means default, < 0 means disabled
int maxMessageSize; // <= 0 means default
} rtcWsConfiguration;
RTC_C_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
RTC_C_EXPORT int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config);
RTC_C_EXPORT int rtcDeleteWebSocket(int ws);
RTC_C_EXPORT int rtcGetWebSocketRemoteAddress(int ws, char *buffer, int size);
RTC_C_EXPORT int rtcGetWebSocketPath(int ws, char *buffer, int size);
// WebSocketServer
typedef void(RTC_API *rtcWebSocketClientCallbackFunc)(int wsserver, int ws, void *ptr);
typedef struct {
uint16_t port; // 0 means automatic selection
bool enableTls; // if true, enable TLS (WSS)
const char *certificatePemFile; // NULL for autogenerated certificate
const char *keyPemFile; // NULL for autogenerated certificate
const char *keyPemPass; // NULL if no pass
const char *bindAddress; // NULL for any
int connectionTimeoutMs; // in milliseconds, 0 means default, < 0 means disabled
int maxMessageSize; // <= 0 means default
} rtcWsServerConfiguration;
RTC_C_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
rtcWebSocketClientCallbackFunc cb); // returns wsserver id
RTC_C_EXPORT int rtcDeleteWebSocketServer(int wsserver);
RTC_C_EXPORT int rtcGetWebSocketServerPort(int wsserver);
#endif
// Global settings
// Note: Applied when threads are spawned
RTC_C_EXPORT int rtcSetThreadPoolSize(unsigned int count);
typedef struct {
int recvBufferSize; // in bytes, <= 0 means optimized default
int sendBufferSize; // in bytes, <= 0 means optimized default
int maxChunksOnQueue; // in chunks, <= 0 means optimized default
int initialCongestionWindow; // in MTUs, <= 0 means optimized default
int maxBurst; // in MTUs, 0 means optimized default, < 0 means disabled
int congestionControlModule; // 0: RFC2581 (default), 1: HSTCP, 2: H-TCP, 3: RTCC
int delayedSackTimeMs; // in milliseconds, 0 means optimized default, < 0 means disabled
int minRetransmitTimeoutMs; // in milliseconds, <= 0 means optimized default
int maxRetransmitTimeoutMs; // in milliseconds, <= 0 means optimized default
int initialRetransmitTimeoutMs; // in milliseconds, <= 0 means optimized default
int maxRetransmitAttempts; // number of retransmissions, <= 0 means optimized default
int heartbeatIntervalMs; // in milliseconds, <= 0 means optimized default
} rtcSctpSettings;
// Note: SCTP settings apply to newly-created PeerConnections only
RTC_C_EXPORT int rtcSetSctpSettings(const rtcSctpSettings *settings);
// Optional global preload and cleanup
RTC_C_EXPORT bool rtcPreload(void);
RTC_C_EXPORT void rtcCleanup(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View File

@ -0,0 +1,53 @@
/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// C API
#include "rtc.h"
// C++ API
#include "common.hpp"
#include "global.hpp"
//
#include "datachannel.hpp"
#include "iceudpmuxlistener.hpp"
#include "peerconnection.hpp"
#include "track.hpp"
#if RTC_ENABLE_WEBSOCKET
// WebSocket
#include "websocket.hpp"
#include "websocketserver.hpp"
#endif // RTC_ENABLE_WEBSOCKET
#if RTC_ENABLE_MEDIA
// Media
#include "av1rtppacketizer.hpp"
#include "dependencydescriptor.hpp"
#include "rtppacketizer.hpp"
#include "rtpdepacketizer.hpp"
#include "h264rtppacketizer.hpp"
#include "h264rtpdepacketizer.hpp"
#include "h265rtppacketizer.hpp"
#include "h265rtpdepacketizer.hpp"
#include "vp8rtppacketizer.hpp"
#include "vp8rtpdepacketizer.hpp"
#include "vp9rtppacketizer.hpp"
#include "vp9rtpdepacketizer.hpp"
#include "mediahandler.hpp"
#include "rtcpapphandler.hpp"
#include "plihandler.hpp"
#include "rembhandler.hpp"
#include "pacinghandler.hpp"
#include "rtcpnackresponder.hpp"
#include "rtcpreceivingsession.hpp"
#include "rtcpsrreporter.hpp"
#endif // RTC_ENABLE_MEDIA

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2026 Apple Inc
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTCP_APP_HANDLER_H
#define RTC_RTCP_APP_HANDLER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "rtp.hpp"
#include "utils.hpp"
namespace rtc {
/// Handles RTCP APP packets (payload type 204) as defined in RFC 3550 section 6.7.
class RTC_CPP_EXPORT RtcpAppHandler final : public MediaHandler {
rtc::synchronized_callback<const RtcpAppName, uint8_t, binary> mOnApp;
public:
/// Constructs the RtcpAppHandler to notify when RTCP APP packets are received.
/// @param onApp Callback invoked with (name, subtype, application-dependent data)
RtcpAppHandler(std::function<void(const RtcpAppName name, uint8_t subtype, binary data)> onApp);
void incoming(message_vector &messages, const message_callback &send) override;
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif // RTC_RTCP_APP_HANDLER_H

View File

@ -0,0 +1,89 @@
/**
* Copyright (c) 2020 Filip Klembara (in2core)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTCP_NACK_RESPONDER_H
#define RTC_RTCP_NACK_RESPONDER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "description.hpp"
#include "rtp.hpp"
#include <mutex>
#include <queue>
#include <unordered_map>
namespace rtc {
class RTC_CPP_EXPORT RtcpNackResponder final : public MediaHandler {
public:
static const size_t DefaultMaxSize = 512;
RtcpNackResponder(size_t maxSize = DefaultMaxSize);
void media(const Description::Media &desc) override;
void incoming(message_vector &messages, const message_callback &send) override;
void outgoing(message_vector &messages, const message_callback &send) override;
private:
message_ptr wrapInRtx(const message_ptr &original);
// RTX state populated by media() from SDP inspection
optional<SSRC> mRtxSsrc;
std::unordered_map<int, int> mRtxPayloadTypeMap; // original PT -> RTX PT
uint16_t mRtxSequenceNumber = 0;
bool mRtxEnabled = false;
std::mutex mMutex;
// Packet storage
class RTC_CPP_EXPORT Storage {
/// Packet storage element
struct RTC_CPP_EXPORT Element {
Element(message_ptr packet, uint16_t sequenceNumber, shared_ptr<Element> next = nullptr);
const message_ptr packet;
const uint16_t sequenceNumber;
/// Pointer to newer element
shared_ptr<Element> next = nullptr;
};
private:
/// Oldest packet in storage
shared_ptr<Element> oldest = nullptr;
/// Newest packet in storage
shared_ptr<Element> newest = nullptr;
/// Inner storage
std::unordered_map<uint16_t, shared_ptr<Element>> storage{};
std::mutex mutex;
/// Maximum storage size
const size_t maxSize;
/// Returns current size
size_t size();
public:
Storage(size_t _maxSize);
/// Returns packet with given sequence number
message_ptr get(uint16_t sequenceNumber);
/// Stores packet
/// @param packet Packet
void store(message_ptr packet);
};
const shared_ptr<Storage> mStorage;
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_RTCP_NACK_RESPONDER_H */

View File

@ -0,0 +1,95 @@
/**
* Copyright (c) 2020 Staz Modrzynski
* Copyright (c) 2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTCP_RECEIVING_SESSION_H
#define RTC_RTCP_RECEIVING_SESSION_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include "description.hpp"
#include "mediahandler.hpp"
#include "message.hpp"
#include "rtp.hpp"
#include <atomic>
#include <mutex>
#include <unordered_map>
#include <vector>
#define RTP_SEQ_MOD (1<<16)
namespace rtc {
// An RtcpSession can be plugged into a Track to handle the whole RTCP session
class RTC_CPP_EXPORT RtcpReceivingSession : public MediaHandler {
public:
RtcpReceivingSession() = default;
virtual ~RtcpReceivingSession() = default;
void media(const Description::Media &desc) override;
void incoming(message_vector &messages, const message_callback &send) override;
bool requestKeyframe(const std::vector<SSRC>& targetSSRCs, bool retransmit, const message_callback &send) override;
bool requestBitrate(unsigned int bitrate, const message_callback &send) override;
// For backward compatibility
[[deprecated("Use Track::requestKeyframe()")]] inline bool requestKeyframe() { return false; };
[[deprecated("Use Track::requestBitrate()")]] inline void requestBitrate(unsigned int) {};
struct SyncTimestamps {
uint64_t rtpTimestamp;
uint64_t ntpTimestamp;
};
SyncTimestamps getSyncTimestamps();
protected:
void pushREMB(const message_callback &send, unsigned int bitrate);
void pushRR(const message_callback &send,unsigned int lastSrDelay);
void pushPLI(const message_callback &send);
void pushFIR(const message_callback &send, const std::vector<SSRC>& targetSSRCs, bool retransmit);
void initSeq(uint16_t seq);
bool updateSeq(uint16_t seq);
SSRC mSsrc = 0;
uint32_t mGreatestSeqNo = 0;
uint16_t mMaxSeq = 0; // highest seq. number seen
uint32_t mCycles = 0; // shifted count of seq. number cycles
uint32_t mBaseSeq = 0; // base seq number
uint32_t mBadSeq = 0; // last 'bad' seq number + 1
uint32_t mProbation = 0; // sequ. packets till source is valid
uint32_t mReceived = 0; // packets received
uint32_t mExpectedPrior = 0; // packet expected at last interval
uint32_t mReceivedPrior = 0; // packet received at last interval
uint32_t mTransit = 0; // relative trans time for prev pkt
uint32_t mJitter = 0;
SyncTimestamps mSyncTimestamps{0,0};
std::atomic<unsigned int> mRequestedBitrate = 0;
std::mutex mSyncMutex;
std::mutex mMutex;
message_ptr unwrapRtx(const message_ptr &rtxPacket);
// RTX state populated by media() from SDP inspection
std::unordered_map<uint8_t, uint8_t> mRtxToPrimaryPtMap; // RTX PT -> primary PT
SSRC mRtxPrimarySsrc = 0;
bool mRtxEnabled = false;
bool mSupportsRfc5104Fir = false;
std::unordered_map<SSRC, uint32_t> mRfc5104FirCmdNums; // SSRC -> seq no mapping
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif // RTC_RTCP_RECEIVING_SESSION_H

View File

@ -0,0 +1,49 @@
/**
* Copyright (c) 2020 Filip Klembara (in2core)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTCP_SR_REPORTER_H
#define RTC_RTCP_SR_REPORTER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "rtp.hpp"
#include "rtppacketizationconfig.hpp"
#include <chrono>
namespace rtc {
class RTC_CPP_EXPORT RtcpSrReporter final : public MediaHandler {
public:
RtcpSrReporter(shared_ptr<RtpPacketizationConfig> rtpConfig);
~RtcpSrReporter();
uint32_t lastReportedTimestamp() const;
[[deprecated]] void setNeedsToReport();
void outgoing(message_vector &messages, const message_callback &send) override;
// TODO: remove this
const shared_ptr<RtpPacketizationConfig> rtpConfig;
private:
void addToReport(RtpHeader *header, size_t size);
message_ptr getSenderReport(uint32_t timestamp);
uint32_t mPacketCount = 0;
uint32_t mPayloadOctets = 0;
uint32_t mLastReportedTimestamp = 0;
std::chrono::steady_clock::time_point mLastReportTime;
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_RTCP_SR_REPORTER_H */

View File

@ -0,0 +1,407 @@
/**
* Copyright (c) 2020 Staz Modrzynski
* Copyright (c) 2020 Paul-Louis Ageneau
* Copyright (c) 2020 Filip Klembara (in2core)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTP_HPP
#define RTC_RTP_HPP
#include "common.hpp"
#include <array>
#include <vector>
namespace rtc {
typedef uint32_t SSRC;
RTC_CPP_EXPORT bool IsRtcp(const binary &data);
#pragma pack(push, 1)
struct RTC_CPP_EXPORT RtpExtensionHeader {
uint16_t _profileSpecificId;
uint16_t _headerLength;
[[nodiscard]] uint16_t profileSpecificId() const;
[[nodiscard]] uint16_t headerLength() const;
[[nodiscard]] size_t getSize() const;
[[nodiscard]] const char *getBody() const;
[[nodiscard]] char *getBody();
void setProfileSpecificId(uint16_t profileSpecificId);
void setHeaderLength(uint16_t headerLength);
void clearBody();
size_t writeCurrentVideoOrientation(bool twoByteHeader, size_t offset, uint8_t id,
uint8_t value);
size_t writeOneByteHeader(size_t offset, uint8_t id, const byte *value, size_t size);
size_t writeTwoByteHeader(size_t offset, uint8_t id, const byte *value, size_t size);
size_t writeHeader(bool twoByteHeader, size_t offset, uint8_t id, const byte *value,
size_t size);
};
struct RTC_CPP_EXPORT RtpHeader {
uint8_t _first;
uint8_t _payloadType;
uint16_t _seqNumber;
uint32_t _timestamp;
SSRC _ssrc;
// The following field is SSRC _csrc[]
[[nodiscard]] uint8_t version() const;
[[nodiscard]] bool padding() const;
[[nodiscard]] bool extension() const;
[[nodiscard]] uint8_t csrcCount() const;
[[nodiscard]] uint8_t marker() const;
[[nodiscard]] uint8_t payloadType() const;
[[nodiscard]] uint16_t seqNumber() const;
[[nodiscard]] uint32_t timestamp() const;
[[nodiscard]] uint32_t ssrc() const;
[[nodiscard]] size_t getSize() const;
[[nodiscard]] size_t getExtensionHeaderSize() const;
[[nodiscard]] const RtpExtensionHeader *getExtensionHeader() const;
[[nodiscard]] RtpExtensionHeader *getExtensionHeader();
[[nodiscard]] const char *getBody() const;
[[nodiscard]] char *getBody();
void log() const;
void preparePacket();
void setSeqNumber(uint16_t newSeqNo);
void setPayloadType(uint8_t newPayloadType);
void setSsrc(uint32_t in_ssrc);
void setMarker(bool marker);
void setTimestamp(uint32_t i);
void setExtension(bool extension);
};
struct RTC_CPP_EXPORT RtcpReportBlock {
SSRC _ssrc;
uint32_t _fractionLostAndPacketsLost; // fraction lost is 8-bit, packets lost is 24-bit
uint16_t _seqNoCycles;
uint16_t _highestSeqNo;
uint32_t _jitter;
uint32_t _lastReport;
uint32_t _delaySinceLastReport;
[[nodiscard]] uint16_t seqNoCycles() const;
[[nodiscard]] uint16_t highestSeqNo() const;
[[nodiscard]] uint32_t extendedHighestSeqNo() const;
[[nodiscard]] uint32_t jitter() const;
[[nodiscard]] uint32_t delaySinceSR() const;
[[nodiscard]] SSRC getSSRC() const;
[[nodiscard]] uint32_t getNTPOfSR() const;
[[nodiscard]] uint8_t getFractionLost() const;
[[nodiscard]] unsigned int getPacketsLostCount() const;
void preparePacket(SSRC in_ssrc, uint8_t fraction, unsigned int totalPacketsLost,
uint16_t highestSeqNo, uint16_t seqNoCycles, uint32_t jitter,
uint64_t lastSR_NTP, uint64_t lastSR_DELAY);
void setSSRC(SSRC in_ssrc);
void setPacketsLost(uint8_t fractionLost, unsigned int packetsLostCount);
void setSeqNo(uint16_t highestSeqNo, uint16_t seqNoCycles);
void setJitter(uint32_t jitter);
void setNTPOfSR(uint64_t ntp);
void setDelaySinceSR(uint32_t sr);
void log() const;
};
struct RTC_CPP_EXPORT RtcpHeader {
uint8_t _first;
uint8_t _payloadType;
uint16_t _length;
[[nodiscard]] uint8_t version() const;
[[nodiscard]] bool padding() const;
[[nodiscard]] uint8_t reportCount() const;
[[nodiscard]] uint8_t payloadType() const;
[[nodiscard]] uint16_t length() const;
[[nodiscard]] size_t lengthInBytes() const;
void prepareHeader(uint8_t payloadType, uint8_t reportCount, uint16_t length);
void setPayloadType(uint8_t type);
void setReportCount(uint8_t count);
void setLength(uint16_t length);
void log() const;
};
struct RTC_CPP_EXPORT RtcpFbHeader {
RtcpHeader header;
SSRC _packetSender;
SSRC _mediaSource;
[[nodiscard]] SSRC packetSenderSSRC() const;
[[nodiscard]] SSRC mediaSourceSSRC() const;
void setPacketSenderSSRC(SSRC ssrc);
void setMediaSourceSSRC(SSRC ssrc);
void log() const;
};
struct RTC_CPP_EXPORT RtcpSr {
RtcpHeader header;
SSRC _senderSSRC;
uint64_t _ntpTimestamp;
uint32_t _rtpTimestamp;
uint32_t _packetCount;
uint32_t _octetCount;
RtcpReportBlock _reportBlocks;
[[nodiscard]] static unsigned int Size(unsigned int reportCount);
[[nodiscard]] uint64_t ntpTimestamp() const;
[[nodiscard]] uint32_t rtpTimestamp() const;
[[nodiscard]] uint32_t packetCount() const;
[[nodiscard]] uint32_t octetCount() const;
[[nodiscard]] uint32_t senderSSRC() const;
[[nodiscard]] const RtcpReportBlock *getReportBlock(int num) const; // nullptr if out-of-bounds
[[nodiscard]] RtcpReportBlock *getReportBlock(int num); // nullptr if out-of-bounds
[[nodiscard]] unsigned int size(unsigned int reportCount);
[[nodiscard]] size_t getSize() const;
void preparePacket(SSRC senderSSRC, uint8_t reportCount);
void setNtpTimestamp(uint64_t ts);
void setRtpTimestamp(uint32_t ts);
void setOctetCount(uint32_t ts);
void setPacketCount(uint32_t ts);
void log() const;
};
struct RTC_CPP_EXPORT RtcpSdesItem {
uint8_t type;
uint8_t _length;
char _text[1];
[[nodiscard]] static unsigned int Size(uint8_t textLength);
[[nodiscard]] string text() const;
[[nodiscard]] uint8_t length() const;
void setText(string text);
};
struct RTC_CPP_EXPORT RtcpSdesChunk {
SSRC _ssrc;
RtcpSdesItem _items;
[[nodiscard]] static unsigned int Size(const std::vector<uint8_t> textLengths);
[[nodiscard]] SSRC ssrc() const;
void setSSRC(SSRC ssrc);
// Get item at given index
// All items with index < num must be valid, otherwise this function has undefined behaviour
// (use safelyCountChunkSize() to check if chunk is valid).
[[nodiscard]] const RtcpSdesItem *getItem(int num) const;
[[nodiscard]] RtcpSdesItem *getItem(int num);
// Get size of chunk
// All items must be valid, otherwise this function has undefined behaviour (use
// safelyCountChunkSize() to check if chunk is valid)
[[nodiscard]] unsigned int getSize() const;
long safelyCountChunkSize(size_t maxChunkSize) const;
};
struct RTC_CPP_EXPORT RtcpSdes {
RtcpHeader header;
RtcpSdesChunk _chunks;
[[nodiscard]] static unsigned int Size(const std::vector<std::vector<uint8_t>> lengths);
bool isValid() const;
// Returns number of chunks in this packet
// Returns 0 if packet is invalid
unsigned int chunksCount() const;
// Get chunk at given index
// All chunks (and their items) with index < `num` must be valid, otherwise this function has
// undefined behaviour (use `isValid` to check if chunk is valid).
const RtcpSdesChunk *getChunk(int num) const;
RtcpSdesChunk *getChunk(int num);
void preparePacket(uint8_t chunkCount);
};
struct RTC_CPP_EXPORT RtcpRr {
RtcpHeader header;
SSRC _senderSSRC;
RtcpReportBlock _reportBlocks;
[[nodiscard]] static size_t SizeWithReportBlocks(uint8_t reportCount);
SSRC senderSSRC() const;
bool isSenderReport();
bool isReceiverReport();
[[nodiscard]] RtcpReportBlock *getReportBlock(int num); // nullptr if out-of-bounds
[[nodiscard]] const RtcpReportBlock *getReportBlock(int num) const; // nullptr if out-of-bounds
[[nodiscard]] size_t getSize() const;
void preparePacket(SSRC senderSSRC, uint8_t reportCount);
void setSenderSSRC(SSRC ssrc);
void log() const;
};
struct RTC_CPP_EXPORT RtcpRemb {
RtcpFbHeader header;
char _id[4]; // Unique identifier ('R' 'E' 'M' 'B')
uint32_t _bitrate; // Num SSRC, Br Exp, Br Mantissa (bit mask)
SSRC _ssrcs[1];
[[nodiscard]] static size_t SizeWithSSRCs(int count);
[[nodiscard]] unsigned int getSize() const;
void preparePacket(SSRC senderSSRC, unsigned int numSSRC, unsigned int in_bitrate);
void setBitrate(unsigned int numSSRC, unsigned int in_bitrate);
SSRC getSSRC(int num) const;
void setSSRC(int num, SSRC newSsrc);
bool hasValidId() const;
int getSSRCCount() const;
unsigned int getBitrate() const;
// Deprecated
[[deprecated("use setSSRC")]] void setSsrc(int num, SSRC newSssrc);
[[deprecated("use getSSRCCount")]] unsigned int getNumSSRC() const;
[[deprecated("use getSSRCCount")]] unsigned int getNumSSRC();
unsigned int getBitrate();
};
struct RTC_CPP_EXPORT RtcpPli {
RtcpFbHeader header;
[[nodiscard]] static unsigned int Size();
void preparePacket(SSRC messageSSRC);
void log() const;
};
struct RTC_CPP_EXPORT RtcpFirFci {
uint32_t _ssrc;
uint8_t _seqNo;
uint8_t _dummy1;
uint16_t _dummy2;
void preparePacket(SSRC ssrc, uint8_t seqNo);
[[nodiscard]] SSRC getSSRC() const;
[[nodiscard]] uint8_t getSeqNo() const;
};
struct RTC_CPP_EXPORT RtcpFir {
RtcpFbHeader header;
RtcpFirFci _fcis[1];
[[nodiscard]] static size_t SizeWithFcis(int count);
int getFciCount() const;
[[nodiscard]] const RtcpFirFci *getFci(int num) const; // nullptr if out-of-bounds
void preparePacket(SSRC senderSSRC, const std::vector<RtcpFirFci> &fcis);
void log() const;
};
struct RTC_CPP_EXPORT RtcpNackPart {
uint16_t _pid;
uint16_t _blp;
uint16_t pid();
uint16_t blp();
void setPid(uint16_t pid);
void setBlp(uint16_t blp);
std::vector<uint16_t> getSequenceNumbers();
};
struct RTC_CPP_EXPORT RtcpNack {
RtcpFbHeader header;
RtcpNackPart parts[1];
[[nodiscard]] static unsigned int Size(unsigned int discreteSeqNoCount);
[[nodiscard]] unsigned int getSeqNoCount();
void preparePacket(SSRC ssrc, unsigned int discreteSeqNoCount);
/**
* Add a packet to the list of missing packets.
* @param fciCount The number of FCI fields that are present in this packet.
* Let the number start at zero and let this function grow the number.
* @param fciPID The seq no of the active FCI. It will be initialized automatically, and will
* change automatically.
* @param missingPacket The seq no of the missing packet. This will be added to the queue.
* @return true if the packet has grown, false otherwise.
*/
bool addMissingPacket(unsigned int *fciCount, uint16_t *fciPID, uint16_t missingPacket);
};
typedef std::array<char, 4> RtcpAppName;
struct RTC_CPP_EXPORT RtcpApp {
RtcpHeader header;
SSRC _ssrc;
char _name[4];
char _data[1];
[[nodiscard]] static size_t SizeWithData(size_t dataLength);
[[nodiscard]] SSRC ssrc() const;
[[nodiscard]] uint8_t subtype() const;
[[nodiscard]] RtcpAppName name() const;
[[nodiscard]] const char *data() const;
[[nodiscard]] size_t dataSize() const;
void preparePacket(SSRC ssrc, const RtcpAppName &name, uint8_t subtype, size_t dataLength);
void setSSRC(SSRC ssrc);
void setName(const RtcpAppName &name);
void log() const;
};
struct RTC_CPP_EXPORT RtpRtx {
RtpHeader header;
[[nodiscard]] const char *getBody() const;
[[nodiscard]] char *getBody();
[[nodiscard]] size_t getBodySize(size_t totalSize) const;
[[nodiscard]] size_t getSize() const;
[[nodiscard]] uint16_t getOriginalSeqNo() const;
// Returns the new size of the packet
size_t normalizePacket(size_t totalSize, SSRC originalSSRC, uint8_t originalPayloadType);
size_t copyTo(RtpHeader *dest, size_t totalSize, uint8_t originalPayloadType);
};
#pragma pack(pop)
} // namespace rtc
#endif

View File

@ -0,0 +1,79 @@
/**
* Copyright (c) 2024 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTP_DEPACKETIZER_H
#define RTC_RTP_DEPACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "message.hpp"
#include <set>
namespace rtc {
// Base RTP depacketizer class
class RTC_CPP_EXPORT RtpDepacketizer : public MediaHandler {
public:
RtpDepacketizer();
RtpDepacketizer(uint32_t clockRate);
virtual ~RtpDepacketizer();
virtual void incoming(message_vector &messages, const message_callback &send) override;
protected:
shared_ptr<FrameInfo> createFrameInfo(uint32_t timestamp, uint8_t payloadType) const;
private:
const uint32_t mClockRate;
};
// Base class for video RTP depacketizer
class RTC_CPP_EXPORT VideoRtpDepacketizer : public RtpDepacketizer {
public:
inline static const uint32_t ClockRate = 90000;
VideoRtpDepacketizer();
virtual ~VideoRtpDepacketizer();
protected:
struct sequence_cmp {
bool operator()(message_ptr a, message_ptr b) const;
};
using message_buffer = std::set<message_ptr, sequence_cmp>;
virtual message_ptr reassemble(message_buffer &messages) = 0;
private:
void incoming(message_vector &messages, const message_callback &send) override;
message_buffer mBuffer;
};
// Generic audio RTP depacketizer
template <uint32_t DEFAULT_CLOCK_RATE>
class RTC_CPP_EXPORT AudioRtpDepacketizer final : public RtpDepacketizer {
public:
inline static const uint32_t DefaultClockRate = DEFAULT_CLOCK_RATE;
AudioRtpDepacketizer(uint32_t clockRate = DefaultClockRate) : RtpDepacketizer(clockRate) {}
};
// Audio RTP depacketizers
using OpusRtpDepacketizer = AudioRtpDepacketizer<48000>;
using AACRtpDepacketizer = AudioRtpDepacketizer<48000>;
using PCMARtpDepacketizer = AudioRtpDepacketizer<8000>;
using PCMURtpDepacketizer = AudioRtpDepacketizer<8000>;
using G722RtpDepacketizer = AudioRtpDepacketizer<8000>;
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_RTP_DEPACKETIZER_H */

View File

@ -0,0 +1,141 @@
/**
* Copyright (c) 2020 Filip Klembara (in2core)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTP_PACKETIZATION_CONFIG_H
#define RTC_RTP_PACKETIZATION_CONFIG_H
#if RTC_ENABLE_MEDIA
#include "dependencydescriptor.hpp"
#include "rtp.hpp"
namespace rtc {
struct RTC_CPP_EXPORT VideoLayersAllocation;
// RTP configuration used in packetization process
class RTC_CPP_EXPORT RtpPacketizationConfig {
public:
SSRC ssrc;
std::string cname;
uint8_t payloadType;
uint32_t clockRate;
uint8_t videoOrientationId;
// current sequence number
uint16_t sequenceNumber;
// current timestamp
uint32_t timestamp;
// start timestamp
uint32_t startTimestamp;
/// Current video orientation
///
/// Bit# 7 6 5 4 3 2 1 0
/// Definition 0 0 0 0 C F R1 R0
///
/// C
/// 0 - Front-facing camera (use this if unsure)
/// 1 - Back-facing camera
///
/// F
/// 0 - No Flip
/// 1 - Horizontal flip
///
/// R1 R0 - CW rotation that receiver must apply
/// 0 - 0 degrees
/// 1 - 90 degrees
/// 2 - 180 degrees
/// 3 - 270 degrees
uint8_t videoOrientation = 0;
// MID Extension Header
uint8_t midId = 0;
optional<std::string> mid;
// RID Extension Header
uint8_t ridId = 0;
optional<std::string> rid;
// Dependency Descriptor Extension Header
uint8_t dependencyDescriptorId = 0;
optional<DependencyDescriptorContext> dependencyDescriptorContext;
// the negotiated ID of the playout delay header extension
// https://webrtc.googlesource.com/src/+/main/docs/native-code/rtp-hdrext/playout-delay/README.md
uint8_t playoutDelayId = 0;
// Minimum/maxiumum playout delay, in 10ms intervals. A value of 10 would equal a 100ms delay
uint16_t playoutDelayMin = 0;
uint16_t playoutDelayMax = 0;
// Google Video Layers Allocation for simulcast
// https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/video-layers-allocation00
//
// The negotiated extension id
uint8_t videoLayersAllocationId = 0;
// Stream index, unique per RID/SSRC
uint8_t videoLayersAllocationStreamIndex = 0;
// Shared data about layers
std::shared_ptr<const VideoLayersAllocation> videoLayersAllocationStreams;
// https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/color-space/
uint8_t colorSpaceId = 0; // the negotiated ID of color space header extension
uint8_t colorChromaSitingHorz = 0; // unspecified
uint8_t colorChromaSitingVert = 0; // unspecified
uint8_t colorRange = 2; // full range
uint8_t colorPrimaries = 1; // BT.709-6
uint8_t colorTransfer = 1; // BT.709-6
uint8_t colorMatrix = 1; // BT.709-6
// abs-capture-time RTP header extension. When absCaptureTimeId > 0 and an
// outgoing FrameInfo carries an absCaptureTimeNtp value, the RtpPacketizer
// writes the 8-byte (shortened) form of the abs-capture-time extension into
// every packet for that frame. The receiver can recover the source's
// capture wallclock and compute true glass-to-glass latency.
// https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/abs-capture-time
uint8_t absCaptureTimeId = 0;
/// Construct RTP configuration used in packetization process
/// @param ssrc SSRC of source
/// @param cname CNAME of source
/// @param payloadType Payload type of source
/// @param clockRate Clock rate of source used in timestamps
/// nullopt)
/// @param videoOrientationId Video orientation (see above)
RtpPacketizationConfig(SSRC ssrc, std::string cname, uint8_t payloadType, uint32_t clockRate,
uint8_t videoOrientationId = 0);
RtpPacketizationConfig(const RtpPacketizationConfig &) = delete;
/// Convert timestamp to seconds
/// @param timestamp Timestamp
/// @param clockRate Clock rate for timestamp calculation
static double getSecondsFromTimestamp(uint32_t timestamp, uint32_t clockRate);
/// Convert timestamp to seconds
/// @param timestamp Timestamp
double timestampToSeconds(uint32_t timestamp);
/// Convert seconds to timestamp
/// @param seconds Number of seconds
/// @param clockRate Clock rate for timestamp calculation
static uint32_t getTimestampFromSeconds(double seconds, uint32_t clockRate);
/// Convert seconds to timestamp
/// @param seconds Number of seconds
uint32_t secondsToTimestamp(double seconds);
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_RTP_PACKETIZATION_CONFIG_H */

View File

@ -0,0 +1,106 @@
/**
* Copyright (c) 2020 Filip Klembara (in2core)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_RTP_PACKETIZER_H
#define RTC_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "mediahandler.hpp"
#include "message.hpp"
#include "rtppacketizationconfig.hpp"
namespace rtc {
/// RTP packetizer
class RTC_CPP_EXPORT RtpPacketizer : public MediaHandler {
public:
/// Default maximum fragment size (for video packetizers)
inline static const size_t DefaultMaxFragmentSize = RTC_DEFAULT_MAX_FRAGMENT_SIZE;
/// Clock rate for video in RTP
inline static const uint32_t VideoClockRate = 90 * 1000;
/// Constructs packetizer with given RTP configuration
/// @note RTP configuration is used in packetization process which may change some configuration
/// properties such as sequence number.
/// @param rtpConfig RTP configuration
RtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig);
virtual ~RtpPacketizer();
virtual void media(const Description::Media &desc) override;
virtual void outgoing(message_vector &messages, const message_callback &send) override;
/// RTP packetization config
const shared_ptr<RtpPacketizationConfig> rtpConfig;
protected:
/// Fragment data into payloads
/// Default implementation returns data as a single payload
/// @param data Input data
virtual std::vector<binary> fragment(binary data);
/// Creates an RTP packet for a payload
/// @note This function increases the sequence number.
/// @param payload RTP payload
/// @param mark Set marker flag in RTP packet if true
virtual message_ptr packetize(const binary &payload, bool mark, shared_ptr<FrameInfo> frameInfo = nullptr);
private:
static const auto RtpHeaderSize = 12;
static const auto RtpExtHeaderCvoSize = 8;
uint32_t videoLayersAllocationInitialPacketCount = 0;
bool shouldEmitVideoLayersAllocation(shared_ptr<FrameInfo> frameInfo);
};
// Generic audio RTP packetizer
template <uint32_t DEFAULT_CLOCK_RATE>
class RTC_CPP_EXPORT AudioRtpPacketizer final : public RtpPacketizer {
public:
inline static const uint32_t DefaultClockRate = DEFAULT_CLOCK_RATE;
inline static const uint32_t defaultClockRate [[deprecated("Use DefaultClockRate")]] =
DEFAULT_CLOCK_RATE; // for backward compatibility
AudioRtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig)
: RtpPacketizer(std::move(rtpConfig)) {}
};
// Audio RTP packetizers
using OpusRtpPacketizer = AudioRtpPacketizer<48000>;
using AACRtpPacketizer = AudioRtpPacketizer<48000>;
using PCMARtpPacketizer = AudioRtpPacketizer<8000>;
using PCMURtpPacketizer = AudioRtpPacketizer<8000>;
using G722RtpPacketizer = AudioRtpPacketizer<8000>;
// Dummy wrapper for backward compatibility, do not use
class RTC_CPP_EXPORT PacketizationHandler final : public MediaHandler {
public:
PacketizationHandler(shared_ptr<RtpPacketizer> packetizer)
: mPacketizer(std::move(packetizer)) {}
inline void outgoing(message_vector &messages, const message_callback &send) {
return mPacketizer->outgoing(messages, send);
}
private:
shared_ptr<RtpPacketizer> mPacketizer;
};
// Audio packetization handlers for backward compatibility, do not use
using OpusPacketizationHandler [[deprecated("Add OpusRtpPacketizer directly")]] =
PacketizationHandler;
using AACPacketizationHandler [[deprecated("Add AACRtpPacketizer directly")]] =
PacketizationHandler;
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_RTP_PACKETIZER_H */

View File

@ -0,0 +1,70 @@
/**
* Copyright (c) 2020 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_TRACK_H
#define RTC_TRACK_H
#include "channel.hpp"
#include "common.hpp"
#include "description.hpp"
#include "mediahandler.hpp"
#include <vector>
namespace rtc {
namespace impl {
class Track;
} // namespace impl
class RTC_CPP_EXPORT Track final : private CheshireCat<impl::Track>, public Channel {
public:
Track(impl_ptr<impl::Track> impl);
~Track() override;
string mid() const;
Description::Direction direction() const;
Description::Media description() const;
void setDescription(Description::Media description);
void close(void) override;
bool send(message_variant data) override;
bool send(const byte *data, size_t size) override;
bool isOpen(void) const override;
bool isClosed(void) const override;
size_t maxMessageSize() const override;
void sendFrame(binary data, FrameInfo info);
void sendFrame(const byte *data, size_t size, FrameInfo info);
void onFrame(std::function<void(binary data, FrameInfo info)> callback);
bool requestKeyframe(SSRC ssrc=0, bool retransmit=false);
bool requestKeyframe(const std::vector<SSRC>& targetSSRCs, bool retransmit=false);
bool requestBitrate(unsigned int bitrate);
bool sendRtcpApp(uint32_t ssrc, const RtcpAppName &name, uint8_t subtype,
const binary &data = binary{});
void setMediaHandler(shared_ptr<MediaHandler> handler);
void chainMediaHandler(shared_ptr<MediaHandler> handler);
shared_ptr<MediaHandler> getMediaHandler();
// Deprecated, use setMediaHandler() and getMediaHandler()
inline void setRtcpHandler(shared_ptr<MediaHandler> handler) { setMediaHandler(handler); }
inline shared_ptr<MediaHandler> getRtcpHandler() { return getMediaHandler(); }
private:
using CheshireCat<impl::Track>::impl;
};
} // namespace rtc
#endif

View File

@ -0,0 +1,174 @@
/**
* Copyright (c) 2019-2021 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_UTILS_H
#define RTC_UTILS_H
#include <algorithm>
#include <cctype>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
namespace rtc {
// overloaded helper
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
// weak_ptr bind helper
template <typename F, typename T, typename... Args> auto weak_bind(F &&f, T *t, Args &&..._args) {
return [bound = std::bind(f, t, _args...), weak_this = t->weak_from_this()](auto &&...args) {
if (auto shared_this = weak_this.lock())
return bound(args...);
else
return static_cast<decltype(bound(args...))>(false);
};
}
// scope_guard helper
class scope_guard final {
public:
scope_guard(std::function<void()> func) : function(std::move(func)) {}
scope_guard(scope_guard &&other) = delete;
scope_guard(const scope_guard &) = delete;
void operator=(const scope_guard &) = delete;
~scope_guard() {
if (function)
function();
}
private:
std::function<void()> function;
};
// callback with built-in synchronization
template <typename... Args> class synchronized_callback {
public:
synchronized_callback() = default;
synchronized_callback(synchronized_callback &&cb) { *this = std::move(cb); }
synchronized_callback(const synchronized_callback &cb) { *this = cb; }
synchronized_callback(std::function<void(Args...)> func) { *this = std::move(func); }
virtual ~synchronized_callback() { *this = nullptr; }
synchronized_callback &operator=(synchronized_callback &&cb) {
std::scoped_lock lock(mutex, cb.mutex);
set(std::exchange(cb.callback, nullptr));
return *this;
}
synchronized_callback &operator=(const synchronized_callback &cb) {
std::scoped_lock lock(mutex, cb.mutex);
set(cb.callback);
return *this;
}
synchronized_callback &operator=(std::function<void(Args...)> func) {
std::lock_guard lock(mutex);
set(std::move(func));
return *this;
}
bool operator()(Args... args) const {
std::lock_guard lock(mutex);
return call(std::move(args)...);
}
operator bool() const {
std::lock_guard lock(mutex);
return callback ? true : false;
}
protected:
virtual void set(std::function<void(Args...)> func) { callback = std::move(func); }
virtual bool call(Args... args) const {
if (!callback)
return false;
callback(std::move(args)...);
return true;
}
std::function<void(Args...)> callback;
mutable std::recursive_mutex mutex;
};
// callback with built-in synchronization and replay of the last missed call
template <typename... Args>
class synchronized_stored_callback final : public synchronized_callback<Args...> {
public:
template <typename... CArgs>
synchronized_stored_callback(CArgs &&...cargs)
: synchronized_callback<Args...>(std::forward<CArgs>(cargs)...) {}
~synchronized_stored_callback() {}
private:
void set(std::function<void(Args...)> func) {
synchronized_callback<Args...>::set(func);
if (func && stored) {
std::apply(func, std::move(*stored));
stored.reset();
}
}
bool call(Args... args) const {
if (!synchronized_callback<Args...>::call(args...))
stored.emplace(std::move(args)...);
return true;
}
mutable std::optional<std::tuple<Args...>> stored;
};
// pimpl base class
template <typename T> using impl_ptr = std::shared_ptr<T>;
template <typename T> class CheshireCat {
public:
CheshireCat(impl_ptr<T> impl) : mImpl(std::move(impl)) {}
template <typename... Args>
CheshireCat(Args... args) : mImpl(std::make_shared<T>(std::forward<Args>(args)...)) {}
CheshireCat(CheshireCat<T> &&cc) { *this = std::move(cc); }
CheshireCat(const CheshireCat<T> &) = delete;
virtual ~CheshireCat() = default;
CheshireCat &operator=(CheshireCat<T> &&cc) {
mImpl = std::move(cc.mImpl);
return *this;
};
CheshireCat &operator=(const CheshireCat<T> &) = delete;
protected:
impl_ptr<T> impl() { return mImpl; }
impl_ptr<const T> impl() const { return mImpl; }
private:
impl_ptr<T> mImpl;
};
// case-insensitive string comparator using std::tolower
class case_insensitive_less : public std::less<std::string> {
public:
bool operator()(const std::string &lhs, const std::string &rhs) const {
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(),
[](auto a, auto b) {
return std::tolower(static_cast<unsigned char>(a)) <
std::tolower(static_cast<unsigned char>(b));
});
}
};
} // namespace rtc
#endif

View File

@ -0,0 +1,9 @@
#ifndef RTC_VERSION_H
#define RTC_VERSION_H
#define RTC_VERSION_MAJOR 0
#define RTC_VERSION_MINOR 24
#define RTC_VERSION_PATCH 4
#define RTC_VERSION "0.24.4"
#endif

View File

@ -0,0 +1,50 @@
/**
* Copyright (c) 2026
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_VIDEO_LAYERS_ALLOCATION_H
#define RTC_VIDEO_LAYERS_ALLOCATION_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include <cstdint>
#include <memory>
#include <vector>
namespace rtc {
// Google Video Layers Allocation for simulcast
//
// https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/video-layers-allocation00
struct RTC_CPP_EXPORT VideoLayersAllocation {
struct SpatialLayer {
uint16_t width = 0;
uint16_t height = 0;
uint8_t fps = 0;
std::vector<uint32_t> targetBitratesKbps; // per temporal layer, cumulative, cannot be empty
};
struct RtpStream {
std::vector<SpatialLayer> spatialLayers;
};
std::vector<RtpStream> rtpStreams; // up to 4 streams
/// Generate the wire format for Google Video Layers Allocation RTP header extension
/// @param streamIndex The RTP stream index (0-3) for this packet's stream
/// @return Binary payload for the RTP header extension, empty if allocation is invalid
binary generate(uint8_t streamIndex) const;
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_VIDEO_LAYERS_ALLOCATION_H */

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2026 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_VP8_RTP_DEPACKETIZER_H
#define RTC_VP8_RTP_DEPACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include "message.hpp"
#include "rtpdepacketizer.hpp"
namespace rtc {
/// RTP depacketization for VP8
class RTC_CPP_EXPORT VP8RtpDepacketizer final : public VideoRtpDepacketizer {
public:
VP8RtpDepacketizer();
~VP8RtpDepacketizer();
private:
message_ptr reassemble(message_buffer &buffer) override;
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif /* RTC_VP8_RTP_DEPACKETIZER_H */

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2026 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_VP8_RTP_PACKETIZER_H
#define RTC_VP8_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "rtppacketizer.hpp"
namespace rtc {
/// RTP packetization for VP8
class RTC_CPP_EXPORT VP8RtpPacketizer final : public RtpPacketizer {
public:
inline static const uint32_t ClockRate = VideoClockRate;
[[deprecated("Use ClockRate")]] inline static const uint32_t defaultClockRate = ClockRate;
/// Constructs VP8 payload packetizer with given RTP configuration.
/// @note RTP configuration is used in packetization process which may change some configuration
/// properties such as sequence number.
/// @param rtpConfig RTP configuration
/// @param maxFragmentSize maximum size of one packet payload
VP8RtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
private:
std::vector<binary> fragment(binary frame) override;
const size_t mMaxFragmentSize;
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_VP8_RTP_PACKETIZER_H */

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2026 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_VP9_RTP_DEPACKETIZER_H
#define RTC_VP9_RTP_DEPACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "common.hpp"
#include "message.hpp"
#include "rtpdepacketizer.hpp"
namespace rtc {
/// RTP depacketization for VP9
class RTC_CPP_EXPORT VP9RtpDepacketizer final : public VideoRtpDepacketizer {
public:
VP9RtpDepacketizer();
~VP9RtpDepacketizer();
private:
message_ptr reassemble(message_buffer &buffer) override;
};
} // namespace rtc
#endif // RTC_ENABLE_MEDIA
#endif /* RTC_VP9_RTP_DEPACKETIZER_H */

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2026 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_VP9_RTP_PACKETIZER_H
#define RTC_VP9_RTP_PACKETIZER_H
#if RTC_ENABLE_MEDIA
#include "rtppacketizer.hpp"
namespace rtc {
/// RTP packetization for VP9
class RTC_CPP_EXPORT VP9RtpPacketizer final : public RtpPacketizer {
public:
inline static const uint32_t ClockRate = VideoClockRate;
/// Constructs VP9 payload packetizer with given RTP configuration.
/// @note RTP configuration is used in packetization process which may change some configuration
/// properties such as sequence number.
/// @param rtpConfig RTP configuration
/// @param maxFragmentSize maximum size of one packet payload
VP9RtpPacketizer(shared_ptr<RtpPacketizationConfig> rtpConfig,
size_t maxFragmentSize = DefaultMaxFragmentSize);
private:
std::vector<binary> fragment(binary frame) override;
const size_t mMaxFragmentSize;
};
} // namespace rtc
#endif /* RTC_ENABLE_MEDIA */
#endif /* RTC_VP9_RTP_PACKETIZER_H */

View File

@ -0,0 +1,72 @@
/**
* Copyright (c) 2020-2021 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_WEBSOCKET_H
#define RTC_WEBSOCKET_H
#if RTC_ENABLE_WEBSOCKET
#include "channel.hpp"
#include "common.hpp"
#include "configuration.hpp"
#include <map>
namespace rtc {
namespace impl {
struct WebSocket;
} // namespace impl
class RTC_CPP_EXPORT WebSocket final : private CheshireCat<impl::WebSocket>, public Channel {
public:
enum class State : int {
Connecting = 0,
Open = 1,
Closing = 2,
Closed = 3,
};
using Configuration = WebSocketConfiguration;
using Headers = std::map<string, string, case_insensitive_less>;
WebSocket();
WebSocket(Configuration config);
WebSocket(impl_ptr<impl::WebSocket> impl);
~WebSocket() override;
State readyState() const;
bool isOpen() const override;
bool isClosed() const override;
size_t maxMessageSize() const override;
void open(const string &url, const Headers &headers = {});
void close() override;
void forceClose();
bool send(const message_variant data) override;
bool send(const byte *data, size_t size) override;
optional<string> remoteAddress() const;
optional<string> path() const;
std::multimap<string, string, case_insensitive_less> requestHeaders() const;
private:
using CheshireCat<impl::WebSocket>::impl;
};
std::ostream &operator<<(std::ostream &out, WebSocket::State state);
} // namespace rtc
#endif
#endif // RTC_WEBSOCKET_H

View File

@ -0,0 +1,48 @@
/**
* Copyright (c) 2021 Paul-Louis Ageneau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef RTC_WEBSOCKETSERVER_H
#define RTC_WEBSOCKETSERVER_H
#if RTC_ENABLE_WEBSOCKET
#include "common.hpp"
#include "configuration.hpp"
#include "websocket.hpp"
namespace rtc {
namespace impl {
struct WebSocketServer;
}
class RTC_CPP_EXPORT WebSocketServer final : private CheshireCat<impl::WebSocketServer> {
public:
using Configuration = WebSocketServerConfiguration;
WebSocketServer();
WebSocketServer(Configuration config);
~WebSocketServer();
void stop();
uint16_t port() const;
void onClient(std::function<void(shared_ptr<WebSocket>)> callback);
private:
using CheshireCat<impl::WebSocketServer>::impl;
};
} // namespace rtc
#endif
#endif // RTC_WEBSOCKET_H

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.