Separate RTP object handling (senders, receivers, transceivers)
This is part of the PeerConnection disassembly project. Bug: webrtc:11995 Change-Id: I4f207c8af39e267c4b5752c0828b84e221e1f080 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188624 Reviewed-by: Henrik Boström <hbos@webrtc.org> Reviewed-by: Niels Moller <nisse@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32443}
This commit is contained in:
parent
82031310f5
commit
e15fb15035
45
pc/BUILD.gn
45
pc/BUILD.gn
@ -195,8 +195,6 @@ rtc_library("peerconnection") {
|
||||
"stream_collection.h",
|
||||
"track_media_info_map.cc",
|
||||
"track_media_info_map.h",
|
||||
"transceiver_list.cc",
|
||||
"transceiver_list.h",
|
||||
"webrtc_sdp.cc",
|
||||
"webrtc_sdp.h",
|
||||
"webrtc_session_description_factory.cc",
|
||||
@ -220,7 +218,9 @@ rtc_library("peerconnection") {
|
||||
":rtp_receiver",
|
||||
":rtp_sender",
|
||||
":rtp_transceiver",
|
||||
":rtp_transmission_manager",
|
||||
":stats_collector_interface",
|
||||
":transceiver_list",
|
||||
":usage_pattern",
|
||||
":video_rtp_receiver",
|
||||
":video_track",
|
||||
@ -365,6 +365,47 @@ rtc_library("rtp_transceiver") {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("rtp_transmission_manager") {
|
||||
sources = [
|
||||
"rtp_transmission_manager.cc",
|
||||
"rtp_transmission_manager.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_rtp_receiver",
|
||||
":rtc_pc_base",
|
||||
":rtp_receiver",
|
||||
":rtp_sender",
|
||||
":rtp_transceiver",
|
||||
":stats_collector_interface",
|
||||
":transceiver_list",
|
||||
":usage_pattern",
|
||||
":video_rtp_receiver",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:media_stream_interface",
|
||||
"../api:rtc_error",
|
||||
"../api:rtp_parameters",
|
||||
"../api:rtp_transceiver_direction",
|
||||
"../api:scoped_refptr",
|
||||
"../media:rtc_media_base",
|
||||
"../rtc_base",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/third_party/sigslot",
|
||||
]
|
||||
absl_deps = [
|
||||
"//third_party/abseil-cpp/absl/algorithm:container",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("transceiver_list") {
|
||||
sources = [
|
||||
"transceiver_list.cc",
|
||||
"transceiver_list.h",
|
||||
]
|
||||
deps = [ ":rtp_transceiver" ]
|
||||
}
|
||||
|
||||
rtc_library("rtp_receiver") {
|
||||
sources = [
|
||||
"rtp_receiver.cc",
|
||||
|
||||
@ -13,6 +13,10 @@
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
@ -83,9 +87,6 @@ namespace {
|
||||
const char kSimulcastNumberOfEncodings[] =
|
||||
"WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings";
|
||||
|
||||
static const char kDefaultAudioSenderId[] = "defaulta0";
|
||||
static const char kDefaultVideoSenderId[] = "defaultv0";
|
||||
|
||||
static const int REPORT_USAGE_PATTERN_DELAY_MS = 60000;
|
||||
|
||||
|
||||
@ -351,8 +352,10 @@ PeerConnection::~PeerConnection() {
|
||||
// Need to stop transceivers before destroying the stats collector because
|
||||
// AudioRtpSender has a reference to the StatsCollector it will update when
|
||||
// stopping.
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
transceiver->StopInternal();
|
||||
if (rtp_manager()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
transceiver->StopInternal();
|
||||
}
|
||||
}
|
||||
|
||||
stats_.reset(nullptr);
|
||||
@ -547,13 +550,20 @@ bool PeerConnection::Initialize(
|
||||
OnTransportControllerConnectionState(s);
|
||||
});
|
||||
|
||||
stats_.reset(new StatsCollector(this));
|
||||
stats_collector_ = RTCStatsCollector::Create(this);
|
||||
|
||||
configuration_ = configuration;
|
||||
|
||||
transport_controller_->SetIceConfig(ParseIceConfig(configuration));
|
||||
|
||||
stats_ = std::make_unique<StatsCollector>(this);
|
||||
stats_collector_ = RTCStatsCollector::Create(this);
|
||||
|
||||
rtp_manager_ = std::make_unique<RtpTransmissionManager>(
|
||||
IsUnifiedPlan(), signaling_thread(), worker_thread(), channel_manager(),
|
||||
&usage_pattern_, observer_, stats_.get(), [this]() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
});
|
||||
|
||||
video_options_.screencast_min_bitrate_kbps =
|
||||
configuration.screencast_min_bitrate;
|
||||
audio_options_.combined_audio_video_bwe =
|
||||
@ -601,10 +611,12 @@ bool PeerConnection::Initialize(
|
||||
|
||||
// Add default audio/video transceivers for Plan B SDP.
|
||||
if (!IsUnifiedPlan()) {
|
||||
transceivers_.Add(RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)));
|
||||
transceivers_.Add(RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO)));
|
||||
rtp_manager()->transceivers()->Add(
|
||||
RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)));
|
||||
rtp_manager()->transceivers()->Add(
|
||||
RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO)));
|
||||
}
|
||||
int delay_ms =
|
||||
return_histogram_very_quickly_ ? 0 : REPORT_USAGE_PATTERN_DELAY_MS;
|
||||
@ -682,14 +694,12 @@ RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
|
||||
"PeerConnection is closed.");
|
||||
}
|
||||
if (FindSenderForTrack(track)) {
|
||||
if (rtp_manager()->FindSenderForTrack(track)) {
|
||||
LOG_AND_RETURN_ERROR(
|
||||
RTCErrorType::INVALID_PARAMETER,
|
||||
"Sender already exists for track " + track->id() + ".");
|
||||
}
|
||||
auto sender_or_error =
|
||||
(IsUnifiedPlan() ? AddTrackUnifiedPlan(track, stream_ids)
|
||||
: AddTrackPlanB(track, stream_ids));
|
||||
auto sender_or_error = rtp_manager()->AddTrack(track, stream_ids);
|
||||
if (sender_or_error.ok()) {
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
stats_->AddTrack(track);
|
||||
@ -697,111 +707,6 @@ RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
||||
return sender_or_error;
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
PeerConnection::AddTrackPlanB(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
if (stream_ids.size() > 1u) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
|
||||
"AddTrack with more than one stream is not "
|
||||
"supported with Plan B semantics.");
|
||||
}
|
||||
std::vector<std::string> adjusted_stream_ids = stream_ids;
|
||||
if (adjusted_stream_ids.empty()) {
|
||||
adjusted_stream_ids.push_back(rtc::CreateRandomUuid());
|
||||
}
|
||||
cricket::MediaType media_type =
|
||||
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
||||
? cricket::MEDIA_TYPE_AUDIO
|
||||
: cricket::MEDIA_TYPE_VIDEO);
|
||||
auto new_sender =
|
||||
CreateSender(media_type, track->id(), track, adjusted_stream_ids, {});
|
||||
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
||||
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
||||
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_audio_sender_infos_,
|
||||
new_sender->internal()->stream_ids()[0], track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
} else {
|
||||
RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
|
||||
new_sender->internal()->SetMediaChannel(video_media_channel());
|
||||
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_video_sender_infos_,
|
||||
new_sender->internal()->stream_ids()[0], track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
}
|
||||
return rtc::scoped_refptr<RtpSenderInterface>(new_sender);
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
PeerConnection::AddTrackUnifiedPlan(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
auto transceiver = FindFirstTransceiverForAddedTrack(track);
|
||||
if (transceiver) {
|
||||
RTC_LOG(LS_INFO) << "Reusing an existing "
|
||||
<< cricket::MediaTypeToString(transceiver->media_type())
|
||||
<< " transceiver for AddTrack.";
|
||||
if (transceiver->stopping()) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
||||
"The existing transceiver is stopping.");
|
||||
}
|
||||
|
||||
if (transceiver->direction() == RtpTransceiverDirection::kRecvOnly) {
|
||||
transceiver->internal()->set_direction(
|
||||
RtpTransceiverDirection::kSendRecv);
|
||||
} else if (transceiver->direction() == RtpTransceiverDirection::kInactive) {
|
||||
transceiver->internal()->set_direction(
|
||||
RtpTransceiverDirection::kSendOnly);
|
||||
}
|
||||
transceiver->sender()->SetTrack(track);
|
||||
transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
|
||||
transceiver->internal()->set_reused_for_addtrack(true);
|
||||
} else {
|
||||
cricket::MediaType media_type =
|
||||
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
||||
? cricket::MEDIA_TYPE_AUDIO
|
||||
: cricket::MEDIA_TYPE_VIDEO);
|
||||
RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
|
||||
<< " transceiver in response to a call to AddTrack.";
|
||||
std::string sender_id = track->id();
|
||||
// Avoid creating a sender with an existing ID by generating a random ID.
|
||||
// This can happen if this is the second time AddTrack has created a sender
|
||||
// for this track.
|
||||
if (FindSenderById(sender_id)) {
|
||||
sender_id = rtc::CreateRandomUuid();
|
||||
}
|
||||
auto sender = CreateSender(media_type, sender_id, track, stream_ids, {});
|
||||
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
|
||||
transceiver = CreateAndAddTransceiver(sender, receiver);
|
||||
transceiver->internal()->set_created_by_addtrack(true);
|
||||
transceiver->internal()->set_direction(RtpTransceiverDirection::kSendRecv);
|
||||
}
|
||||
return transceiver->sender();
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
PeerConnection::FindFirstTransceiverForAddedTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
||||
RTC_DCHECK(track);
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (!transceiver->sender()->track() &&
|
||||
cricket::MediaTypeToString(transceiver->media_type()) ==
|
||||
track->kind() &&
|
||||
!transceiver->internal()->has_ever_been_used_to_send() &&
|
||||
!transceiver->stopped()) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) {
|
||||
TRACE_EVENT0("webrtc", "PeerConnection::RemoveTrack");
|
||||
return RemoveTrackNew(sender).ok();
|
||||
@ -833,10 +738,12 @@ RTCError PeerConnection::RemoveTrackNew(
|
||||
} else {
|
||||
bool removed;
|
||||
if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
removed = GetAudioTransceiver()->internal()->RemoveSender(sender);
|
||||
removed = rtp_manager()->GetAudioTransceiver()->internal()->RemoveSender(
|
||||
sender);
|
||||
} else {
|
||||
RTC_DCHECK_EQ(cricket::MEDIA_TYPE_VIDEO, sender->media_type());
|
||||
removed = GetVideoTransceiver()->internal()->RemoveSender(sender);
|
||||
removed = rtp_manager()->GetVideoTransceiver()->internal()->RemoveSender(
|
||||
sender);
|
||||
}
|
||||
if (!removed) {
|
||||
LOG_AND_RETURN_ERROR(
|
||||
@ -851,7 +758,7 @@ RTCError PeerConnection::RemoveTrackNew(
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
PeerConnection::FindTransceiverBySender(
|
||||
rtc::scoped_refptr<RtpSenderInterface> sender) {
|
||||
return transceivers_.FindBySender(sender);
|
||||
return rtp_manager()->transceivers()->FindBySender(sender);
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||
@ -987,13 +894,14 @@ PeerConnection::AddTransceiver(
|
||||
<< " transceiver in response to a call to AddTransceiver.";
|
||||
// Set the sender ID equal to the track ID if the track is specified unless
|
||||
// that sender ID is already in use.
|
||||
std::string sender_id =
|
||||
(track && !FindSenderById(track->id()) ? track->id()
|
||||
: rtc::CreateRandomUuid());
|
||||
auto sender = CreateSender(media_type, sender_id, track, init.stream_ids,
|
||||
parameters.encodings);
|
||||
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
|
||||
auto transceiver = CreateAndAddTransceiver(sender, receiver);
|
||||
std::string sender_id = (track && !rtp_manager()->FindSenderById(track->id())
|
||||
? track->id()
|
||||
: rtc::CreateRandomUuid());
|
||||
auto sender = rtp_manager()->CreateSender(
|
||||
media_type, sender_id, track, init.stream_ids, parameters.encodings);
|
||||
auto receiver =
|
||||
rtp_manager()->CreateReceiver(media_type, rtc::CreateRandomUuid());
|
||||
auto transceiver = rtp_manager()->CreateAndAddTransceiver(sender, receiver);
|
||||
transceiver->internal()->set_direction(init.direction);
|
||||
|
||||
if (update_negotiation_needed) {
|
||||
@ -1003,81 +911,6 @@ PeerConnection::AddTransceiver(
|
||||
return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
PeerConnection::CreateSender(
|
||||
cricket::MediaType media_type,
|
||||
const std::string& id,
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& send_encodings) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender;
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
RTC_DCHECK(!track ||
|
||||
(track->kind() == MediaStreamTrackInterface::kAudioKind));
|
||||
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||
signaling_thread(),
|
||||
AudioRtpSender::Create(worker_thread(), id, stats_.get(), this));
|
||||
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
||||
} else {
|
||||
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
|
||||
RTC_DCHECK(!track ||
|
||||
(track->kind() == MediaStreamTrackInterface::kVideoKind));
|
||||
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||
signaling_thread(), VideoRtpSender::Create(worker_thread(), id, this));
|
||||
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
||||
}
|
||||
bool set_track_succeeded = sender->SetTrack(track);
|
||||
RTC_DCHECK(set_track_succeeded);
|
||||
sender->internal()->set_stream_ids(stream_ids);
|
||||
sender->internal()->set_init_send_encodings(send_encodings);
|
||||
return sender;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
PeerConnection::CreateReceiver(cricket::MediaType media_type,
|
||||
const std::string& receiver_id) {
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
receiver;
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), new AudioRtpReceiver(worker_thread(), receiver_id,
|
||||
std::vector<std::string>({})));
|
||||
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
||||
} else {
|
||||
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
|
||||
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), new VideoRtpReceiver(worker_thread(), receiver_id,
|
||||
std::vector<std::string>({})));
|
||||
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
PeerConnection::CreateAndAddTransceiver(
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
receiver) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// Ensure that the new sender does not have an ID that is already in use by
|
||||
// another sender.
|
||||
// Allow receiver IDs to conflict since those come from remote SDP (which
|
||||
// could be invalid, but should not cause a crash).
|
||||
RTC_DCHECK(!FindSenderById(sender->id()));
|
||||
auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||
signaling_thread(),
|
||||
new RtpTransceiver(
|
||||
sender, receiver, channel_manager(),
|
||||
sender->media_type() == cricket::MEDIA_TYPE_AUDIO
|
||||
? channel_manager()->GetSupportedAudioRtpHeaderExtensions()
|
||||
: channel_manager()->GetSupportedVideoRtpHeaderExtensions()));
|
||||
transceivers_.Add(transceiver);
|
||||
transceiver->internal()->SignalNegotiationNeeded.connect(
|
||||
this, &PeerConnection::OnNegotiationNeeded);
|
||||
return transceiver;
|
||||
}
|
||||
|
||||
void PeerConnection::OnNegotiationNeeded() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsClosed());
|
||||
@ -1112,18 +945,18 @@ rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
|
||||
if (kind == MediaStreamTrackInterface::kAudioKind) {
|
||||
auto audio_sender = AudioRtpSender::Create(
|
||||
worker_thread(), rtc::CreateRandomUuid(), stats_.get(), this);
|
||||
audio_sender->SetMediaChannel(voice_media_channel());
|
||||
worker_thread(), rtc::CreateRandomUuid(), stats_.get(), rtp_manager());
|
||||
audio_sender->SetMediaChannel(rtp_manager()->voice_media_channel());
|
||||
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||
signaling_thread(), audio_sender);
|
||||
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
rtp_manager()->GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
} else if (kind == MediaStreamTrackInterface::kVideoKind) {
|
||||
auto video_sender =
|
||||
VideoRtpSender::Create(worker_thread(), rtc::CreateRandomUuid(), this);
|
||||
video_sender->SetMediaChannel(video_media_channel());
|
||||
auto video_sender = VideoRtpSender::Create(
|
||||
worker_thread(), rtc::CreateRandomUuid(), rtp_manager());
|
||||
video_sender->SetMediaChannel(rtp_manager()->video_media_channel());
|
||||
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||
signaling_thread(), video_sender);
|
||||
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
||||
rtp_manager()->GetVideoTransceiver()->internal()->AddSender(new_sender);
|
||||
} else {
|
||||
RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
|
||||
return nullptr;
|
||||
@ -1137,61 +970,29 @@ std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
|
||||
const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::vector<rtc::scoped_refptr<RtpSenderInterface>> ret;
|
||||
for (const auto& sender : GetSendersInternal()) {
|
||||
for (const auto& sender : rtp_manager()->GetSendersInternal()) {
|
||||
ret.push_back(sender);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
||||
PeerConnection::GetSendersInternal() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
||||
all_senders;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
if (IsUnifiedPlan() && transceiver->internal()->stopped())
|
||||
continue;
|
||||
|
||||
auto senders = transceiver->internal()->senders();
|
||||
all_senders.insert(all_senders.end(), senders.begin(), senders.end());
|
||||
}
|
||||
return all_senders;
|
||||
}
|
||||
|
||||
std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
|
||||
PeerConnection::GetReceivers() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> ret;
|
||||
for (const auto& receiver : GetReceiversInternal()) {
|
||||
for (const auto& receiver : rtp_manager()->GetReceiversInternal()) {
|
||||
ret.push_back(receiver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
||||
PeerConnection::GetReceiversInternal() const {
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
||||
all_receivers;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
if (IsUnifiedPlan() && transceiver->internal()->stopped())
|
||||
continue;
|
||||
|
||||
auto receivers = transceiver->internal()->receivers();
|
||||
all_receivers.insert(all_receivers.end(), receivers.begin(),
|
||||
receivers.end());
|
||||
}
|
||||
return all_receivers;
|
||||
}
|
||||
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||
PeerConnection::GetTransceivers() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_CHECK(IsUnifiedPlan())
|
||||
<< "GetTransceivers is only supported with Unified Plan SdpSemantics.";
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> all_transceivers;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
all_transceivers.push_back(transceiver);
|
||||
}
|
||||
return all_transceivers;
|
||||
@ -1236,7 +1037,8 @@ void PeerConnection::GetStats(
|
||||
RTC_DCHECK(stats_collector_);
|
||||
rtc::scoped_refptr<RtpSenderInternal> internal_sender;
|
||||
if (selector) {
|
||||
for (const auto& proxy_transceiver : transceivers_.List()) {
|
||||
for (const auto& proxy_transceiver :
|
||||
rtp_manager()->transceivers()->List()) {
|
||||
for (const auto& proxy_sender :
|
||||
proxy_transceiver->internal()->senders()) {
|
||||
if (proxy_sender == selector) {
|
||||
@ -1265,7 +1067,8 @@ void PeerConnection::GetStats(
|
||||
RTC_DCHECK(stats_collector_);
|
||||
rtc::scoped_refptr<RtpReceiverInternal> internal_receiver;
|
||||
if (selector) {
|
||||
for (const auto& proxy_transceiver : transceivers_.List()) {
|
||||
for (const auto& proxy_transceiver :
|
||||
rtp_manager()->transceivers()->List()) {
|
||||
for (const auto& proxy_receiver :
|
||||
proxy_transceiver->internal()->receivers()) {
|
||||
if (proxy_receiver == selector) {
|
||||
@ -1552,7 +1355,7 @@ RTCError PeerConnection::SetConfiguration(
|
||||
|
||||
if (modified_config.allow_codec_switching.has_value()) {
|
||||
std::vector<cricket::VideoMediaChannel*> channels;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO)
|
||||
continue;
|
||||
|
||||
@ -1673,7 +1476,7 @@ PeerConnection::GetRemoteAudioSSLCertificate() {
|
||||
std::unique_ptr<rtc::SSLCertChain>
|
||||
PeerConnection::GetRemoteAudioSSLCertChain() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
auto audio_transceiver = GetFirstAudioTransceiver();
|
||||
auto audio_transceiver = rtp_manager()->GetFirstAudioTransceiver();
|
||||
if (!audio_transceiver || !audio_transceiver->internal()->channel()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1681,16 +1484,6 @@ PeerConnection::GetRemoteAudioSSLCertChain() {
|
||||
audio_transceiver->internal()->channel()->transport_name());
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
PeerConnection::GetFirstAudioTransceiver() const {
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PeerConnection::AddAdaptationResource(
|
||||
rtc::scoped_refptr<Resource> resource) {
|
||||
if (!worker_thread()->IsCurrent()) {
|
||||
@ -1807,7 +1600,7 @@ void PeerConnection::Close() {
|
||||
|
||||
NoteUsageEvent(UsageEvent::CLOSE_CALLED);
|
||||
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
transceiver->internal()->SetPeerConnectionClosed();
|
||||
if (!transceiver->stopped())
|
||||
transceiver->StopInternal();
|
||||
@ -1830,6 +1623,7 @@ void PeerConnection::Close() {
|
||||
// call the transport controller.
|
||||
sdp_handler_.ResetSessionDescFactory();
|
||||
transport_controller_.reset();
|
||||
rtp_manager_->Close();
|
||||
|
||||
network_thread()->Invoke<void>(
|
||||
RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::DiscardCandidatePool,
|
||||
@ -1848,176 +1642,6 @@ void PeerConnection::Close() {
|
||||
observer_ = nullptr;
|
||||
}
|
||||
|
||||
cricket::VoiceMediaChannel* PeerConnection::voice_media_channel() const {
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto* voice_channel = static_cast<cricket::VoiceChannel*>(
|
||||
GetAudioTransceiver()->internal()->channel());
|
||||
if (voice_channel) {
|
||||
return voice_channel->media_channel();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
cricket::VideoMediaChannel* PeerConnection::video_media_channel() const {
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto* video_channel = static_cast<cricket::VideoChannel*>(
|
||||
GetVideoTransceiver()->internal()->channel());
|
||||
if (video_channel) {
|
||||
return video_channel->media_channel();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::CreateAudioReceiver(
|
||||
MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info) {
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
||||
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
|
||||
// TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
|
||||
// the constructor taking stream IDs instead.
|
||||
auto* audio_receiver = new AudioRtpReceiver(
|
||||
worker_thread(), remote_sender_info.sender_id, streams);
|
||||
audio_receiver->SetMediaChannel(voice_media_channel());
|
||||
if (remote_sender_info.sender_id == kDefaultAudioSenderId) {
|
||||
audio_receiver->SetupUnsignaledMediaChannel();
|
||||
} else {
|
||||
audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
|
||||
}
|
||||
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), audio_receiver);
|
||||
GetAudioTransceiver()->internal()->AddReceiver(receiver);
|
||||
Observer()->OnAddTrack(receiver, streams);
|
||||
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
||||
}
|
||||
|
||||
void PeerConnection::CreateVideoReceiver(
|
||||
MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info) {
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
||||
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
|
||||
// TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
|
||||
// the constructor taking stream IDs instead.
|
||||
auto* video_receiver = new VideoRtpReceiver(
|
||||
worker_thread(), remote_sender_info.sender_id, streams);
|
||||
video_receiver->SetMediaChannel(video_media_channel());
|
||||
if (remote_sender_info.sender_id == kDefaultVideoSenderId) {
|
||||
video_receiver->SetupUnsignaledMediaChannel();
|
||||
} else {
|
||||
video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
|
||||
}
|
||||
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), video_receiver);
|
||||
GetVideoTransceiver()->internal()->AddReceiver(receiver);
|
||||
Observer()->OnAddTrack(receiver, streams);
|
||||
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
||||
}
|
||||
|
||||
// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
|
||||
// description.
|
||||
rtc::scoped_refptr<RtpReceiverInterface> PeerConnection::RemoveAndStopReceiver(
|
||||
const RtpSenderInfo& remote_sender_info) {
|
||||
auto receiver = FindReceiverById(remote_sender_info.sender_id);
|
||||
if (!receiver) {
|
||||
RTC_LOG(LS_WARNING) << "RtpReceiver for track with id "
|
||||
<< remote_sender_info.sender_id << " doesn't exist.";
|
||||
return nullptr;
|
||||
}
|
||||
if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
GetAudioTransceiver()->internal()->RemoveReceiver(receiver);
|
||||
} else {
|
||||
GetVideoTransceiver()->internal()->RemoveReceiver(receiver);
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
void PeerConnection::AddAudioTrack(AudioTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsClosed());
|
||||
RTC_DCHECK(track);
|
||||
RTC_DCHECK(stream);
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (sender) {
|
||||
// We already have a sender for this track, so just change the stream_id
|
||||
// so that it's correct in the next call to CreateOffer.
|
||||
sender->internal()->set_stream_ids({stream->id()});
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal case; we've never seen this track before.
|
||||
auto new_sender = CreateSender(cricket::MEDIA_TYPE_AUDIO, track->id(), track,
|
||||
{stream->id()}, {});
|
||||
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
||||
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
// If the sender has already been configured in SDP, we call SetSsrc,
|
||||
// which will connect the sender to the underlying transport. This can
|
||||
// occur if a local session description that contains the ID of the sender
|
||||
// is set before AddStream is called. It can also occur if the local
|
||||
// session description is not changed and RemoveStream is called, and
|
||||
// later AddStream is called again with the same stream.
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_audio_sender_infos_, stream->id(), track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
|
||||
// indefinitely, when we have unified plan SDP.
|
||||
void PeerConnection::RemoveAudioTrack(AudioTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsClosed());
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (!sender) {
|
||||
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
|
||||
<< " doesn't exist.";
|
||||
return;
|
||||
}
|
||||
GetAudioTransceiver()->internal()->RemoveSender(sender);
|
||||
}
|
||||
|
||||
void PeerConnection::AddVideoTrack(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsClosed());
|
||||
RTC_DCHECK(track);
|
||||
RTC_DCHECK(stream);
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (sender) {
|
||||
// We already have a sender for this track, so just change the stream_id
|
||||
// so that it's correct in the next call to CreateOffer.
|
||||
sender->internal()->set_stream_ids({stream->id()});
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal case; we've never seen this track before.
|
||||
auto new_sender = CreateSender(cricket::MEDIA_TYPE_VIDEO, track->id(), track,
|
||||
{stream->id()}, {});
|
||||
new_sender->internal()->SetMediaChannel(video_media_channel());
|
||||
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_video_sender_infos_, stream->id(), track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::RemoveVideoTrack(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsClosed());
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (!sender) {
|
||||
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
|
||||
<< " doesn't exist.";
|
||||
return;
|
||||
}
|
||||
GetVideoTransceiver()->internal()->RemoveSender(sender);
|
||||
}
|
||||
|
||||
void PeerConnection::SetIceConnectionState(IceConnectionState new_state) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (ice_connection_state_ == new_state) {
|
||||
@ -2126,7 +1750,7 @@ void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
|
||||
if (IsClosed()) {
|
||||
return;
|
||||
}
|
||||
AddAudioTrack(track, stream);
|
||||
rtp_manager()->AddAudioTrack(track, stream);
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
}
|
||||
|
||||
@ -2135,7 +1759,7 @@ void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
|
||||
if (IsClosed()) {
|
||||
return;
|
||||
}
|
||||
RemoveAudioTrack(track, stream);
|
||||
rtp_manager()->RemoveAudioTrack(track, stream);
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
}
|
||||
|
||||
@ -2144,7 +1768,7 @@ void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
|
||||
if (IsClosed()) {
|
||||
return;
|
||||
}
|
||||
AddVideoTrack(track, stream);
|
||||
rtp_manager()->AddVideoTrack(track, stream);
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
}
|
||||
|
||||
@ -2153,7 +1777,7 @@ void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
|
||||
if (IsClosed()) {
|
||||
return;
|
||||
}
|
||||
RemoveVideoTrack(track, stream);
|
||||
rtp_manager()->RemoveVideoTrack(track, stream);
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
}
|
||||
|
||||
@ -2172,104 +1796,6 @@ absl::optional<std::string> PeerConnection::GetDataMid() const {
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::OnRemoteSenderAdded(const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_LOG(LS_INFO) << "Creating " << cricket::MediaTypeToString(media_type)
|
||||
<< " receiver for track_id=" << sender_info.sender_id
|
||||
<< " and stream_id=" << sender_info.stream_id;
|
||||
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
CreateAudioReceiver(stream, sender_info);
|
||||
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
CreateVideoReceiver(stream, sender_info);
|
||||
} else {
|
||||
RTC_NOTREACHED() << "Invalid media type";
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::OnRemoteSenderRemoved(const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_LOG(LS_INFO) << "Removing " << cricket::MediaTypeToString(media_type)
|
||||
<< " receiver for track_id=" << sender_info.sender_id
|
||||
<< " and stream_id=" << sender_info.stream_id;
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverInterface> receiver;
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
// When the MediaEngine audio channel is destroyed, the RemoteAudioSource
|
||||
// will be notified which will end the AudioRtpReceiver::track().
|
||||
receiver = RemoveAndStopReceiver(sender_info);
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track =
|
||||
stream->FindAudioTrack(sender_info.sender_id);
|
||||
if (audio_track) {
|
||||
stream->RemoveTrack(audio_track);
|
||||
}
|
||||
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
// Stopping or destroying a VideoRtpReceiver will end the
|
||||
// VideoRtpReceiver::track().
|
||||
receiver = RemoveAndStopReceiver(sender_info);
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track =
|
||||
stream->FindVideoTrack(sender_info.sender_id);
|
||||
if (video_track) {
|
||||
// There's no guarantee the track is still available, e.g. the track may
|
||||
// have been removed from the stream by an application.
|
||||
stream->RemoveTrack(video_track);
|
||||
}
|
||||
} else {
|
||||
RTC_NOTREACHED() << "Invalid media type";
|
||||
}
|
||||
if (receiver) {
|
||||
Observer()->OnRemoveTrack(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::OnLocalSenderAdded(const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto sender = FindSenderById(sender_info.sender_id);
|
||||
if (!sender) {
|
||||
RTC_LOG(LS_WARNING) << "An unknown RtpSender with id "
|
||||
<< sender_info.sender_id
|
||||
<< " has been configured in the local description.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender->media_type() != media_type) {
|
||||
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
|
||||
" description with an unexpected media type.";
|
||||
return;
|
||||
}
|
||||
|
||||
sender->internal()->set_stream_ids({sender_info.stream_id});
|
||||
sender->internal()->SetSsrc(sender_info.first_ssrc);
|
||||
}
|
||||
|
||||
void PeerConnection::OnLocalSenderRemoved(const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
auto sender = FindSenderById(sender_info.sender_id);
|
||||
if (!sender) {
|
||||
// This is the normal case. I.e., RemoveStream has been called and the
|
||||
// SessionDescriptions has been renegotiated.
|
||||
return;
|
||||
}
|
||||
|
||||
// A sender has been removed from the SessionDescription but it's still
|
||||
// associated with the PeerConnection. This only occurs if the SDP doesn't
|
||||
// match with the calls to CreateSender, AddStream and RemoveStream.
|
||||
if (sender->media_type() != media_type) {
|
||||
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
|
||||
" description with an unexpected media type.";
|
||||
return;
|
||||
}
|
||||
|
||||
sender->internal()->SetSsrc(0);
|
||||
}
|
||||
|
||||
void PeerConnection::OnSctpDataChannelClosed(DataChannelInterface* channel) {
|
||||
// Since data_channel_controller doesn't do signals, this
|
||||
// signal is relayed here.
|
||||
@ -2277,102 +1803,6 @@ void PeerConnection::OnSctpDataChannelClosed(DataChannelInterface* channel) {
|
||||
static_cast<SctpDataChannel*>(channel));
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
PeerConnection::GetAudioTransceiver() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// This method only works with Plan B SDP, where there is a single
|
||||
// audio/video transceiver.
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
RTC_NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
PeerConnection::GetVideoTransceiver() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// This method only works with Plan B SDP, where there is a single
|
||||
// audio/video transceiver.
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
RTC_NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) const {
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (auto sender : transceiver->internal()->senders()) {
|
||||
if (sender->track() == track) {
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
PeerConnection::FindSenderById(const std::string& sender_id) const {
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (auto sender : transceiver->internal()->senders()) {
|
||||
if (sender->id() == sender_id) {
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
PeerConnection::FindReceiverById(const std::string& receiver_id) const {
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (auto receiver : transceiver->internal()->receivers()) {
|
||||
if (receiver->id() == receiver_id) {
|
||||
return receiver;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<PeerConnection::RtpSenderInfo>*
|
||||
PeerConnection::GetRemoteSenderInfos(cricket::MediaType media_type) {
|
||||
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
media_type == cricket::MEDIA_TYPE_VIDEO);
|
||||
return (media_type == cricket::MEDIA_TYPE_AUDIO)
|
||||
? &remote_audio_sender_infos_
|
||||
: &remote_video_sender_infos_;
|
||||
}
|
||||
|
||||
std::vector<PeerConnection::RtpSenderInfo>* PeerConnection::GetLocalSenderInfos(
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
media_type == cricket::MEDIA_TYPE_VIDEO);
|
||||
return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_sender_infos_
|
||||
: &local_video_sender_infos_;
|
||||
}
|
||||
|
||||
const PeerConnection::RtpSenderInfo* PeerConnection::FindSenderInfo(
|
||||
const std::vector<PeerConnection::RtpSenderInfo>& infos,
|
||||
const std::string& stream_id,
|
||||
const std::string sender_id) const {
|
||||
for (const RtpSenderInfo& sender_info : infos) {
|
||||
if (sender_info.stream_id == stream_id &&
|
||||
sender_info.sender_id == sender_id) {
|
||||
return &sender_info;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SctpDataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
|
||||
return data_channel_controller_.FindDataChannelBySid(sid);
|
||||
}
|
||||
@ -2497,7 +1927,7 @@ void PeerConnection::StopRtcEventLog_w() {
|
||||
|
||||
cricket::ChannelInterface* PeerConnection::GetChannel(
|
||||
const std::string& content_name) {
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
if (channel && channel->content_name() == content_name) {
|
||||
return channel;
|
||||
@ -2641,7 +2071,7 @@ std::map<std::string, std::string> PeerConnection::GetTransportNamesByMid()
|
||||
const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::map<std::string, std::string> transport_names_by_mid;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
if (channel) {
|
||||
transport_names_by_mid[channel->content_name()] =
|
||||
@ -3007,7 +2437,7 @@ void PeerConnection::OnTransportControllerGatheringState(
|
||||
void PeerConnection::ReportTransportStats() {
|
||||
std::map<std::string, std::set<cricket::MediaType>>
|
||||
media_types_by_transport_name;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
if (transceiver->internal()->channel()) {
|
||||
const std::string& transport_name =
|
||||
transceiver->internal()->channel()->transport_name();
|
||||
@ -3173,12 +2603,6 @@ bool PeerConnection::OnTransportChanged(
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PeerConnection::OnSetStreams() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (IsUnifiedPlan())
|
||||
sdp_handler_.UpdateNegotiationNeeded();
|
||||
}
|
||||
|
||||
PeerConnectionObserver* PeerConnection::Observer() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(observer_);
|
||||
|
||||
@ -73,8 +73,10 @@
|
||||
#include "pc/rtp_receiver.h"
|
||||
#include "pc/rtp_sender.h"
|
||||
#include "pc/rtp_transceiver.h"
|
||||
#include "pc/rtp_transmission_manager.h"
|
||||
#include "pc/rtp_transport_internal.h"
|
||||
#include "pc/sctp_data_channel.h"
|
||||
#include "pc/sctp_transport.h"
|
||||
#include "pc/sdp_offer_answer.h"
|
||||
#include "pc/session_description.h"
|
||||
#include "pc/stats_collector.h"
|
||||
@ -114,7 +116,6 @@ namespace webrtc {
|
||||
// - Generating stats.
|
||||
class PeerConnection : public PeerConnectionInternal,
|
||||
public JsepTransportController::Observer,
|
||||
public RtpSenderBase::SetStreamsObserver,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
explicit PeerConnection(rtc::scoped_refptr<ConnectionContext> context,
|
||||
@ -291,7 +292,7 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
|
||||
GetTransceiversInternal() const override {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
return transceivers_.List();
|
||||
return rtp_manager()->transceivers()->List();
|
||||
}
|
||||
|
||||
sigslot::signal1<RtpDataChannel*>& SignalRtpDataChannelCreated() override {
|
||||
@ -366,6 +367,11 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
return &message_handler_;
|
||||
}
|
||||
|
||||
RtpTransmissionManager* rtp_manager() { return rtp_manager_.get(); }
|
||||
const RtpTransmissionManager* rtp_manager() const {
|
||||
return rtp_manager_.get();
|
||||
}
|
||||
|
||||
// Functions made public for testing.
|
||||
void ReturnHistogramVeryQuicklyForTesting() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
@ -381,83 +387,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
// TOOD(https://bugs.webrtc.org/11995): Remove friendship.
|
||||
friend class SdpOfferAnswerHandler;
|
||||
|
||||
struct RtpSenderInfo {
|
||||
RtpSenderInfo() : first_ssrc(0) {}
|
||||
RtpSenderInfo(const std::string& stream_id,
|
||||
const std::string sender_id,
|
||||
uint32_t ssrc)
|
||||
: stream_id(stream_id), sender_id(sender_id), first_ssrc(ssrc) {}
|
||||
bool operator==(const RtpSenderInfo& other) {
|
||||
return this->stream_id == other.stream_id &&
|
||||
this->sender_id == other.sender_id &&
|
||||
this->first_ssrc == other.first_ssrc;
|
||||
}
|
||||
std::string stream_id;
|
||||
std::string sender_id;
|
||||
// An RtpSender can have many SSRCs. The first one is used as a sort of ID
|
||||
// for communicating with the lower layers.
|
||||
uint32_t first_ssrc;
|
||||
};
|
||||
|
||||
// Plan B helpers for getting the voice/video media channels for the single
|
||||
// audio/video transceiver, if it exists.
|
||||
cricket::VoiceMediaChannel* voice_media_channel() const
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
cricket::VideoMediaChannel* video_media_channel() const
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
||||
GetSendersInternal() const;
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
||||
GetReceiversInternal() const RTC_RUN_ON(signaling_thread());
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
GetAudioTransceiver() const;
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
GetVideoTransceiver() const;
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
GetFirstAudioTransceiver() const RTC_RUN_ON(signaling_thread());
|
||||
|
||||
|
||||
void CreateAudioReceiver(MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
void CreateVideoReceiver(MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
rtc::scoped_refptr<RtpReceiverInterface> RemoveAndStopReceiver(
|
||||
const RtpSenderInfo& remote_sender_info) RTC_RUN_ON(signaling_thread());
|
||||
|
||||
// May be called either by AddStream/RemoveStream, or when a track is
|
||||
// added/removed from a stream previously added via AddStream.
|
||||
void AddAudioTrack(AudioTrackInterface* track, MediaStreamInterface* stream);
|
||||
void RemoveAudioTrack(AudioTrackInterface* track,
|
||||
MediaStreamInterface* stream);
|
||||
void AddVideoTrack(VideoTrackInterface* track, MediaStreamInterface* stream);
|
||||
void RemoveVideoTrack(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream);
|
||||
|
||||
// AddTrack implementation when Unified Plan is specified.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrackUnifiedPlan(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
// AddTrack implementation when Plan B is specified.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrackPlanB(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
// Returns the first RtpTransceiver suitable for a newly added track, if such
|
||||
// transceiver is available.
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
FindFirstTransceiverForAddedTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
FindTransceiverBySender(rtc::scoped_refptr<RtpSenderInterface> sender)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
@ -470,24 +399,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
const RtpTransceiverInit& init,
|
||||
bool fire_callback = true);
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
CreateSender(cricket::MediaType media_type,
|
||||
const std::string& id,
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& send_encodings);
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
CreateReceiver(cricket::MediaType media_type, const std::string& receiver_id);
|
||||
|
||||
// Create a new RtpTransceiver of the given type and add it to the list of
|
||||
// transceivers.
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
CreateAndAddTransceiver(
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
receiver);
|
||||
|
||||
void SetIceConnectionState(IceConnectionState new_state);
|
||||
void SetStandardizedIceConnectionState(
|
||||
PeerConnectionInterface::IceConnectionState new_state)
|
||||
@ -539,36 +450,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
// channels are configured this will return nullopt.
|
||||
absl::optional<std::string> GetDataMid() const;
|
||||
|
||||
// Triggered when a remote sender has been seen for the first time in a remote
|
||||
// session description. It creates a remote MediaStreamTrackInterface
|
||||
// implementation and triggers CreateAudioReceiver or CreateVideoReceiver.
|
||||
void OnRemoteSenderAdded(const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Triggered when a remote sender has been removed from a remote session
|
||||
// description. It removes the remote sender with id |sender_id| from a remote
|
||||
// MediaStream and triggers DestroyAudioReceiver or DestroyVideoReceiver.
|
||||
void OnRemoteSenderRemoved(const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Triggered when a local sender has been seen for the first time in a local
|
||||
// session description.
|
||||
// This method triggers CreateAudioSender or CreateVideoSender if the rtp
|
||||
// streams in the local SessionDescription can be mapped to a MediaStreamTrack
|
||||
// in a MediaStream in |local_streams_|
|
||||
void OnLocalSenderAdded(const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Triggered when a local sender has been removed from a local session
|
||||
// description.
|
||||
// This method triggers DestroyAudioSender or DestroyVideoSender if a stream
|
||||
// has been removed from the local SessionDescription and the stream can be
|
||||
// mapped to a MediaStreamTrack in a MediaStream in |local_streams_|.
|
||||
void OnLocalSenderRemoved(const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Returns true if the PeerConnection is configured to use Unified Plan
|
||||
// semantics for creating offers/answers and setting local/remote
|
||||
// descriptions. If this is true the RtpTransceiver API will also be available
|
||||
@ -580,29 +461,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
return configuration_.sdp_semantics == SdpSemantics::kUnifiedPlan;
|
||||
}
|
||||
|
||||
// Return the RtpSender with the given track attached.
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
FindSenderForTrack(MediaStreamTrackInterface* track) const
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
// Return the RtpSender with the given id, or null if none exists.
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
FindSenderById(const std::string& sender_id) const
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
// Return the RtpReceiver with the given id, or null if none exists.
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
FindReceiverById(const std::string& receiver_id) const
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
std::vector<RtpSenderInfo>* GetRemoteSenderInfos(
|
||||
cricket::MediaType media_type);
|
||||
std::vector<RtpSenderInfo>* GetLocalSenderInfos(
|
||||
cricket::MediaType media_type);
|
||||
const RtpSenderInfo* FindSenderInfo(const std::vector<RtpSenderInfo>& infos,
|
||||
const std::string& stream_id,
|
||||
const std::string sender_id) const;
|
||||
|
||||
// Returns the specified SCTP DataChannel in sctp_data_channels_,
|
||||
// or nullptr if not found.
|
||||
SctpDataChannel* FindDataChannelBySid(int sid) const
|
||||
@ -739,9 +597,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
rtc::scoped_refptr<DtlsTransport> dtls_transport,
|
||||
DataChannelTransportInterface* data_channel_transport) override;
|
||||
|
||||
// RtpSenderBase::SetStreamsObserver override.
|
||||
void OnSetStreams() override;
|
||||
|
||||
// Returns the CryptoOptions for this PeerConnection. This will always
|
||||
// return the RTCConfiguration.crypto_options if set and will only default
|
||||
// back to the PeerConnectionFactory settings if nothing was set.
|
||||
@ -806,16 +661,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
tls_cert_verifier_; // TODO(bugs.webrtc.org/9987): Accessed on both
|
||||
// signaling and network thread.
|
||||
|
||||
// These lists store sender info seen in local/remote descriptions.
|
||||
std::vector<RtpSenderInfo> remote_audio_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
std::vector<RtpSenderInfo> remote_video_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
std::vector<RtpSenderInfo> local_audio_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
std::vector<RtpSenderInfo> local_video_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
|
||||
// The unique_ptr belongs to the worker thread, but the Call object manages
|
||||
// its own thread safety.
|
||||
std::unique_ptr<Call> call_ RTC_GUARDED_BY(worker_thread());
|
||||
@ -832,7 +677,6 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
RTC_GUARDED_BY(signaling_thread()); // A pointer is passed to senders_
|
||||
rtc::scoped_refptr<RTCStatsCollector> stats_collector_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
TransceiverList transceivers_;
|
||||
|
||||
std::string session_id_ RTC_GUARDED_BY(signaling_thread());
|
||||
|
||||
@ -882,6 +726,10 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
|
||||
// Machinery for handling messages posted to oneself
|
||||
PeerConnectionMessageHandler message_handler_;
|
||||
|
||||
// Administration of senders, receivers and transceivers
|
||||
// Accessed on both signaling and network thread. Const after Initialize().
|
||||
std::unique_ptr<RtpTransmissionManager> rtp_manager_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
692
pc/rtp_transmission_manager.cc
Normal file
692
pc/rtp_transmission_manager.cc
Normal file
@ -0,0 +1,692 @@
|
||||
/*
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
|
||||
#include "pc/rtp_transmission_manager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/rtp_transceiver_direction.h"
|
||||
#include "pc/audio_rtp_receiver.h"
|
||||
#include "pc/channel.h"
|
||||
#include "pc/stats_collector_interface.h"
|
||||
#include "pc/video_rtp_receiver.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/helpers.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kDefaultAudioSenderId[] = "defaulta0";
|
||||
static const char kDefaultVideoSenderId[] = "defaultv0";
|
||||
|
||||
} // namespace
|
||||
|
||||
RtpTransmissionManager::RtpTransmissionManager(
|
||||
bool is_unified_plan,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
cricket::ChannelManager* channel_manager,
|
||||
UsagePattern* usage_pattern,
|
||||
PeerConnectionObserver* observer,
|
||||
StatsCollectorInterface* stats,
|
||||
std::function<void()> on_negotiation_needed)
|
||||
: is_unified_plan_(is_unified_plan),
|
||||
signaling_thread_(signaling_thread),
|
||||
worker_thread_(worker_thread),
|
||||
channel_manager_(channel_manager),
|
||||
usage_pattern_(usage_pattern),
|
||||
observer_(observer),
|
||||
stats_(stats),
|
||||
on_negotiation_needed_(on_negotiation_needed) {}
|
||||
|
||||
void RtpTransmissionManager::Close() {
|
||||
closed_ = true;
|
||||
observer_ = nullptr;
|
||||
}
|
||||
|
||||
// Implementation of SetStreamsObserver
|
||||
void RtpTransmissionManager::OnSetStreams() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (IsUnifiedPlan())
|
||||
OnNegotiationNeeded();
|
||||
}
|
||||
|
||||
// Function to call back to the PeerConnection when negotiation is needed
|
||||
void RtpTransmissionManager::OnNegotiationNeeded() {
|
||||
on_negotiation_needed_();
|
||||
}
|
||||
|
||||
// Function that returns the currently valid observer
|
||||
PeerConnectionObserver* RtpTransmissionManager::Observer() const {
|
||||
RTC_DCHECK(!closed_);
|
||||
RTC_DCHECK(observer_);
|
||||
return observer_;
|
||||
}
|
||||
|
||||
cricket::VoiceMediaChannel* RtpTransmissionManager::voice_media_channel()
|
||||
const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto* voice_channel = static_cast<cricket::VoiceChannel*>(
|
||||
GetAudioTransceiver()->internal()->channel());
|
||||
if (voice_channel) {
|
||||
return voice_channel->media_channel();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
cricket::VideoMediaChannel* RtpTransmissionManager::video_media_channel()
|
||||
const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto* video_channel = static_cast<cricket::VideoChannel*>(
|
||||
GetVideoTransceiver()->internal()->channel());
|
||||
if (video_channel) {
|
||||
return video_channel->media_channel();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
RtpTransmissionManager::AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
|
||||
return (IsUnifiedPlan() ? AddTrackUnifiedPlan(track, stream_ids)
|
||||
: AddTrackPlanB(track, stream_ids));
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
RtpTransmissionManager::AddTrackPlanB(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (stream_ids.size() > 1u) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
|
||||
"AddTrack with more than one stream is not "
|
||||
"supported with Plan B semantics.");
|
||||
}
|
||||
std::vector<std::string> adjusted_stream_ids = stream_ids;
|
||||
if (adjusted_stream_ids.empty()) {
|
||||
adjusted_stream_ids.push_back(rtc::CreateRandomUuid());
|
||||
}
|
||||
cricket::MediaType media_type =
|
||||
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
||||
? cricket::MEDIA_TYPE_AUDIO
|
||||
: cricket::MEDIA_TYPE_VIDEO);
|
||||
auto new_sender =
|
||||
CreateSender(media_type, track->id(), track, adjusted_stream_ids, {});
|
||||
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
||||
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
||||
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_audio_sender_infos_,
|
||||
new_sender->internal()->stream_ids()[0], track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
} else {
|
||||
RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
|
||||
new_sender->internal()->SetMediaChannel(video_media_channel());
|
||||
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_video_sender_infos_,
|
||||
new_sender->internal()->stream_ids()[0], track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
}
|
||||
return rtc::scoped_refptr<RtpSenderInterface>(new_sender);
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
RtpTransmissionManager::AddTrackUnifiedPlan(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
auto transceiver = FindFirstTransceiverForAddedTrack(track);
|
||||
if (transceiver) {
|
||||
RTC_LOG(LS_INFO) << "Reusing an existing "
|
||||
<< cricket::MediaTypeToString(transceiver->media_type())
|
||||
<< " transceiver for AddTrack.";
|
||||
if (transceiver->stopping()) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
||||
"The existing transceiver is stopping.");
|
||||
}
|
||||
|
||||
if (transceiver->direction() == RtpTransceiverDirection::kRecvOnly) {
|
||||
transceiver->internal()->set_direction(
|
||||
RtpTransceiverDirection::kSendRecv);
|
||||
} else if (transceiver->direction() == RtpTransceiverDirection::kInactive) {
|
||||
transceiver->internal()->set_direction(
|
||||
RtpTransceiverDirection::kSendOnly);
|
||||
}
|
||||
transceiver->sender()->SetTrack(track);
|
||||
transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
|
||||
transceiver->internal()->set_reused_for_addtrack(true);
|
||||
} else {
|
||||
cricket::MediaType media_type =
|
||||
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
||||
? cricket::MEDIA_TYPE_AUDIO
|
||||
: cricket::MEDIA_TYPE_VIDEO);
|
||||
RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
|
||||
<< " transceiver in response to a call to AddTrack.";
|
||||
std::string sender_id = track->id();
|
||||
// Avoid creating a sender with an existing ID by generating a random ID.
|
||||
// This can happen if this is the second time AddTrack has created a sender
|
||||
// for this track.
|
||||
if (FindSenderById(sender_id)) {
|
||||
sender_id = rtc::CreateRandomUuid();
|
||||
}
|
||||
auto sender = CreateSender(media_type, sender_id, track, stream_ids, {});
|
||||
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
|
||||
transceiver = CreateAndAddTransceiver(sender, receiver);
|
||||
transceiver->internal()->set_created_by_addtrack(true);
|
||||
transceiver->internal()->set_direction(RtpTransceiverDirection::kSendRecv);
|
||||
}
|
||||
return transceiver->sender();
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
RtpTransmissionManager::CreateSender(
|
||||
cricket::MediaType media_type,
|
||||
const std::string& id,
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& send_encodings) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender;
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
RTC_DCHECK(!track ||
|
||||
(track->kind() == MediaStreamTrackInterface::kAudioKind));
|
||||
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||
signaling_thread(),
|
||||
AudioRtpSender::Create(worker_thread(), id, stats_, this));
|
||||
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
||||
} else {
|
||||
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
|
||||
RTC_DCHECK(!track ||
|
||||
(track->kind() == MediaStreamTrackInterface::kVideoKind));
|
||||
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||
signaling_thread(), VideoRtpSender::Create(worker_thread(), id, this));
|
||||
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
||||
}
|
||||
bool set_track_succeeded = sender->SetTrack(track);
|
||||
RTC_DCHECK(set_track_succeeded);
|
||||
sender->internal()->set_stream_ids(stream_ids);
|
||||
sender->internal()->set_init_send_encodings(send_encodings);
|
||||
return sender;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
RtpTransmissionManager::CreateReceiver(cricket::MediaType media_type,
|
||||
const std::string& receiver_id) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
receiver;
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), new AudioRtpReceiver(worker_thread(), receiver_id,
|
||||
std::vector<std::string>({})));
|
||||
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
||||
} else {
|
||||
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
|
||||
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), new VideoRtpReceiver(worker_thread(), receiver_id,
|
||||
std::vector<std::string>({})));
|
||||
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
RtpTransmissionManager::CreateAndAddTransceiver(
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
receiver) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// Ensure that the new sender does not have an ID that is already in use by
|
||||
// another sender.
|
||||
// Allow receiver IDs to conflict since those come from remote SDP (which
|
||||
// could be invalid, but should not cause a crash).
|
||||
RTC_DCHECK(!FindSenderById(sender->id()));
|
||||
auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||
signaling_thread(),
|
||||
new RtpTransceiver(
|
||||
sender, receiver, channel_manager(),
|
||||
sender->media_type() == cricket::MEDIA_TYPE_AUDIO
|
||||
? channel_manager()->GetSupportedAudioRtpHeaderExtensions()
|
||||
: channel_manager()->GetSupportedVideoRtpHeaderExtensions()));
|
||||
transceivers()->Add(transceiver);
|
||||
transceiver->internal()->SignalNegotiationNeeded.connect(
|
||||
this, &RtpTransmissionManager::OnNegotiationNeeded);
|
||||
return transceiver;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
RtpTransmissionManager::FindFirstTransceiverForAddedTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(track);
|
||||
for (auto transceiver : transceivers()->List()) {
|
||||
if (!transceiver->sender()->track() &&
|
||||
cricket::MediaTypeToString(transceiver->media_type()) ==
|
||||
track->kind() &&
|
||||
!transceiver->internal()->has_ever_been_used_to_send() &&
|
||||
!transceiver->stopped()) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
||||
RtpTransmissionManager::GetSendersInternal() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
||||
all_senders;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
if (IsUnifiedPlan() && transceiver->internal()->stopped())
|
||||
continue;
|
||||
|
||||
auto senders = transceiver->internal()->senders();
|
||||
all_senders.insert(all_senders.end(), senders.begin(), senders.end());
|
||||
}
|
||||
return all_senders;
|
||||
}
|
||||
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
||||
RtpTransmissionManager::GetReceiversInternal() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
||||
all_receivers;
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
if (IsUnifiedPlan() && transceiver->internal()->stopped())
|
||||
continue;
|
||||
|
||||
auto receivers = transceiver->internal()->receivers();
|
||||
all_receivers.insert(all_receivers.end(), receivers.begin(),
|
||||
receivers.end());
|
||||
}
|
||||
return all_receivers;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
RtpTransmissionManager::GetAudioTransceiver() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// This method only works with Plan B SDP, where there is a single
|
||||
// audio/video transceiver.
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
RTC_NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
RtpTransmissionManager::GetVideoTransceiver() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// This method only works with Plan B SDP, where there is a single
|
||||
// audio/video transceiver.
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
RTC_NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::AddAudioTrack(AudioTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(track);
|
||||
RTC_DCHECK(stream);
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (sender) {
|
||||
// We already have a sender for this track, so just change the stream_id
|
||||
// so that it's correct in the next call to CreateOffer.
|
||||
sender->internal()->set_stream_ids({stream->id()});
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal case; we've never seen this track before.
|
||||
auto new_sender = CreateSender(cricket::MEDIA_TYPE_AUDIO, track->id(), track,
|
||||
{stream->id()}, {});
|
||||
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
||||
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
// If the sender has already been configured in SDP, we call SetSsrc,
|
||||
// which will connect the sender to the underlying transport. This can
|
||||
// occur if a local session description that contains the ID of the sender
|
||||
// is set before AddStream is called. It can also occur if the local
|
||||
// session description is not changed and RemoveStream is called, and
|
||||
// later AddStream is called again with the same stream.
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_audio_sender_infos_, stream->id(), track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
|
||||
// indefinitely, when we have unified plan SDP.
|
||||
void RtpTransmissionManager::RemoveAudioTrack(AudioTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (!sender) {
|
||||
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
|
||||
<< " doesn't exist.";
|
||||
return;
|
||||
}
|
||||
GetAudioTransceiver()->internal()->RemoveSender(sender);
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::AddVideoTrack(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(track);
|
||||
RTC_DCHECK(stream);
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (sender) {
|
||||
// We already have a sender for this track, so just change the stream_id
|
||||
// so that it's correct in the next call to CreateOffer.
|
||||
sender->internal()->set_stream_ids({stream->id()});
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal case; we've never seen this track before.
|
||||
auto new_sender = CreateSender(cricket::MEDIA_TYPE_VIDEO, track->id(), track,
|
||||
{stream->id()}, {});
|
||||
new_sender->internal()->SetMediaChannel(video_media_channel());
|
||||
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
||||
const RtpSenderInfo* sender_info =
|
||||
FindSenderInfo(local_video_sender_infos_, stream->id(), track->id());
|
||||
if (sender_info) {
|
||||
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::RemoveVideoTrack(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto sender = FindSenderForTrack(track);
|
||||
if (!sender) {
|
||||
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
|
||||
<< " doesn't exist.";
|
||||
return;
|
||||
}
|
||||
GetVideoTransceiver()->internal()->RemoveSender(sender);
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
RtpTransmissionManager::GetFirstAudioTransceiver() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
for (auto transceiver : transceivers_.List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
return transceiver;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::CreateAudioReceiver(
|
||||
MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info) {
|
||||
RTC_DCHECK(!closed_);
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
||||
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
|
||||
// TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
|
||||
// the constructor taking stream IDs instead.
|
||||
auto* audio_receiver = new AudioRtpReceiver(
|
||||
worker_thread(), remote_sender_info.sender_id, streams);
|
||||
audio_receiver->SetMediaChannel(voice_media_channel());
|
||||
if (remote_sender_info.sender_id == kDefaultAudioSenderId) {
|
||||
audio_receiver->SetupUnsignaledMediaChannel();
|
||||
} else {
|
||||
audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
|
||||
}
|
||||
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), audio_receiver);
|
||||
GetAudioTransceiver()->internal()->AddReceiver(receiver);
|
||||
Observer()->OnAddTrack(receiver, streams);
|
||||
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::CreateVideoReceiver(
|
||||
MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info) {
|
||||
RTC_DCHECK(!closed_);
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
||||
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
|
||||
// TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
|
||||
// the constructor taking stream IDs instead.
|
||||
auto* video_receiver = new VideoRtpReceiver(
|
||||
worker_thread(), remote_sender_info.sender_id, streams);
|
||||
video_receiver->SetMediaChannel(video_media_channel());
|
||||
if (remote_sender_info.sender_id == kDefaultVideoSenderId) {
|
||||
video_receiver->SetupUnsignaledMediaChannel();
|
||||
} else {
|
||||
video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
|
||||
}
|
||||
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||
signaling_thread(), video_receiver);
|
||||
GetVideoTransceiver()->internal()->AddReceiver(receiver);
|
||||
Observer()->OnAddTrack(receiver, streams);
|
||||
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
||||
}
|
||||
|
||||
// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
|
||||
// description.
|
||||
rtc::scoped_refptr<RtpReceiverInterface>
|
||||
RtpTransmissionManager::RemoveAndStopReceiver(
|
||||
const RtpSenderInfo& remote_sender_info) {
|
||||
auto receiver = FindReceiverById(remote_sender_info.sender_id);
|
||||
if (!receiver) {
|
||||
RTC_LOG(LS_WARNING) << "RtpReceiver for track with id "
|
||||
<< remote_sender_info.sender_id << " doesn't exist.";
|
||||
return nullptr;
|
||||
}
|
||||
if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
GetAudioTransceiver()->internal()->RemoveReceiver(receiver);
|
||||
} else {
|
||||
GetVideoTransceiver()->internal()->RemoveReceiver(receiver);
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::OnRemoteSenderAdded(
|
||||
const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_LOG(LS_INFO) << "Creating " << cricket::MediaTypeToString(media_type)
|
||||
<< " receiver for track_id=" << sender_info.sender_id
|
||||
<< " and stream_id=" << sender_info.stream_id;
|
||||
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
CreateAudioReceiver(stream, sender_info);
|
||||
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
CreateVideoReceiver(stream, sender_info);
|
||||
} else {
|
||||
RTC_NOTREACHED() << "Invalid media type";
|
||||
}
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::OnRemoteSenderRemoved(
|
||||
const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_LOG(LS_INFO) << "Removing " << cricket::MediaTypeToString(media_type)
|
||||
<< " receiver for track_id=" << sender_info.sender_id
|
||||
<< " and stream_id=" << sender_info.stream_id;
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverInterface> receiver;
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||
// When the MediaEngine audio channel is destroyed, the RemoteAudioSource
|
||||
// will be notified which will end the AudioRtpReceiver::track().
|
||||
receiver = RemoveAndStopReceiver(sender_info);
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track =
|
||||
stream->FindAudioTrack(sender_info.sender_id);
|
||||
if (audio_track) {
|
||||
stream->RemoveTrack(audio_track);
|
||||
}
|
||||
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
// Stopping or destroying a VideoRtpReceiver will end the
|
||||
// VideoRtpReceiver::track().
|
||||
receiver = RemoveAndStopReceiver(sender_info);
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track =
|
||||
stream->FindVideoTrack(sender_info.sender_id);
|
||||
if (video_track) {
|
||||
// There's no guarantee the track is still available, e.g. the track may
|
||||
// have been removed from the stream by an application.
|
||||
stream->RemoveTrack(video_track);
|
||||
}
|
||||
} else {
|
||||
RTC_NOTREACHED() << "Invalid media type";
|
||||
}
|
||||
if (receiver) {
|
||||
RTC_DCHECK(!closed_);
|
||||
Observer()->OnRemoveTrack(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::OnLocalSenderAdded(
|
||||
const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
auto sender = FindSenderById(sender_info.sender_id);
|
||||
if (!sender) {
|
||||
RTC_LOG(LS_WARNING) << "An unknown RtpSender with id "
|
||||
<< sender_info.sender_id
|
||||
<< " has been configured in the local description.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender->media_type() != media_type) {
|
||||
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
|
||||
" description with an unexpected media type.";
|
||||
return;
|
||||
}
|
||||
|
||||
sender->internal()->set_stream_ids({sender_info.stream_id});
|
||||
sender->internal()->SetSsrc(sender_info.first_ssrc);
|
||||
}
|
||||
|
||||
void RtpTransmissionManager::OnLocalSenderRemoved(
|
||||
const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
auto sender = FindSenderById(sender_info.sender_id);
|
||||
if (!sender) {
|
||||
// This is the normal case. I.e., RemoveStream has been called and the
|
||||
// SessionDescriptions has been renegotiated.
|
||||
return;
|
||||
}
|
||||
|
||||
// A sender has been removed from the SessionDescription but it's still
|
||||
// associated with the PeerConnection. This only occurs if the SDP doesn't
|
||||
// match with the calls to CreateSender, AddStream and RemoveStream.
|
||||
if (sender->media_type() != media_type) {
|
||||
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
|
||||
" description with an unexpected media type.";
|
||||
return;
|
||||
}
|
||||
|
||||
sender->internal()->SetSsrc(0);
|
||||
}
|
||||
|
||||
std::vector<RtpSenderInfo>* RtpTransmissionManager::GetRemoteSenderInfos(
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
media_type == cricket::MEDIA_TYPE_VIDEO);
|
||||
return (media_type == cricket::MEDIA_TYPE_AUDIO)
|
||||
? &remote_audio_sender_infos_
|
||||
: &remote_video_sender_infos_;
|
||||
}
|
||||
|
||||
std::vector<RtpSenderInfo>* RtpTransmissionManager::GetLocalSenderInfos(
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
media_type == cricket::MEDIA_TYPE_VIDEO);
|
||||
return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_sender_infos_
|
||||
: &local_video_sender_infos_;
|
||||
}
|
||||
|
||||
const RtpSenderInfo* RtpTransmissionManager::FindSenderInfo(
|
||||
const std::vector<RtpSenderInfo>& infos,
|
||||
const std::string& stream_id,
|
||||
const std::string sender_id) const {
|
||||
for (const RtpSenderInfo& sender_info : infos) {
|
||||
if (sender_info.stream_id == stream_id &&
|
||||
sender_info.sender_id == sender_id) {
|
||||
return &sender_info;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
RtpTransmissionManager::FindSenderForTrack(
|
||||
MediaStreamTrackInterface* track) const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (auto sender : transceiver->internal()->senders()) {
|
||||
if (sender->track() == track) {
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
RtpTransmissionManager::FindSenderById(const std::string& sender_id) const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (auto sender : transceiver->internal()->senders()) {
|
||||
if (sender->id() == sender_id) {
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
RtpTransmissionManager::FindReceiverById(const std::string& receiver_id) const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
for (const auto& transceiver : transceivers_.List()) {
|
||||
for (auto receiver : transceiver->internal()->receivers()) {
|
||||
if (receiver->id() == receiver_id) {
|
||||
return receiver;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
270
pc/rtp_transmission_manager.h
Normal file
270
pc/rtp_transmission_manager.h
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef PC_RTP_TRANSMISSION_MANAGER_H_
|
||||
#define PC_RTP_TRANSMISSION_MANAGER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/rtc_error.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_receiver_interface.h"
|
||||
#include "api/rtp_sender_interface.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "pc/channel_manager.h"
|
||||
#include "pc/rtp_receiver.h"
|
||||
#include "pc/rtp_sender.h"
|
||||
#include "pc/rtp_transceiver.h"
|
||||
#include "pc/stats_collector_interface.h"
|
||||
#include "pc/transceiver_list.h"
|
||||
#include "pc/usage_pattern.h"
|
||||
#include "rtc_base/synchronization/sequence_checker.h"
|
||||
#include "rtc_base/third_party/sigslot/sigslot.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
namespace rtc {
|
||||
class Thread;
|
||||
}
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This class contains information about
|
||||
// an RTPSender, used for things like looking it up by SSRC.
|
||||
struct RtpSenderInfo {
|
||||
RtpSenderInfo() : first_ssrc(0) {}
|
||||
RtpSenderInfo(const std::string& stream_id,
|
||||
const std::string sender_id,
|
||||
uint32_t ssrc)
|
||||
: stream_id(stream_id), sender_id(sender_id), first_ssrc(ssrc) {}
|
||||
bool operator==(const RtpSenderInfo& other) {
|
||||
return this->stream_id == other.stream_id &&
|
||||
this->sender_id == other.sender_id &&
|
||||
this->first_ssrc == other.first_ssrc;
|
||||
}
|
||||
std::string stream_id;
|
||||
std::string sender_id;
|
||||
// An RtpSender can have many SSRCs. The first one is used as a sort of ID
|
||||
// for communicating with the lower layers.
|
||||
uint32_t first_ssrc;
|
||||
};
|
||||
|
||||
// The RtpTransmissionManager class is responsible for managing the lifetime
|
||||
// and relationships between objects of type RtpSender, RtpReceiver and
|
||||
// RtpTransceiver.
|
||||
class RtpTransmissionManager : public RtpSenderBase::SetStreamsObserver,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
RtpTransmissionManager(bool is_unified_plan,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
cricket::ChannelManager* channel_manager,
|
||||
UsagePattern* usage_pattern,
|
||||
PeerConnectionObserver* observer,
|
||||
StatsCollectorInterface* stats_,
|
||||
std::function<void()> on_negotiation_needed);
|
||||
|
||||
// No move or copy permitted.
|
||||
RtpTransmissionManager(const RtpTransmissionManager&) = delete;
|
||||
RtpTransmissionManager& operator=(const RtpTransmissionManager&) = delete;
|
||||
|
||||
// Stop activity. In particular, don't call observer_ any more.
|
||||
void Close();
|
||||
|
||||
// RtpSenderBase::SetStreamsObserver override.
|
||||
void OnSetStreams() override;
|
||||
|
||||
// Add a new track, creating transceiver if required.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
|
||||
// Create a new RTP sender. Does not associate with a transceiver.
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
CreateSender(cricket::MediaType media_type,
|
||||
const std::string& id,
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& send_encodings);
|
||||
|
||||
// Create a new RTP receiver. Does not associate with a transceiver.
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
CreateReceiver(cricket::MediaType media_type, const std::string& receiver_id);
|
||||
|
||||
// Create a new RtpTransceiver of the given type and add it to the list of
|
||||
// registered transceivers.
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
CreateAndAddTransceiver(
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
receiver);
|
||||
|
||||
// Returns the first RtpTransceiver suitable for a newly added track, if such
|
||||
// transceiver is available.
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
FindFirstTransceiverForAddedTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track);
|
||||
|
||||
// Returns the list of senders currently associated with some
|
||||
// registered transceiver
|
||||
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
||||
GetSendersInternal() const;
|
||||
|
||||
// Returns the list of receivers currently associated with a transceiver
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
||||
GetReceiversInternal() const;
|
||||
|
||||
// Plan B: Get the transceiver containing all audio senders and receivers
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
GetAudioTransceiver() const;
|
||||
// Plan B: Get the transceiver containing all video senders and receivers
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
GetVideoTransceiver() const;
|
||||
|
||||
// Gets the first audio transceiver.
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
GetFirstAudioTransceiver() const;
|
||||
|
||||
// Add an audio track, reusing or creating the sender.
|
||||
void AddAudioTrack(AudioTrackInterface* track, MediaStreamInterface* stream);
|
||||
// Plan B: Remove an audio track, removing the sender.
|
||||
void RemoveAudioTrack(AudioTrackInterface* track,
|
||||
MediaStreamInterface* stream);
|
||||
// Add a video track, reusing or creating the sender.
|
||||
void AddVideoTrack(VideoTrackInterface* track, MediaStreamInterface* stream);
|
||||
// Plan B: Remove a video track, removing the sender.
|
||||
void RemoveVideoTrack(VideoTrackInterface* track,
|
||||
MediaStreamInterface* stream);
|
||||
|
||||
// Triggered when a remote sender has been seen for the first time in a remote
|
||||
// session description. It creates a remote MediaStreamTrackInterface
|
||||
// implementation and triggers CreateAudioReceiver or CreateVideoReceiver.
|
||||
void OnRemoteSenderAdded(const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Triggered when a remote sender has been removed from a remote session
|
||||
// description. It removes the remote sender with id |sender_id| from a remote
|
||||
// MediaStream and triggers DestroyAudioReceiver or DestroyVideoReceiver.
|
||||
void OnRemoteSenderRemoved(const RtpSenderInfo& sender_info,
|
||||
MediaStreamInterface* stream,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Triggered when a local sender has been seen for the first time in a local
|
||||
// session description.
|
||||
// This method triggers CreateAudioSender or CreateVideoSender if the rtp
|
||||
// streams in the local SessionDescription can be mapped to a MediaStreamTrack
|
||||
// in a MediaStream in |local_streams_|
|
||||
void OnLocalSenderAdded(const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
// Triggered when a local sender has been removed from a local session
|
||||
// description.
|
||||
// This method triggers DestroyAudioSender or DestroyVideoSender if a stream
|
||||
// has been removed from the local SessionDescription and the stream can be
|
||||
// mapped to a MediaStreamTrack in a MediaStream in |local_streams_|.
|
||||
void OnLocalSenderRemoved(const RtpSenderInfo& sender_info,
|
||||
cricket::MediaType media_type);
|
||||
|
||||
std::vector<RtpSenderInfo>* GetRemoteSenderInfos(
|
||||
cricket::MediaType media_type);
|
||||
std::vector<RtpSenderInfo>* GetLocalSenderInfos(
|
||||
cricket::MediaType media_type);
|
||||
const RtpSenderInfo* FindSenderInfo(const std::vector<RtpSenderInfo>& infos,
|
||||
const std::string& stream_id,
|
||||
const std::string sender_id) const;
|
||||
|
||||
// Return the RtpSender with the given track attached.
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
FindSenderForTrack(MediaStreamTrackInterface* track) const;
|
||||
|
||||
// Return the RtpSender with the given id, or null if none exists.
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
FindSenderById(const std::string& sender_id) const;
|
||||
|
||||
// Return the RtpReceiver with the given id, or null if none exists.
|
||||
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||
FindReceiverById(const std::string& receiver_id) const;
|
||||
|
||||
TransceiverList* transceivers() { return &transceivers_; }
|
||||
const TransceiverList* transceivers() const { return &transceivers_; }
|
||||
|
||||
// Plan B helpers for getting the voice/video media channels for the single
|
||||
// audio/video transceiver, if it exists.
|
||||
cricket::VoiceMediaChannel* voice_media_channel() const;
|
||||
cricket::VideoMediaChannel* video_media_channel() const;
|
||||
|
||||
private:
|
||||
rtc::Thread* signaling_thread() const { return signaling_thread_; }
|
||||
rtc::Thread* worker_thread() const { return worker_thread_; }
|
||||
cricket::ChannelManager* channel_manager() const { return channel_manager_; }
|
||||
bool IsUnifiedPlan() const { return is_unified_plan_; }
|
||||
void NoteUsageEvent(UsageEvent event) {
|
||||
usage_pattern_->NoteUsageEvent(event);
|
||||
}
|
||||
|
||||
// AddTrack implementation when Unified Plan is specified.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrackUnifiedPlan(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
// AddTrack implementation when Plan B is specified.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrackPlanB(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
|
||||
// Create an RtpReceiver that sources an audio track.
|
||||
void CreateAudioReceiver(MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
|
||||
// Create an RtpReceiver that sources a video track.
|
||||
void CreateVideoReceiver(MediaStreamInterface* stream,
|
||||
const RtpSenderInfo& remote_sender_info)
|
||||
RTC_RUN_ON(signaling_thread());
|
||||
rtc::scoped_refptr<RtpReceiverInterface> RemoveAndStopReceiver(
|
||||
const RtpSenderInfo& remote_sender_info) RTC_RUN_ON(signaling_thread());
|
||||
|
||||
PeerConnectionObserver* Observer() const;
|
||||
void OnNegotiationNeeded();
|
||||
|
||||
TransceiverList transceivers_;
|
||||
|
||||
// These lists store sender info seen in local/remote descriptions.
|
||||
std::vector<RtpSenderInfo> remote_audio_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
std::vector<RtpSenderInfo> remote_video_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
std::vector<RtpSenderInfo> local_audio_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
std::vector<RtpSenderInfo> local_video_sender_infos_
|
||||
RTC_GUARDED_BY(signaling_thread());
|
||||
|
||||
bool closed_ = false;
|
||||
bool const is_unified_plan_;
|
||||
rtc::Thread* signaling_thread_;
|
||||
rtc::Thread* worker_thread_;
|
||||
cricket::ChannelManager* channel_manager_;
|
||||
UsagePattern* usage_pattern_;
|
||||
PeerConnectionObserver* observer_;
|
||||
StatsCollectorInterface* const stats_;
|
||||
std::function<void()> on_negotiation_needed_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // PC_RTP_TRANSMISSION_MANAGER_H_
|
||||
@ -947,11 +947,17 @@ SdpOfferAnswerHandler::~SdpOfferAnswerHandler() {}
|
||||
cricket::ChannelManager* SdpOfferAnswerHandler::channel_manager() const {
|
||||
return pc_->channel_manager();
|
||||
}
|
||||
TransceiverList& SdpOfferAnswerHandler::transceivers() {
|
||||
return pc_->transceivers_;
|
||||
TransceiverList* SdpOfferAnswerHandler::transceivers() {
|
||||
if (!pc_->rtp_manager()) {
|
||||
return nullptr;
|
||||
}
|
||||
return pc_->rtp_manager()->transceivers();
|
||||
}
|
||||
const TransceiverList& SdpOfferAnswerHandler::transceivers() const {
|
||||
return pc_->transceivers_;
|
||||
const TransceiverList* SdpOfferAnswerHandler::transceivers() const {
|
||||
if (!pc_->rtp_manager()) {
|
||||
return nullptr;
|
||||
}
|
||||
return pc_->rtp_manager()->transceivers();
|
||||
}
|
||||
JsepTransportController* SdpOfferAnswerHandler::transport_controller() {
|
||||
return pc_->transport_controller_.get();
|
||||
@ -969,6 +975,12 @@ cricket::PortAllocator* SdpOfferAnswerHandler::port_allocator() {
|
||||
const cricket::PortAllocator* SdpOfferAnswerHandler::port_allocator() const {
|
||||
return pc_->port_allocator_.get();
|
||||
}
|
||||
RtpTransmissionManager* SdpOfferAnswerHandler::rtp_manager() {
|
||||
return pc_->rtp_manager();
|
||||
}
|
||||
const RtpTransmissionManager* SdpOfferAnswerHandler::rtp_manager() const {
|
||||
return pc_->rtp_manager();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -1211,7 +1223,7 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
|
||||
}
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
if (transceiver->stopped()) {
|
||||
continue;
|
||||
}
|
||||
@ -1300,7 +1312,7 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
|
||||
}
|
||||
|
||||
if (IsUnifiedPlan()) {
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
if (transceiver->stopped()) {
|
||||
continue;
|
||||
}
|
||||
@ -1577,7 +1589,7 @@ RTCError SdpOfferAnswerHandler::ApplyRemoteDescription(
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> added_streams;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
const ContentInfo* content =
|
||||
FindMediaSectionForTransceiver(transceiver, remote_description());
|
||||
if (!content) {
|
||||
@ -1597,7 +1609,7 @@ RTCError SdpOfferAnswerHandler::ApplyRemoteDescription(
|
||||
stream_ids = media_desc->streams()[0].stream_ids();
|
||||
}
|
||||
transceivers()
|
||||
.StableState(transceiver)
|
||||
->StableState(transceiver)
|
||||
->SetRemoteStreamIdsIfUnset(transceiver->receiver()->stream_ids());
|
||||
|
||||
RTC_LOG(LS_INFO) << "Processing the MSIDs for MID=" << content->name
|
||||
@ -2401,7 +2413,7 @@ RTCError SdpOfferAnswerHandler::UpdateSessionState(
|
||||
} else {
|
||||
RTC_DCHECK(type == SdpType::kAnswer);
|
||||
ChangeSignalingState(PeerConnectionInterface::kStable);
|
||||
transceivers().DiscardStableStates();
|
||||
transceivers()->DiscardStableStates();
|
||||
have_pending_rtp_data_channel_ = false;
|
||||
}
|
||||
|
||||
@ -2492,10 +2504,10 @@ bool SdpOfferAnswerHandler::AddStream(MediaStreamInterface* local_stream) {
|
||||
stream_observers_.push_back(std::unique_ptr<MediaStreamObserver>(observer));
|
||||
|
||||
for (const auto& track : local_stream->GetAudioTracks()) {
|
||||
pc_->AddAudioTrack(track.get(), local_stream);
|
||||
rtp_manager()->AddAudioTrack(track.get(), local_stream);
|
||||
}
|
||||
for (const auto& track : local_stream->GetVideoTracks()) {
|
||||
pc_->AddVideoTrack(track.get(), local_stream);
|
||||
rtp_manager()->AddVideoTrack(track.get(), local_stream);
|
||||
}
|
||||
|
||||
pc_->stats()->AddStream(local_stream);
|
||||
@ -2511,10 +2523,10 @@ void SdpOfferAnswerHandler::RemoveStream(MediaStreamInterface* local_stream) {
|
||||
TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
|
||||
if (!pc_->IsClosed()) {
|
||||
for (const auto& track : local_stream->GetAudioTracks()) {
|
||||
pc_->RemoveAudioTrack(track.get(), local_stream);
|
||||
rtp_manager()->RemoveAudioTrack(track.get(), local_stream);
|
||||
}
|
||||
for (const auto& track : local_stream->GetVideoTracks()) {
|
||||
pc_->RemoveVideoTrack(track.get(), local_stream);
|
||||
rtp_manager()->RemoveVideoTrack(track.get(), local_stream);
|
||||
}
|
||||
}
|
||||
local_streams_->RemoveStream(local_stream);
|
||||
@ -2546,7 +2558,7 @@ RTCError SdpOfferAnswerHandler::Rollback(SdpType desc_type) {
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> all_removed_streams;
|
||||
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> removed_receivers;
|
||||
|
||||
for (auto&& transceivers_stable_state_pair : transceivers().StableStates()) {
|
||||
for (auto&& transceivers_stable_state_pair : transceivers()->StableStates()) {
|
||||
auto transceiver = transceivers_stable_state_pair.first;
|
||||
auto state = transceivers_stable_state_pair.second;
|
||||
|
||||
@ -2577,7 +2589,7 @@ RTCError SdpOfferAnswerHandler::Rollback(SdpType desc_type) {
|
||||
if (transceiver->internal()->reused_for_addtrack()) {
|
||||
transceiver->internal()->set_created_by_addtrack(true);
|
||||
} else {
|
||||
transceivers().Remove(transceiver);
|
||||
transceivers()->Remove(transceiver);
|
||||
}
|
||||
}
|
||||
transceiver->internal()->sender_internal()->set_transport(nullptr);
|
||||
@ -2590,7 +2602,7 @@ RTCError SdpOfferAnswerHandler::Rollback(SdpType desc_type) {
|
||||
DestroyDataChannelTransport();
|
||||
have_pending_rtp_data_channel_ = false;
|
||||
}
|
||||
transceivers().DiscardStableStates();
|
||||
transceivers()->DiscardStableStates();
|
||||
pending_local_description_.reset();
|
||||
pending_remote_description_.reset();
|
||||
ChangeSignalingState(PeerConnectionInterface::kStable);
|
||||
@ -2742,7 +2754,7 @@ bool SdpOfferAnswerHandler::CheckIfNegotiationIsNeeded() {
|
||||
|
||||
// 5. For each transceiver in connection's set of transceivers, perform the
|
||||
// following checks:
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
const ContentInfo* current_local_msection =
|
||||
FindTransceiverMSection(transceiver.get(), description);
|
||||
|
||||
@ -3060,27 +3072,27 @@ SdpOfferAnswerHandler::AssociateTransceiver(
|
||||
// If this is an offer then the m= section might be recycled. If the m=
|
||||
// section is being recycled (defined as: rejected in the current local or
|
||||
// remote description and not rejected in new description), the transceiver
|
||||
// should have been removed by RemoveStoppedTransceivers().
|
||||
// should have been removed by RemoveStoppedtransceivers()->
|
||||
if (IsMediaSectionBeingRecycled(type, content, old_local_content,
|
||||
old_remote_content)) {
|
||||
const std::string& old_mid =
|
||||
(old_local_content && old_local_content->rejected)
|
||||
? old_local_content->name
|
||||
: old_remote_content->name;
|
||||
auto old_transceiver = transceivers().FindByMid(old_mid);
|
||||
auto old_transceiver = transceivers()->FindByMid(old_mid);
|
||||
// The transceiver should be disassociated in RemoveStoppedTransceivers()
|
||||
RTC_DCHECK(!old_transceiver);
|
||||
}
|
||||
#endif
|
||||
|
||||
const MediaContentDescription* media_desc = content.media_description();
|
||||
auto transceiver = transceivers().FindByMid(content.name);
|
||||
auto transceiver = transceivers()->FindByMid(content.name);
|
||||
if (source == cricket::CS_LOCAL) {
|
||||
// Find the RtpTransceiver that corresponds to this m= section, using the
|
||||
// mapping between transceivers and m= section indices established when
|
||||
// creating the offer.
|
||||
if (!transceiver) {
|
||||
transceiver = transceivers().FindByMLineIndex(mline_index);
|
||||
transceiver = transceivers()->FindByMLineIndex(mline_index);
|
||||
}
|
||||
if (!transceiver) {
|
||||
// This may happen normally when media sections are rejected.
|
||||
@ -3109,20 +3121,21 @@ SdpOfferAnswerHandler::AssociateTransceiver(
|
||||
std::string sender_id = rtc::CreateRandomUuid();
|
||||
std::vector<RtpEncodingParameters> send_encodings =
|
||||
GetSendEncodingsFromRemoteDescription(*media_desc);
|
||||
auto sender = pc_->CreateSender(media_desc->type(), sender_id, nullptr,
|
||||
{}, send_encodings);
|
||||
auto sender = rtp_manager()->CreateSender(media_desc->type(), sender_id,
|
||||
nullptr, {}, send_encodings);
|
||||
std::string receiver_id;
|
||||
if (!media_desc->streams().empty()) {
|
||||
receiver_id = media_desc->streams()[0].id;
|
||||
} else {
|
||||
receiver_id = rtc::CreateRandomUuid();
|
||||
}
|
||||
auto receiver = pc_->CreateReceiver(media_desc->type(), receiver_id);
|
||||
transceiver = pc_->CreateAndAddTransceiver(sender, receiver);
|
||||
auto receiver =
|
||||
rtp_manager()->CreateReceiver(media_desc->type(), receiver_id);
|
||||
transceiver = rtp_manager()->CreateAndAddTransceiver(sender, receiver);
|
||||
transceiver->internal()->set_direction(
|
||||
RtpTransceiverDirection::kRecvOnly);
|
||||
if (type == SdpType::kOffer) {
|
||||
transceivers().StableState(transceiver)->set_newly_created();
|
||||
transceivers()->StableState(transceiver)->set_newly_created();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3166,7 +3179,7 @@ SdpOfferAnswerHandler::AssociateTransceiver(
|
||||
transceiver->internal()->mline_index() != mline_index;
|
||||
if (state_changes) {
|
||||
transceivers()
|
||||
.StableState(transceiver)
|
||||
->StableState(transceiver)
|
||||
->SetMSectionIfUnset(transceiver->internal()->mid(),
|
||||
transceiver->internal()->mline_index());
|
||||
}
|
||||
@ -3337,7 +3350,7 @@ SdpOfferAnswerHandler::FindAvailableTransceiverToReceive(
|
||||
// the same type that were added to the PeerConnection by addTrack and are not
|
||||
// associated with any m= section and are not stopped, find the first such
|
||||
// RtpTransceiver.
|
||||
for (auto transceiver : transceivers().List()) {
|
||||
for (auto transceiver : transceivers()->List()) {
|
||||
if (transceiver->media_type() == media_type &&
|
||||
transceiver->internal()->created_by_addtrack() && !transceiver->mid() &&
|
||||
!transceiver->stopped()) {
|
||||
@ -3421,8 +3434,10 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBOffer(
|
||||
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options,
|
||||
cricket::MediaSessionOptions* session_options) {
|
||||
// Figure out transceiver directional preferences.
|
||||
bool send_audio = !pc_->GetAudioTransceiver()->internal()->senders().empty();
|
||||
bool send_video = !pc_->GetVideoTransceiver()->internal()->senders().empty();
|
||||
bool send_audio =
|
||||
!rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
|
||||
bool send_video =
|
||||
!rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
|
||||
|
||||
// By default, generate sendrecv/recvonly m= sections.
|
||||
bool recv_audio = true;
|
||||
@ -3496,7 +3511,7 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBOffer(
|
||||
!video_index ? nullptr
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddPlanBRtpSenderOptions(pc_->GetSendersInternal(),
|
||||
AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
|
||||
audio_media_description_options,
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
@ -3545,7 +3560,7 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer(
|
||||
media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
// A media section is considered eligible for recycling if it is marked as
|
||||
// rejected in either the current local or current remote description.
|
||||
auto transceiver = transceivers().FindByMid(mid);
|
||||
auto transceiver = transceivers()->FindByMid(mid);
|
||||
if (!transceiver) {
|
||||
// No associated transceiver. The media section has been stopped.
|
||||
recycleable_mline_indices.push(i);
|
||||
@ -3599,7 +3614,7 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer(
|
||||
// and not associated). Reuse media sections marked as recyclable first,
|
||||
// otherwise append to the end of the offer. New media sections should be
|
||||
// added in the order they were added to the PeerConnection.
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
if (transceiver->mid() || transceiver->stopping()) {
|
||||
continue;
|
||||
}
|
||||
@ -3670,8 +3685,10 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBAnswer(
|
||||
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options,
|
||||
cricket::MediaSessionOptions* session_options) {
|
||||
// Figure out transceiver directional preferences.
|
||||
bool send_audio = !pc_->GetAudioTransceiver()->internal()->senders().empty();
|
||||
bool send_video = !pc_->GetVideoTransceiver()->internal()->senders().empty();
|
||||
bool send_audio =
|
||||
!rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
|
||||
bool send_video =
|
||||
!rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
|
||||
|
||||
// By default, generate sendrecv/recvonly m= sections. The direction is also
|
||||
// restricted by the direction in the offer.
|
||||
@ -3708,7 +3725,7 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBAnswer(
|
||||
!video_index ? nullptr
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddPlanBRtpSenderOptions(pc_->GetSendersInternal(),
|
||||
AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
|
||||
audio_media_description_options,
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
@ -3726,7 +3743,7 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanAnswer(
|
||||
cricket::MediaType media_type = content.media_description()->type();
|
||||
if (media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||
media_type == cricket::MEDIA_TYPE_VIDEO) {
|
||||
auto transceiver = transceivers().FindByMid(content.name);
|
||||
auto transceiver = transceivers()->FindByMid(content.name);
|
||||
if (transceiver) {
|
||||
session_options->media_description_options.push_back(
|
||||
GetMediaDescriptionOptionsForTransceiver(
|
||||
@ -3855,7 +3872,7 @@ SdpOfferAnswerHandler::GetReceivingTransceiversOfType(
|
||||
std::vector<
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
|
||||
receiving_transceivers;
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
if (!transceiver->stopped() && transceiver->media_type() == media_type &&
|
||||
RtpTransceiverDirectionHasRecv(transceiver->direction())) {
|
||||
receiving_transceivers.push_back(transceiver);
|
||||
@ -3907,20 +3924,20 @@ void SdpOfferAnswerHandler::UpdateLocalSenders(
|
||||
const std::vector<cricket::StreamParams>& streams,
|
||||
cricket::MediaType media_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
std::vector<PeerConnection::RtpSenderInfo>* current_senders =
|
||||
pc_->GetLocalSenderInfos(media_type);
|
||||
std::vector<RtpSenderInfo>* current_senders =
|
||||
rtp_manager()->GetLocalSenderInfos(media_type);
|
||||
|
||||
// Find removed tracks. I.e., tracks where the track id, stream id or ssrc
|
||||
// don't match the new StreamParam.
|
||||
for (auto sender_it = current_senders->begin();
|
||||
sender_it != current_senders->end();
|
||||
/* incremented manually */) {
|
||||
const PeerConnection::RtpSenderInfo& info = *sender_it;
|
||||
const RtpSenderInfo& info = *sender_it;
|
||||
const cricket::StreamParams* params =
|
||||
cricket::GetStreamBySsrc(streams, info.first_ssrc);
|
||||
if (!params || params->id != info.sender_id ||
|
||||
params->first_stream_id() != info.stream_id) {
|
||||
pc_->OnLocalSenderRemoved(info, media_type);
|
||||
rtp_manager()->OnLocalSenderRemoved(info, media_type);
|
||||
sender_it = current_senders->erase(sender_it);
|
||||
} else {
|
||||
++sender_it;
|
||||
@ -3934,12 +3951,11 @@ void SdpOfferAnswerHandler::UpdateLocalSenders(
|
||||
const std::string& stream_id = params.first_stream_id();
|
||||
const std::string& sender_id = params.id;
|
||||
uint32_t ssrc = params.first_ssrc();
|
||||
const PeerConnection::RtpSenderInfo* sender_info =
|
||||
pc_->FindSenderInfo(*current_senders, stream_id, sender_id);
|
||||
const RtpSenderInfo* sender_info =
|
||||
rtp_manager()->FindSenderInfo(*current_senders, stream_id, sender_id);
|
||||
if (!sender_info) {
|
||||
current_senders->push_back(
|
||||
PeerConnection::RtpSenderInfo(stream_id, sender_id, ssrc));
|
||||
pc_->OnLocalSenderAdded(current_senders->back(), media_type);
|
||||
current_senders->push_back(RtpSenderInfo(stream_id, sender_id, ssrc));
|
||||
rtp_manager()->OnLocalSenderAdded(current_senders->back(), media_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3952,15 +3968,15 @@ void SdpOfferAnswerHandler::UpdateRemoteSendersList(
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(!IsUnifiedPlan());
|
||||
|
||||
std::vector<PeerConnection::RtpSenderInfo>* current_senders =
|
||||
pc_->GetRemoteSenderInfos(media_type);
|
||||
std::vector<RtpSenderInfo>* current_senders =
|
||||
rtp_manager()->GetRemoteSenderInfos(media_type);
|
||||
|
||||
// Find removed senders. I.e., senders where the sender id or ssrc don't match
|
||||
// the new StreamParam.
|
||||
for (auto sender_it = current_senders->begin();
|
||||
sender_it != current_senders->end();
|
||||
/* incremented manually */) {
|
||||
const PeerConnection::RtpSenderInfo& info = *sender_it;
|
||||
const RtpSenderInfo& info = *sender_it;
|
||||
const cricket::StreamParams* params =
|
||||
cricket::GetStreamBySsrc(streams, info.first_ssrc);
|
||||
std::string params_stream_id;
|
||||
@ -3976,8 +3992,8 @@ void SdpOfferAnswerHandler::UpdateRemoteSendersList(
|
||||
sender_exists) {
|
||||
++sender_it;
|
||||
} else {
|
||||
pc_->OnRemoteSenderRemoved(info, remote_streams_->find(info.stream_id),
|
||||
media_type);
|
||||
rtp_manager()->OnRemoteSenderRemoved(
|
||||
info, remote_streams_->find(info.stream_id), media_type);
|
||||
sender_it = current_senders->erase(sender_it);
|
||||
}
|
||||
}
|
||||
@ -4013,12 +4029,12 @@ void SdpOfferAnswerHandler::UpdateRemoteSendersList(
|
||||
new_streams->AddStream(stream);
|
||||
}
|
||||
|
||||
const PeerConnection::RtpSenderInfo* sender_info =
|
||||
pc_->FindSenderInfo(*current_senders, stream_id, sender_id);
|
||||
const RtpSenderInfo* sender_info =
|
||||
rtp_manager()->FindSenderInfo(*current_senders, stream_id, sender_id);
|
||||
if (!sender_info) {
|
||||
current_senders->push_back(
|
||||
PeerConnection::RtpSenderInfo(stream_id, sender_id, ssrc));
|
||||
pc_->OnRemoteSenderAdded(current_senders->back(), stream, media_type);
|
||||
current_senders->push_back(RtpSenderInfo(stream_id, sender_id, ssrc));
|
||||
rtp_manager()->OnRemoteSenderAdded(current_senders->back(), stream,
|
||||
media_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4036,21 +4052,20 @@ void SdpOfferAnswerHandler::UpdateRemoteSendersList(
|
||||
std::string default_sender_id = (media_type == cricket::MEDIA_TYPE_AUDIO)
|
||||
? kDefaultAudioSenderId
|
||||
: kDefaultVideoSenderId;
|
||||
const PeerConnection::RtpSenderInfo* default_sender_info =
|
||||
pc_->FindSenderInfo(*current_senders, kDefaultStreamId,
|
||||
default_sender_id);
|
||||
const RtpSenderInfo* default_sender_info = rtp_manager()->FindSenderInfo(
|
||||
*current_senders, kDefaultStreamId, default_sender_id);
|
||||
if (!default_sender_info) {
|
||||
current_senders->push_back(PeerConnection::RtpSenderInfo(
|
||||
kDefaultStreamId, default_sender_id, /*ssrc=*/0));
|
||||
pc_->OnRemoteSenderAdded(current_senders->back(), default_stream,
|
||||
media_type);
|
||||
current_senders->push_back(
|
||||
RtpSenderInfo(kDefaultStreamId, default_sender_id, /*ssrc=*/0));
|
||||
rtp_manager()->OnRemoteSenderAdded(current_senders->back(),
|
||||
default_stream, media_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SdpOfferAnswerHandler::EnableSending() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
if (channel && !channel->enabled()) {
|
||||
channel->Enable(true);
|
||||
@ -4081,7 +4096,7 @@ RTCError SdpOfferAnswerHandler::PushdownMediaDescription(
|
||||
}
|
||||
|
||||
// Push down the new SDP media section for each audio/video transceiver.
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
const ContentInfo* content_info =
|
||||
FindMediaSectionForTransceiver(transceiver, sdesc);
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
@ -4178,7 +4193,7 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() {
|
||||
if (!IsUnifiedPlan())
|
||||
return;
|
||||
// Traverse a copy of the transceiver list.
|
||||
auto transceiver_list = transceivers().List();
|
||||
auto transceiver_list = transceivers()->List();
|
||||
for (auto transceiver : transceiver_list) {
|
||||
// 3.2.10.1.1: If transceiver is stopped, associated with an m= section
|
||||
// and the associated m= section is rejected in
|
||||
@ -4198,7 +4213,7 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() {
|
||||
<< " since the media section is being recycled.";
|
||||
transceiver->internal()->set_mid(absl::nullopt);
|
||||
transceiver->internal()->set_mline_index(absl::nullopt);
|
||||
transceivers().Remove(transceiver);
|
||||
transceivers()->Remove(transceiver);
|
||||
continue;
|
||||
}
|
||||
if (!local_content && !remote_content) {
|
||||
@ -4206,7 +4221,7 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() {
|
||||
// See https://github.com/w3c/webrtc-pc/issues/2576
|
||||
RTC_LOG(LS_INFO)
|
||||
<< "Dropping stopped transceiver that was never associated";
|
||||
transceivers().Remove(transceiver);
|
||||
transceivers()->Remove(transceiver);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -4219,12 +4234,12 @@ void SdpOfferAnswerHandler::RemoveUnusedChannels(
|
||||
// voice channel.
|
||||
const cricket::ContentInfo* video_info = cricket::GetFirstVideoContent(desc);
|
||||
if (!video_info || video_info->rejected) {
|
||||
DestroyTransceiverChannel(pc_->GetVideoTransceiver());
|
||||
DestroyTransceiverChannel(rtp_manager()->GetVideoTransceiver());
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* audio_info = cricket::GetFirstAudioContent(desc);
|
||||
if (!audio_info || audio_info->rejected) {
|
||||
DestroyTransceiverChannel(pc_->GetAudioTransceiver());
|
||||
DestroyTransceiverChannel(rtp_manager()->GetAudioTransceiver());
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* data_info = cricket::GetFirstDataContent(desc);
|
||||
@ -4432,24 +4447,24 @@ RTCError SdpOfferAnswerHandler::CreateChannels(const SessionDescription& desc) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(&desc);
|
||||
if (voice && !voice->rejected &&
|
||||
!pc_->GetAudioTransceiver()->internal()->channel()) {
|
||||
!rtp_manager()->GetAudioTransceiver()->internal()->channel()) {
|
||||
cricket::VoiceChannel* voice_channel = CreateVoiceChannel(voice->name);
|
||||
if (!voice_channel) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
|
||||
"Failed to create voice channel.");
|
||||
}
|
||||
pc_->GetAudioTransceiver()->internal()->SetChannel(voice_channel);
|
||||
rtp_manager()->GetAudioTransceiver()->internal()->SetChannel(voice_channel);
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* video = cricket::GetFirstVideoContent(&desc);
|
||||
if (video && !video->rejected &&
|
||||
!pc_->GetVideoTransceiver()->internal()->channel()) {
|
||||
!rtp_manager()->GetVideoTransceiver()->internal()->channel()) {
|
||||
cricket::VideoChannel* video_channel = CreateVideoChannel(video->name);
|
||||
if (!video_channel) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
|
||||
"Failed to create video channel.");
|
||||
}
|
||||
pc_->GetVideoTransceiver()->internal()->SetChannel(video_channel);
|
||||
rtp_manager()->GetVideoTransceiver()->internal()->SetChannel(video_channel);
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* data = cricket::GetFirstDataContent(&desc);
|
||||
@ -4627,14 +4642,17 @@ void SdpOfferAnswerHandler::DestroyChannelInterface(
|
||||
|
||||
void SdpOfferAnswerHandler::DestroyAllChannels() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (!transceivers()) {
|
||||
return;
|
||||
}
|
||||
// Destroy video channels first since they may have a pointer to a voice
|
||||
// channel.
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
|
||||
DestroyTransceiverChannel(transceiver);
|
||||
}
|
||||
}
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
DestroyTransceiverChannel(transceiver);
|
||||
}
|
||||
@ -4819,7 +4837,7 @@ bool SdpOfferAnswerHandler::UpdatePayloadTypeDemuxingState(
|
||||
// single Invoke; necessary due to thread guards.
|
||||
std::vector<std::pair<RtpTransceiverDirection, cricket::ChannelInterface*>>
|
||||
channels_to_update;
|
||||
for (const auto& transceiver : transceivers().List()) {
|
||||
for (const auto& transceiver : transceivers()->List()) {
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
const ContentInfo* content =
|
||||
FindMediaSectionForTransceiver(transceiver, sdesc);
|
||||
|
||||
@ -74,6 +74,7 @@ class MediaStreamObserver;
|
||||
class PeerConnection;
|
||||
class VideoRtpReceiver;
|
||||
class RtcEventLog;
|
||||
class RtpTransmissionManager;
|
||||
class TransceiverList;
|
||||
|
||||
// SdpOfferAnswerHandler is a component
|
||||
@ -525,13 +526,15 @@ class SdpOfferAnswerHandler {
|
||||
// ==================================================================
|
||||
// Access to pc_ variables
|
||||
cricket::ChannelManager* channel_manager() const;
|
||||
TransceiverList& transceivers();
|
||||
const TransceiverList& transceivers() const;
|
||||
TransceiverList* transceivers();
|
||||
const TransceiverList* transceivers() const;
|
||||
JsepTransportController* transport_controller();
|
||||
DataChannelController* data_channel_controller();
|
||||
const DataChannelController* data_channel_controller() const;
|
||||
cricket::PortAllocator* port_allocator();
|
||||
const cricket::PortAllocator* port_allocator() const;
|
||||
RtpTransmissionManager* rtp_manager();
|
||||
const RtpTransmissionManager* rtp_manager() const;
|
||||
// ===================================================================
|
||||
|
||||
PeerConnection* const pc_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user