diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index cc7ec5d986..f778745e31 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -62,11 +62,12 @@ std::unique_ptr CreateChannelAndProxy( RtcpRttStats* rtcp_rtt_stats, RtcEventLog* event_log, FrameEncryptorInterface* frame_encryptor, - const webrtc::CryptoOptions& crypto_options) { + const webrtc::CryptoOptions& crypto_options, + bool extmap_allow_mixed) { return absl::make_unique( absl::make_unique( worker_queue, module_process_thread, media_transport, rtcp_rtt_stats, - event_log, frame_encryptor, crypto_options)); + event_log, frame_encryptor, crypto_options, extmap_allow_mixed)); } } // namespace @@ -119,7 +120,8 @@ AudioSendStream::AudioSendStream( rtcp_rtt_stats, event_log, config.frame_encryptor, - config.crypto_options)) {} + config.crypto_options, + config.rtp.extmap_allow_mixed)) {} AudioSendStream::AudioSendStream( const webrtc::AudioSendStream::Config& config, @@ -258,6 +260,11 @@ void AudioSendStream::ConfigureStream( channel_proxy->SetFrameEncryptor(new_config.frame_encryptor); } + if (first_time || + new_config.rtp.extmap_allow_mixed != old_config.rtp.extmap_allow_mixed) { + channel_proxy->SetExtmapAllowMixed(new_config.rtp.extmap_allow_mixed); + } + const ExtensionIds old_ids = FindExtensionIds(old_config.rtp.extensions); const ExtensionIds new_ids = FindExtensionIds(new_config.rtp.extensions); // Audio level indication diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc index e17030f2d1..6a9232998b 100644 --- a/audio/audio_send_stream_unittest.cc +++ b/audio/audio_send_stream_unittest.cc @@ -198,6 +198,7 @@ struct ConfigHelper { EXPECT_CALL(*channel_proxy_, SetRTCP_CNAME(StrEq(kCName))).Times(1); EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 10)).Times(1); EXPECT_CALL(*channel_proxy_, SetFrameEncryptor(_)).Times(1); + EXPECT_CALL(*channel_proxy_, SetExtmapAllowMixed(false)).Times(1); EXPECT_CALL(*channel_proxy_, SetSendAudioLevelIndicationStatus(true, kAudioLevelId)) .Times(1); @@ -330,10 +331,11 @@ TEST(AudioSendStreamTest, ConfigToString) { config.send_codec_spec->transport_cc_enabled = false; config.send_codec_spec->cng_payload_type = 42; config.encoder_factory = MockAudioEncoderFactory::CreateUnusedFactory(); + config.rtp.extmap_allow_mixed = true; config.rtp.extensions.push_back( RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId)); EXPECT_EQ( - "{rtp: {ssrc: 1234, extensions: [{uri: " + "{rtp: {ssrc: 1234, extmap-allow-mixed: true, extensions: [{uri: " "urn:ietf:params:rtp-hdrext:ssrc-audio-level, id: 2}], nack: " "{rtp_history_ms: 0}, c_name: foo_name}, send_transport: null, " "media_transport: null, " diff --git a/audio/channel_send.cc b/audio/channel_send.cc index 4490b19f5a..cc8b1f7842 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -453,7 +453,8 @@ ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue, RtcpRttStats* rtcp_rtt_stats, RtcEventLog* rtc_event_log, FrameEncryptorInterface* frame_encryptor, - const webrtc::CryptoOptions& crypto_options) + const webrtc::CryptoOptions& crypto_options, + bool extmap_allow_mixed) : event_log_(rtc_event_log), _timeStamp(0), // This is just an offset, RTP module will add it's own // random offset @@ -496,6 +497,7 @@ ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue, configuration.rtt_stats = rtcp_rtt_stats; configuration.retransmission_rate_limiter = retransmission_rate_limiter_.get(); + configuration.extmap_allow_mixed = extmap_allow_mixed; _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); _rtpRtcpModule->SetSendingMediaStatus(false); @@ -836,6 +838,10 @@ void ChannelSend::SetMid(const std::string& mid, int extension_id) { _rtpRtcpModule->SetMid(mid); } +void ChannelSend::SetExtmapAllowMixed(bool extmap_allow_mixed) { + _rtpRtcpModule->SetExtmapAllowMixed(extmap_allow_mixed); +} + int ChannelSend::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) { _includeAudioLevelIndication = enable; diff --git a/audio/channel_send.h b/audio/channel_send.h index deca5b194d..407303f54f 100644 --- a/audio/channel_send.h +++ b/audio/channel_send.h @@ -124,7 +124,8 @@ class ChannelSend RtcpRttStats* rtcp_rtt_stats, RtcEventLog* rtc_event_log, FrameEncryptorInterface* frame_encryptor, - const webrtc::CryptoOptions& crypto_options); + const webrtc::CryptoOptions& crypto_options, + bool extmap_allow_mixed); virtual ~ChannelSend(); @@ -171,6 +172,7 @@ class ChannelSend int SetLocalSSRC(unsigned int ssrc); void SetMid(const std::string& mid, int extension_id); + void SetExtmapAllowMixed(bool extmap_allow_mixed); int SetSendAudioLevelIndicationStatus(bool enable, unsigned char id); void EnableSendTransportSequenceNumber(int id); diff --git a/audio/channel_send_proxy.cc b/audio/channel_send_proxy.cc index 33bed43b5a..2d0bdd37b2 100644 --- a/audio/channel_send_proxy.cc +++ b/audio/channel_send_proxy.cc @@ -88,6 +88,11 @@ void ChannelSendProxy::SetRTCP_CNAME(const std::string& c_name) { RTC_DCHECK_EQ(0, error); } +void ChannelSendProxy::SetExtmapAllowMixed(bool extmap_allow_mixed) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + channel_->SetExtmapAllowMixed(extmap_allow_mixed); +} + void ChannelSendProxy::SetSendAudioLevelIndicationStatus(bool enable, int id) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); int error = channel_->SetSendAudioLevelIndicationStatus(enable, id); diff --git a/audio/channel_send_proxy.h b/audio/channel_send_proxy.h index 9eae6288a1..3146830351 100644 --- a/audio/channel_send_proxy.h +++ b/audio/channel_send_proxy.h @@ -58,6 +58,7 @@ class ChannelSendProxy { virtual void SetRTCPStatus(bool enable); virtual void SetMid(const std::string& mid, int extension_id); virtual void SetRTCP_CNAME(const std::string& c_name); + virtual void SetExtmapAllowMixed(bool extmap_allow_mixed); virtual void SetSendAudioLevelIndicationStatus(bool enable, int id); virtual void EnableSendTransportSequenceNumber(int id); virtual void RegisterSenderCongestionControlObjects( diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h index adf85dbfea..962152f2e6 100644 --- a/audio/mock_voe_channel_proxy.h +++ b/audio/mock_voe_channel_proxy.h @@ -76,6 +76,7 @@ class MockChannelSendProxy : public voe::ChannelSendProxy { MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc)); MOCK_METHOD1(SetRTCP_CNAME, void(const std::string& c_name)); MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets)); + MOCK_METHOD1(SetExtmapAllowMixed, void(bool extmap_allow_mixed)); MOCK_METHOD2(SetSendAudioLevelIndicationStatus, void(bool enable, int id)); MOCK_METHOD1(EnableSendTransportSequenceNumber, void(int id)); MOCK_METHOD2(RegisterSenderCongestionControlObjects, diff --git a/call/audio_send_stream.cc b/call/audio_send_stream.cc index 398b722e61..372126858f 100644 --- a/call/audio_send_stream.cc +++ b/call/audio_send_stream.cc @@ -52,6 +52,7 @@ std::string AudioSendStream::Config::Rtp::ToString() const { char buf[1024]; rtc::SimpleStringBuilder ss(buf); ss << "{ssrc: " << ssrc; + ss << ", extmap-allow-mixed: " << (extmap_allow_mixed ? "true" : "false"); ss << ", extensions: ["; for (size_t i = 0; i < extensions.size(); ++i) { ss << extensions[i].ToString(); diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h index 3595b6c7b5..ba0d652fdf 100644 --- a/call/audio_send_stream.h +++ b/call/audio_send_stream.h @@ -83,6 +83,9 @@ class AudioSendStream { // included in the list of extensions. std::string mid; + // Corresponds to the SDP attribute extmap-allow-mixed. + bool extmap_allow_mixed = false; + // RTP header extensions used for the sent stream. std::vector extensions; diff --git a/call/rtp_config.cc b/call/rtp_config.cc index c4f9d41009..30631f59cb 100644 --- a/call/rtp_config.cc +++ b/call/rtp_config.cc @@ -63,6 +63,7 @@ std::string RtpConfig::ToString() const { << (rtcp_mode == RtcpMode::kCompound ? "RtcpMode::kCompound" : "RtcpMode::kReducedSize"); ss << ", max_packet_size: " << max_packet_size; + ss << ", extmap-allow-mixed: " << (extmap_allow_mixed ? "true" : "false"); ss << ", extensions: ["; for (size_t i = 0; i < extensions.size(); ++i) { ss << extensions[i].ToString(); diff --git a/call/rtp_config.h b/call/rtp_config.h index 0acddc3ee2..5d2218297f 100644 --- a/call/rtp_config.h +++ b/call/rtp_config.h @@ -76,6 +76,9 @@ struct RtpConfig { // Max RTP packet size delivered to send transport from VideoEngine. size_t max_packet_size = kDefaultMaxPacketSize; + // Corresponds to the SDP attribute extmap-allow-mixed. + bool extmap_allow_mixed = false; + // RTP header extensions to use for this send stream. std::vector extensions; diff --git a/call/rtp_video_sender.cc b/call/rtp_video_sender.cc index 7364cf9fe1..214fe96603 100644 --- a/call/rtp_video_sender.cc +++ b/call/rtp_video_sender.cc @@ -40,7 +40,7 @@ static const size_t kPathMTU = 1500; std::vector> CreateRtpRtcpModules( const std::vector& ssrcs, - const std::vector& protected_media_ssrcs, + const RtpConfig& rtp_config, const RtcpConfig& rtcp_config, Transport* send_transport, RtcpIntraFrameObserver* intra_frame_callback, @@ -89,9 +89,11 @@ std::vector> CreateRtpRtcpModules( configuration.frame_encryptor = frame_encryptor; configuration.require_frame_encryption = crypto_options.sframe.require_frame_encryption; + configuration.extmap_allow_mixed = rtp_config.extmap_allow_mixed; std::vector> modules; - const std::vector& flexfec_protected_ssrcs = protected_media_ssrcs; + const std::vector& flexfec_protected_ssrcs = + rtp_config.flexfec.protected_media_ssrcs; for (uint32_t ssrc : ssrcs) { bool enable_flexfec = flexfec_sender != nullptr && std::find(flexfec_protected_ssrcs.begin(), @@ -200,27 +202,26 @@ RtpVideoSender::RtpVideoSender( suspended_ssrcs_(std::move(suspended_ssrcs)), flexfec_sender_(MaybeCreateFlexfecSender(rtp_config, suspended_ssrcs_)), fec_controller_(std::move(fec_controller)), - rtp_modules_( - CreateRtpRtcpModules(ssrcs, - rtp_config.flexfec.protected_media_ssrcs, - rtcp_config, - send_transport, - observers.intra_frame_callback, - transport->GetBandwidthObserver(), - transport, - observers.rtcp_rtt_stats, - flexfec_sender_.get(), - observers.bitrate_observer, - observers.frame_count_observer, - observers.rtcp_type_observer, - observers.send_delay_observer, - observers.send_packet_observer, - event_log, - retransmission_limiter, - this, - transport->keepalive_config(), - frame_encryptor, - crypto_options)), + rtp_modules_(CreateRtpRtcpModules(ssrcs, + rtp_config, + rtcp_config, + send_transport, + observers.intra_frame_callback, + transport->GetBandwidthObserver(), + transport, + observers.rtcp_rtt_stats, + flexfec_sender_.get(), + observers.bitrate_observer, + observers.frame_count_observer, + observers.rtcp_type_observer, + observers.send_delay_observer, + observers.send_packet_observer, + event_log, + retransmission_limiter, + this, + transport->keepalive_config(), + frame_encryptor, + crypto_options)), rtp_config_(rtp_config), transport_(transport), transport_overhead_bytes_per_packet_(0), diff --git a/media/base/fakemediaengine.cc b/media/base/fakemediaengine.cc index 047ad3fc41..b2557a98a7 100644 --- a/media/base/fakemediaengine.cc +++ b/media/base/fakemediaengine.cc @@ -79,6 +79,7 @@ bool FakeVoiceMediaChannel::SetSendParameters( const AudioSendParameters& params) { set_send_rtcp_parameters(params.rtcp); return (SetSendCodecs(params.codecs) && + SetSendExtmapAllowMixed(params.extmap_allow_mixed) && SetSendRtpHeaderExtensions(params.extensions) && SetMaxSendBandwidth(params.max_bandwidth_bps) && SetOptions(params.options)); @@ -260,6 +261,7 @@ bool FakeVideoMediaChannel::SetSendParameters( const VideoSendParameters& params) { set_send_rtcp_parameters(params.rtcp); return (SetSendCodecs(params.codecs) && + SetSendExtmapAllowMixed(params.extmap_allow_mixed) && SetSendRtpHeaderExtensions(params.extensions) && SetMaxSendBandwidth(params.max_bandwidth_bps)); } diff --git a/media/base/fakemediaengine.h b/media/base/fakemediaengine.h index 08062edcb9..acd3faa0db 100644 --- a/media/base/fakemediaengine.h +++ b/media/base/fakemediaengine.h @@ -252,6 +252,12 @@ class RtpHelper : public Base { recv_extensions_ = extensions; return true; } + bool SetSendExtmapAllowMixed(bool extmap_allow_mixed) { + if (Base::ExtmapAllowMixed() != extmap_allow_mixed) { + Base::SetExtmapAllowMixed(extmap_allow_mixed); + } + return true; + } bool SetSendRtpHeaderExtensions(const std::vector& extensions) { send_extensions_ = extensions; return true; diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h index 56edab72f2..fefb9933be 100644 --- a/media/base/mediachannel.h +++ b/media/base/mediachannel.h @@ -262,6 +262,15 @@ class MediaChannel : public sigslot::has_slots<> { return media_transport_; } + // Corresponds to the SDP attribute extmap-allow-mixed, see RFC8285. + // Set to true if it's allowed to mix one- and two-byte RTP header extensions + // in the same stream. The setter and getter must only be called from + // worker_thread. + void SetExtmapAllowMixed(bool extmap_allow_mixed) { + extmap_allow_mixed_ = extmap_allow_mixed; + } + bool ExtmapAllowMixed() const { return extmap_allow_mixed_; } + protected: virtual rtc::DiffServCodePoint PreferredDscp() const; @@ -298,6 +307,7 @@ class MediaChannel : public sigslot::has_slots<> { rtc::CriticalSection network_interface_crit_; NetworkInterface* network_interface_ = nullptr; webrtc::MediaTransportInterface* media_transport_ = nullptr; + bool extmap_allow_mixed_ = false; }; // The stats information is structured as follows: @@ -661,12 +671,14 @@ struct RtpSendParameters : RtpParameters { // This is the value to be sent in the MID RTP header extension (if the header // extension in included in the list of extensions). std::string mid; + bool extmap_allow_mixed = false; protected: std::map ToStringMap() const override { auto params = RtpParameters::ToStringMap(); params["max_bandwidth_bps"] = rtc::ToString(max_bandwidth_bps); params["mid"] = (mid.empty() ? "" : mid); + params["extmap-allow-mixed"] = extmap_allow_mixed ? "true" : "false"; return params; } }; diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc index 7310e4c9db..d0f12c04f8 100644 --- a/media/engine/webrtcvideoengine.cc +++ b/media/engine/webrtcvideoengine.cc @@ -624,6 +624,9 @@ bool WebRtcVideoChannel::GetChangedSendParameters( changed_params->codec = selected_send_codec; // Handle RTP header extensions. + if (params.extmap_allow_mixed != ExtmapAllowMixed()) { + changed_params->extmap_allow_mixed = params.extmap_allow_mixed; + } std::vector filtered_extensions = FilterRtpExtensions( params.extensions, webrtc::RtpExtension::IsSupportedForVideo, true); if (!send_rtp_extensions_ || (*send_rtp_extensions_ != filtered_extensions)) { @@ -678,6 +681,9 @@ bool WebRtcVideoChannel::SetSendParameters(const VideoSendParameters& params) { RTC_LOG(LS_INFO) << "Using codec: " << codec_settings.codec.ToString(); } + if (changed_params.extmap_allow_mixed) { + SetExtmapAllowMixed(*changed_params.extmap_allow_mixed); + } if (changed_params.rtp_header_extensions) { send_rtp_extensions_ = changed_params.rtp_header_extensions; } @@ -1064,6 +1070,7 @@ bool WebRtcVideoChannel::AddSendStream(const StreamParams& sp) { video_config_.experiment_cpu_load_estimator; config.encoder_settings.encoder_factory = encoder_factory_; config.crypto_options = crypto_options_; + config.rtp.extmap_allow_mixed = ExtmapAllowMixed(); WebRtcVideoSendStream* stream = new WebRtcVideoSendStream( call_, sp, std::move(config), default_send_options_, @@ -1630,7 +1637,6 @@ WebRtcVideoChannel::WebRtcVideoSendStream::WebRtcVideoSendStream( ? webrtc::RtcpMode::kReducedSize : webrtc::RtcpMode::kCompound; parameters_.config.rtp.mid = send_params.mid; - rtp_parameters_.rtcp.reduced_size = send_params.rtcp.reduced_size; if (codec_settings) { @@ -1760,6 +1766,10 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::SetSendParameters( parameters_.config.rtp.rtcp_mode == webrtc::RtcpMode::kReducedSize; recreate_stream = true; } + if (params.extmap_allow_mixed) { + parameters_.config.rtp.extmap_allow_mixed = *params.extmap_allow_mixed; + recreate_stream = true; + } if (params.rtp_header_extensions) { parameters_.config.rtp.extensions = *params.rtp_header_extensions; rtp_parameters_.header_extensions = *params.rtp_header_extensions; diff --git a/media/engine/webrtcvideoengine.h b/media/engine/webrtcvideoengine.h index f327bad388..083fc9f41d 100644 --- a/media/engine/webrtcvideoengine.h +++ b/media/engine/webrtcvideoengine.h @@ -219,6 +219,7 @@ class WebRtcVideoChannel : public VideoMediaChannel, public webrtc::Transport { absl::optional codec; absl::optional> rtp_header_extensions; absl::optional mid; + absl::optional extmap_allow_mixed; absl::optional max_bandwidth_bps; absl::optional conference_mode; absl::optional rtcp_mode; diff --git a/media/engine/webrtcvideoengine_unittest.cc b/media/engine/webrtcvideoengine_unittest.cc index e269632ccc..36a0e14a38 100644 --- a/media/engine/webrtcvideoengine_unittest.cc +++ b/media/engine/webrtcvideoengine_unittest.cc @@ -2090,6 +2090,29 @@ class WebRtcVideoChannelTest : public WebRtcVideoEngineTest { &BitrateConstraints::max_bitrate_bps, max_bitrate_bps))); } + void TestExtmapAllowMixedCaller(bool extmap_allow_mixed) { + // For a caller, the answer will be applied in set remote description + // where SetSendParameters() is called. + EXPECT_TRUE( + channel_->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); + send_parameters_.extmap_allow_mixed = extmap_allow_mixed; + EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); + const webrtc::VideoSendStream::Config& config = + fake_call_->GetVideoSendStreams()[0]->GetConfig(); + EXPECT_EQ(extmap_allow_mixed, config.rtp.extmap_allow_mixed); + } + + void TestExtmapAllowMixedCallee(bool extmap_allow_mixed) { + // For a callee, the answer will be applied in set local description + // where SetExtmapAllowMixed() and AddSendStream() are called. + channel_->SetExtmapAllowMixed(extmap_allow_mixed); + EXPECT_TRUE( + channel_->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); + const webrtc::VideoSendStream::Config& config = + fake_call_->GetVideoSendStreams()[0]->GetConfig(); + EXPECT_EQ(extmap_allow_mixed, config.rtp.extmap_allow_mixed); + } + void TestSetSendRtpHeaderExtensions(const std::string& ext_uri) { // Enable extension. const int id = 1; @@ -2346,6 +2369,20 @@ TEST_F(WebRtcVideoChannelTest, RecvStreamNoRtx) { ASSERT_EQ(0U, recv_stream->GetConfig().rtp.rtx_ssrc); } +// Test propagation of extmap allow mixed setting. +TEST_F(WebRtcVideoChannelTest, SetExtmapAllowMixedAsCaller) { + TestExtmapAllowMixedCaller(/*extmap_allow_mixed=*/true); +} +TEST_F(WebRtcVideoChannelTest, SetExtmapAllowMixedDisabledAsCaller) { + TestExtmapAllowMixedCaller(/*extmap_allow_mixed=*/false); +} +TEST_F(WebRtcVideoChannelTest, SetExtmapAllowMixedAsCallee) { + TestExtmapAllowMixedCallee(/*extmap_allow_mixed=*/true); +} +TEST_F(WebRtcVideoChannelTest, SetExtmapAllowMixedDisabledAsCallee) { + TestExtmapAllowMixedCallee(/*extmap_allow_mixed=*/false); +} + TEST_F(WebRtcVideoChannelTest, NoHeaderExtesionsByDefault) { FakeVideoSendStream* send_stream = AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0])); diff --git a/media/engine/webrtcvoiceengine.cc b/media/engine/webrtcvoiceengine.cc index 889c7ec729..4fc25cb88a 100644 --- a/media/engine/webrtcvoiceengine.cc +++ b/media/engine/webrtcvoiceengine.cc @@ -705,6 +705,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream const std::string track_id, const absl::optional& send_codec_spec, + bool extmap_allow_mixed, const std::vector& extensions, int max_send_bitrate_bps, const absl::optional& audio_network_adaptor_config, @@ -726,6 +727,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream config_.rtp.ssrc = ssrc; config_.rtp.mid = mid; config_.rtp.c_name = c_name; + config_.rtp.extmap_allow_mixed = extmap_allow_mixed; config_.rtp.extensions = extensions; config_.has_dscp = rtp_parameters_.encodings[0].network_priority != webrtc::kDefaultBitratePriority; @@ -765,6 +767,11 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream ReconfigureAudioSendStream(); } + void SetExtmapAllowMixed(bool extmap_allow_mixed) { + config_.rtp.extmap_allow_mixed = extmap_allow_mixed; + ReconfigureAudioSendStream(); + } + void SetMid(const std::string& mid) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); if (config_.rtp.mid == mid) { @@ -1293,6 +1300,14 @@ bool WebRtcVoiceMediaChannel::SetSendParameters( if (!ValidateRtpExtensions(params.extensions)) { return false; } + + if (ExtmapAllowMixed() != params.extmap_allow_mixed) { + SetExtmapAllowMixed(params.extmap_allow_mixed); + for (auto& it : send_streams_) { + it.second->SetExtmapAllowMixed(params.extmap_allow_mixed); + } + } + std::vector filtered_extensions = FilterRtpExtensions( params.extensions, webrtc::RtpExtension::IsSupportedForAudio, true); if (send_rtp_extensions_ != filtered_extensions) { @@ -1794,10 +1809,10 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { absl::optional audio_network_adaptor_config = GetAudioNetworkAdaptorConfig(options_); WebRtcAudioSendStream* stream = new WebRtcAudioSendStream( - ssrc, mid_, sp.cname, sp.id, send_codec_spec_, send_rtp_extensions_, - max_send_bitrate_bps_, audio_network_adaptor_config, call_, this, - media_transport(), engine()->encoder_factory_, codec_pair_id_, nullptr, - crypto_options_); + ssrc, mid_, sp.cname, sp.id, send_codec_spec_, ExtmapAllowMixed(), + send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config, + call_, this, media_transport(), engine()->encoder_factory_, + codec_pair_id_, nullptr, crypto_options_); send_streams_.insert(std::make_pair(ssrc, stream)); // At this point the stream's local SSRC has been updated. If it is the first diff --git a/media/engine/webrtcvoiceengine_unittest.cc b/media/engine/webrtcvoiceengine_unittest.cc index eefa6f0822..00e552dab5 100644 --- a/media/engine/webrtcvoiceengine_unittest.cc +++ b/media/engine/webrtcvoiceengine_unittest.cc @@ -351,6 +351,30 @@ class WebRtcVoiceEngineTestFake : public testing::Test { EXPECT_EQ(123, telephone_event.duration_ms); } + void TestExtmapAllowMixedCaller(bool extmap_allow_mixed) { + // For a caller, the answer will be applied in set remote description + // where SetSendParameters() is called. + EXPECT_TRUE(SetupChannel()); + EXPECT_TRUE( + channel_->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcX))); + send_parameters_.extmap_allow_mixed = extmap_allow_mixed; + SetSendParameters(send_parameters_); + const webrtc::AudioSendStream::Config& config = GetSendStreamConfig(kSsrcX); + EXPECT_EQ(extmap_allow_mixed, config.rtp.extmap_allow_mixed); + } + + void TestExtmapAllowMixedCallee(bool extmap_allow_mixed) { + // For a callee, the answer will be applied in set local description + // where SetExtmapAllowMixed() and AddSendStream() are called. + EXPECT_TRUE(SetupChannel()); + channel_->SetExtmapAllowMixed(extmap_allow_mixed); + EXPECT_TRUE( + channel_->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcX))); + + const webrtc::AudioSendStream::Config& config = GetSendStreamConfig(kSsrcX); + EXPECT_EQ(extmap_allow_mixed, config.rtp.extmap_allow_mixed); + } + // Test that send bandwidth is set correctly. // |codec| is the codec under test. // |max_bitrate| is a parameter to set to SetMaxSendBandwidth(). @@ -2823,6 +2847,20 @@ TEST_F(WebRtcVoiceEngineTestFake, InsertDtmfOnSendStreamAsCallee) { TestInsertDtmf(kSsrcX, false, kTelephoneEventCodec1); } +// Test propagation of extmap allow mixed setting. +TEST_F(WebRtcVoiceEngineTestFake, SetExtmapAllowMixedAsCaller) { + TestExtmapAllowMixedCaller(/*extmap_allow_mixed=*/true); +} +TEST_F(WebRtcVoiceEngineTestFake, SetExtmapAllowMixedDisabledAsCaller) { + TestExtmapAllowMixedCaller(/*extmap_allow_mixed=*/false); +} +TEST_F(WebRtcVoiceEngineTestFake, SetExtmapAllowMixedAsCallee) { + TestExtmapAllowMixedCallee(/*extmap_allow_mixed=*/true); +} +TEST_F(WebRtcVoiceEngineTestFake, SetExtmapAllowMixedDisabledAsCallee) { + TestExtmapAllowMixedCallee(/*extmap_allow_mixed=*/false); +} + TEST_F(WebRtcVoiceEngineTestFake, SetAudioOptions) { EXPECT_TRUE(SetupSendStream()); EXPECT_TRUE(AddRecvStream(kSsrcY)); diff --git a/modules/rtp_rtcp/include/rtp_header_extension_map.h b/modules/rtp_rtcp/include/rtp_header_extension_map.h index b691cdd030..391c5beaa5 100644 --- a/modules/rtp_rtcp/include/rtp_header_extension_map.h +++ b/modules/rtp_rtcp/include/rtp_header_extension_map.h @@ -59,6 +59,9 @@ class RtpHeaderExtensionMap { // Set to true if it's allowed to mix one- and two-byte RTP header extensions // in the same stream. bool ExtmapAllowMixed() const { return extmap_allow_mixed_; } + void SetExtmapAllowMixed(bool extmap_allow_mixed) { + extmap_allow_mixed_ = extmap_allow_mixed; + } private: bool Register(int id, RTPExtensionType type, const char* uri); diff --git a/modules/rtp_rtcp/include/rtp_rtcp.h b/modules/rtp_rtcp/include/rtp_rtcp.h index 8fa0faab7a..265046c932 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp.h +++ b/modules/rtp_rtcp/include/rtp_rtcp.h @@ -103,6 +103,9 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface { // Require all outgoing frames to be encrypted with a FrameEncryptor. bool require_frame_encryption = false; + // Corresponds to extmap-allow-mixed in SDP negotiation. + bool extmap_allow_mixed = false; + private: RTC_DISALLOW_COPY_AND_ASSIGN(Configuration); }; @@ -142,6 +145,8 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface { // Returns -1 on failure else 0. virtual int32_t DeRegisterSendPayload(int8_t payload_type) = 0; + virtual void SetExtmapAllowMixed(bool extmap_allow_mixed) = 0; + // (De)registers RTP header extension type and id. // Returns -1 on failure else 0. virtual int32_t RegisterSendRtpHeaderExtension(RTPExtensionType type, diff --git a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index e95bdd38b8..9f00654d71 100644 --- a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -52,6 +52,7 @@ class MockRtpRtcp : public RtpRtcp { MOCK_METHOD2(RegisterVideoSendPayload, void(int payload_type, const char* payload_name)); MOCK_METHOD1(DeRegisterSendPayload, int32_t(int8_t payload_type)); + MOCK_METHOD1(SetExtmapAllowMixed, void(bool extmap_allow_mixed)); MOCK_METHOD2(RegisterSendRtpHeaderExtension, int32_t(RTPExtensionType type, uint8_t id)); MOCK_METHOD2(RegisterRtpHeaderExtension, diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 6e40d0271a..5726284008 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -102,7 +102,8 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration) configuration.retransmission_rate_limiter, configuration.overhead_observer, configuration.populate_network2_timestamp, - configuration.frame_encryptor, configuration.require_frame_encryption)); + configuration.frame_encryptor, configuration.require_frame_encryption, + configuration.extmap_allow_mixed)); // Make sure rtcp sender use same timestamp offset as rtp sender. rtcp_sender_.SetTimestampOffset(rtp_sender_->TimestampOffset()); @@ -615,6 +616,10 @@ void ModuleRtpRtcpImpl::UnsetRemb() { rtcp_sender_.UnsetRemb(); } +void ModuleRtpRtcpImpl::SetExtmapAllowMixed(bool extmap_allow_mixed) { + rtp_sender_->SetExtmapAllowMixed(extmap_allow_mixed); +} + int32_t ModuleRtpRtcpImpl::RegisterSendRtpHeaderExtension( const RTPExtensionType type, const uint8_t id) { diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h index c7a0c3bf27..37516de093 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -70,6 +70,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp { int32_t DeRegisterSendPayload(int8_t payload_type) override; + void SetExtmapAllowMixed(bool extmap_allow_mixed) override; + // Register RTP header extension. int32_t RegisterSendRtpHeaderExtension(RTPExtensionType type, uint8_t id) override; diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index d180013188..5b952d0343 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -121,7 +121,8 @@ RTPSender::RTPSender( OverheadObserver* overhead_observer, bool populate_network2_timestamp, FrameEncryptorInterface* frame_encryptor, - bool require_frame_encryption) + bool require_frame_encryption, + bool extmap_allow_mixed) : clock_(clock), // TODO(holmer): Remove this conversion? clock_delta_ms_(clock_->TimeInMilliseconds() - rtc::TimeMillis()), @@ -144,7 +145,7 @@ RTPSender::RTPSender( max_packet_size_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP. last_payload_type_(-1), payload_type_map_(), - rtp_header_extension_map_(), + rtp_header_extension_map_(extmap_allow_mixed), packet_history_(clock), flexfec_packet_history_(clock), // Statistics @@ -245,6 +246,11 @@ uint32_t RTPSender::NackOverheadRate() const { return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0); } +void RTPSender::SetExtmapAllowMixed(bool extmap_allow_mixed) { + rtc::CritScope lock(&send_critsect_); + rtp_header_extension_map_.SetExtmapAllowMixed(extmap_allow_mixed); +} + int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id) { rtc::CritScope lock(&send_critsect_); diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h index dd70bb3803..53bc8f1c51 100644 --- a/modules/rtp_rtcp/source/rtp_sender.h +++ b/modules/rtp_rtcp/source/rtp_sender.h @@ -65,7 +65,8 @@ class RTPSender { OverheadObserver* overhead_observer, bool populate_network2_timestamp, FrameEncryptorInterface* frame_encryptor, - bool require_frame_encryption); + bool require_frame_encryption, + bool extmap_allow_mixed); ~RTPSender(); @@ -118,6 +119,8 @@ class RTPSender { uint32_t* transport_frame_id_out, int64_t expected_retransmission_time_ms); + void SetExtmapAllowMixed(bool extmap_allow_mixed); + // RTP header extension int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id); bool RegisterRtpHeaderExtension(const std::string& uri, int id); diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index ace34ff07a..f30b383e49 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -185,7 +185,7 @@ class RtpSenderTest : public ::testing::TestWithParam { nullptr, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, &retransmission_rate_limiter_, nullptr, populate_network2, nullptr, - false)); + false, false)); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetTimestampOffset(0); rtp_sender_->SetSSRC(kSsrc); @@ -383,7 +383,8 @@ TEST_P(RtpSenderTest, AssignSequenceNumberAllowsPaddingOnAudio) { rtp_sender_.reset(new RTPSender( kEnableAudio, &fake_clock_, &transport, &mock_paced_sender_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, - nullptr, &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + nullptr, &retransmission_rate_limiter_, nullptr, false, nullptr, false, + false)); rtp_sender_->SetTimestampOffset(0); rtp_sender_->SetSSRC(kSsrc); @@ -430,7 +431,7 @@ TEST_P(RtpSenderTestWithoutPacer, false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_, &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr, &retransmission_rate_limiter_, &mock_overhead_observer, false, - nullptr, false)); + nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( kRtpExtensionTransportSequenceNumber, @@ -458,7 +459,7 @@ TEST_P(RtpSenderTestWithoutPacer, SendsPacketsWithTransportSequenceNumber) { false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_, &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, &retransmission_rate_limiter_, nullptr, false, - nullptr, false)); + nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( kRtpExtensionTransportSequenceNumber, @@ -490,7 +491,7 @@ TEST_P(RtpSenderTestWithoutPacer, PacketOptionsNoRetransmission) { false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_, &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, &retransmission_rate_limiter_, nullptr, false, - nullptr, false)); + nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); SendGenericPayload(); @@ -544,7 +545,7 @@ TEST_P(RtpSenderTestWithoutPacer, OnSendSideDelayUpdated) { rtp_sender_.reset(new RTPSender( false, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &send_side_delay_observer_, &mock_rtc_event_log_, - nullptr, nullptr, nullptr, false, nullptr, false)); + nullptr, nullptr, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); const uint8_t kPayloadType = 127; @@ -622,7 +623,7 @@ TEST_P(RtpSenderTest, SendsPacketsWithTransportSequenceNumber) { false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr, &seq_num_allocator_, &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetSSRC(kSsrc); rtp_sender_->SetStorePacketsStatus(true, 10); @@ -982,7 +983,7 @@ TEST_P(RtpSenderTest, OnSendPacketNotUpdatedWithoutSeqNumAllocator) { false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr, nullptr /* TransportSequenceNumberAllocator */, nullptr, nullptr, nullptr, nullptr, nullptr, &send_packet_observer_, &retransmission_rate_limiter_, - nullptr, false, nullptr, false)); + nullptr, false, nullptr, false, false)); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetSSRC(kSsrc); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( @@ -1008,7 +1009,7 @@ TEST_P(RtpSenderTest, SendRedundantPayloads) { rtp_sender_.reset(new RTPSender( false, &fake_clock_, &transport, &mock_paced_sender_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetSSRC(kSsrc); rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload); @@ -1132,7 +1133,7 @@ TEST_P(RtpSenderTest, SendFlexfecPackets) { false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kMediaSsrc); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetStorePacketsStatus(true, 10); @@ -1192,7 +1193,7 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kMediaSsrc); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetStorePacketsStatus(true, 10); @@ -1291,7 +1292,7 @@ TEST_P(RtpSenderTestWithoutPacer, SendFlexfecPackets) { false, &fake_clock_, &transport_, nullptr, &flexfec_sender, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kMediaSsrc); rtp_sender_->SetSequenceNumber(kSeqNum); @@ -1355,7 +1356,7 @@ TEST_P(RtpSenderTest, FecOverheadRate) { false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, &send_packet_observer_, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kMediaSsrc); rtp_sender_->SetSequenceNumber(kSeqNum); @@ -1407,7 +1408,7 @@ TEST_P(RtpSenderTest, FrameCountCallbacks) { rtp_sender_.reset(new RTPSender( false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr, nullptr, nullptr, nullptr, &callback, nullptr, nullptr, nullptr, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC"; const uint8_t payload_type = 127; @@ -1470,7 +1471,7 @@ TEST_P(RtpSenderTest, BitrateCallbacks) { rtp_sender_.reset(new RTPSender( false, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr, &callback, nullptr, nullptr, nullptr, nullptr, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); // Simulate kNumPackets sent with kPacketInterval ms intervals, with the @@ -1530,7 +1531,7 @@ class RtpSenderAudioTest : public RtpSenderTest { rtp_sender_.reset(new RTPSender( true, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); rtp_sender_->SetSequenceNumber(kSeqNum); } @@ -2197,7 +2198,7 @@ TEST_P(RtpSenderTest, OnOverheadChanged) { new RTPSender(false, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &retransmission_rate_limiter_, &mock_overhead_observer, - false, nullptr, false)); + false, nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); // RTP overhead is 12B. @@ -2219,7 +2220,7 @@ TEST_P(RtpSenderTest, DoesNotUpdateOverheadOnEqualSize) { new RTPSender(false, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &retransmission_rate_limiter_, &mock_overhead_observer, - false, nullptr, false)); + false, nullptr, false, false)); rtp_sender_->SetSSRC(kSsrc); EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(_)).Times(1); @@ -2232,7 +2233,7 @@ TEST_P(RtpSenderTest, SendsKeepAlive) { rtp_sender_.reset(new RTPSender( false, &fake_clock_, &transport, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr, - &retransmission_rate_limiter_, nullptr, false, nullptr, false)); + &retransmission_rate_limiter_, nullptr, false, nullptr, false, false)); rtp_sender_->SetSequenceNumber(kSeqNum); rtp_sender_->SetTimestampOffset(0); rtp_sender_->SetSSRC(kSsrc); diff --git a/pc/channel.cc b/pc/channel.cc index 91d8cbf669..8e1d5ff015 100644 --- a/pc/channel.cc +++ b/pc/channel.cc @@ -93,6 +93,7 @@ void RtpSendParametersFromMediaDescription( RtpSendParameters* send_params) { RtpParametersFromMediaDescription(desc, extensions, send_params); send_params->max_bandwidth_bps = desc->bandwidth(); + send_params->extmap_allow_mixed = desc->extmap_allow_mixed(); } BaseChannel::BaseChannel(rtc::Thread* worker_thread, @@ -799,6 +800,7 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, RtpHeaderExtensions rtp_header_extensions = GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions()); UpdateRtpHeaderExtensionMap(rtp_header_extensions); + media_channel()->SetExtmapAllowMixed(audio->extmap_allow_mixed()); AudioRecvParameters recv_params = last_recv_params_; RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params); @@ -934,6 +936,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, RtpHeaderExtensions rtp_header_extensions = GetFilteredRtpHeaderExtensions(video->rtp_header_extensions()); UpdateRtpHeaderExtensionMap(rtp_header_extensions); + media_channel()->SetExtmapAllowMixed(video->extmap_allow_mixed()); VideoRecvParameters recv_params = last_recv_params_; RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params); diff --git a/pc/channel_unittest.cc b/pc/channel_unittest.cc index fc3f20ac1e..5d4d4c7f9e 100644 --- a/pc/channel_unittest.cc +++ b/pc/channel_unittest.cc @@ -576,6 +576,37 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> { CodecMatches(content.codecs()[0], media_channel1_->codecs()[0])); } + // Test that SetLocalContent and SetRemoteContent properly configure + // extmap-allow-mixed. + void TestSetContentsExtmapAllowMixedCaller(bool offer, bool answer) { + // For a caller, SetLocalContent() is called first with an offer and next + // SetRemoteContent() is called with the answer. + CreateChannels(0, 0); + typename T::Content content; + CreateContent(0, kPcmuCodec, kH264Codec, &content); + auto offer_enum = offer ? (T::Content::kSession) : (T::Content::kNo); + auto answer_enum = answer ? (T::Content::kSession) : (T::Content::kNo); + content.set_extmap_allow_mixed_enum(offer_enum); + EXPECT_TRUE(channel1_->SetLocalContent(&content, SdpType::kOffer, NULL)); + content.set_extmap_allow_mixed_enum(answer_enum); + EXPECT_TRUE(channel1_->SetRemoteContent(&content, SdpType::kAnswer, NULL)); + EXPECT_EQ(answer, media_channel1_->ExtmapAllowMixed()); + } + void TestSetContentsExtmapAllowMixedCallee(bool offer, bool answer) { + // For a callee, SetRemoteContent() is called first with an offer and next + // SetLocalContent() is called with the answer. + CreateChannels(0, 0); + typename T::Content content; + CreateContent(0, kPcmuCodec, kH264Codec, &content); + auto offer_enum = offer ? (T::Content::kSession) : (T::Content::kNo); + auto answer_enum = answer ? (T::Content::kSession) : (T::Content::kNo); + content.set_extmap_allow_mixed_enum(offer_enum); + EXPECT_TRUE(channel1_->SetRemoteContent(&content, SdpType::kOffer, NULL)); + content.set_extmap_allow_mixed_enum(answer_enum); + EXPECT_TRUE(channel1_->SetLocalContent(&content, SdpType::kAnswer, NULL)); + EXPECT_EQ(answer, media_channel1_->ExtmapAllowMixed()); + } + // Test that SetLocalContent and SetRemoteContent properly deals // with an empty offer. void TestSetContentsNullOffer() { @@ -1614,6 +1645,24 @@ TEST_F(VoiceChannelSingleThreadTest, TestSetContents) { Base::TestSetContents(); } +TEST_F(VoiceChannelSingleThreadTest, TestSetContentsExtmapAllowMixedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VoiceChannelSingleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/false); +} + +TEST_F(VoiceChannelSingleThreadTest, TestSetContentsExtmapAllowMixedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VoiceChannelSingleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/false); +} + TEST_F(VoiceChannelSingleThreadTest, TestSetContentsNullOffer) { Base::TestSetContentsNullOffer(); } @@ -1749,6 +1798,24 @@ TEST_F(VoiceChannelDoubleThreadTest, TestSetContents) { Base::TestSetContents(); } +TEST_F(VoiceChannelDoubleThreadTest, TestSetContentsExtmapAllowMixedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VoiceChannelDoubleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/false); +} + +TEST_F(VoiceChannelDoubleThreadTest, TestSetContentsExtmapAllowMixedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VoiceChannelDoubleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/false); +} + TEST_F(VoiceChannelDoubleThreadTest, TestSetContentsNullOffer) { Base::TestSetContentsNullOffer(); } @@ -1882,6 +1949,24 @@ TEST_F(VideoChannelSingleThreadTest, TestSetContents) { Base::TestSetContents(); } +TEST_F(VideoChannelSingleThreadTest, TestSetContentsExtmapAllowMixedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VideoChannelSingleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/false); +} + +TEST_F(VideoChannelSingleThreadTest, TestSetContentsExtmapAllowMixedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VideoChannelSingleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/false); +} + TEST_F(VideoChannelSingleThreadTest, TestSetContentsNullOffer) { Base::TestSetContentsNullOffer(); } @@ -2015,6 +2100,24 @@ TEST_F(VideoChannelDoubleThreadTest, TestSetContents) { Base::TestSetContents(); } +TEST_F(VideoChannelDoubleThreadTest, TestSetContentsExtmapAllowMixedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VideoChannelDoubleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCaller) { + Base::TestSetContentsExtmapAllowMixedCaller(/*offer=*/true, /*answer=*/false); +} + +TEST_F(VideoChannelDoubleThreadTest, TestSetContentsExtmapAllowMixedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/true); +} + +TEST_F(VideoChannelDoubleThreadTest, + TestSetContentsExtmapAllowMixedNotSupportedAsCallee) { + Base::TestSetContentsExtmapAllowMixedCallee(/*offer=*/true, /*answer=*/false); +} + TEST_F(VideoChannelDoubleThreadTest, TestSetContentsNullOffer) { Base::TestSetContentsNullOffer(); }