Sfoglia il codice sorgente

Add Media Interceptor C API

SE2Dev 3 anni fa
parent
commit
a0982bd891
4 ha cambiato i file con 103 aggiunte e 0 eliminazioni
  1. 8 0
      include/rtc/message.hpp
  2. 16 0
      include/rtc/rtc.h
  3. 70 0
      src/capi.cpp
  4. 9 0
      src/message.cpp

+ 8 - 0
include/rtc/message.hpp

@@ -70,6 +70,14 @@ RTC_CPP_EXPORT message_ptr make_message(binary &&data, Message::Type type = Mess
 
 RTC_CPP_EXPORT message_ptr make_message(message_variant data);
 
+#if RTC_ENABLE_MEDIA
+
+// Reconstructs a message_ptr from an opaque rtcMessage pointer that
+// was allocated by rtcCreateOpaqueMessage().
+message_ptr make_message_from_opaque_ptr(rtcMessage *&&message);
+
+#endif
+
 RTC_CPP_EXPORT message_variant to_variant(Message &&message);
 RTC_CPP_EXPORT message_variant to_variant(const Message &message);
 

+ 16 - 0
include/rtc/rtc.h

@@ -135,6 +135,8 @@ typedef void(RTC_API *rtcOpenCallbackFunc)(int id, void *ptr);
 typedef void(RTC_API *rtcClosedCallbackFunc)(int id, void *ptr);
 typedef void(RTC_API *rtcErrorCallbackFunc)(int id, const char *error, void *ptr);
 typedef void(RTC_API *rtcMessageCallbackFunc)(int id, const char *message, int size, void *ptr);
+typedef void *(RTC_API *rtcInterceptorCallbackFunc)(int pc, const char *message, int size,
+                                                    void *ptr);
 typedef void(RTC_API *rtcBufferedAmountLowCallbackFunc)(int id, void *ptr);
 typedef void(RTC_API *rtcAvailableCallbackFunc)(int id, void *ptr);
 
@@ -303,6 +305,20 @@ typedef struct {
 	const char *trackId; // optional, track ID used in MSID
 } rtcSsrcForTypeInit;
 
+// Opaque message
+
+// Opaque type used (via rtcMessage*) to reference an rtc::Message
+typedef void* rtcMessage;
+
+// Allocate a new opaque message.
+// Must be explicitly freed by rtcDeleteOpaqueMessage() unless
+// explicitly returned by a media interceptor callback;
+RTC_EXPORT rtcMessage *rtcCreateOpaqueMessage(void *data, int size);
+RTC_EXPORT void rtcDeleteOpaqueMessage(rtcMessage *msg);
+
+// Set MediaInterceptor for peer connection
+RTC_EXPORT int rtcSetMediaInterceptorCallback(int id, rtcInterceptorCallbackFunc cb);
+
 // Set H264PacketizationHandler for track
 RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init);
 

+ 70 - 0
src/capi.cpp

@@ -281,6 +281,43 @@ createRtpPacketizationConfig(const rtcPacketizationHandlerInit *init) {
 	                                                init->timestamp);
 }
 
+class MediaInterceptor final : public MediaHandler {
+public:
+	using MessageCallback = std::function<void *(void *data, int size)>;
+
+	MediaInterceptor(MessageCallback cb) : incomingCallback(cb) {}
+
+	// Called when there is traffic coming from the peer
+	message_ptr incoming(message_ptr msg) override {
+		// If no callback is provided, just forward the message on
+		if (!incomingCallback) {
+			return msg;
+		}
+
+		auto res = incomingCallback(reinterpret_cast<void *>(msg->data()), msg->size());
+
+		// If a null pointer was returned, drop the incoming message
+		if (res == nullptr) {
+			return nullptr;
+		}
+
+		// If the original data pointer was returned, forward the incoming message
+		if (res == msg->data()) {
+			return msg;
+		}
+
+		// Construct a true message_ptr from the returned opaque pointer
+		return make_message_from_opaque_ptr(std::move(reinterpret_cast<rtcMessage *>(res)));
+	};
+
+	// Called when there is traffic that needs to be sent to the peer
+	// This is a no-op for media interceptors
+	message_ptr outgoing(message_ptr ptr) override { return ptr; };
+
+private:
+	MessageCallback incomingCallback;
+};
+
 #endif // RTC_ENABLE_MEDIA
 
 #if RTC_ENABLE_WEBSOCKET
@@ -1064,6 +1101,39 @@ void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name,
 	description->addSSRC(ssrc, name, msid, trackID);
 }
 
+rtcMessage *rtcCreateOpaqueMessage(void *data, int size) {
+	auto src = reinterpret_cast<std::byte *>(data);
+	auto msg = new Message(src, src + size);
+	// Downgrade the message pointer to the opaque rtcMessage* type
+	return reinterpret_cast<rtcMessage *>(msg);
+}
+
+void rtcDeleteOpaqueMessage(rtcMessage *msg) {
+	// Cast the opaque pointer back to it's true type before deleting
+	delete reinterpret_cast<Message *>(msg);
+}
+
+int rtcSetMediaInterceptorCallback(int pc, rtcInterceptorCallbackFunc cb) {
+	return wrap([&] {
+		auto peerConnection = getPeerConnection(pc);
+
+		if (cb == nullptr) {
+			peerConnection->setMediaHandler(nullptr);
+			return RTC_ERR_SUCCESS;
+		}
+
+		auto interceptor = std::make_shared<MediaInterceptor>([pc, cb](void *data, int size) {
+			if (auto ptr = getUserPointer(pc))
+				return cb(pc, reinterpret_cast<const char *>(data), size, *ptr);
+			return data;
+		});
+
+		peerConnection->setMediaHandler(interceptor);
+
+		return RTC_ERR_SUCCESS;
+	});
+}
+
 int rtcSetH264PacketizationHandler(int tr, const rtcPacketizationHandlerInit *init) {
 	return wrap([&] {
 		auto track = getTrack(tr);

+ 9 - 0
src/message.cpp

@@ -48,6 +48,15 @@ message_ptr make_message(message_variant data) {
 	    std::move(data));
 }
 
+#if RTC_ENABLE_MEDIA
+
+message_ptr make_message_from_opaque_ptr(rtcMessage *&&message) {
+	auto ptr = std::unique_ptr<Message>(reinterpret_cast<Message *>(message));
+	return message_ptr(std::move(ptr));
+}
+
+#endif
+
 message_variant to_variant(Message &&message) {
 	switch (message.type) {
 	case Message::String: