Merge pull request #416 from paullouisageneau/cleanup-api

Refactor C media API
This commit is contained in:
Paul-Louis Ageneau
2021-04-29 17:12:37 +02:00
committed by GitHub
3 changed files with 346 additions and 389 deletions

View File

@ -42,7 +42,14 @@ class RTC_CPP_EXPORT Description {
public:
enum class Type { Unspec, Offer, Answer, Pranswer, Rollback };
enum class Role { ActPass, Passive, Active };
enum class Direction { SendOnly, RecvOnly, SendRecv, Inactive, Unknown };
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);

View File

@ -95,8 +95,6 @@ typedef enum {
RTC_CERTIFICATE_RSA = 2,
} rtcCertificateType;
#if RTC_ENABLE_MEDIA
typedef enum {
// video
RTC_CODEC_H264 = 0,
@ -115,41 +113,12 @@ typedef enum {
RTC_DIRECTION_INACTIVE = 4
} rtcDirection;
#endif // RTC_ENABLE_MEDIA
#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 struct {
const char **iceServers;
int iceServersCount;
rtcCertificateType certificateType;
bool enableIceTcp;
bool disableAutoNegotiation;
uint16_t portRangeBegin;
uint16_t portRangeEnd;
int mtu; // <= 0 means automatic
int maxMessageSize; // <= 0 means default
} rtcConfiguration;
typedef struct {
bool unordered;
bool unreliable;
int maxPacketLifeTime; // ignored if reliable
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;
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);
@ -168,6 +137,7 @@ typedef void(RTC_API *rtcBufferedAmountLowCallbackFunc)(int id, void *ptr);
typedef void(RTC_API *rtcAvailableCallbackFunc)(int id, void *ptr);
// Log
// NULL cb on the first call will log to stdout
RTC_EXPORT void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb);
@ -176,6 +146,19 @@ RTC_EXPORT void rtcSetUserPointer(int id, void *ptr);
RTC_EXPORT void *rtcGetUserPointer(int i);
// PeerConnection
typedef struct {
const char **iceServers;
int iceServersCount;
rtcCertificateType certificateType;
bool enableIceTcp;
bool disableAutoNegotiation;
uint16_t portRangeBegin;
uint16_t portRangeEnd;
int mtu; // <= 0 means automatic
int maxMessageSize; // <= 0 means default
} rtcConfiguration;
RTC_EXPORT int rtcCreatePeerConnection(const rtcConfiguration *config); // returns pc id
RTC_EXPORT int rtcDeletePeerConnection(int pc);
@ -202,6 +185,22 @@ RTC_EXPORT int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, c
int remoteSize);
// DataChannel
typedef struct {
bool unordered;
bool unreliable;
int maxPacketLifeTime; // ignored if reliable
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_EXPORT int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb);
RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label,
@ -214,131 +213,96 @@ RTC_EXPORT int rtcGetDataChannelProtocol(int dc, char *buffer, int size);
RTC_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
} rtcTrackInit;
RTC_EXPORT int rtcSetTrackCallback(int pc, rtcTrackCallbackFunc cb);
RTC_EXPORT int rtcAddTrack(int pc, const char *mediaDescriptionSdp); // returns tr id
RTC_EXPORT int rtcAddTrackEx(int pc, const rtcTrackInit *init); // returns tr id
RTC_EXPORT int rtcDeleteTrack(int tr);
RTC_EXPORT int rtcGetTrackDescription(int tr, char *buffer, int size);
// SCTP settings
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 msecs, <= 0 means optimized default
} rtcSctpSettings;
// Note: SCTP settings apply to newly-created PeerConnections only
RTC_EXPORT int rtcSetSctpSettings(const rtcSctpSettings *settings);
// Media
#if RTC_ENABLE_MEDIA
/// Add track
/// @param pc Peer connection id
/// @param codec Codec
/// @param payloadType Payload type
/// @param ssrc SSRC
/// @param _mid MID
/// @param _direction Direction
/// @param _name Name (optional)
/// @param _msid MSID (optional)
/// @param _trackID Track ID used in MSID (optional)
/// @returns Track id
RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc,
const char *_mid, rtcDirection direction, const char *_name,
const char *_msid, const char *_trackID);
// Media
/// Set H264PacketizationHandler for track
/// @param tr Track id
/// @param ssrc SSRC
/// @param cname CName
/// @param payloadType Payload Type
/// @param clockRate Clock rate
/// @param maxFragmentSize Maximum NALU fragment size
/// @param sequenceNumber Sequence number
/// @param timestamp Timestamp
RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, uint32_t ssrc, const char *cname,
uint8_t payloadType, uint32_t clockRate,
uint16_t maxFragmentSize, uint16_t sequenceNumber,
uint32_t timestamp);
typedef struct {
uint32_t ssrc;
const char *cname;
uint8_t payloadType;
uint32_t clockRate;
uint16_t maxFragmentSize; // Maximum NALU fragment size
uint16_t sequenceNumber;
uint32_t timestamp;
} rtcPacketizationHandlerInit;
/// Set OpusPacketizationHandler for track
/// @param tr Track id
/// @param ssrc SSRC
/// @param cname CName
/// @param payloadType Payload Type
/// @param clockRate Clock rate
/// @param _sequenceNumber Sequence number
/// @param _timestamp Timestamp
RTC_EXPORT int rtcSetOpusPacketizationHandler(int tr, uint32_t ssrc, const char *cname,
uint8_t payloadType, uint32_t clockRate,
uint16_t _sequenceNumber, uint32_t _timestamp);
typedef struct {
double seconds; // Start time in seconds
bool since1970; // true if seconds since 1970
// false if seconds since 1900
uint32_t timestamp; // Start timestamp
} rtcStartTime;
/// Chain RtcpSrReporter to handler chain for given track
/// @param tr Track id
int rtcChainRtcpSrReporter(int tr);
// Set H264PacketizationHandler for track
RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init);
/// Chain RtcpNackResponder to handler chain for given track
/// @param tr Track id
/// @param maxStoredPacketsCount Maximum stored packet count
int rtcChainRtcpNackResponder(int tr, unsigned int maxStoredPacketsCount);
// Set OpusPacketizationHandler for track
RTC_EXPORT int rtcSetOpusPacketizationHandler(int tr, const rtcPacketizationHandlerInit *init);
// Chain RtcpSrReporter to handler chain for given track
RTC_EXPORT int rtcChainRtcpSrReporter(int tr);
// Chain RtcpNackResponder to handler chain for given track
RTC_EXPORT int rtcChainRtcpNackResponder(int tr, unsigned int maxStoredPacketsCount);
/// Set start time for RTP stream
/// @param startTime_s Start time in seconds
/// @param timeIntervalSince1970 Set true if `startTime_s` is time interval since 1970, false if
/// `startTime_s` is time interval since 1900
/// @param _timestamp Start timestamp
int rtcSetRtpConfigurationStartTime(int id, double startTime_s, bool timeIntervalSince1970,
uint32_t _timestamp);
RTC_EXPORT int rtcSetRtpConfigurationStartTime(int id, const rtcStartTime *startTime);
/// Start stats recording for RTCP Sender Reporter
/// @param id Track identifier
int rtcStartRtcpSenderReporterRecording(int id);
// Start stats recording for RTCP Sender Reporter
RTC_EXPORT int rtcStartRtcpSenderReporterRecording(int id);
/// Transform seconds to timestamp using track's clock rate
/// @param id Track id
/// @param seconds Seconds
/// @param timestamp Pointer to result
int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp);
// Transform seconds to timestamp using track's clock rate
// Result is written to timestamp
RTC_EXPORT int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp);
/// Transform timestamp to seconds using track's clock rate
/// @param id Track id
/// @param timestamp Timestamp
/// @param seconds Pointer for result
int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds);
// Transform timestamp to seconds using track's clock rate
// Result is written to seconds
RTC_EXPORT int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds);
/// Get current timestamp
/// @param id Track id
/// @param timestamp Pointer for result
int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp);
// Get current timestamp
// Result is written to timestamp
RTC_EXPORT int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp);
/// Get start timestamp for track identified by given id
/// @param id Track id
/// @param timestamp Pointer for result
int rtcGetTrackStartTimestamp(int id, uint32_t *timestamp);
// Get start timestamp for track identified by given id
// Result is written to timestamp
RTC_EXPORT int rtcGetTrackStartTimestamp(int id, uint32_t *timestamp);
/// Set RTP timestamp for track identified by given id
/// @param id Track id
/// @param timestamp New timestamp
int rtcSetTrackRTPTimestamp(int id, uint32_t timestamp);
// Set RTP timestamp for track identified by given id
RTC_EXPORT int rtcSetTrackRtpTimestamp(int id, uint32_t timestamp);
/// Get timestamp of previous RTCP SR
/// @param id Track id
/// @param timestamp Pointer for result
int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timestamp);
// Get timestamp of previous RTCP SR
// Result is written to timestamp
RTC_EXPORT int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timestamp);
/// Set `NeedsToReport` flag in RtcpSrReporter handler identified by given track id
/// @param id Track id
int rtcSetNeedsToSendRtcpSr(int id);
// Set NeedsToReport flag in RtcpSrReporter handler identified by given track id
RTC_EXPORT int rtcSetNeedsToSendRtcpSr(int id);
#endif // RTC_ENABLE_MEDIA
// WebSocket
#if RTC_ENABLE_WEBSOCKET
// WebSocket
typedef struct {
bool disableTlsVerification; // if true, don't verify the TLS certificate
} rtcWsConfiguration;
@ -346,9 +310,11 @@ typedef struct {
RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
RTC_EXPORT int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config);
RTC_EXPORT int rtcDeleteWebsocket(int ws);
#endif
// DataChannel, Track, and WebSocket common API
RTC_EXPORT int rtcSetOpenCallback(int id, rtcOpenCallbackFunc cb);
RTC_EXPORT int rtcSetClosedCallback(int id, rtcClosedCallbackFunc cb);
RTC_EXPORT int rtcSetErrorCallback(int id, rtcErrorCallbackFunc cb);
@ -360,14 +326,31 @@ RTC_EXPORT int rtcSetBufferedAmountLowThreshold(int id, int amount);
RTC_EXPORT int rtcSetBufferedAmountLowCallback(int id, rtcBufferedAmountLowCallbackFunc cb);
// DataChannel, Track, and WebSocket common extended API
RTC_EXPORT int rtcGetAvailableAmount(int id); // total size available to receive
RTC_EXPORT int rtcSetAvailableCallback(int id, rtcAvailableCallbackFunc cb);
RTC_EXPORT int rtcReceiveMessage(int id, char *buffer, int *size);
// Optional preload and cleanup
// Optional global preload and cleanup
RTC_EXPORT void rtcPreload(void);
RTC_EXPORT void rtcCleanup(void);
// SCTP global settings
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 msecs, <= 0 means optimized default
} rtcSctpSettings;
// Note: SCTP settings apply to newly-created PeerConnections only
RTC_EXPORT int rtcSetSctpSettings(const rtcSctpSettings *settings);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -110,14 +110,14 @@ int emplaceTrack(shared_ptr<Track> ptr) {
void erasePeerConnection(int pc) {
std::lock_guard lock(mutex);
if (peerConnectionMap.erase(pc) == 0)
throw std::invalid_argument("PeerConnection ID does not exist");
throw std::invalid_argument("Peer Connection ID does not exist");
userPointerMap.erase(pc);
}
void eraseDataChannel(int dc) {
std::lock_guard lock(mutex);
if (dataChannelMap.erase(dc) == 0)
throw std::invalid_argument("DataChannel ID does not exist");
throw std::invalid_argument("Data Channel ID does not exist");
userPointerMap.erase(dc);
}
@ -140,7 +140,7 @@ shared_ptr<RtcpSrReporter> getRtcpSrReporter(int id) {
if (auto it = rtcpSrReporterMap.find(id); it != rtcpSrReporterMap.end()) {
return it->second;
} else {
throw std::invalid_argument("RtcpSRReporter ID does not exist");
throw std::invalid_argument("RTCP SR reporter ID does not exist");
}
}
@ -154,7 +154,7 @@ shared_ptr<MediaChainableHandler> getMediaChainableHandler(int id) {
if (auto it = rtcpChainableHandlerMap.find(id); it != rtcpChainableHandlerMap.end()) {
return it->second;
} else {
throw std::invalid_argument("RtcpChainableHandler ID does not exist");
throw std::invalid_argument("RTCP chainable handler ID does not exist");
}
}
@ -163,44 +163,31 @@ void emplaceMediaChainableHandler(shared_ptr<MediaChainableHandler> ptr, int tr)
rtcpChainableHandlerMap.emplace(std::make_pair(tr, ptr));
}
shared_ptr<RtpPacketizationConfig> getRTPConfig(int id) {
shared_ptr<RtpPacketizationConfig> getRtpConfig(int id) {
std::lock_guard lock(mutex);
if (auto it = rtpConfigMap.find(id); it != rtpConfigMap.end()) {
return it->second;
} else {
throw std::invalid_argument("RTPConfiguration ID does not exist");
throw std::invalid_argument("RTP configuration ID does not exist");
}
}
void emplaceRTPConfig(shared_ptr<RtpPacketizationConfig> ptr, int tr) {
void emplaceRtpConfig(shared_ptr<RtpPacketizationConfig> ptr, int tr) {
std::lock_guard lock(mutex);
rtpConfigMap.emplace(std::make_pair(tr, ptr));
}
Description::Direction rtcDirectionToDirection(rtcDirection direction) {
switch (direction) {
case RTC_DIRECTION_SENDONLY:
return Description::Direction::SendOnly;
case RTC_DIRECTION_RECVONLY:
return Description::Direction::RecvOnly;
case RTC_DIRECTION_SENDRECV:
return Description::Direction::SendRecv;
case RTC_DIRECTION_INACTIVE:
return Description::Direction::Inactive;
default:
return Description::Direction::Unknown;
}
}
shared_ptr<RtpPacketizationConfig>
getNewRtpPacketizationConfig(uint32_t ssrc, const char *cname, uint8_t payloadType,
uint32_t clockRate, uint16_t sequenceNumber, uint32_t timestamp) {
if (!cname) {
throw std::invalid_argument("Unexpected null pointer for cname");
}
createRtpPacketizationConfig(const rtcPacketizationHandlerInit *init) {
if (!init)
throw std::invalid_argument("Unexpected null pointer for packetization handler init");
return std::make_shared<RtpPacketizationConfig>(ssrc, cname, payloadType, clockRate,
sequenceNumber, timestamp);
if (!init->cname)
throw std::invalid_argument("Unexpected null pointer for cname");
return std::make_shared<RtpPacketizationConfig>(init->ssrc, init->cname, init->payloadType,
init->clockRate, init->sequenceNumber,
init->timestamp);
}
#endif // RTC_ENABLE_MEDIA
@ -390,69 +377,65 @@ int rtcDeleteDataChannel(int dc) {
});
}
#if RTC_ENABLE_MEDIA
int rtcAddTrack(int pc, const char *mediaDescriptionSdp) {
return wrap([&] {
if (!mediaDescriptionSdp)
throw std::invalid_argument("Unexpected null pointer for track media description");
void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid,
const char *_trackID) {
auto peerConnection = getPeerConnection(pc);
Description::Media media{string(mediaDescriptionSdp)};
int tr = emplaceTrack(peerConnection->addTrack(std::move(media)));
if (auto ptr = getUserPointer(pc))
rtcSetUserPointer(tr, *ptr);
optional<string> name = nullopt;
if (_name) {
name = string(_name);
}
optional<string> msid = nullopt;
if (_msid) {
msid = string(_msid);
}
optional<string> trackID = nullopt;
if (_trackID) {
trackID = string(_trackID);
}
description->addSSRC(ssrc, name, msid, trackID);
return tr;
});
}
int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid,
rtcDirection _direction, const char *_name, const char *_msid,
const char *_trackID) {
int rtcAddTrackEx(int pc, const rtcTrackInit *init) {
return wrap([&] {
auto peerConnection = getPeerConnection(pc);
auto direction = rtcDirectionToDirection(_direction);
if (!init)
throw std::invalid_argument("Unexpected null pointer for track init");
string mid = "video";
switch (codec) {
case RTC_CODEC_H264:
case RTC_CODEC_VP8:
case RTC_CODEC_VP9:
mid = "video";
break;
case RTC_CODEC_OPUS:
mid = "audio";
break;
}
auto direction = static_cast<Description::Direction>(init->direction);
if (_mid) {
mid = string(_mid);
string mid;
if (init->mid) {
mid = string(init->mid);
} else {
switch (init->codec) {
case RTC_CODEC_H264:
case RTC_CODEC_VP8:
case RTC_CODEC_VP9:
mid = "video";
break;
case RTC_CODEC_OPUS:
mid = "audio";
break;
default:
mid = "video";
break;
}
}
optional<Description::Media> optDescription = nullopt;
switch (codec) {
switch (init->codec) {
case RTC_CODEC_H264:
case RTC_CODEC_VP8:
case RTC_CODEC_VP9: {
auto desc = Description::Video(mid, direction);
switch (codec) {
switch (init->codec) {
case RTC_CODEC_H264:
desc.addH264Codec(payloadType);
desc.addH264Codec(init->payloadType);
break;
case RTC_CODEC_VP8:
desc.addVP8Codec(payloadType);
desc.addVP8Codec(init->payloadType);
break;
case RTC_CODEC_VP9:
desc.addVP8Codec(payloadType);
desc.addVP8Codec(init->payloadType);
break;
default:
break;
@ -462,9 +445,9 @@ int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const
}
case RTC_CODEC_OPUS: {
auto desc = Description::Audio(mid, direction);
switch (codec) {
switch (init->codec) {
case RTC_CODEC_OPUS:
desc.addOpusCodec(payloadType);
desc.addOpusCodec(init->payloadType);
break;
default:
break;
@ -476,168 +459,16 @@ int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const
break;
}
if (!optDescription.has_value()) {
if (!optDescription)
throw std::invalid_argument("Unexpected codec");
} else {
auto description = optDescription.value();
setSSRC(&description, ssrc, _name, _msid, _trackID);
int tr = emplaceTrack(peerConnection->addTrack(std::move(description)));
if (auto ptr = getUserPointer(pc)) {
rtcSetUserPointer(tr, *ptr);
}
return tr;
}
});
}
auto desc = std::move(*optDescription);
desc.addSSRC(init->ssrc, init->name ? std::make_optional(string(init->name)) : nullopt,
init->msid ? std::make_optional(string(init->msid)) : nullopt,
init->trackId ? std::make_optional(string(init->trackId)) : nullopt);
int rtcSetH264PacketizationHandler(int tr, uint32_t ssrc, const char *cname, uint8_t payloadType,
uint32_t clockRate, uint16_t maxFragmentSize,
uint16_t sequenceNumber, uint32_t timestamp) {
return wrap([&] {
auto track = getTrack(tr);
// create RTP configuration
auto rtpConfig = getNewRtpPacketizationConfig(ssrc, cname, payloadType, clockRate,
sequenceNumber, timestamp);
// create packetizer
auto packetizer = std::make_shared<H264RtpPacketizer>(rtpConfig, maxFragmentSize);
// create H264 handler
auto h264Handler = std::make_shared<H264PacketizationHandler>(packetizer);
emplaceMediaChainableHandler(h264Handler, tr);
emplaceRTPConfig(rtpConfig, tr);
// set handler
track->setMediaHandler(h264Handler);
return RTC_ERR_SUCCESS;
});
}
int tr = emplaceTrack(peerConnection->addTrack(std::move(desc)));
int rtcSetOpusPacketizationHandler(int tr, uint32_t ssrc, const char *cname, uint8_t payloadType,
uint32_t clockRate, uint16_t sequenceNumber,
uint32_t timestamp) {
return wrap([&] {
auto track = getTrack(tr);
// create RTP configuration
auto rtpConfig = getNewRtpPacketizationConfig(ssrc, cname, payloadType, clockRate,
sequenceNumber, timestamp);
// create packetizer
auto packetizer = std::make_shared<OpusRtpPacketizer>(rtpConfig);
// create Opus handler
auto opusHandler = std::make_shared<OpusPacketizationHandler>(packetizer);
emplaceMediaChainableHandler(opusHandler, tr);
emplaceRTPConfig(rtpConfig, tr);
// set handler
track->setMediaHandler(opusHandler);
return RTC_ERR_SUCCESS;
});
}
int rtcChainRtcpSrReporter(int tr) {
return wrap([tr] {
auto config = getRTPConfig(tr);
auto reporter = std::make_shared<RtcpSrReporter>(config);
emplaceRtcpSrReporter(reporter, tr);
auto chainableHandler = getMediaChainableHandler(tr);
chainableHandler->addToChain(reporter);
return RTC_ERR_SUCCESS;
});
}
int rtcChainRtcpNackResponder(int tr, unsigned int maxStoredPacketsCount) {
return wrap([tr, maxStoredPacketsCount] {
auto responder = std::make_shared<RtcpNackResponder>(maxStoredPacketsCount);
auto chainableHandler = getMediaChainableHandler(tr);
chainableHandler->addToChain(responder);
return RTC_ERR_SUCCESS;
});
}
int rtcSetRtpConfigurationStartTime(int id, double startTime_s, bool timeIntervalSince1970,
uint32_t timestamp) {
return wrap([&] {
auto config = getRTPConfig(id);
auto epoch = RtpPacketizationConfig::EpochStart::T1900;
if (timeIntervalSince1970) {
epoch = RtpPacketizationConfig::EpochStart::T1970;
}
config->setStartTime(startTime_s, epoch, timestamp);
return RTC_ERR_SUCCESS;
});
}
int rtcStartRtcpSenderReporterRecording(int id) {
return wrap([id] {
auto sender = getRtcpSrReporter(id);
sender->startRecording();
return RTC_ERR_SUCCESS;
});
}
int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp) {
return wrap([&] {
auto config = getRTPConfig(id);
*timestamp = config->secondsToTimestamp(seconds);
return RTC_ERR_SUCCESS;
});
}
int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds) {
return wrap([&] {
auto config = getRTPConfig(id);
*seconds = config->timestampToSeconds(timestamp);
return RTC_ERR_SUCCESS;
});
}
int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp) {
return wrap([&] {
auto config = getRTPConfig(id);
*timestamp = config->timestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcGetTrackStartTimestamp(int id, uint32_t *timestamp) {
return wrap([&] {
auto config = getRTPConfig(id);
*timestamp = config->startTimestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcSetTrackRTPTimestamp(int id, uint32_t timestamp) {
return wrap([&] {
auto config = getRTPConfig(id);
config->timestamp = timestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timestamp) {
return wrap([&] {
auto sender = getRtcpSrReporter(id);
*timestamp = sender->previousReportedTimestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcSetNeedsToSendRtcpSr(int id) {
return wrap([id] {
auto sender = getRtcpSrReporter(id);
sender->setNeedsToReport();
return RTC_ERR_SUCCESS;
});
}
#endif // RTC_ENABLE_MEDIA
int rtcAddTrack(int pc, const char *mediaDescriptionSdp) {
return wrap([&] {
if (!mediaDescriptionSdp)
throw std::invalid_argument("Unexpected null pointer for track media description");
auto peerConnection = getPeerConnection(pc);
Description::Media media{string(mediaDescriptionSdp)};
int tr = emplaceTrack(peerConnection->addTrack(std::move(media)));
if (auto ptr = getUserPointer(pc))
rtcSetUserPointer(tr, *ptr);
@ -667,39 +498,141 @@ int rtcGetTrackDescription(int tr, char *buffer, int size) {
});
}
int rtcSetSctpSettings(const rtcSctpSettings *settings) {
#if RTC_ENABLE_MEDIA
int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return wrap([&] {
SctpSettings s = {};
if (settings->recvBufferSize > 0)
s.recvBufferSize = size_t(settings->recvBufferSize);
if (settings->sendBufferSize > 0)
s.sendBufferSize = size_t(settings->sendBufferSize);
if (settings->maxChunksOnQueue > 0)
s.maxChunksOnQueue = size_t(settings->maxChunksOnQueue);
if (settings->initialCongestionWindow > 0)
s.initialCongestionWindow = size_t(settings->initialCongestionWindow);
if (settings->maxBurst > 0)
s.maxBurst = size_t(settings->maxBurst);
else if (settings->maxBurst < 0)
s.maxBurst = size_t(0); // setting to 0 disables, not setting chooses optimized default
if (settings->congestionControlModule >= 0)
s.congestionControlModule = unsigned(settings->congestionControlModule);
if (settings->delayedSackTimeMs > 0)
s.delayedSackTime = std::chrono::milliseconds(settings->delayedSackTimeMs);
SetSctpSettings(std::move(s));
auto track = getTrack(tr);
// create RTP configuration
auto rtpConfig = createRtpPacketizationConfig(init);
// create packetizer
auto maxFragmentSize = init && init->maxFragmentSize ? init->maxFragmentSize
: RTC_DEFAULT_MAXIMUM_FRAGMENT_SIZE;
auto packetizer = std::make_shared<H264RtpPacketizer>(rtpConfig, maxFragmentSize);
// create H264 handler
auto h264Handler = std::make_shared<H264PacketizationHandler>(packetizer);
emplaceMediaChainableHandler(h264Handler, tr);
emplaceRtpConfig(rtpConfig, tr);
// set handler
track->setMediaHandler(h264Handler);
return RTC_ERR_SUCCESS;
});
}
int rtcSetOpusPacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
return wrap([&] {
auto track = getTrack(tr);
// create RTP configuration
auto rtpConfig = createRtpPacketizationConfig(init);
// create packetizer
auto packetizer = std::make_shared<OpusRtpPacketizer>(rtpConfig);
// create Opus handler
auto opusHandler = std::make_shared<OpusPacketizationHandler>(packetizer);
emplaceMediaChainableHandler(opusHandler, tr);
emplaceRtpConfig(rtpConfig, tr);
// set handler
track->setMediaHandler(opusHandler);
return RTC_ERR_SUCCESS;
});
}
int rtcChainRtcpSrReporter(int tr) {
return wrap([tr] {
auto config = getRtpConfig(tr);
auto reporter = std::make_shared<RtcpSrReporter>(config);
emplaceRtcpSrReporter(reporter, tr);
auto chainableHandler = getMediaChainableHandler(tr);
chainableHandler->addToChain(reporter);
return RTC_ERR_SUCCESS;
});
}
int rtcChainRtcpNackResponder(int tr, unsigned int maxStoredPacketsCount) {
return wrap([tr, maxStoredPacketsCount] {
auto responder = std::make_shared<RtcpNackResponder>(maxStoredPacketsCount);
auto chainableHandler = getMediaChainableHandler(tr);
chainableHandler->addToChain(responder);
return RTC_ERR_SUCCESS;
});
}
int rtcSetRtpConfigurationStartTime(int id, const rtcStartTime *startTime) {
return wrap([&] {
auto config = getRtpConfig(id);
auto epoch = startTime->since1970 ? RtpPacketizationConfig::EpochStart::T1970
: RtpPacketizationConfig::EpochStart::T1900;
config->setStartTime(startTime->seconds, epoch, startTime->timestamp);
return RTC_ERR_SUCCESS;
});
}
int rtcStartRtcpSenderReporterRecording(int id) {
return wrap([id] {
auto sender = getRtcpSrReporter(id);
sender->startRecording();
return RTC_ERR_SUCCESS;
});
}
int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp) {
return wrap([&] {
auto config = getRtpConfig(id);
*timestamp = config->secondsToTimestamp(seconds);
return RTC_ERR_SUCCESS;
});
}
int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds) {
return wrap([&] {
auto config = getRtpConfig(id);
*seconds = config->timestampToSeconds(timestamp);
return RTC_ERR_SUCCESS;
});
}
int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp) {
return wrap([&] {
auto config = getRtpConfig(id);
*timestamp = config->timestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcGetTrackStartTimestamp(int id, uint32_t *timestamp) {
return wrap([&] {
auto config = getRtpConfig(id);
*timestamp = config->startTimestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcSetTrackRtpTimestamp(int id, uint32_t timestamp) {
return wrap([&] {
auto config = getRtpConfig(id);
config->timestamp = timestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timestamp) {
return wrap([&] {
auto sender = getRtcpSrReporter(id);
*timestamp = sender->previousReportedTimestamp;
return RTC_ERR_SUCCESS;
});
}
int rtcSetNeedsToSendRtcpSr(int id) {
return wrap([id] {
auto sender = getRtcpSrReporter(id);
sender->setNeedsToReport();
return RTC_ERR_SUCCESS;
});
}
#endif // RTC_ENABLE_MEDIA
#if RTC_ENABLE_WEBSOCKET
int rtcCreateWebSocket(const char *url) {
return wrap([&] {
auto ws = std::make_shared<WebSocket>();
@ -732,6 +665,7 @@ int rtcDeleteWebsocket(int ws) {
return RTC_ERR_SUCCESS;
});
}
#endif
int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb) {
@ -1173,4 +1107,37 @@ int rtcReceiveMessage(int id, char *buffer, int *size) {
}
void rtcPreload() { rtc::Preload(); }
void rtcCleanup() { rtc::Cleanup(); }
int rtcSetSctpSettings(const rtcSctpSettings *settings) {
return wrap([&] {
SctpSettings s = {};
if (settings->recvBufferSize > 0)
s.recvBufferSize = size_t(settings->recvBufferSize);
if (settings->sendBufferSize > 0)
s.sendBufferSize = size_t(settings->sendBufferSize);
if (settings->maxChunksOnQueue > 0)
s.maxChunksOnQueue = size_t(settings->maxChunksOnQueue);
if (settings->initialCongestionWindow > 0)
s.initialCongestionWindow = size_t(settings->initialCongestionWindow);
if (settings->maxBurst > 0)
s.maxBurst = size_t(settings->maxBurst);
else if (settings->maxBurst < 0)
s.maxBurst = size_t(0); // setting to 0 disables, not setting chooses optimized default
if (settings->congestionControlModule >= 0)
s.congestionControlModule = unsigned(settings->congestionControlModule);
if (settings->delayedSackTimeMs > 0)
s.delayedSackTime = std::chrono::milliseconds(settings->delayedSackTimeMs);
SetSctpSettings(std::move(s));
return RTC_ERR_SUCCESS;
});
}