diff --git a/erizo/src/erizo/WebRtcConnection.cpp b/erizo/src/erizo/WebRtcConnection.cpp index c819436c2a..253eecdb9a 100644 --- a/erizo/src/erizo/WebRtcConnection.cpp +++ b/erizo/src/erizo/WebRtcConnection.cpp @@ -470,22 +470,46 @@ void WebRtcConnection::onCandidate(const CandidateInfo& cand, Transport *transpo } } +void WebRtcConnection::onRtcpFromTransport(std::shared_ptr packet, Transport *transport) { + RtpUtils::forEachRtcpBlock(packet, [this, packet, transport](RtcpHeader *chead) { + uint32_t ssrc = chead->isFeedback() ? chead->getSourceSSRC() : chead->getSSRC(); + std::shared_ptr rtcp = std::make_shared(*packet); + rtcp->length = (ntohs(chead->length) + 1) * 4; + std::memcpy(rtcp->data, chead, rtcp->length); + forEachMediaStream([rtcp, transport, ssrc, chead] (const std::shared_ptr &media_stream) { + if (chead->isREMB()) { + for (uint8_t index = 0; index < chead->getREMBNumSSRC(); index++) { + uint32_t ssrc_feed = chead->getREMBFeedSSRC(index); + if (media_stream->isSourceSSRC(ssrc_feed) || media_stream->isSinkSSRC(ssrc_feed)) { + // TODO(javier): Calculate the portion of bitrate that corresponds to this stream. + media_stream->onTransportData(rtcp, transport); + } + } + } else if (media_stream->isSourceSSRC(ssrc) || media_stream->isSinkSSRC(ssrc)) { + media_stream->onTransportData(rtcp, transport); + } + }); + }); +} + void WebRtcConnection::onTransportData(std::shared_ptr packet, Transport *transport) { if (getCurrentState() != CONN_READY) { return; } char* buf = packet->data; - RtpHeader *head = reinterpret_cast (buf); RtcpHeader *chead = reinterpret_cast (buf); - uint32_t ssrc = head->getSSRC(); - if (chead->isRtcp() && chead->packettype != RTCP_Sender_PT) { // Sender Report - ssrc = chead->getSourceSSRC(); + if (chead->isRtcp()) { + onRtcpFromTransport(packet, transport); + return; + } else { + RtpHeader *head = reinterpret_cast (buf); + uint32_t ssrc = head->getSSRC(); + forEachMediaStream([packet, transport, ssrc] (const std::shared_ptr &media_stream) { + if (media_stream->isSourceSSRC(ssrc) || media_stream->isSinkSSRC(ssrc)) { + media_stream->onTransportData(packet, transport); + } + }); } - forEachMediaStream([packet, transport, ssrc] (const std::shared_ptr &media_stream) { - if (media_stream->isSourceSSRC(ssrc) || media_stream->isSinkSSRC(ssrc)) { - media_stream->onTransportData(packet, transport); - } - }); } void WebRtcConnection::asyncTask(std::function)> f) { diff --git a/erizo/src/erizo/WebRtcConnection.h b/erizo/src/erizo/WebRtcConnection.h index af52533798..686a2a236e 100644 --- a/erizo/src/erizo/WebRtcConnection.h +++ b/erizo/src/erizo/WebRtcConnection.h @@ -158,6 +158,7 @@ class WebRtcConnection: public TransportListener, public LogContext, void onRemoteSdpsSetToMediaStreams(std::string stream_id); std::string getJSONCandidate(const std::string& mid, const std::string& sdp); void trackTransportInfo(); + void onRtcpFromTransport(std::shared_ptr packet, Transport *transport); private: std::string connection_id_; diff --git a/erizo/src/erizo/rtp/BandwidthEstimationHandler.cpp b/erizo/src/erizo/rtp/BandwidthEstimationHandler.cpp index 8c31085e37..a9666e0d74 100644 --- a/erizo/src/erizo/rtp/BandwidthEstimationHandler.cpp +++ b/erizo/src/erizo/rtp/BandwidthEstimationHandler.cpp @@ -227,7 +227,7 @@ void BandwidthEstimationHandler::sendREMBPacket() { ELOG_DEBUG("Bitrates min(%u,%u) = %u", bitrate_, max_video_bw_, capped_bitrate); remb_packet_.setREMBBitRate(capped_bitrate); remb_packet_.setREMBNumSSRC(1); - remb_packet_.setREMBFeedSSRC(stream_->getVideoSourceSSRC()); + remb_packet_.setREMBFeedSSRC(0, stream_->getVideoSourceSSRC()); int remb_length = (remb_packet_.getLength() + 1) * 4; if (active_) { ELOG_DEBUG("BWE Estimation is %d", last_send_bitrate_); diff --git a/erizo/src/erizo/rtp/QualityFilterHandler.cpp b/erizo/src/erizo/rtp/QualityFilterHandler.cpp index aa7c2a22dc..c22d225c03 100644 --- a/erizo/src/erizo/rtp/QualityFilterHandler.cpp +++ b/erizo/src/erizo/rtp/QualityFilterHandler.cpp @@ -29,7 +29,7 @@ void QualityFilterHandler::disable() { } void QualityFilterHandler::handleFeedbackPackets(const std::shared_ptr &packet) { - RtpUtils::forEachRRBlock(packet, [this](RtcpHeader *chead) { + RtpUtils::forEachRtcpBlock(packet, [this](RtcpHeader *chead) { if (chead->packettype == RTCP_PS_Feedback_PT && (chead->getBlockCount() == RTCP_PLI_FMT || chead->getBlockCount() == RTCP_SLI_FMT || diff --git a/erizo/src/erizo/rtp/RtcpAggregator.cpp b/erizo/src/erizo/rtp/RtcpAggregator.cpp index 34457ca8c6..4837f440f8 100644 --- a/erizo/src/erizo/rtp/RtcpAggregator.cpp +++ b/erizo/src/erizo/rtp/RtcpAggregator.cpp @@ -384,7 +384,7 @@ int RtcpAggregator::addREMB(char* buf, int len, uint32_t bitrate) { theREMB.setLength(5); theREMB.setREMBBitRate(bitrate); theREMB.setREMBNumSSRC(1); - theREMB.setREMBFeedSSRC(rtcpSource_->getVideoSourceSSRC()); + theREMB.setREMBFeedSSRC(0, rtcpSource_->getVideoSourceSSRC()); int rembLength = (theREMB.getLength()+1)*4; memcpy(buf, reinterpret_cast(&theREMB), rembLength); diff --git a/erizo/src/erizo/rtp/RtcpForwarder.cpp b/erizo/src/erizo/rtp/RtcpForwarder.cpp index 1c2ab1d225..a8d00bd0eb 100644 --- a/erizo/src/erizo/rtp/RtcpForwarder.cpp +++ b/erizo/src/erizo/rtp/RtcpForwarder.cpp @@ -177,7 +177,7 @@ int RtcpForwarder::addREMB(char* buf, int len, uint32_t bitrate) { theREMB.setLength(5); theREMB.setREMBBitRate(bitrate); theREMB.setREMBNumSSRC(1); - theREMB.setREMBFeedSSRC(rtcpSource_->getVideoSourceSSRC()); + theREMB.setREMBFeedSSRC(0, rtcpSource_->getVideoSourceSSRC()); int rembLength = (theREMB.getLength()+1)*4; memcpy(buf, reinterpret_cast(&theREMB), rembLength); diff --git a/erizo/src/erizo/rtp/RtpHeaders.h b/erizo/src/erizo/rtp/RtpHeaders.h index 60d0e25255..632b05af58 100644 --- a/erizo/src/erizo/rtp/RtpHeaders.h +++ b/erizo/src/erizo/rtp/RtpHeaders.h @@ -348,7 +348,7 @@ class RtcpHeader { uint32_t uniqueid; uint32_t numssrc:8; uint32_t brLength :24; - uint32_t ssrcfeedb; + uint32_t ssrcfeedb[50]; } rembPacket; struct pli_t { @@ -372,6 +372,9 @@ class RtcpHeader { packettype == RTCP_PS_Feedback_PT || packettype == RTCP_RTP_Feedback_PT); } + inline bool isREMB() { + return packettype == RTCP_PS_Feedback_PT && blockcount == RTCP_AFB; + } inline bool isRtcp(void) { return (packettype >= RTCP_MIN_PT && packettype <= RTCP_MAX_PT); } @@ -511,11 +514,11 @@ class RtcpHeader { inline void setREMBNumSSRC(uint8_t num) { report.rembPacket.numssrc = num; } - inline uint32_t getREMBFeedSSRC() { - return ntohl(report.rembPacket.ssrcfeedb); + inline uint32_t getREMBFeedSSRC(uint8_t index) { + return ntohl(report.rembPacket.ssrcfeedb[index]); } - inline void setREMBFeedSSRC(uint32_t ssrc) { - report.rembPacket.ssrcfeedb = htonl(ssrc); + inline void setREMBFeedSSRC(uint8_t index, uint32_t ssrc) { + report.rembPacket.ssrcfeedb[index] = htonl(ssrc); } inline uint32_t getFCI() { return ntohl(report.pli.fci); diff --git a/erizo/src/erizo/rtp/RtpPaddingRemovalHandler.cpp b/erizo/src/erizo/rtp/RtpPaddingRemovalHandler.cpp index 41a7d769c9..5a81005e82 100644 --- a/erizo/src/erizo/rtp/RtpPaddingRemovalHandler.cpp +++ b/erizo/src/erizo/rtp/RtpPaddingRemovalHandler.cpp @@ -54,7 +54,7 @@ void RtpPaddingRemovalHandler::write(Context *ctx, std::shared_ptr p ctx->fireWrite(std::move(packet)); return; } - RtpUtils::forEachRRBlock(packet, [this, translator, ssrc](RtcpHeader *chead) { + RtpUtils::forEachRtcpBlock(packet, [this, translator, ssrc](RtcpHeader *chead) { if (chead->packettype == RTCP_RTP_Feedback_PT) { RtpUtils::forEachNack(chead, [this, translator, ssrc](uint16_t new_seq_num, uint16_t new_plb, RtcpHeader* nack_header) { diff --git a/erizo/src/erizo/rtp/RtpRetransmissionHandler.cpp b/erizo/src/erizo/rtp/RtpRetransmissionHandler.cpp index 01311176c9..7292cd90c1 100644 --- a/erizo/src/erizo/rtp/RtpRetransmissionHandler.cpp +++ b/erizo/src/erizo/rtp/RtpRetransmissionHandler.cpp @@ -71,7 +71,7 @@ void RtpRetransmissionHandler::read(Context *ctx, std::shared_ptr pa bool contains_nack = false; bool is_fully_recovered = true; - RtpUtils::forEachRRBlock(packet, [this, &contains_nack, &is_fully_recovered](RtcpHeader *chead) { + RtpUtils::forEachRtcpBlock(packet, [this, &contains_nack, &is_fully_recovered](RtcpHeader *chead) { if (chead->packettype == RTCP_RTP_Feedback_PT) { contains_nack = true; diff --git a/erizo/src/erizo/rtp/RtpSlideShowHandler.cpp b/erizo/src/erizo/rtp/RtpSlideShowHandler.cpp index 010cde2e09..9a43e0c391 100644 --- a/erizo/src/erizo/rtp/RtpSlideShowHandler.cpp +++ b/erizo/src/erizo/rtp/RtpSlideShowHandler.cpp @@ -50,7 +50,7 @@ void RtpSlideShowHandler::read(Context *ctx, std::shared_ptr packet) ctx->fireRead(std::move(packet)); return; } - RtpUtils::forEachRRBlock(packet, [this](RtcpHeader *chead) { + RtpUtils::forEachRtcpBlock(packet, [this](RtcpHeader *chead) { switch (chead->packettype) { case RTCP_Receiver_PT: { diff --git a/erizo/src/erizo/rtp/RtpUtils.cpp b/erizo/src/erizo/rtp/RtpUtils.cpp index 8016e9a788..82f4230e09 100644 --- a/erizo/src/erizo/rtp/RtpUtils.cpp +++ b/erizo/src/erizo/rtp/RtpUtils.cpp @@ -40,7 +40,7 @@ void RtpUtils::forEachNack(RtcpHeader *chead, std::function packet) { bool is_pli = false; - forEachRRBlock(packet, [&is_pli] (RtcpHeader *header) { + forEachRtcpBlock(packet, [&is_pli] (RtcpHeader *header) { if (header->getPacketType() == RTCP_PS_Feedback_PT && header->getBlockCount() == RTCP_PLI_FMT) { is_pli = true; @@ -51,7 +51,7 @@ bool RtpUtils::isPLI(std::shared_ptr packet) { bool RtpUtils::isFIR(std::shared_ptr packet) { bool is_fir = false; - forEachRRBlock(packet, [&is_fir] (RtcpHeader *header) { + forEachRtcpBlock(packet, [&is_fir] (RtcpHeader *header) { if (header->getPacketType() == RTCP_PS_Feedback_PT && header->getBlockCount() == RTCP_FIR_FMT) { is_fir = true; @@ -95,10 +95,10 @@ int RtpUtils::getPaddingLength(std::shared_ptr packet) { return 0; } -void RtpUtils::forEachRRBlock(std::shared_ptr packet, std::function f) { +void RtpUtils::forEachRtcpBlock(std::shared_ptr packet, std::function f) { RtcpHeader *chead = reinterpret_cast(packet->data); int len = packet->length; - if (chead->isFeedback()) { + if (chead->isRtcp()) { char* moving_buffer = packet->data; int rtcp_length = 0; int total_length = 0; diff --git a/erizo/src/erizo/rtp/RtpUtils.h b/erizo/src/erizo/rtp/RtpUtils.h index 77e997dc95..ff47a2d50c 100644 --- a/erizo/src/erizo/rtp/RtpUtils.h +++ b/erizo/src/erizo/rtp/RtpUtils.h @@ -15,7 +15,7 @@ class RtpUtils { public: static bool sequenceNumberLessThan(uint16_t first, uint16_t second); - static void forEachRRBlock(std::shared_ptr packet, std::function f); + static void forEachRtcpBlock(std::shared_ptr packet, std::function f); static void updateREMB(RtcpHeader *chead, uint bitrate); diff --git a/erizo/src/test/utils/Tools.h b/erizo/src/test/utils/Tools.h index 207dc2ae43..04db2e854d 100644 --- a/erizo/src/test/utils/Tools.h +++ b/erizo/src/test/utils/Tools.h @@ -249,7 +249,7 @@ class PacketTools { remb_packet->setLength(5); remb_packet->setREMBBitRate(bitrate); remb_packet->setREMBNumSSRC(1); - remb_packet->setREMBFeedSSRC(55554); + remb_packet->setREMBFeedSSRC(0, 55554); int remb_length = (remb_packet->getLength() + 1) * 4; char *buf = reinterpret_cast(remb_packet); auto packet = std::make_shared(0, buf, remb_length, erizo::OTHER_PACKET);