Browse Source

Improve capi for ssrc manipulation

Filip Klembara 4 years ago
parent
commit
c5e4b972c2
4 changed files with 187 additions and 1 deletions
  1. 1 0
      include/rtc/description.hpp
  2. 24 0
      include/rtc/rtc.h
  3. 148 0
      src/capi.cpp
  4. 14 1
      src/description.cpp

+ 1 - 0
include/rtc/description.hpp

@@ -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;

+ 24 - 0
include/rtc/rtc.h

@@ -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 rtcIsDataChannelOpen(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 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
 
 #if RTC_ENABLE_WEBSOCKET

+ 148 - 0
src/capi.cpp

@@ -268,6 +268,21 @@ 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;
+	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
 
 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) {
 	return wrap([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) {
 	return wrap([&] {
 		if (!mediaDescriptionSdp)
@@ -503,6 +552,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 +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
 #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) {
 	return wrap([&] {
 		auto peerConnection = getPeerConnection(pc);

+ 14 - 1
src/description.cpp

@@ -858,7 +858,11 @@ 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);
+			}
+			mAttributes.emplace_back(attr);
 		} else {
 			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::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() {
 	return mRtpMap.begin();
 }