Add support for target rate constraints
WebRTC video engine now configures bitrate on media transport
correctly.
Bug: webrtc:9719
Change-Id: I85884cd76644b7eca3763cec8ce9e31b5b64db27
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/127941
Commit-Queue: Peter Slatala <psla@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Bjorn Mellem <mellem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27167}
diff --git a/api/media_transport_interface.h b/api/media_transport_interface.h
index 1b5f735..718000e 100644
--- a/api/media_transport_interface.h
+++ b/api/media_transport_interface.h
@@ -50,12 +50,22 @@
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<DataRate> min_bitrate;
+ absl::optional<DataRate> max_bitrate;
+ absl::optional<DataRate> starting_bitrate;
+};
+
// A collection of settings for creation of media transport.
struct MediaTransportSettings final {
MediaTransportSettings();
@@ -315,6 +325,11 @@
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 1cfd340..a085bc0 100644
--- a/api/test/fake_media_transport.h
+++ b/api/test/fake_media_transport.h
@@ -103,6 +103,16 @@
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<MediaTransportTargetRateConstraints>&
+ 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 @@
const absl::optional<std::string> transport_offer_;
const absl::optional<std::string> remote_transport_parameters_;
bool is_connected_ = false;
+ std::vector<MediaTransportTargetRateConstraints>
+ target_rate_constraints_in_order_;
};
// Fake media transport factory creates fake media transport.
diff --git a/call/call.cc b/call/call.cc
index 67d1c53..bf42ee3 100644
--- a/call/call.cc
+++ b/call/call.cc
@@ -567,6 +567,20 @@
<< ", (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 3484b40..0f6315c 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -492,6 +492,7 @@
":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 54eeb1f..36473cb 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -717,8 +717,26 @@
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 1649244..da205e1 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 @@
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<cricket::FakeNetworkInterface> 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);