Merge pull request #431 from in2core/feature/improve-capi-sscr

Improve capi for ssrc manipulation
This commit is contained in:
Paul-Louis Ageneau
2021-06-03 13:06:42 +02:00
committed by GitHub
4 changed files with 171 additions and 3 deletions

View File

@ -150,6 +150,7 @@ public:
optional<string> msid = nullopt, optional<string> trackID = nullopt);
bool hasSSRC(uint32_t ssrc);
std::vector<uint32_t> getSSRCs();
std::optional<std::string> getCNameForSsrc(uint32_t ssrc);
void setBitrate(int bitrate);
int getBitrate() const;
@ -195,6 +196,7 @@ public:
std::map<int, RTPMap> mRtpMap;
std::vector<uint32_t> mSsrcs;
std::map<uint32_t, string> mCNameMap;
public:
void addRTPMap(const RTPMap &map);

View File

@ -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 rtcCreateDataChannelEx(int pc, const char *label,
const rtcDataChannelInit *init); // returns dc id
RTC_EXPORT int rtcIsOpen(int dc);
RTC_EXPORT int rtcDeleteDataChannel(int dc);
RTC_EXPORT int rtcGetDataChannelStream(int dc);
@ -254,6 +255,13 @@ typedef struct {
uint32_t timestamp; // Start timestamp
} 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
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
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 count);
/// 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
#if RTC_ENABLE_WEBSOCKET

View File

@ -268,6 +268,24 @@ int copyAndReturn(binary b, char *buffer, int 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;
std::copy(b.begin(), b.end(), buffer);
return int(b.size());
}
#if RTC_ENABLE_MEDIA
// function is used in RTC_ENABLE_MEDIA only
string lowercased(string str) {
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });
return str;
}
#endif // RTC_ENABLE_MEDIA
} // namespace
void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb) {
@ -365,6 +383,12 @@ int rtcCreateDataChannelEx(int pc, const char *label, const rtcDataChannelInit *
});
}
int rtcIsOpen(int cid) {
return wrap([cid] {
return getChannel(cid)->isOpen();
});
}
int rtcDeleteDataChannel(int dc) {
return wrap([dc] {
auto dataChannel = getDataChannel(dc);
@ -503,6 +527,26 @@ int rtcGetTrackDescription(int tr, char *buffer, int size) {
#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) {
return wrap([&] {
auto track = getTrack(tr);
@ -633,6 +677,85 @@ 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);
});
}
int rtcGetSsrcsForTrack(int tr, uint32_t * buffer, int count) {
return wrap([&] {
auto track = getTrack(tr);
auto ssrcs = track->description().getSSRCs();
return copyAndReturn(ssrcs, buffer, count);
});
}
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 (unsigned int 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 (unsigned int 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);
});
}
#endif // RTC_ENABLE_MEDIA
#if RTC_ENABLE_WEBSOCKET

View File

@ -556,10 +556,12 @@ Description::Entry::removeAttribute(std::vector<string>::iterator it) {
void Description::Media::addSSRC(uint32_t ssrc, optional<string> name, optional<string> msid,
optional<string> trackID) {
if (name)
if (name) {
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
else
mCNameMap.emplace(ssrc, *name);
} else {
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
}
if (msid)
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " +
@ -858,7 +860,16 @@ void Description::Media::parseSdpLine(string_view line) {
} else if (key == "rtcp-mux") {
// always added
} 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);
}
auto cnamePos = value.find("cname:");
if (cnamePos != std::string::npos) {
auto cname = value.substr(cnamePos + 6);
mCNameMap.emplace(ssrc, cname);
}
mAttributes.emplace_back(attr);
} else {
Entry::parseSdpLine(line);
}
@ -875,6 +886,14 @@ void Description::Media::addRTPMap(const Description::Media::RTPMap &map) {
std::vector<uint32_t> Description::Media::getSSRCs() { return mSsrcs; }
std::optional<std::string> Description::Media::getCNameForSsrc(uint32_t ssrc) {
auto it = mCNameMap.find(ssrc);
if (it != mCNameMap.end()) {
return it->second;
}
return std::nullopt;
}
std::map<int, Description::Media::RTPMap>::iterator Description::Media::beginMaps() {
return mRtpMap.begin();
}