소스 검색

Added support to route RTCP packets with SSRC=1's to the right client

Staz M 4 년 전
부모
커밋
fcb8d7b3df
4개의 변경된 파일81개의 추가작업 그리고 33개의 파일을 삭제
  1. 1 0
      include/rtc/peerconnection.hpp
  2. 9 5
      include/rtc/rtp.hpp
  3. 69 26
      src/peerconnection.cpp
  4. 2 2
      src/rtcp.cpp

+ 1 - 0
include/rtc/peerconnection.hpp

@@ -123,6 +123,7 @@ private:
 	void forwardMessage(message_ptr message);
 	void forwardMedia(message_ptr message);
 	void forwardBufferedAmount(uint16_t stream, size_t amount);
+    std::optional<std::string> getMidFromSSRC(SSRC ssrc);
 
 	std::shared_ptr<DataChannel> emplaceDataChannel(Description::Role role, string label,
 	                                                string protocol, Reliability reliability);

+ 9 - 5
include/rtc/rtp.hpp

@@ -265,7 +265,7 @@ public:
 
 struct RTCP_RR {
     RTCP_HEADER header;
-    SSRC senderSSRC;
+    SSRC _senderSSRC;
 
 private:
     RTCP_ReportBlock _reportBlocks;
@@ -274,8 +274,8 @@ public:
     inline RTCP_ReportBlock *getReportBlock(int num) { return &_reportBlocks + num; }
     inline const RTCP_ReportBlock *getReportBlock(int num) const { return &_reportBlocks + num; }
 
-    inline SSRC getSenderSSRC() const { return ntohl(senderSSRC); }
-    inline void setSenderSSRC(SSRC ssrc) { this->senderSSRC = htonl(ssrc); }
+    inline SSRC senderSSRC() const { return ntohl(_senderSSRC); }
+    inline void setSenderSSRC(SSRC ssrc) { this->_senderSSRC = htonl(ssrc); }
 
     [[nodiscard]] inline size_t getSize() const {
         // "length" in packet is one less than the number of 32 bit words in the packet.
@@ -286,17 +286,21 @@ public:
         // "length" in packet is one less than the number of 32 bit words in the packet.
         size_t length = (sizeWithReportBlocks(reportCount) / 4) - 1;
         header.prepareHeader(201, reportCount, uint16_t(length));
-        this->senderSSRC = htonl(senderSSRC);
+        this->_senderSSRC = htonl(senderSSRC);
     }
 
     inline static size_t sizeWithReportBlocks(uint8_t reportCount) {
         return sizeof(header) + 4 + size_t(reportCount) * sizeof(RTCP_ReportBlock);
     }
 
+    inline bool isReceiverReport() {
+        return header.payloadType() == 201;
+    }
+
     inline void log() const {
         header.log();
         PLOG_VERBOSE << "RTCP RR: "
-                   << " SSRC=" << ntohl(senderSSRC);
+                   << " SSRC=" << ntohl(_senderSSRC);
 
         for (unsigned i = 0; i < unsigned(header.reportCount()); i++) {
             getReportBlock(i)->log();

+ 69 - 26
src/peerconnection.cpp

@@ -550,32 +550,30 @@ void PeerConnection::forwardMedia(message_ptr message) {
 		return;
 
 	unsigned int ssrc = message->stream;
-	std::optional<string> mid;
-	if (auto it = mMidFromSssrc.find(ssrc); it != mMidFromSssrc.end()) {
-		mid = it->second;
-	} else {
-		std::lock_guard lock(mLocalDescriptionMutex);
-		if (!mLocalDescription)
-			return;
-
-		for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
-			if (auto found = std::visit(
-			        rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
-				                        return std::nullopt;
-			                        },
-			                        [&](Description::Media *media) -> std::optional<string> {
-				                        return media->hasSSRC(ssrc)
-				                                   ? std::make_optional(media->mid())
-				                                   : nullopt;
-			                        }},
-                    mRemoteDescription->media(i))) {
-
-				mMidFromSssrc.emplace(ssrc, *found);
-				mid = *found;
-				break;
-			}
-		}
-	}
+	std::optional<string> mid = getMidFromSSRC(ssrc);
+
+	// Because chrome likes to send all report blocks as SSRC=1
+	// we have to do this monstrosity to distribute the report blocks
+    if (!mid && message->type == Message::Control) {
+        RTCP_RR* sr = (RTCP_RR*) message->data();
+        if (sr->senderSSRC() == 1 && sr->isReceiverReport()) {
+        bool hasFound = false;
+            for (int i = 0; i < sr->header.reportCount(); i++) {
+                auto block = sr->getReportBlock(i);
+                auto ssrc = block->getSSRC();
+                auto mid = getMidFromSSRC(ssrc);
+                if (mid.has_value()) {
+                    hasFound = true;
+                    std::shared_lock lock(mTracksMutex); // read-only
+                    if (auto it = mTracks.find(*mid); it != mTracks.end())
+                        if (auto track = it->second.lock())
+                            track->incoming(message);
+                }
+            }
+            if (hasFound)
+                return;
+        }
+    }
 
 	if (!mid) {
 		PLOG_WARNING << "Track not found for SSRC " << ssrc << ", dropping";
@@ -588,6 +586,51 @@ void PeerConnection::forwardMedia(message_ptr message) {
 			track->incoming(message);
 }
 
+std::optional<std::string> PeerConnection::getMidFromSSRC(SSRC ssrc) {
+    if (auto it = mMidFromSssrc.find(ssrc); it != mMidFromSssrc.end()) {
+        return it->second;
+    } else {
+        std::lock_guard lock(mLocalDescriptionMutex);
+        if (!mLocalDescription)
+            return nullopt;
+
+        for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
+            if (auto found = std::visit(
+                    rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
+                        return std::nullopt;
+                    },
+                                    [&](Description::Media *media) -> std::optional<string> {
+                                        return media->hasSSRC(ssrc)
+                                               ? std::make_optional(media->mid())
+                                               : nullopt;
+                                    }},
+                    mRemoteDescription->media(i))) {
+
+                mMidFromSssrc.emplace(ssrc, *found);
+                return *found;
+            }
+        }
+
+        for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) {
+            if (auto found = std::visit(
+                    rtc::overloaded{[&](Description::Application *) -> std::optional<string> {
+                        return std::nullopt;
+                    },
+                                    [&](Description::Media *media) -> std::optional<string> {
+                                        return media->hasSSRC(ssrc)
+                                               ? std::make_optional(media->mid())
+                                               : nullopt;
+                                    }},
+                    mLocalDescription->media(i))) {
+
+                mMidFromSssrc.emplace(ssrc, *found);
+                return *found;
+            }
+        }
+    }
+    return nullopt;
+}
+
 void PeerConnection::forwardBufferedAmount(uint16_t stream, size_t amount) {
 	if (auto channel = findDataChannel(stream))
 		channel->triggerBufferedAmount(amount);

+ 2 - 2
src/rtcp.cpp

@@ -66,11 +66,11 @@ rtc::message_ptr RtcpReceivingSession::incoming(rtc::message_ptr ptr) {
 	auto rr = reinterpret_cast<const RTCP_RR *>(ptr->data());
 	if (rr->header.payloadType() == 201) {
 		// RR
-		mSsrc = rr->getSenderSSRC();
+		mSsrc = rr->senderSSRC();
 		rr->log();
 	} else if (rr->header.payloadType() == 200) {
 		// SR
-		mSsrc = rr->getSenderSSRC();
+		mSsrc = rr->senderSSRC();
 		auto sr = reinterpret_cast<const RTCP_SR *>(ptr->data());
 		mSyncRTPTS = sr->rtpTimestamp();
 		mSyncNTPTS = sr->ntpTimestamp();