// We return false instead of DCHECKing for logical conflicts with the new // criteria because new sinks are created according to user-specified SDP and // we do not want to crash due to a data validation error.
if (CriteriaWouldConflict(criteria)) {
RTC_LOG(LS_ERROR) << "Unable to add sink=" << sink
<< " due to conflicting criteria " << criteria.ToString(); return false;
}
if (criteria.match_any()) {
match_any_sink_ = sink;
}
if (!criteria.mid().empty()) {
if (criteria.rsid().empty()) {
sink_by_mid_.emplace(criteria.mid(), sink);
} else {
sink_by_mid_and_rsid_.emplace(
std::make_pair(criteria.mid(), criteria.rsid()), sink);
}
} else {
if (!criteria.rsid().empty()) {
sink_by_rsid_.emplace(criteria.rsid(), sink);
}
}
for (uint32_t ssrc : criteria.ssrcs()) { auto result = sink_by_ssrc_.emplace(ssrc, sink);
if (!result.second) {
if (signaled_ssrcs_.find(ssrc) == signaled_ssrcs_.end()) {
result.first->second = sink;
}
}
signaled_ssrcs_.insert(ssrc);
}
for (uint8_t payload_type : criteria.payload_types()) {
sinks_by_pt_.emplace(payload_type, sink);
}
bool RtpDemuxer::CriteriaWouldConflict( const RtpDemuxerCriteria& criteria) const {
if (match_any_sink_) { // If we already have a sink matching all packets, any new criteria would // conflict. returntrue;
}
if (criteria.match_any()) { // A match_all criteria conflicts if and only if we have another sink // already registered. return (!sink_by_mid_.empty() || !sink_by_ssrc_.empty() ||
!sinks_by_pt_.empty() || !sink_by_mid_and_rsid_.empty() ||
!sink_by_rsid_.empty());
}
if (!criteria.mid().empty()) {
if (criteria.rsid().empty()) { // If the MID is in the known_mids_ set, then there is already a sink // added for this MID directly, or there is a sink already added with a // MID, RSID pair for our MID and some RSID. // Adding this criteria would cause one of these rules to be shadowed, so // reject this new criteria.
if (known_mids_.find(criteria.mid()) != known_mids_.end()) {
RTC_LOG(LS_INFO) << criteria.ToString()
<< " would conflict with known mid"; returntrue;
}
} else { // If the exact rule already exists, then reject this duplicate. constauto sink_by_mid_and_rsid = sink_by_mid_and_rsid_.find(
std::make_pair(criteria.mid(), criteria.rsid()));
if (sink_by_mid_and_rsid != sink_by_mid_and_rsid_.end()) {
RTC_LOG(LS_INFO) << criteria.ToString()
<< " would conflict with existing sink = "
<< sink_by_mid_and_rsid->second
<< " by mid+rsid binding"; returntrue;
} // If there is already a sink registered for the bare MID, then this // criteria will never receive any packets because they will just be // directed to that MID sink, so reject this new criteria. constauto sink_by_mid = sink_by_mid_.find(criteria.mid());
if (sink_by_mid != sink_by_mid_.end()) {
RTC_LOG(LS_INFO) << criteria.ToString()
<< " would conflict with existing sink = "
<< sink_by_mid->second << " by mid binding"; returntrue;
}
}
}
for (uint32_t ssrc : criteria.ssrcs()) { constauto sink_by_ssrc = sink_by_ssrc_.find(ssrc);
if (sink_by_ssrc != sink_by_ssrc_.end()) {
if (signaled_ssrcs_.find(ssrc) != signaled_ssrcs_.end()) {
RTC_LOG(LS_INFO) << criteria.ToString()
<< " would conflict with existing sink = "
<< sink_by_ssrc->second << " binding by SSRC=" << ssrc; returntrue;
}
}
}
// TODO(steveanton): May also sanity check payload types.
// RSID and RRID are routed to the same sinks. If an RSID is specified on a // repair packet, it should be ignored and the RRID should be used.
std::string packet_mid, packet_rsid; //bool has_mid = use_mid_ && packet.GetExtension<RtpMid>(&packet_mid); bool has_rsid = packet.GetExtension<RepairedRtpStreamId>(&packet_rsid);
if (!has_rsid) {
has_rsid = packet.GetExtension<RtpStreamId>(&packet_rsid);
}
uint32_t ssrc = packet.Ssrc();
// Mid support is half-baked in branch 64. RtpStreamReceiverController only // supports adding sinks by ssrc, so our mids will never show up in // known_mids_, causing us to drop packets here. #if0 // The BUNDLE spec says to drop any packets with unknown MIDs, even if the // SSRC is known/latched.
if (has_mid && known_mids_.find(packet_mid) == known_mids_.end()) { return nullptr;
}
// Cache information we learn about SSRCs and IDs. We need to do this even if // there isn't a rule/sink yet because we might add an MID/RSID rule after // learning an MID/RSID<->SSRC association.
std::string* mid = nullptr;
if (has_mid) {
mid_by_ssrc_[ssrc] = packet_mid;
mid = &packet_mid;
} else { // If the packet does not include a MID header extension, check if there is // a latched MID for the SSRC. constauto it = mid_by_ssrc_.find(ssrc);
if (it != mid_by_ssrc_.end()) {
mid = &it->second;
}
}
std::string* rsid = nullptr;
if (has_rsid) {
rsid_by_ssrc_[ssrc] = packet_rsid;
rsid = &packet_rsid;
} else { // If the packet does not include an RRID/RSID header extension, check if // there is a latched RSID for the SSRC. constauto it = rsid_by_ssrc_.find(ssrc);
if (it != rsid_by_ssrc_.end()) {
rsid = &it->second;
}
}
// If MID and/or RSID is specified, prioritize that for demuxing the packet. // The motivation behind the BUNDLE algorithm is that we trust these are used // deliberately by senders and are more likely to be correct than SSRC/payload // type which are included with every packet. // TODO(steveanton): According to the BUNDLE spec, new SSRC mappings are only // accepted if the packet's extended sequence number is // greater than that of the last SSRC mapping update. // https://tools.ietf.org/html/rfc7941#section-4.2.6
if (mid != nullptr) {
RtpPacketSinkInterface* sink_by_mid = ResolveSinkByMid(*mid, ssrc);
if (sink_by_mid != nullptr) { return sink_by_mid;
}
// RSID is scoped to a given MID if both are included.
if (rsid != nullptr) {
RtpPacketSinkInterface* sink_by_mid_rsid =
ResolveSinkByMidRsid(*mid, *rsid, ssrc);
if (sink_by_mid_rsid != nullptr) { return sink_by_mid_rsid;
}
}
// At this point, there is at least one sink added for this MID and an RSID // but either the packet does not have an RSID or it is for a different // RSID. This falls outside the BUNDLE spec so drop the packet. return nullptr;
}
// RSID can be used without MID as long as they are unique.
if (rsid != nullptr) {
RtpPacketSinkInterface* sink_by_rsid = ResolveSinkByRsid(*rsid, ssrc);
if (sink_by_rsid != nullptr) { return sink_by_rsid;
}
}
#endif // We trust signaled SSRC more than payload type which is likely to conflict // between streams. constauto ssrc_sink_it = sink_by_ssrc_.find(ssrc);
if (ssrc_sink_it != sink_by_ssrc_.end()) { return ssrc_sink_it->second;
}
if (use_payload_type_demuxing_) { // Legacy senders will only signal payload type. // Support that as a last resort. return ResolveSinkByPayloadType(packet.PayloadType(), ssrc);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.