/* * Copyright 2021 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
void BundleManager::Update(const cricket::SessionDescription* description,
SdpType type) {
RTC_DCHECK_RUN_ON(&sequence_checker_); // Rollbacks should call Rollback, not Update.
RTC_DCHECK(type != SdpType::kRollback); bool bundle_groups_changed = false; // TODO(bugs.webrtc.org/3349): Do this for kPrAnswer as well. To make this // work, we also need to make sure PRANSWERs don't call // MaybeDestroyJsepTransport, because the final answer may need the destroyed // transport if it changes the BUNDLE group. if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle ||
type == SdpType::kAnswer) { // If our policy is "max-bundle" or this is an answer, update all bundle // groups.
bundle_groups_changed = true;
bundle_groups_.clear(); for (const cricket::ContentGroup* new_bundle_group :
description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)) {
bundle_groups_.push_back(
std::make_unique<cricket::ContentGroup>(*new_bundle_group));
RTC_DLOG(LS_VERBOSE) << "Establishing bundle group "
<< new_bundle_group->ToString();
}
} elseif (type == SdpType::kOffer) { // If this is an offer, update existing bundle groups. // We do this because as per RFC 8843, section 7.3.2, the answerer cannot // remove an m= section from an existing BUNDLE group without rejecting it. // Thus any m= sections added to a BUNDLE group in this offer can // preemptively start using the bundled transport, as there is no possible // non-bundled fallback. for (const cricket::ContentGroup* new_bundle_group :
description->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE)) { // Attempt to find a matching existing group. for (const std::string& mid : new_bundle_group->content_names()) { auto it = established_bundle_groups_by_mid_.find(mid); if (it != established_bundle_groups_by_mid_.end()) {
*it->second = *new_bundle_group;
bundle_groups_changed = true;
RTC_DLOG(LS_VERBOSE)
<< "Establishing bundle group " << new_bundle_group->ToString(); break;
}
}
}
} if (bundle_groups_changed) {
RefreshEstablishedBundleGroupsByMid();
}
}
const cricket::ContentGroup* BundleManager::LookupGroupByMid( const std::string& mid) const { auto it = established_bundle_groups_by_mid_.find(mid); return it != established_bundle_groups_by_mid_.end() ? it->second : nullptr;
} bool BundleManager::IsFirstMidInGroup(const std::string& mid) const { auto group = LookupGroupByMid(mid); if (!group) { returntrue; // Unbundled MIDs are considered group leaders
} return mid == *(group->FirstContentName());
}
cricket::ContentGroup* BundleManager::LookupGroupByMid(const std::string& mid) { auto it = established_bundle_groups_by_mid_.find(mid); return it != established_bundle_groups_by_mid_.end() ? it->second : nullptr;
}
void BundleManager::DeleteMid(const cricket::ContentGroup* bundle_group, const std::string& mid) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_LOG(LS_VERBOSE) << "Deleting mid " << mid << " from bundle group "
<< bundle_group->ToString(); // Remove the rejected content from the `bundle_group`. // The const pointer arg is used to identify the group, we verify // it before we use it to make a modification. auto bundle_group_it = std::find_if(
bundle_groups_.begin(), bundle_groups_.end(),
[bundle_group](std::unique_ptr<cricket::ContentGroup>& group) { return bundle_group == group.get();
});
RTC_DCHECK(bundle_group_it != bundle_groups_.end());
(*bundle_group_it)->RemoveContentName(mid);
established_bundle_groups_by_mid_.erase(
established_bundle_groups_by_mid_.find(mid));
}
cricket::JsepTransport* JsepTransportCollection::GetTransportByName( const std::string& transport_name) {
RTC_DCHECK_RUN_ON(&sequence_checker_); auto it = jsep_transports_by_name_.find(transport_name); return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get();
}
cricket::JsepTransport* JsepTransportCollection::GetTransportForMid( const std::string& mid) {
RTC_DCHECK_RUN_ON(&sequence_checker_); auto it = mid_to_transport_.find(mid); return it == mid_to_transport_.end() ? nullptr : it->second;
}
const cricket::JsepTransport* JsepTransportCollection::GetTransportForMid( const std::string& mid) const {
RTC_DCHECK_RUN_ON(&sequence_checker_); auto it = mid_to_transport_.find(mid); return it == mid_to_transport_.end() ? nullptr : it->second;
}
cricket::JsepTransport* JsepTransportCollection::GetTransportForMid(
absl::string_view mid) {
RTC_DCHECK_RUN_ON(&sequence_checker_); // TODO(hta): should be a better way. auto it = mid_to_transport_.find(std::string(mid)); return it == mid_to_transport_.end() ? nullptr : it->second;
}
const cricket::JsepTransport* JsepTransportCollection::GetTransportForMid(
absl::string_view mid) const {
RTC_DCHECK_RUN_ON(&sequence_checker_); // TODO(hta): Should be a better way auto it = mid_to_transport_.find(std::string(mid)); return it == mid_to_transport_.end() ? nullptr : it->second;
}
auto it = mid_to_transport_.find(mid); if (it != mid_to_transport_.end() && it->second == jsep_transport) returntrue;
// The map_change_callback must be called before destroying the // transport, because it removes references to the transport // in the RTP demuxer. bool result = map_change_callback_(mid, jsep_transport);
void JsepTransportCollection::RemoveTransportForMid(const std::string& mid) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK(IsConsistent()); bool ret = map_change_callback_(mid, nullptr); // Calling OnTransportChanged with nullptr should always succeed, since it is // only expected to fail when adding media to a transport (not removing).
RTC_DCHECK(ret);
auto old_transport = GetTransportForMid(mid); if (old_transport) {
mid_to_transport_.erase(mid);
MaybeDestroyJsepTransport(old_transport);
}
RTC_DCHECK(IsConsistent());
}
bool JsepTransportCollection::RollbackTransports() {
RTC_DCHECK_RUN_ON(&sequence_checker_); bool ret = true; // First, remove any new mid->transport mappings. for (constauto& kv : mid_to_transport_) { if (stable_mid_to_transport_.count(kv.first) == 0) {
ret = ret && map_change_callback_(kv.first, nullptr);
}
} // Next, restore old mappings. for (constauto& kv : stable_mid_to_transport_) { auto it = mid_to_transport_.find(kv.first); if (it == mid_to_transport_.end() || it->second != kv.second) {
ret = ret && map_change_callback_(kv.first, kv.second);
}
}
mid_to_transport_ = stable_mid_to_transport_; // Moving a transport back to mid_to_transport_ means it's now included in // the aggregate state if it wasn't previously.
state_change_callback_();
DestroyUnusedTransports();
RTC_DCHECK(IsConsistent()); return ret;
}
void JsepTransportCollection::CommitTransports() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
stable_mid_to_transport_ = mid_to_transport_;
DestroyUnusedTransports(); for (auto& transport : jsep_transports_by_name_) {
transport.second->CommitPayloadTypes();
}
RTC_DCHECK(IsConsistent());
}
void JsepTransportCollection::MaybeDestroyJsepTransport(
cricket::JsepTransport* transport) {
RTC_DCHECK_RUN_ON(&sequence_checker_); // Don't destroy the JsepTransport if there are still media sections referring // to it, or if it will be needed in case of rollback. if (TransportInUse(transport)) { return;
} // If this transport is needed for rollback, don't destroy it yet, but make // sure the aggregate state is updated since this transport is no longer // included in it. if (TransportNeededForRollback(transport)) {
state_change_callback_(); return;
} for (constauto& it : jsep_transports_by_name_) { if (it.second.get() == transport) {
jsep_transports_by_name_.erase(it.first);
state_change_callback_(); break;
}
}
RTC_DCHECK(IsConsistent());
}
void JsepTransportCollection::DestroyUnusedTransports() {
RTC_DCHECK_RUN_ON(&sequence_checker_); bool need_state_change_callback = false; auto it = jsep_transports_by_name_.begin(); while (it != jsep_transports_by_name_.end()) { if (TransportInUse(it->second.get()) ||
TransportNeededForRollback(it->second.get())) {
++it;
} else {
it = jsep_transports_by_name_.erase(it);
need_state_change_callback = true;
}
} if (need_state_change_callback) {
state_change_callback_();
}
}
bool JsepTransportCollection::IsConsistent() {
RTC_DCHECK_RUN_ON(&sequence_checker_); for (constauto& it : jsep_transports_by_name_) { if (!TransportInUse(it.second.get()) &&
!TransportNeededForRollback(it.second.get())) {
RTC_LOG(LS_ERROR) << "Transport registered with mid " << it.first
<< " is not in use, transport " << it.second.get(); returnfalse;
}
} returntrue;
}
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.