diff --git a/api/media_transport_interface.h b/api/media_transport_interface.h index 1b5f735180..718000e961 100644 --- a/api/media_transport_interface.h +++ b/api/media_transport_interface.h @@ -50,12 +50,22 @@ class AudioPacketReceivedObserver { virtual void OnFirstAudioPacketReceived(int64_t channel_id) = 0; }; +// Used to configure stream allocations. struct MediaTransportAllocatedBitrateLimits { DataRate min_pacing_rate = DataRate::Zero(); DataRate max_padding_bitrate = DataRate::Zero(); DataRate max_total_allocated_bitrate = DataRate::Zero(); }; +// Used to configure target bitrate constraints. +// If the value is provided, the constraint is updated. +// If the value is omitted, the value is left unchanged. +struct MediaTransportTargetRateConstraints { + absl::optional min_bitrate; + absl::optional max_bitrate; + absl::optional starting_bitrate; +}; + // A collection of settings for creation of media transport. struct MediaTransportSettings final { MediaTransportSettings(); @@ -315,6 +325,11 @@ class MediaTransportInterface { virtual void SetAllocatedBitrateLimits( const MediaTransportAllocatedBitrateLimits& limits); + // Sets starting rate. + // TODO(psla): Make abstract when downstream implementation implement it. + virtual void SetTargetBitrateLimits( + const MediaTransportTargetRateConstraints& target_rate_constraints) {} + // Opens a data |channel_id| for sending. May return an error if the // specified |channel_id| is unusable. Must be called before |SendData|. virtual RTCError OpenChannel(int channel_id) = 0; diff --git a/api/test/fake_media_transport.h b/api/test/fake_media_transport.h index 1cfd340765..a085bc04b0 100644 --- a/api/test/fake_media_transport.h +++ b/api/test/fake_media_transport.h @@ -103,6 +103,16 @@ class FakeMediaTransport : public MediaTransportInterface { void SetAllocatedBitrateLimits( const MediaTransportAllocatedBitrateLimits& limits) override {} + void SetTargetBitrateLimits(const MediaTransportTargetRateConstraints& + target_rate_constraints) override { + target_rate_constraints_in_order_.push_back(target_rate_constraints); + } + + const std::vector& + target_rate_constraints_in_order() { + return target_rate_constraints_in_order_; + } + int target_rate_observers_size() { return target_rate_observers_.size(); } // Settings that were passed down to fake media transport. @@ -133,6 +143,8 @@ class FakeMediaTransport : public MediaTransportInterface { const absl::optional transport_offer_; const absl::optional remote_transport_parameters_; bool is_connected_ = false; + std::vector + target_rate_constraints_in_order_; }; // Fake media transport factory creates fake media transport. diff --git a/call/call.cc b/call/call.cc index 67d1c53ed9..bf42ee3e6f 100644 --- a/call/call.cc +++ b/call/call.cc @@ -567,6 +567,20 @@ void Call::MediaTransportChange(MediaTransportInterface* media_transport) { << ", (media_transport_==media_transport)=" << (media_transport_ == media_transport); media_transport_ = media_transport; + MediaTransportTargetRateConstraints constraints; + if (config_.bitrate_config.start_bitrate_bps > 0) { + constraints.starting_bitrate = + DataRate::bps(config_.bitrate_config.start_bitrate_bps); + } + if (config_.bitrate_config.max_bitrate_bps > 0) { + constraints.max_bitrate = + DataRate::bps(config_.bitrate_config.max_bitrate_bps); + } + if (config_.bitrate_config.min_bitrate_bps > 0) { + constraints.min_bitrate = + DataRate::bps(config_.bitrate_config.min_bitrate_bps); + } + media_transport_->SetTargetBitrateLimits(constraints); } } diff --git a/media/BUILD.gn b/media/BUILD.gn index 3484b408db..0f6315c543 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -492,6 +492,7 @@ if (rtc_include_tests) { ":rtc_constants", ":rtc_data", "../:webrtc_common", + "../api:fake_media_transport", "../api:scoped_refptr", "../api/test/video:function_video_factory", "../api/units:time_delta", diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 54eeb1fcce..36473cb2d4 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -717,8 +717,26 @@ bool WebRtcVideoChannel::SetSendParameters(const VideoSendParameters& params) { bitrate_config_.max_bitrate_bps = params.max_bandwidth_bps == 0 ? -1 : params.max_bandwidth_bps; } - call_->GetTransportControllerSend()->SetSdpBitrateParameters( - bitrate_config_); + + if (media_transport()) { + webrtc::MediaTransportTargetRateConstraints constraints; + if (bitrate_config_.start_bitrate_bps >= 0) { + constraints.starting_bitrate = + webrtc::DataRate::bps(bitrate_config_.start_bitrate_bps); + } + if (bitrate_config_.max_bitrate_bps > 0) { + constraints.max_bitrate = + webrtc::DataRate::bps(bitrate_config_.max_bitrate_bps); + } + if (bitrate_config_.min_bitrate_bps >= 0) { + constraints.min_bitrate = + webrtc::DataRate::bps(bitrate_config_.min_bitrate_bps); + } + media_transport()->SetTargetBitrateLimits(constraints); + } else { + call_->GetTransportControllerSend()->SetSdpBitrateParameters( + bitrate_config_); + } } for (auto& kv : send_streams_) { diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc index 1649244fbc..da205e1219 100644 --- a/media/engine/webrtc_video_engine_unittest.cc +++ b/media/engine/webrtc_video_engine_unittest.cc @@ -17,6 +17,7 @@ #include "absl/memory/memory.h" #include "absl/strings/match.h" #include "api/rtp_parameters.h" +#include "api/test/fake_media_transport.h" #include "api/test/mock_video_bitrate_allocator.h" #include "api/test/mock_video_bitrate_allocator_factory.h" #include "api/test/mock_video_decoder_factory.h" @@ -3892,6 +3893,81 @@ TEST_F(WebRtcVideoChannelTest, SetSendCodecsWithBitratesAndMaxSendBandwidth) { EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); } +// Test that when both the codec-specific bitrate params and max_bandwidth_bps +// are present in the same send parameters, the settings are combined correctly. +TEST_F(WebRtcVideoChannelTest, + SetSendCodecsWithBitratesAndMaxSendBandwidthForMediaTransport) { + // Same as SetSendCodecsWithBitratesAndMaxSendBandwidth but with Media + // Transport. + webrtc::MediaTransportSettings settings; + settings.is_caller = true; + webrtc::FakeMediaTransport fake_media_transport(settings); + std::unique_ptr network_interface( + new cricket::FakeNetworkInterface); + channel_->SetInterface(network_interface.get(), &fake_media_transport); + + send_parameters_.codecs[0].params[kCodecParamMinBitrate] = "100"; + send_parameters_.codecs[0].params[kCodecParamStartBitrate] = "200"; + send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "300"; + send_parameters_.max_bandwidth_bps = 400000; + { + // We expect max_bandwidth_bps to take priority, if set. + ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); + ASSERT_EQ(1u, + fake_media_transport.target_rate_constraints_in_order().size()); + const webrtc::MediaTransportTargetRateConstraints& constraint = + fake_media_transport.target_rate_constraints_in_order()[0]; + ASSERT_EQ(webrtc::DataRate::bps(100000), constraint.min_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(200000), constraint.starting_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(400000), constraint.max_bitrate); + } + + { + // Decrease max_bandwidth_bps. + send_parameters_.max_bandwidth_bps = 350000; + ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); + ASSERT_EQ(2u, + fake_media_transport.target_rate_constraints_in_order().size()); + const webrtc::MediaTransportTargetRateConstraints& constraint = + fake_media_transport.target_rate_constraints_in_order()[1]; + + // Since the codec isn't changing, start_bitrate_bps should be 0. + ASSERT_EQ(webrtc::DataRate::bps(100000), constraint.min_bitrate); + ASSERT_EQ(absl::nullopt, constraint.starting_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(350000), constraint.max_bitrate); + } + + { + // Now try again with the values flipped around. + send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "400"; + send_parameters_.max_bandwidth_bps = 300000; + ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); + ASSERT_EQ(3u, + fake_media_transport.target_rate_constraints_in_order().size()); + const webrtc::MediaTransportTargetRateConstraints& constraint = + fake_media_transport.target_rate_constraints_in_order()[2]; + + ASSERT_EQ(webrtc::DataRate::bps(100000), constraint.min_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(200000), constraint.starting_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(300000), constraint.max_bitrate); + } + + { + // Now try again with the values flipped around. + // If we change the codec max, max_bandwidth_bps should still apply. + send_parameters_.codecs[0].params[kCodecParamMaxBitrate] = "350"; + ASSERT_TRUE(channel_->SetSendParameters(send_parameters_)); + ASSERT_EQ(4u, + fake_media_transport.target_rate_constraints_in_order().size()); + const webrtc::MediaTransportTargetRateConstraints& constraint = + fake_media_transport.target_rate_constraints_in_order()[3]; + + ASSERT_EQ(webrtc::DataRate::bps(100000), constraint.min_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(200000), constraint.starting_bitrate); + ASSERT_EQ(webrtc::DataRate::bps(300000), constraint.max_bitrate); + } +} + TEST_F(WebRtcVideoChannelTest, SetMaxSendBandwidthShouldPreserveOtherBitrates) { SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200", 200000);