mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-08-22 15:15:28 +00:00
Improve capi for ssrc manipulation
This commit is contained in:
@ -150,6 +150,7 @@ public:
|
|||||||
optional<string> msid = nullopt, optional<string> trackID = nullopt);
|
optional<string> msid = nullopt, optional<string> trackID = nullopt);
|
||||||
bool hasSSRC(uint32_t ssrc);
|
bool hasSSRC(uint32_t ssrc);
|
||||||
std::vector<uint32_t> getSSRCs();
|
std::vector<uint32_t> getSSRCs();
|
||||||
|
std::optional<std::string> getCNameForSsrc(uint32_t ssrc);
|
||||||
|
|
||||||
void setBitrate(int bitrate);
|
void setBitrate(int bitrate);
|
||||||
int getBitrate() const;
|
int getBitrate() const;
|
||||||
|
@ -206,6 +206,7 @@ RTC_EXPORT int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb);
|
|||||||
RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
|
RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
|
||||||
RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label,
|
RTC_EXPORT int rtcCreateDataChannelEx(int pc, const char *label,
|
||||||
const rtcDataChannelInit *init); // returns dc id
|
const rtcDataChannelInit *init); // returns dc id
|
||||||
|
RTC_EXPORT int rtcIsDataChannelOpen(int dc);
|
||||||
RTC_EXPORT int rtcDeleteDataChannel(int dc);
|
RTC_EXPORT int rtcDeleteDataChannel(int dc);
|
||||||
|
|
||||||
RTC_EXPORT int rtcGetDataChannelStream(int dc);
|
RTC_EXPORT int rtcGetDataChannelStream(int dc);
|
||||||
@ -254,6 +255,13 @@ typedef struct {
|
|||||||
uint32_t timestamp; // Start timestamp
|
uint32_t timestamp; // Start timestamp
|
||||||
} rtcStartTime;
|
} rtcStartTime;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t ssrc;
|
||||||
|
const char *name; // optional
|
||||||
|
const char *msid; // optional
|
||||||
|
const char *trackId; // optional, track ID used in MSID
|
||||||
|
} rtcSsrcForTypeInit;
|
||||||
|
|
||||||
// Set H264PacketizationHandler for track
|
// Set H264PacketizationHandler for track
|
||||||
RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init);
|
RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init);
|
||||||
|
|
||||||
@ -298,6 +306,22 @@ RTC_EXPORT int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timest
|
|||||||
// Set NeedsToReport flag in RtcpSrReporter handler identified by given track id
|
// Set NeedsToReport flag in RtcpSrReporter handler identified by given track id
|
||||||
RTC_EXPORT int rtcSetNeedsToSendRtcpSr(int id);
|
RTC_EXPORT int rtcSetNeedsToSendRtcpSr(int id);
|
||||||
|
|
||||||
|
/// Get all available payload types for given codec and stores them in buffer, does nothing if buffer is NULL
|
||||||
|
int rtcGetTrackPayloadTypesForCodec(int tr, const char * ccodec, int * buffer, int size);
|
||||||
|
|
||||||
|
/// Get all SSRCs for given track
|
||||||
|
int rtcGetSsrcsForTrack(int tr, uint32_t * buffer, int bufferSize);
|
||||||
|
|
||||||
|
/// Get CName for SSRC
|
||||||
|
int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char * cname, int cnameSize);
|
||||||
|
|
||||||
|
/// Get all SSRCs for given media type in given SDP
|
||||||
|
/// @param mediaType Media type (audio/video)
|
||||||
|
int rtcGetSsrcsForType(const char * mediaType, const char * sdp, uint32_t * buffer, int bufferSize);
|
||||||
|
|
||||||
|
/// Set SSRC for given media type in given SDP
|
||||||
|
int rtcSetSsrcForType(const char * mediaType, const char * sdp, char * buffer, const int bufferSize, rtcSsrcForTypeInit * init);
|
||||||
|
|
||||||
#endif // RTC_ENABLE_MEDIA
|
#endif // RTC_ENABLE_MEDIA
|
||||||
|
|
||||||
#if RTC_ENABLE_WEBSOCKET
|
#if RTC_ENABLE_WEBSOCKET
|
||||||
|
148
src/capi.cpp
148
src/capi.cpp
@ -268,6 +268,21 @@ int copyAndReturn(binary b, char *buffer, int size) {
|
|||||||
return int(b.size());
|
return int(b.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int copyAndReturn(std::vector<T> b, T *buffer, int size) {
|
||||||
|
if (!buffer)
|
||||||
|
return int(b.size());
|
||||||
|
|
||||||
|
if (size < int(b.size()))
|
||||||
|
return RTC_ERR_TOO_SMALL;
|
||||||
|
memcpy(buffer, b.data(), size * sizeof(*buffer));
|
||||||
|
return int(b.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
string lowercased(string str) {
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||||
|
return str;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb) {
|
void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb) {
|
||||||
@ -365,6 +380,12 @@ int rtcCreateDataChannelEx(int pc, const char *label, const rtcDataChannelInit *
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtcIsDataChannelOpen(int dc) {
|
||||||
|
return wrap([dc] {
|
||||||
|
return getDataChannel(dc)->isOpen() ? RTC_ERR_SUCCESS : RTC_ERR_FAILURE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
int rtcDeleteDataChannel(int dc) {
|
int rtcDeleteDataChannel(int dc) {
|
||||||
return wrap([dc] {
|
return wrap([dc] {
|
||||||
auto dataChannel = getDataChannel(dc);
|
auto dataChannel = getDataChannel(dc);
|
||||||
@ -380,6 +401,34 @@ int rtcDeleteDataChannel(int dc) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtcIsDataChannelOpen(int dc) {
|
||||||
|
return wrap([dc] {
|
||||||
|
return getDataChannel(dc)->isOpen() ? RTC_ERR_SUCCESS : RTC_ERR_FAILURE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RTC_ENABLE_MEDIA
|
||||||
|
|
||||||
|
void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid, const char *_trackID) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
int rtcAddTrack(int pc, const char *mediaDescriptionSdp) {
|
int rtcAddTrack(int pc, const char *mediaDescriptionSdp) {
|
||||||
return wrap([&] {
|
return wrap([&] {
|
||||||
if (!mediaDescriptionSdp)
|
if (!mediaDescriptionSdp)
|
||||||
@ -503,6 +552,26 @@ int rtcGetTrackDescription(int tr, char *buffer, int size) {
|
|||||||
|
|
||||||
#if RTC_ENABLE_MEDIA
|
#if RTC_ENABLE_MEDIA
|
||||||
|
|
||||||
|
void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid, const char *_trackID) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
|
int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
|
||||||
return wrap([&] {
|
return wrap([&] {
|
||||||
auto track = getTrack(tr);
|
auto track = getTrack(tr);
|
||||||
@ -633,6 +702,23 @@ int rtcSetNeedsToSendRtcpSr(int id) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtcGetTrackPayloadTypesForCodec(int tr, const char * ccodec, int * buffer, int size) {
|
||||||
|
return wrap([&] {
|
||||||
|
auto track = getTrack(tr);
|
||||||
|
auto codec = lowercased(string(ccodec));
|
||||||
|
auto description = track->description();
|
||||||
|
std::vector<int> payloadTypes{};
|
||||||
|
payloadTypes.reserve(std::max(size, 0));
|
||||||
|
for (auto it = description.beginMaps(); it != description.endMaps(); it++) {
|
||||||
|
auto element = *it;
|
||||||
|
if (lowercased(element.second.format) == codec) {
|
||||||
|
payloadTypes.push_back(element.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return copyAndReturn(payloadTypes, buffer, size);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#endif // RTC_ENABLE_MEDIA
|
#endif // RTC_ENABLE_MEDIA
|
||||||
#if RTC_ENABLE_WEBSOCKET
|
#if RTC_ENABLE_WEBSOCKET
|
||||||
|
|
||||||
@ -784,6 +870,68 @@ int rtcSetLocalDescription(int pc, const char *type) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtcGetSsrcsForTrack(int tr, uint32_t * buffer, int bufferSize) {
|
||||||
|
return wrap([&] {
|
||||||
|
auto track = getTrack(tr);
|
||||||
|
auto ssrcs = track->description().getSSRCs();
|
||||||
|
return copyAndReturn(ssrcs, buffer, bufferSize);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char * cname, int cnameSize) {
|
||||||
|
return wrap([&] {
|
||||||
|
auto track = getTrack(tr);
|
||||||
|
auto description = track->description();
|
||||||
|
auto optCName = description.getCNameForSsrc(ssrc);
|
||||||
|
if (optCName.has_value()) {
|
||||||
|
return copyAndReturn(optCName.value(), cname, cnameSize);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtcGetSsrcsForType(const char * mediaType, const char * sdp, uint32_t * buffer, int bufferSize) {
|
||||||
|
return wrap([&] {
|
||||||
|
auto type = lowercased(string(mediaType));
|
||||||
|
auto oldSDP = string(sdp);
|
||||||
|
auto description = Description(oldSDP, "unspec");
|
||||||
|
auto mediaCount = description.mediaCount();
|
||||||
|
for (auto i = 0; i < mediaCount; i++) {
|
||||||
|
if (std::holds_alternative<Description::Media *>(description.media(i))) {
|
||||||
|
auto media = std::get<Description::Media *>(description.media(i));
|
||||||
|
auto currentMediaType = lowercased(media->type());
|
||||||
|
if (currentMediaType == type) {
|
||||||
|
auto ssrcs = media->getSSRCs();
|
||||||
|
return copyAndReturn(ssrcs, buffer, bufferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtcSetSsrcForType(const char * mediaType, const char * sdp, char * buffer, const int bufferSize,
|
||||||
|
rtcSsrcForTypeInit * init) {
|
||||||
|
return wrap([&] {
|
||||||
|
auto type = lowercased(string(mediaType));
|
||||||
|
auto prevSDP = string(sdp);
|
||||||
|
auto description = Description(prevSDP, "unspec");
|
||||||
|
auto mediaCount = description.mediaCount();
|
||||||
|
for (auto i = 0; i < mediaCount; i++) {
|
||||||
|
if (std::holds_alternative<Description::Media *>(description.media(i))) {
|
||||||
|
auto media = std::get<Description::Media *>(description.media(i));
|
||||||
|
auto currentMediaType = lowercased(media->type());
|
||||||
|
if (currentMediaType == type) {
|
||||||
|
setSSRC(media, init->ssrc, init->name, init->msid, init->trackId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return copyAndReturn(string(description), buffer, bufferSize);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
int rtcSetRemoteDescription(int pc, const char *sdp, const char *type) {
|
int rtcSetRemoteDescription(int pc, const char *sdp, const char *type) {
|
||||||
return wrap([&] {
|
return wrap([&] {
|
||||||
auto peerConnection = getPeerConnection(pc);
|
auto peerConnection = getPeerConnection(pc);
|
||||||
|
@ -858,7 +858,11 @@ void Description::Media::parseSdpLine(string_view line) {
|
|||||||
} else if (key == "rtcp-mux") {
|
} else if (key == "rtcp-mux") {
|
||||||
// always added
|
// always added
|
||||||
} else if (key == "ssrc") {
|
} else if (key == "ssrc") {
|
||||||
mSsrcs.emplace_back(to_integer<uint32_t>(value));
|
auto ssrc = to_integer<uint32_t>(value);
|
||||||
|
if (!hasSSRC(ssrc)) {
|
||||||
|
mSsrcs.emplace_back(ssrc);
|
||||||
|
}
|
||||||
|
mAttributes.emplace_back(attr);
|
||||||
} else {
|
} else {
|
||||||
Entry::parseSdpLine(line);
|
Entry::parseSdpLine(line);
|
||||||
}
|
}
|
||||||
@ -875,6 +879,15 @@ void Description::Media::addRTPMap(const Description::Media::RTPMap &map) {
|
|||||||
|
|
||||||
std::vector<uint32_t> Description::Media::getSSRCs() { return mSsrcs; }
|
std::vector<uint32_t> Description::Media::getSSRCs() { return mSsrcs; }
|
||||||
|
|
||||||
|
std::optional<std::string> Description::Media::getCNameForSsrc(uint32_t ssrc) {
|
||||||
|
for (auto &val : mAttributes) {
|
||||||
|
if (val.find("ssrc:") == 0 && val.find("cname:") != std::string::npos) {
|
||||||
|
return val.substr(val.find("cname:") + 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
std::map<int, Description::Media::RTPMap>::iterator Description::Media::beginMaps() {
|
std::map<int, Description::Media::RTPMap>::iterator Description::Media::beginMaps() {
|
||||||
return mRtpMap.begin();
|
return mRtpMap.begin();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user