Reland "Don't create channel_manager++ when media_engine is not set"
This reverts commit c6c02efb56b24df04ed9ab61252c14c7bddcca93. Reason for revert: Test now passes (and channel manager is gone) Original change's description: > Revert "Don't create channel_manager when media_engine is not set" > > This reverts commit c48ad732d6eb69f14dd6d44f801d62997cef2c2f. > > Reason for revert: breaks downstream project > > Original change's description: > > Don't create channel_manager when media_engine is not set > > > > Also remove a bunch of functions in ChannelManager that were just > > forwarding to MediaEngineInterface. > > > > Bug: webrtc:13931 > > Change-Id: Ia38591fd22c665cace16d032f5c1e384e413cded > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261304 > > Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> > > Reviewed-by: Henrik Boström <hbos@webrtc.org> > > Commit-Queue: Harald Alvestrand <hta@webrtc.org> > > Cr-Commit-Position: refs/heads/main@{#36801} > > Bug: webrtc:13931 > Change-Id: I1e260a2489547bd9483b50e043c28d2805b0fa5a > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261660 > Commit-Queue: Artem Titov <titovartem@webrtc.org> > Reviewed-by: Harald Alvestrand <hta@webrtc.org> > Owners-Override: Artem Titov <titovartem@webrtc.org> > Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com> > Cr-Commit-Position: refs/heads/main@{#36811} Bug: webrtc:13931 Change-Id: I7b5b45b46095c18d489b6a9fe4c625971d6b3da6 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261661 Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Cr-Commit-Position: refs/heads/main@{#36976}
This commit is contained in:
parent
2377226851
commit
8101e7b79b
@ -329,6 +329,7 @@ rtc_source_set("media_session") {
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base/memory:always_valid_pointer",
|
||||
"../rtc_base/third_party/base64",
|
||||
]
|
||||
absl_deps = [
|
||||
|
||||
@ -58,10 +58,24 @@ namespace {
|
||||
|
||||
class DataChannelIntegrationTest
|
||||
: public PeerConnectionIntegrationBaseTest,
|
||||
public ::testing::WithParamInterface<SdpSemantics> {
|
||||
public ::testing::WithParamInterface<std::tuple<SdpSemantics, bool>> {
|
||||
protected:
|
||||
DataChannelIntegrationTest()
|
||||
: PeerConnectionIntegrationBaseTest(GetParam()) {}
|
||||
: PeerConnectionIntegrationBaseTest(std::get<0>(GetParam())),
|
||||
allow_media_(std::get<1>(GetParam())) {}
|
||||
bool allow_media() { return allow_media_; }
|
||||
|
||||
bool CreatePeerConnectionWrappers() {
|
||||
if (allow_media_) {
|
||||
return PeerConnectionIntegrationBaseTest::CreatePeerConnectionWrappers();
|
||||
}
|
||||
return PeerConnectionIntegrationBaseTest::
|
||||
CreatePeerConnectionWrappersWithoutMediaEngine();
|
||||
}
|
||||
|
||||
private:
|
||||
// True if media is allowed to be added
|
||||
const bool allow_media_;
|
||||
};
|
||||
|
||||
// Fake clock must be set before threads are started to prevent race on
|
||||
@ -173,14 +187,18 @@ TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannel) {
|
||||
// Expect that data channel created on caller side will show up for callee as
|
||||
// well.
|
||||
caller()->CreateDataChannel();
|
||||
caller()->AddAudioVideoTracks();
|
||||
callee()->AddAudioVideoTracks();
|
||||
if (allow_media()) {
|
||||
caller()->AddAudioVideoTracks();
|
||||
callee()->AddAudioVideoTracks();
|
||||
}
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||
// Ensure the existence of the SCTP data channel didn't impede audio/video.
|
||||
MediaExpectations media_expectations;
|
||||
media_expectations.ExpectBidirectionalAudioAndVideo();
|
||||
ASSERT_TRUE(ExpectNewFrames(media_expectations));
|
||||
if (allow_media()) {
|
||||
// Ensure the existence of the SCTP data channel didn't impede audio/video.
|
||||
MediaExpectations media_expectations;
|
||||
media_expectations.ExpectBidirectionalAudioAndVideo();
|
||||
ASSERT_TRUE(ExpectNewFrames(media_expectations));
|
||||
}
|
||||
// Caller data channel should already exist (it created one). Callee data
|
||||
// channel may not exist yet, since negotiation happens in-band, not in SDP.
|
||||
ASSERT_NE(nullptr, caller()->data_channel());
|
||||
@ -202,7 +220,7 @@ TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannel) {
|
||||
// data channel only, and sends messages of various sizes.
|
||||
TEST_P(DataChannelIntegrationTest,
|
||||
EndToEndCallWithSctpDataChannelVariousSizes) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappersWithoutMediaEngine());
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
// Expect that data channel created on caller side will show up for callee as
|
||||
// well.
|
||||
@ -241,7 +259,7 @@ TEST_P(DataChannelIntegrationTest,
|
||||
// data channel only, and sends empty messages
|
||||
TEST_P(DataChannelIntegrationTest,
|
||||
EndToEndCallWithSctpDataChannelEmptyMessages) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappersWithoutMediaEngine());
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
// Expect that data channel created on caller side will show up for callee as
|
||||
// well.
|
||||
@ -291,7 +309,7 @@ TEST_P(DataChannelIntegrationTest,
|
||||
// this test does not use TURN.
|
||||
const size_t kLowestSafePayloadSizeLimit = 1225;
|
||||
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappersWithoutMediaEngine());
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
// Expect that data channel created on caller side will show up for callee as
|
||||
// well.
|
||||
@ -328,7 +346,7 @@ TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannelHarmfulMtu) {
|
||||
// The size of the smallest message that fails to be delivered.
|
||||
const size_t kMessageSizeThatIsNotDelivered = 1157;
|
||||
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappersWithoutMediaEngine());
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
caller()->CreateDataChannel();
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
@ -369,8 +387,10 @@ TEST_P(DataChannelIntegrationTest, CalleeClosesSctpDataChannel) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
caller()->CreateDataChannel();
|
||||
caller()->AddAudioVideoTracks();
|
||||
callee()->AddAudioVideoTracks();
|
||||
if (allow_media()) {
|
||||
caller()->AddAudioVideoTracks();
|
||||
callee()->AddAudioVideoTracks();
|
||||
}
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||
ASSERT_NE(nullptr, caller()->data_channel());
|
||||
@ -406,8 +426,10 @@ TEST_P(DataChannelIntegrationTest, SctpDataChannelConfigSentToOtherSide) {
|
||||
init.id = 53;
|
||||
init.maxRetransmits = 52;
|
||||
caller()->CreateDataChannel("data-channel", &init);
|
||||
caller()->AddAudioVideoTracks();
|
||||
callee()->AddAudioVideoTracks();
|
||||
if (allow_media()) {
|
||||
caller()->AddAudioVideoTracks();
|
||||
callee()->AddAudioVideoTracks();
|
||||
}
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
|
||||
@ -429,7 +451,7 @@ TEST_P(DataChannelIntegrationTest, StressTestUnorderedSctpDataChannel) {
|
||||
virtual_socket_server()->set_delay_stddev(5);
|
||||
virtual_socket_server()->UpdateDelayDistribution();
|
||||
// Normal procedure, but with unordered data channel config.
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappersWithoutMediaEngine());
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
webrtc::DataChannelInit init;
|
||||
init.ordered = false;
|
||||
@ -633,6 +655,10 @@ TEST_P(DataChannelIntegrationTest, StressTestOpenCloseChannelWithDelay) {
|
||||
// This test sets up a call between two parties with audio, and video. When
|
||||
// audio and video are setup and flowing, an SCTP data channel is negotiated.
|
||||
TEST_P(DataChannelIntegrationTest, AddSctpDataChannelInSubsequentOffer) {
|
||||
// This test can't be performed without media.
|
||||
if (!allow_media()) {
|
||||
return;
|
||||
}
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
// Do initial offer/answer with audio/video.
|
||||
@ -665,6 +691,10 @@ TEST_P(DataChannelIntegrationTest, AddSctpDataChannelInSubsequentOffer) {
|
||||
// Effectively the inverse of the test above. This was broken in M57; see
|
||||
// https://crbug.com/711243
|
||||
TEST_P(DataChannelIntegrationTest, SctpDataChannelToAudioVideoUpgrade) {
|
||||
// This test can't be performed without media.
|
||||
if (!allow_media()) {
|
||||
return;
|
||||
}
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
// Do initial offer/answer with just data channel.
|
||||
@ -724,6 +754,10 @@ TEST_P(DataChannelIntegrationTest,
|
||||
// Test that after closing PeerConnections, they stop sending any packets
|
||||
// (ICE, DTLS, RTP...).
|
||||
TEST_P(DataChannelIntegrationTest, ClosingConnectionStopsPacketFlow) {
|
||||
// This test can't be performed without media.
|
||||
if (!allow_media()) {
|
||||
return;
|
||||
}
|
||||
// Set up audio/video/data, wait for some frames to be received.
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
@ -1055,8 +1089,9 @@ TEST_P(DataChannelIntegrationTest,
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DataChannelIntegrationTest,
|
||||
DataChannelIntegrationTest,
|
||||
Values(SdpSemantics::kPlanB_DEPRECATED,
|
||||
SdpSemantics::kUnifiedPlan));
|
||||
Combine(Values(SdpSemantics::kPlanB_DEPRECATED,
|
||||
SdpSemantics::kUnifiedPlan),
|
||||
testing::Bool()));
|
||||
|
||||
TEST_F(DataChannelIntegrationTestUnifiedPlan,
|
||||
EndToEndCallWithBundledSctpDataChannel) {
|
||||
|
||||
@ -1566,9 +1566,7 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
|
||||
const TransportDescriptionFactory* transport_desc_factory,
|
||||
rtc::UniqueRandomIdGenerator* ssrc_generator)
|
||||
: ssrc_generator_(ssrc_generator),
|
||||
transport_desc_factory_(transport_desc_factory) {
|
||||
RTC_DCHECK(ssrc_generator_);
|
||||
}
|
||||
transport_desc_factory_(transport_desc_factory) {}
|
||||
|
||||
MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
|
||||
cricket::MediaEngineInterface* media_engine,
|
||||
@ -2366,7 +2364,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForOffer(
|
||||
if (!CreateMediaContentOffer(
|
||||
media_description_options, session_options, filtered_codecs,
|
||||
sdes_policy, GetCryptos(current_content), crypto_suites,
|
||||
audio_rtp_extensions, ssrc_generator_, current_streams, audio.get(),
|
||||
audio_rtp_extensions, ssrc_generator(), current_streams, audio.get(),
|
||||
transport_desc_factory_->trials())) {
|
||||
return false;
|
||||
}
|
||||
@ -2478,7 +2476,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
|
||||
if (!CreateMediaContentOffer(
|
||||
media_description_options, session_options, filtered_codecs,
|
||||
sdes_policy, GetCryptos(current_content), crypto_suites,
|
||||
video_rtp_extensions, ssrc_generator_, current_streams, video.get(),
|
||||
video_rtp_extensions, ssrc_generator(), current_streams, video.get(),
|
||||
transport_desc_factory_->trials())) {
|
||||
return false;
|
||||
}
|
||||
@ -2531,8 +2529,8 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer(
|
||||
|
||||
if (!CreateContentOffer(media_description_options, session_options,
|
||||
sdes_policy, GetCryptos(current_content),
|
||||
crypto_suites, RtpHeaderExtensions(), ssrc_generator_,
|
||||
current_streams, data.get())) {
|
||||
crypto_suites, RtpHeaderExtensions(),
|
||||
ssrc_generator(), current_streams, data.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2673,7 +2671,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
|
||||
audio_transport->secure() ? cricket::SEC_DISABLED : secure();
|
||||
if (!SetCodecsInAnswer(offer_audio_description, filtered_codecs,
|
||||
media_description_options, session_options,
|
||||
ssrc_generator_, current_streams, audio_answer.get(),
|
||||
ssrc_generator(), current_streams, audio_answer.get(),
|
||||
transport_desc_factory_->trials())) {
|
||||
return false;
|
||||
}
|
||||
@ -2681,7 +2679,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
|
||||
offer_audio_description, media_description_options, session_options,
|
||||
sdes_policy, GetCryptos(current_content),
|
||||
filtered_rtp_header_extensions(default_audio_rtp_header_extensions),
|
||||
ssrc_generator_, enable_encrypted_rtp_header_extensions_,
|
||||
ssrc_generator(), enable_encrypted_rtp_header_extensions_,
|
||||
current_streams, bundle_enabled, audio_answer.get())) {
|
||||
return false; // Fails the session setup.
|
||||
}
|
||||
@ -2809,7 +2807,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
|
||||
video_transport->secure() ? cricket::SEC_DISABLED : secure();
|
||||
if (!SetCodecsInAnswer(offer_video_description, filtered_codecs,
|
||||
media_description_options, session_options,
|
||||
ssrc_generator_, current_streams, video_answer.get(),
|
||||
ssrc_generator(), current_streams, video_answer.get(),
|
||||
transport_desc_factory_->trials())) {
|
||||
return false;
|
||||
}
|
||||
@ -2817,7 +2815,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
|
||||
offer_video_description, media_description_options, session_options,
|
||||
sdes_policy, GetCryptos(current_content),
|
||||
filtered_rtp_header_extensions(default_video_rtp_header_extensions),
|
||||
ssrc_generator_, enable_encrypted_rtp_header_extensions_,
|
||||
ssrc_generator(), enable_encrypted_rtp_header_extensions_,
|
||||
current_streams, bundle_enabled, video_answer.get())) {
|
||||
return false; // Failed the session setup.
|
||||
}
|
||||
@ -2890,7 +2888,7 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
|
||||
if (!CreateMediaContentAnswer(
|
||||
offer_data_description, media_description_options, session_options,
|
||||
sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
|
||||
ssrc_generator_, enable_encrypted_rtp_header_extensions_,
|
||||
ssrc_generator(), enable_encrypted_rtp_header_extensions_,
|
||||
current_streams, bundle_enabled, data_answer.get())) {
|
||||
return false; // Fails the session setup.
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "pc/media_protocol_names.h"
|
||||
#include "pc/session_description.h"
|
||||
#include "pc/simulcast_description.h"
|
||||
#include "rtc_base/memory/always_valid_pointer.h"
|
||||
#include "rtc_base/unique_id_generator.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -331,6 +332,10 @@ class MediaSessionDescriptionFactory {
|
||||
|
||||
void ComputeVideoCodecsIntersectionAndUnion();
|
||||
|
||||
rtc::UniqueRandomIdGenerator* ssrc_generator() const {
|
||||
return ssrc_generator_.get();
|
||||
}
|
||||
|
||||
bool is_unified_plan_ = false;
|
||||
AudioCodecs audio_send_codecs_;
|
||||
AudioCodecs audio_recv_codecs_;
|
||||
@ -344,8 +349,9 @@ class MediaSessionDescriptionFactory {
|
||||
VideoCodecs video_sendrecv_codecs_;
|
||||
// Union of send and recv.
|
||||
VideoCodecs all_video_codecs_;
|
||||
// This object is not owned by the channel so it must outlive it.
|
||||
rtc::UniqueRandomIdGenerator* const ssrc_generator_;
|
||||
// This object may or may not be owned by this class.
|
||||
webrtc::AlwaysValidPointer<rtc::UniqueRandomIdGenerator> const
|
||||
ssrc_generator_;
|
||||
bool enable_encrypted_rtp_header_extensions_ = false;
|
||||
// TODO(zhihuang): Rename secure_ to sdec_policy_; rename the related getter
|
||||
// and setter.
|
||||
|
||||
@ -1172,8 +1172,10 @@ 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 : rtp_manager()->GetSendersInternal()) {
|
||||
ret.push_back(sender);
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& sender : rtp_manager()->GetSendersInternal()) {
|
||||
ret.push_back(sender);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1182,8 +1184,10 @@ 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 : rtp_manager()->GetReceiversInternal()) {
|
||||
ret.push_back(receiver);
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& receiver : rtp_manager()->GetReceiversInternal()) {
|
||||
ret.push_back(receiver);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1194,8 +1198,10 @@ PeerConnection::GetTransceivers() const {
|
||||
RTC_CHECK(IsUnifiedPlan())
|
||||
<< "GetTransceivers is only supported with Unified Plan SdpSemantics.";
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> all_transceivers;
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
all_transceivers.push_back(transceiver);
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
all_transceivers.push_back(transceiver);
|
||||
}
|
||||
}
|
||||
return all_transceivers;
|
||||
}
|
||||
@ -1814,12 +1820,13 @@ void PeerConnection::Close() {
|
||||
|
||||
NoteUsageEvent(UsageEvent::CLOSE_CALLED);
|
||||
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
transceiver->internal()->SetPeerConnectionClosed();
|
||||
if (!transceiver->stopped())
|
||||
transceiver->StopInternal();
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
|
||||
transceiver->internal()->SetPeerConnectionClosed();
|
||||
if (!transceiver->stopped())
|
||||
transceiver->StopInternal();
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that all asynchronous stats requests are completed before destroying
|
||||
// the transport controller below.
|
||||
if (stats_collector_) {
|
||||
@ -1836,7 +1843,9 @@ void PeerConnection::Close() {
|
||||
// WebRTC session description factory, the session description factory would
|
||||
// call the transport controller.
|
||||
sdp_handler_->ResetSessionDescFactory();
|
||||
rtp_manager_->Close();
|
||||
if (ConfiguredForMedia()) {
|
||||
rtp_manager_->Close();
|
||||
}
|
||||
|
||||
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
|
||||
// Data channels will already have been unset via the DestroyAllChannels()
|
||||
@ -2727,12 +2736,15 @@ void PeerConnection::ReportTransportStats() {
|
||||
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
||||
std::map<std::string, std::set<cricket::MediaType>>
|
||||
media_types_by_transport_name;
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->UnsafeList()) {
|
||||
if (transceiver->internal()->channel()) {
|
||||
std::string transport_name(
|
||||
transceiver->internal()->channel()->transport_name());
|
||||
media_types_by_transport_name[transport_name].insert(
|
||||
transceiver->media_type());
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& transceiver :
|
||||
rtp_manager()->transceivers()->UnsafeList()) {
|
||||
if (transceiver->internal()->channel()) {
|
||||
std::string transport_name(
|
||||
transceiver->internal()->channel()->transport_name());
|
||||
media_types_by_transport_name[transport_name].insert(
|
||||
transceiver->media_type());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2880,10 +2892,13 @@ bool PeerConnection::OnTransportChanged(
|
||||
DataChannelTransportInterface* data_channel_transport) {
|
||||
RTC_DCHECK_RUN_ON(network_thread());
|
||||
bool ret = true;
|
||||
for (const auto& transceiver : rtp_manager()->transceivers()->UnsafeList()) {
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
if (channel && channel->mid() == mid) {
|
||||
ret = channel->SetRtpTransport(rtp_transport);
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& transceiver :
|
||||
rtp_manager()->transceivers()->UnsafeList()) {
|
||||
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
||||
if (channel && channel->mid() == mid) {
|
||||
ret = channel->SetRtpTransport(rtp_transport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -273,6 +273,9 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
|
||||
GetTransceiversInternal() const override {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (!ConfiguredForMedia()) {
|
||||
return {};
|
||||
}
|
||||
return rtp_manager()->transceivers()->List();
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "api/sequence_checker.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "media/base/media_engine.h"
|
||||
#include "pc/channel.h"
|
||||
#include "pc/rtp_media_utils.h"
|
||||
#include "pc/session_description.h"
|
||||
@ -602,7 +603,6 @@ void RtpTransceiver::StopTransceiverProcedure() {
|
||||
RTCError RtpTransceiver::SetCodecPreferences(
|
||||
rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
|
||||
RTC_DCHECK(unified_plan_);
|
||||
|
||||
// 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
|
||||
// to codecs and abort these steps.
|
||||
if (codec_capabilities.empty()) {
|
||||
|
||||
@ -1549,56 +1549,60 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
|
||||
<< ")";
|
||||
return error;
|
||||
}
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
|
||||
for (const auto& transceiver_ext : transceivers()->List()) {
|
||||
auto transceiver = transceiver_ext->internal();
|
||||
if (transceiver->stopped()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2.2.7.1.1.(6-9): Set sender and receiver's transport slots.
|
||||
// Note that code paths that don't set MID won't be able to use
|
||||
// information about DTLS transports.
|
||||
if (transceiver->mid()) {
|
||||
auto dtls_transport = LookupDtlsTransportByMid(
|
||||
context_->network_thread(), transport_controller_s(),
|
||||
*transceiver->mid());
|
||||
transceiver->sender_internal()->set_transport(dtls_transport);
|
||||
transceiver->receiver_internal()->set_transport(dtls_transport);
|
||||
}
|
||||
|
||||
const ContentInfo* content =
|
||||
FindMediaSectionForTransceiver(transceiver, local_description());
|
||||
if (!content) {
|
||||
continue;
|
||||
}
|
||||
const MediaContentDescription* media_desc = content->media_description();
|
||||
// 2.2.7.1.6: If description is of type "answer" or "pranswer", then run
|
||||
// the following steps:
|
||||
if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
|
||||
// 2.2.7.1.6.1: If direction is "sendonly" or "inactive", and
|
||||
// transceiver's [[FiredDirection]] slot is either "sendrecv" or
|
||||
// "recvonly", process the removal of a remote track for the media
|
||||
// description, given transceiver, removeList, and muteTracks.
|
||||
if (!RtpTransceiverDirectionHasRecv(media_desc->direction()) &&
|
||||
(transceiver->fired_direction() &&
|
||||
RtpTransceiverDirectionHasRecv(*transceiver->fired_direction()))) {
|
||||
ProcessRemovalOfRemoteTrack(transceiver_ext, &remove_list,
|
||||
&removed_streams);
|
||||
if (ConfiguredForMedia()) {
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
|
||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
|
||||
for (const auto& transceiver_ext : transceivers()->List()) {
|
||||
auto transceiver = transceiver_ext->internal();
|
||||
if (transceiver->stopped()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2.2.7.1.1.(6-9): Set sender and receiver's transport slots.
|
||||
// Note that code paths that don't set MID won't be able to use
|
||||
// information about DTLS transports.
|
||||
if (transceiver->mid()) {
|
||||
auto dtls_transport = LookupDtlsTransportByMid(
|
||||
context_->network_thread(), transport_controller_s(),
|
||||
*transceiver->mid());
|
||||
transceiver->sender_internal()->set_transport(dtls_transport);
|
||||
transceiver->receiver_internal()->set_transport(dtls_transport);
|
||||
}
|
||||
|
||||
const ContentInfo* content =
|
||||
FindMediaSectionForTransceiver(transceiver, local_description());
|
||||
if (!content) {
|
||||
continue;
|
||||
}
|
||||
const MediaContentDescription* media_desc =
|
||||
content->media_description();
|
||||
// 2.2.7.1.6: If description is of type "answer" or "pranswer", then run
|
||||
// the following steps:
|
||||
if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
|
||||
// 2.2.7.1.6.1: If direction is "sendonly" or "inactive", and
|
||||
// transceiver's [[FiredDirection]] slot is either "sendrecv" or
|
||||
// "recvonly", process the removal of a remote track for the media
|
||||
// description, given transceiver, removeList, and muteTracks.
|
||||
if (!RtpTransceiverDirectionHasRecv(media_desc->direction()) &&
|
||||
(transceiver->fired_direction() &&
|
||||
RtpTransceiverDirectionHasRecv(
|
||||
*transceiver->fired_direction()))) {
|
||||
ProcessRemovalOfRemoteTrack(transceiver_ext, &remove_list,
|
||||
&removed_streams);
|
||||
}
|
||||
// 2.2.7.1.6.2: Set transceiver's [[CurrentDirection]] and
|
||||
// [[FiredDirection]] slots to direction.
|
||||
transceiver->set_current_direction(media_desc->direction());
|
||||
transceiver->set_fired_direction(media_desc->direction());
|
||||
}
|
||||
// 2.2.7.1.6.2: Set transceiver's [[CurrentDirection]] and
|
||||
// [[FiredDirection]] slots to direction.
|
||||
transceiver->set_current_direction(media_desc->direction());
|
||||
transceiver->set_fired_direction(media_desc->direction());
|
||||
}
|
||||
}
|
||||
auto observer = pc_->Observer();
|
||||
for (const auto& transceiver : remove_list) {
|
||||
observer->OnRemoveTrack(transceiver->receiver());
|
||||
}
|
||||
for (const auto& stream : removed_streams) {
|
||||
observer->OnRemoveStream(stream);
|
||||
auto observer = pc_->Observer();
|
||||
for (const auto& transceiver : remove_list) {
|
||||
observer->OnRemoveTrack(transceiver->receiver());
|
||||
}
|
||||
for (const auto& stream : removed_streams) {
|
||||
observer->OnRemoveStream(stream);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Media channels will be created only when offer is set. These may use new
|
||||
@ -1642,35 +1646,39 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
|
||||
}
|
||||
|
||||
if (IsUnifiedPlan()) {
|
||||
// We must use List and not ListInternal here because
|
||||
// transceivers()->StableState() is indexed by the non-internal refptr.
|
||||
for (const auto& transceiver_ext : transceivers()->List()) {
|
||||
auto transceiver = transceiver_ext->internal();
|
||||
if (transceiver->stopped()) {
|
||||
continue;
|
||||
}
|
||||
const ContentInfo* content =
|
||||
FindMediaSectionForTransceiver(transceiver, local_description());
|
||||
if (!content) {
|
||||
continue;
|
||||
}
|
||||
cricket::ChannelInterface* channel = transceiver->channel();
|
||||
if (content->rejected || !channel || channel->local_streams().empty()) {
|
||||
// 0 is a special value meaning "this sender has no associated send
|
||||
// stream". Need to call this so the sender won't attempt to configure
|
||||
// a no longer existing stream and run into DCHECKs in the lower
|
||||
// layers.
|
||||
transceiver->sender_internal()->SetSsrc(0);
|
||||
} else {
|
||||
// Get the StreamParams from the channel which could generate SSRCs.
|
||||
const std::vector<StreamParams>& streams = channel->local_streams();
|
||||
transceiver->sender_internal()->set_stream_ids(streams[0].stream_ids());
|
||||
auto encodings = transceiver->sender_internal()->init_send_encodings();
|
||||
transceiver->sender_internal()->SetSsrc(streams[0].first_ssrc());
|
||||
if (!encodings.empty()) {
|
||||
transceivers()
|
||||
->StableState(transceiver_ext)
|
||||
->SetInitSendEncodings(encodings);
|
||||
if (ConfiguredForMedia()) {
|
||||
// We must use List and not ListInternal here because
|
||||
// transceivers()->StableState() is indexed by the non-internal refptr.
|
||||
for (const auto& transceiver_ext : transceivers()->List()) {
|
||||
auto transceiver = transceiver_ext->internal();
|
||||
if (transceiver->stopped()) {
|
||||
continue;
|
||||
}
|
||||
const ContentInfo* content =
|
||||
FindMediaSectionForTransceiver(transceiver, local_description());
|
||||
if (!content) {
|
||||
continue;
|
||||
}
|
||||
cricket::ChannelInterface* channel = transceiver->channel();
|
||||
if (content->rejected || !channel || channel->local_streams().empty()) {
|
||||
// 0 is a special value meaning "this sender has no associated send
|
||||
// stream". Need to call this so the sender won't attempt to configure
|
||||
// a no longer existing stream and run into DCHECKs in the lower
|
||||
// layers.
|
||||
transceiver->sender_internal()->SetSsrc(0);
|
||||
} else {
|
||||
// Get the StreamParams from the channel which could generate SSRCs.
|
||||
const std::vector<StreamParams>& streams = channel->local_streams();
|
||||
transceiver->sender_internal()->set_stream_ids(
|
||||
streams[0].stream_ids());
|
||||
auto encodings =
|
||||
transceiver->sender_internal()->init_send_encodings();
|
||||
transceiver->sender_internal()->SetSsrc(streams[0].first_ssrc());
|
||||
if (!encodings.empty()) {
|
||||
transceivers()
|
||||
->StableState(transceiver_ext)
|
||||
->SetInitSendEncodings(encodings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1930,6 +1938,9 @@ void SdpOfferAnswerHandler::ApplyRemoteDescriptionUpdateTransceiverState(
|
||||
SdpType sdp_type) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(IsUnifiedPlan());
|
||||
if (!ConfiguredForMedia()) {
|
||||
return;
|
||||
}
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||
now_receiving_transceivers;
|
||||
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
|
||||
@ -2717,7 +2728,9 @@ RTCError SdpOfferAnswerHandler::UpdateSessionState(
|
||||
} else {
|
||||
RTC_DCHECK(type == SdpType::kAnswer);
|
||||
ChangeSignalingState(PeerConnectionInterface::kStable);
|
||||
transceivers()->DiscardStableStates();
|
||||
if (ConfiguredForMedia()) {
|
||||
transceivers()->DiscardStableStates();
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal objects according to the session description's media
|
||||
@ -3143,6 +3156,9 @@ bool SdpOfferAnswerHandler::CheckIfNegotiationIsNeeded() {
|
||||
if (!cricket::GetFirstDataContent(description->description()->contents()))
|
||||
return true;
|
||||
}
|
||||
if (!ConfiguredForMedia()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. For each transceiver in connection's set of transceivers, perform the
|
||||
// following checks:
|
||||
@ -3254,7 +3270,6 @@ bool SdpOfferAnswerHandler::CheckIfNegotiationIsNeeded() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If all the preceding checks were performed and true was not returned,
|
||||
// nothing remains to be negotiated; return false.
|
||||
return false;
|
||||
@ -3833,38 +3848,43 @@ void SdpOfferAnswerHandler::GetOptionsForOffer(
|
||||
void SdpOfferAnswerHandler::GetOptionsForPlanBOffer(
|
||||
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options,
|
||||
cricket::MediaSessionOptions* session_options) {
|
||||
// Figure out transceiver directional preferences.
|
||||
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;
|
||||
bool recv_video = true;
|
||||
bool offer_new_data_description =
|
||||
data_channel_controller()->HasDataChannels();
|
||||
bool send_audio = false;
|
||||
bool send_video = false;
|
||||
bool recv_audio = false;
|
||||
bool recv_video = false;
|
||||
if (ConfiguredForMedia()) {
|
||||
// Figure out transceiver directional preferences.
|
||||
send_audio =
|
||||
!rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
|
||||
send_video =
|
||||
!rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
|
||||
|
||||
// By default, generate sendrecv/recvonly m= sections.
|
||||
recv_audio = true;
|
||||
recv_video = true;
|
||||
}
|
||||
// By default, only offer a new m= section if we have media to send with it.
|
||||
bool offer_new_audio_description = send_audio;
|
||||
bool offer_new_video_description = send_video;
|
||||
bool offer_new_data_description =
|
||||
data_channel_controller()->HasDataChannels();
|
||||
|
||||
// The "offer_to_receive_X" options allow those defaults to be overridden.
|
||||
if (offer_answer_options.offer_to_receive_audio !=
|
||||
PeerConnectionInterface::RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_audio = (offer_answer_options.offer_to_receive_audio > 0);
|
||||
offer_new_audio_description =
|
||||
offer_new_audio_description ||
|
||||
(offer_answer_options.offer_to_receive_audio > 0);
|
||||
if (ConfiguredForMedia()) {
|
||||
// The "offer_to_receive_X" options allow those defaults to be overridden.
|
||||
if (offer_answer_options.offer_to_receive_audio !=
|
||||
PeerConnectionInterface::RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_audio = (offer_answer_options.offer_to_receive_audio > 0);
|
||||
offer_new_audio_description =
|
||||
offer_new_audio_description ||
|
||||
(offer_answer_options.offer_to_receive_audio > 0);
|
||||
}
|
||||
if (offer_answer_options.offer_to_receive_video !=
|
||||
RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_video = (offer_answer_options.offer_to_receive_video > 0);
|
||||
offer_new_video_description =
|
||||
offer_new_video_description ||
|
||||
(offer_answer_options.offer_to_receive_video > 0);
|
||||
}
|
||||
}
|
||||
if (offer_answer_options.offer_to_receive_video !=
|
||||
RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_video = (offer_answer_options.offer_to_receive_video > 0);
|
||||
offer_new_video_description =
|
||||
offer_new_video_description ||
|
||||
(offer_answer_options.offer_to_receive_video > 0);
|
||||
}
|
||||
|
||||
absl::optional<size_t> audio_index;
|
||||
absl::optional<size_t> video_index;
|
||||
absl::optional<size_t> data_index;
|
||||
@ -3879,42 +3899,44 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBOffer(
|
||||
&audio_index, &video_index, &data_index, session_options);
|
||||
}
|
||||
|
||||
// Add audio/video/data m= sections to the end if needed.
|
||||
if (!audio_index && offer_new_audio_description) {
|
||||
cricket::MediaDescriptionOptions options(
|
||||
cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
|
||||
RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), false);
|
||||
options.header_extensions =
|
||||
media_engine()->voice().GetRtpHeaderExtensions();
|
||||
session_options->media_description_options.push_back(options);
|
||||
audio_index = session_options->media_description_options.size() - 1;
|
||||
}
|
||||
if (!video_index && offer_new_video_description) {
|
||||
cricket::MediaDescriptionOptions options(
|
||||
cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
|
||||
RtpTransceiverDirectionFromSendRecv(send_video, recv_video), false);
|
||||
options.header_extensions =
|
||||
media_engine()->video().GetRtpHeaderExtensions();
|
||||
session_options->media_description_options.push_back(options);
|
||||
video_index = session_options->media_description_options.size() - 1;
|
||||
if (ConfiguredForMedia()) {
|
||||
// Add audio/video/data m= sections to the end if needed.
|
||||
if (!audio_index && offer_new_audio_description) {
|
||||
cricket::MediaDescriptionOptions options(
|
||||
cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
|
||||
RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), false);
|
||||
options.header_extensions =
|
||||
media_engine()->voice().GetRtpHeaderExtensions();
|
||||
session_options->media_description_options.push_back(options);
|
||||
audio_index = session_options->media_description_options.size() - 1;
|
||||
}
|
||||
if (!video_index && offer_new_video_description) {
|
||||
cricket::MediaDescriptionOptions options(
|
||||
cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
|
||||
RtpTransceiverDirectionFromSendRecv(send_video, recv_video), false);
|
||||
options.header_extensions =
|
||||
media_engine()->video().GetRtpHeaderExtensions();
|
||||
session_options->media_description_options.push_back(options);
|
||||
video_index = session_options->media_description_options.size() - 1;
|
||||
}
|
||||
cricket::MediaDescriptionOptions* audio_media_description_options =
|
||||
!audio_index
|
||||
? nullptr
|
||||
: &session_options->media_description_options[*audio_index];
|
||||
cricket::MediaDescriptionOptions* video_media_description_options =
|
||||
!video_index
|
||||
? nullptr
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
|
||||
audio_media_description_options,
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
}
|
||||
if (!data_index && offer_new_data_description) {
|
||||
session_options->media_description_options.push_back(
|
||||
GetMediaDescriptionOptionsForActiveData(cricket::CN_DATA));
|
||||
data_index = session_options->media_description_options.size() - 1;
|
||||
}
|
||||
|
||||
cricket::MediaDescriptionOptions* audio_media_description_options =
|
||||
!audio_index ? nullptr
|
||||
: &session_options->media_description_options[*audio_index];
|
||||
cricket::MediaDescriptionOptions* video_media_description_options =
|
||||
!video_index ? nullptr
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
|
||||
audio_media_description_options,
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
}
|
||||
|
||||
void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer(
|
||||
@ -4020,27 +4042,29 @@ 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()->ListInternal()) {
|
||||
if (transceiver->mid() || transceiver->stopping()) {
|
||||
continue;
|
||||
if (ConfiguredForMedia()) {
|
||||
for (const auto& transceiver : transceivers()->ListInternal()) {
|
||||
if (transceiver->mid() || transceiver->stopping()) {
|
||||
continue;
|
||||
}
|
||||
size_t mline_index;
|
||||
if (!recycleable_mline_indices.empty()) {
|
||||
mline_index = recycleable_mline_indices.front();
|
||||
recycleable_mline_indices.pop();
|
||||
session_options->media_description_options[mline_index] =
|
||||
GetMediaDescriptionOptionsForTransceiver(
|
||||
transceiver, mid_generator_.GenerateString(),
|
||||
/*is_create_offer=*/true);
|
||||
} else {
|
||||
mline_index = session_options->media_description_options.size();
|
||||
session_options->media_description_options.push_back(
|
||||
GetMediaDescriptionOptionsForTransceiver(
|
||||
transceiver, mid_generator_.GenerateString(),
|
||||
/*is_create_offer=*/true));
|
||||
}
|
||||
// See comment above for why CreateOffer changes the transceiver's state.
|
||||
transceiver->set_mline_index(mline_index);
|
||||
}
|
||||
size_t mline_index;
|
||||
if (!recycleable_mline_indices.empty()) {
|
||||
mline_index = recycleable_mline_indices.front();
|
||||
recycleable_mline_indices.pop();
|
||||
session_options->media_description_options[mline_index] =
|
||||
GetMediaDescriptionOptionsForTransceiver(
|
||||
transceiver, mid_generator_.GenerateString(),
|
||||
/*is_create_offer=*/true);
|
||||
} else {
|
||||
mline_index = session_options->media_description_options.size();
|
||||
session_options->media_description_options.push_back(
|
||||
GetMediaDescriptionOptionsForTransceiver(
|
||||
transceiver, mid_generator_.GenerateString(),
|
||||
/*is_create_offer=*/true));
|
||||
}
|
||||
// See comment above for why CreateOffer changes the transceiver's state.
|
||||
transceiver->set_mline_index(mline_index);
|
||||
}
|
||||
// Lastly, add a m-section if we have local data channels and an m section
|
||||
// does not already exist.
|
||||
@ -4080,25 +4104,32 @@ void SdpOfferAnswerHandler::GetOptionsForAnswer(
|
||||
void SdpOfferAnswerHandler::GetOptionsForPlanBAnswer(
|
||||
const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options,
|
||||
cricket::MediaSessionOptions* session_options) {
|
||||
// Figure out transceiver directional preferences.
|
||||
bool send_audio =
|
||||
!rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
|
||||
bool send_video =
|
||||
!rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
|
||||
bool send_audio = false;
|
||||
bool recv_audio = false;
|
||||
bool send_video = false;
|
||||
bool recv_video = false;
|
||||
|
||||
// By default, generate sendrecv/recvonly m= sections. The direction is also
|
||||
// restricted by the direction in the offer.
|
||||
bool recv_audio = true;
|
||||
bool recv_video = true;
|
||||
if (ConfiguredForMedia()) {
|
||||
// Figure out transceiver directional preferences.
|
||||
send_audio =
|
||||
!rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
|
||||
send_video =
|
||||
!rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
|
||||
|
||||
// The "offer_to_receive_X" options allow those defaults to be overridden.
|
||||
if (offer_answer_options.offer_to_receive_audio !=
|
||||
RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_audio = (offer_answer_options.offer_to_receive_audio > 0);
|
||||
}
|
||||
if (offer_answer_options.offer_to_receive_video !=
|
||||
RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_video = (offer_answer_options.offer_to_receive_video > 0);
|
||||
// By default, generate sendrecv/recvonly m= sections. The direction is also
|
||||
// restricted by the direction in the offer.
|
||||
recv_audio = true;
|
||||
recv_video = true;
|
||||
|
||||
// The "offer_to_receive_X" options allow those defaults to be overridden.
|
||||
if (offer_answer_options.offer_to_receive_audio !=
|
||||
RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_audio = (offer_answer_options.offer_to_receive_audio > 0);
|
||||
}
|
||||
if (offer_answer_options.offer_to_receive_video !=
|
||||
RTCOfferAnswerOptions::kUndefined) {
|
||||
recv_video = (offer_answer_options.offer_to_receive_video > 0);
|
||||
}
|
||||
}
|
||||
|
||||
absl::optional<size_t> audio_index;
|
||||
@ -4121,10 +4152,12 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBAnswer(
|
||||
!video_index ? nullptr
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
|
||||
audio_media_description_options,
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
if (ConfiguredForMedia()) {
|
||||
AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
|
||||
audio_media_description_options,
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
}
|
||||
}
|
||||
|
||||
void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanAnswer(
|
||||
@ -4469,6 +4502,9 @@ void SdpOfferAnswerHandler::UpdateRemoteSendersList(
|
||||
void SdpOfferAnswerHandler::EnableSending() {
|
||||
TRACE_EVENT0("webrtc", "SdpOfferAnswerHandler::EnableSending");
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (!ConfiguredForMedia()) {
|
||||
return;
|
||||
}
|
||||
for (const auto& transceiver : transceivers()->ListInternal()) {
|
||||
cricket::ChannelInterface* channel = transceiver->channel();
|
||||
if (channel) {
|
||||
@ -4489,60 +4525,63 @@ RTCError SdpOfferAnswerHandler::PushdownMediaDescription(
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(sdesc);
|
||||
|
||||
// Note: This will perform an Invoke over to the worker thread, which we'll
|
||||
// also do in a loop below.
|
||||
if (!UpdatePayloadTypeDemuxingState(source, bundle_groups_by_mid)) {
|
||||
// Note that this is never expected to fail, since RtpDemuxer doesn't return
|
||||
// an error when changing payload type demux criteria, which is all this
|
||||
// does.
|
||||
return RTCError(RTCErrorType::INTERNAL_ERROR,
|
||||
"Failed to update payload type demuxing state.");
|
||||
}
|
||||
|
||||
// Push down the new SDP media section for each audio/video transceiver.
|
||||
auto rtp_transceivers = transceivers()->ListInternal();
|
||||
std::vector<
|
||||
std::pair<cricket::ChannelInterface*, const MediaContentDescription*>>
|
||||
channels;
|
||||
for (const auto& transceiver : rtp_transceivers) {
|
||||
const ContentInfo* content_info =
|
||||
FindMediaSectionForTransceiver(transceiver, sdesc);
|
||||
cricket::ChannelInterface* channel = transceiver->channel();
|
||||
if (!channel || !content_info || content_info->rejected) {
|
||||
continue;
|
||||
}
|
||||
const MediaContentDescription* content_desc =
|
||||
content_info->media_description();
|
||||
if (!content_desc) {
|
||||
continue;
|
||||
if (ConfiguredForMedia()) {
|
||||
// Note: This will perform an Invoke over to the worker thread, which we'll
|
||||
// also do in a loop below.
|
||||
if (!UpdatePayloadTypeDemuxingState(source, bundle_groups_by_mid)) {
|
||||
// Note that this is never expected to fail, since RtpDemuxer doesn't
|
||||
// return an error when changing payload type demux criteria, which is all
|
||||
// this does.
|
||||
return RTCError(RTCErrorType::INTERNAL_ERROR,
|
||||
"Failed to update payload type demuxing state.");
|
||||
}
|
||||
|
||||
transceiver->OnNegotiationUpdate(type, content_desc);
|
||||
channels.push_back(std::make_pair(channel, content_desc));
|
||||
}
|
||||
// Push down the new SDP media section for each audio/video transceiver.
|
||||
auto rtp_transceivers = transceivers()->ListInternal();
|
||||
std::vector<
|
||||
std::pair<cricket::ChannelInterface*, const MediaContentDescription*>>
|
||||
channels;
|
||||
for (const auto& transceiver : rtp_transceivers) {
|
||||
const ContentInfo* content_info =
|
||||
FindMediaSectionForTransceiver(transceiver, sdesc);
|
||||
cricket::ChannelInterface* channel = transceiver->channel();
|
||||
if (!channel || !content_info || content_info->rejected) {
|
||||
continue;
|
||||
}
|
||||
const MediaContentDescription* content_desc =
|
||||
content_info->media_description();
|
||||
if (!content_desc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This for-loop of invokes helps audio impairment during re-negotiations.
|
||||
// One of the causes is that downstairs decoder creation is synchronous at the
|
||||
// moment, and that a decoder is created for each codec listed in the SDP.
|
||||
//
|
||||
// TODO(bugs.webrtc.org/12840): consider merging the invokes again after
|
||||
// these projects have shipped:
|
||||
// - bugs.webrtc.org/12462
|
||||
// - crbug.com/1157227
|
||||
// - crbug.com/1187289
|
||||
for (const auto& entry : channels) {
|
||||
std::string error;
|
||||
bool success =
|
||||
context_->worker_thread()->Invoke<bool>(RTC_FROM_HERE, [&]() {
|
||||
return (source == cricket::CS_LOCAL)
|
||||
? entry.first->SetLocalContent(entry.second, type, error)
|
||||
: entry.first->SetRemoteContent(entry.second, type, error);
|
||||
});
|
||||
if (!success) {
|
||||
return RTCError(RTCErrorType::INVALID_PARAMETER, error);
|
||||
transceiver->OnNegotiationUpdate(type, content_desc);
|
||||
channels.push_back(std::make_pair(channel, content_desc));
|
||||
}
|
||||
|
||||
// This for-loop of invokes helps audio impairment during re-negotiations.
|
||||
// One of the causes is that downstairs decoder creation is synchronous at
|
||||
// the moment, and that a decoder is created for each codec listed in the
|
||||
// SDP.
|
||||
//
|
||||
// TODO(bugs.webrtc.org/12840): consider merging the invokes again after
|
||||
// these projects have shipped:
|
||||
// - bugs.webrtc.org/12462
|
||||
// - crbug.com/1157227
|
||||
// - crbug.com/1187289
|
||||
for (const auto& entry : channels) {
|
||||
std::string error;
|
||||
bool success =
|
||||
context_->worker_thread()->Invoke<bool>(RTC_FROM_HERE, [&]() {
|
||||
return (source == cricket::CS_LOCAL)
|
||||
? entry.first->SetLocalContent(entry.second, type, error)
|
||||
: entry.first->SetRemoteContent(entry.second, type,
|
||||
error);
|
||||
});
|
||||
if (!success) {
|
||||
return RTCError(RTCErrorType::INVALID_PARAMETER, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need complete offer/answer with an SCTP m= section before starting SCTP,
|
||||
// according to https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-19
|
||||
if (pc_->sctp_mid() && local_description() && remote_description()) {
|
||||
@ -4596,6 +4635,9 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() {
|
||||
// run the following steps:
|
||||
if (!IsUnifiedPlan())
|
||||
return;
|
||||
if (!ConfiguredForMedia()) {
|
||||
return;
|
||||
}
|
||||
// Traverse a copy of the transceiver list.
|
||||
auto transceiver_list = transceivers()->List();
|
||||
for (auto transceiver : transceiver_list) {
|
||||
@ -4630,18 +4672,21 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() {
|
||||
void SdpOfferAnswerHandler::RemoveUnusedChannels(
|
||||
const SessionDescription* desc) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
// Destroy video channel first since it may have a pointer to the
|
||||
// voice channel.
|
||||
const cricket::ContentInfo* video_info = cricket::GetFirstVideoContent(desc);
|
||||
if (!video_info || video_info->rejected) {
|
||||
rtp_manager()->GetVideoTransceiver()->internal()->ClearChannel();
|
||||
}
|
||||
if (ConfiguredForMedia()) {
|
||||
// Destroy video channel first since it may have a pointer to the
|
||||
// voice channel.
|
||||
const cricket::ContentInfo* video_info =
|
||||
cricket::GetFirstVideoContent(desc);
|
||||
if (!video_info || video_info->rejected) {
|
||||
rtp_manager()->GetVideoTransceiver()->internal()->ClearChannel();
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* audio_info = cricket::GetFirstAudioContent(desc);
|
||||
if (!audio_info || audio_info->rejected) {
|
||||
rtp_manager()->GetAudioTransceiver()->internal()->ClearChannel();
|
||||
const cricket::ContentInfo* audio_info =
|
||||
cricket::GetFirstAudioContent(desc);
|
||||
if (!audio_info || audio_info->rejected) {
|
||||
rtp_manager()->GetAudioTransceiver()->internal()->ClearChannel();
|
||||
}
|
||||
}
|
||||
|
||||
const cricket::ContentInfo* data_info = cricket::GetFirstDataContent(desc);
|
||||
if (!data_info) {
|
||||
RTCError error(RTCErrorType::OPERATION_ERROR_WITH_DATA,
|
||||
@ -5200,4 +5245,8 @@ bool SdpOfferAnswerHandler::UpdatePayloadTypeDemuxingState(
|
||||
});
|
||||
}
|
||||
|
||||
bool SdpOfferAnswerHandler::ConfiguredForMedia() const {
|
||||
return context_->media_engine();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -478,7 +478,7 @@ class SdpOfferAnswerHandler : public SdpStateProvider,
|
||||
// This enables media to flow on all configured audio/video channels.
|
||||
void EnableSending();
|
||||
// Push the media parts of the local or remote session description
|
||||
// down to all of the channels.
|
||||
// down to all of the channels, and start SCTP if needed.
|
||||
RTCError PushdownMediaDescription(
|
||||
SdpType type,
|
||||
cricket::ContentSource source,
|
||||
@ -596,6 +596,7 @@ class SdpOfferAnswerHandler : public SdpStateProvider,
|
||||
// ===================================================================
|
||||
const cricket::AudioOptions& audio_options() { return audio_options_; }
|
||||
const cricket::VideoOptions& video_options() { return video_options_; }
|
||||
bool ConfiguredForMedia() const;
|
||||
|
||||
PeerConnectionSdpMethods* const pc_;
|
||||
ConnectionContext* const context_;
|
||||
|
||||
@ -373,9 +373,17 @@ class PeerConnectionIntegrationWrapper : public webrtc::PeerConnectionObserver,
|
||||
rtc::scoped_refptr<RtpSenderInterface> AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids = {}) {
|
||||
EXPECT_TRUE(track);
|
||||
if (!track) {
|
||||
return nullptr;
|
||||
}
|
||||
auto result = pc()->AddTrack(track, stream_ids);
|
||||
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
||||
return result.MoveValue();
|
||||
if (result.ok()) {
|
||||
return result.MoveValue();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceiversOfType(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user