mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-08-22 15:15:28 +00:00
Merge pull request #416 from paullouisageneau/cleanup-api
Refactor C media API
This commit is contained in:
@ -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);
|
||||
|
@ -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
|
||||
|
481
src/capi.cpp
481
src/capi.cpp
@ -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;
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user