Add functionality to set min/max bitrate per simulcast layer through RtpEncodingParameters.

Target bitrate is set to 0.75 of the max bitrate.

Bug: webrtc:9341, webrtc:8655
Change-Id: I9a8c8bb95bb1532d45f05578832418464452340e
Reviewed-on: https://webrtc-review.googlesource.com/79821
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23676}
This commit is contained in:
Åsa Persson
2018-06-18 17:51:32 +02:00
committed by Commit Bot
parent f88a22cf11
commit 5565981e17
8 changed files with 508 additions and 48 deletions

View File

@ -401,14 +401,6 @@ struct RtpEncodingParameters {
// bitrate. Currently this is implemented for the entire rtp sender by using
// the value of the first encoding parameter.
//
// TODO(webrtc.bugs.org/8655): Implement this per encoding parameter.
// Current implementation for a sender:
// The max bitrate is decided by taking the minimum of the first encoding
// parameter's max_bitrate_bps and the max bitrate specified by the sdp with
// the b=AS attribute. In the case of simulcast video, default values are used
// for each simulcast layer, and if there is some bitrate left over from the
// sender's max bitrate then it will roll over into the highest quality layer.
//
// Just called "maxBitrate" in ORTC spec.
//
// TODO(deadbeef): With ORTC RtpSenders, this currently sets the total
@ -417,7 +409,9 @@ struct RtpEncodingParameters {
// fixed.
rtc::Optional<int> max_bitrate_bps;
// TODO(asapersson): Not implemented.
// Specifies the minimum bitrate in bps for video.
// TODO(asapersson): Not implemented for ORTC API.
// TODO(asapersson): Not implemented for single layer.
rtc::Optional<int> min_bitrate_bps;
// TODO(deadbeef): Not implemented.

View File

@ -57,6 +57,7 @@ class RtpSenderInterface : public rtc::RefCountInterface {
virtual RtpParameters GetParameters() = 0;
// Note that only a subset of the parameters can currently be changed. See
// rtpparameters.h
// The encodings are in increasing quality order for simulcast.
virtual RTCError SetParameters(const RtpParameters& parameters) = 0;
// Returns null for a video sender.

View File

@ -151,6 +151,9 @@ void SlotSimulcastMaxResolution(size_t max_layers, int* width, int* height) {
void BoostMaxSimulcastLayer(int max_bitrate_bps,
std::vector<webrtc::VideoStream>* layers) {
if (layers->empty())
return;
// Spend additional bits to boost the max layer.
int bitrate_left_bps = max_bitrate_bps - GetTotalMaxBitrateBps(*layers);
if (bitrate_left_bps > 0) {
@ -159,6 +162,9 @@ void BoostMaxSimulcastLayer(int max_bitrate_bps,
}
int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& layers) {
if (layers.empty())
return 0;
int total_max_bitrate_bps = 0;
for (size_t s = 0; s < layers.size() - 1; ++s) {
total_max_bitrate_bps += layers[s].target_bitrate_bps;
@ -170,18 +176,18 @@ int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& layers) {
std::vector<webrtc::VideoStream> GetSimulcastConfig(size_t max_layers,
int width,
int height,
int max_bitrate_bps,
int /*max_bitrate_bps*/,
double bitrate_priority,
int max_qp,
int max_framerate,
bool is_screenshare) {
if (is_screenshare) {
return GetScreenshareLayers(max_layers, width, height, max_bitrate_bps,
bitrate_priority, max_qp, max_framerate,
return GetScreenshareLayers(max_layers, width, height, bitrate_priority,
max_qp, max_framerate,
ScreenshareSimulcastFieldTrialEnabled());
} else {
return GetNormalSimulcastLayers(max_layers, width, height, max_bitrate_bps,
bitrate_priority, max_qp, max_framerate);
return GetNormalSimulcastLayers(max_layers, width, height, bitrate_priority,
max_qp, max_framerate);
}
}
@ -189,7 +195,6 @@ std::vector<webrtc::VideoStream> GetNormalSimulcastLayers(
size_t max_layers,
int width,
int height,
int max_bitrate_bps,
double bitrate_priority,
int max_qp,
int max_framerate) {
@ -249,8 +254,6 @@ std::vector<webrtc::VideoStream> GetNormalSimulcastLayers(
break;
}
}
// If there is bitrate leftover, give it to the largest layer.
BoostMaxSimulcastLayer(max_bitrate_bps, &layers);
// Currently the relative bitrate priority of the sender is controlled by
// the value of the lowest VideoStream.
// TODO(bugs.webrtc.org/8630): The web specification describes being able to
@ -264,7 +267,6 @@ std::vector<webrtc::VideoStream> GetScreenshareLayers(
size_t max_layers,
int width,
int height,
int max_bitrate_bps,
double bitrate_priority,
int max_qp,
int max_framerate,

View File

@ -21,35 +21,39 @@ namespace cricket {
// TODO(pthatcher): Write unit tests just for these functions,
// independent of WebrtcVideoEngine.
// Gets the total maximum bitrate for the |streams|.
int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& streams);
// Get simulcast settings.
std::vector<webrtc::VideoStream> GetSimulcastConfig(
size_t max_layers,
int width,
int height,
int max_bitrate_bps,
double bitrate_priority,
int max_qp,
int max_framerate,
bool is_screenshare);
// Adds any bitrate of |max_bitrate_bps| that is above the total maximum bitrate
// for the |layers| to the highest quality layer.
void BoostMaxSimulcastLayer(int max_bitrate_bps,
std::vector<webrtc::VideoStream>* layers);
// Gets simulcast settings.
// TODO(asapersson): Remove max_bitrate_bps.
std::vector<webrtc::VideoStream> GetSimulcastConfig(size_t max_layers,
int width,
int height,
int /*max_bitrate_bps*/,
double bitrate_priority,
int max_qp,
int max_framerate,
bool is_screenshare);
// Gets the simulcast config layers for a non-screensharing case.
std::vector<webrtc::VideoStream> GetNormalSimulcastLayers(
size_t max_layers,
int width,
int height,
int max_bitrate_bps,
double bitrate_priority,
int max_qp,
int max_framerate);
// Get simulcast config layers for screenshare settings.
// Gets simulcast config layers for screenshare settings.
std::vector<webrtc::VideoStream> GetScreenshareLayers(
size_t max_layers,
int width,
int height,
int max_bitrate_bps,
double bitrate_priority,
int max_qp,
int max_framerate,

View File

@ -1800,13 +1800,23 @@ webrtc::RTCError WebRtcVideoChannel::WebRtcVideoSendStream::SetRtpParameters(
return error;
}
bool new_bitrate = false;
for (size_t i = 0; i < rtp_parameters_.encodings.size(); ++i) {
if ((new_parameters.encodings[i].min_bitrate_bps !=
rtp_parameters_.encodings[i].min_bitrate_bps) ||
(new_parameters.encodings[i].max_bitrate_bps !=
rtp_parameters_.encodings[i].max_bitrate_bps)) {
new_bitrate = true;
}
}
// TODO(bugs.webrtc.org/8807): The bitrate priority really doesn't require an
// entire encoder reconfiguration, it just needs to update the bitrate
// allocator.
bool reconfigure_encoder = (new_parameters.encodings[0].max_bitrate_bps !=
rtp_parameters_.encodings[0].max_bitrate_bps) ||
(new_parameters.encodings[0].bitrate_priority !=
rtp_parameters_.encodings[0].bitrate_priority);
bool reconfigure_encoder =
new_bitrate || (new_parameters.encodings[0].bitrate_priority !=
rtp_parameters_.encodings[0].bitrate_priority);
// TODO(bugs.webrtc.org/8807): The active field as well should not require
// a full encoder reconfiguration, but it needs to update both the bitrate
// allocator and the video bitrate allocator.
@ -1864,6 +1874,17 @@ WebRtcVideoChannel::WebRtcVideoSendStream::ValidateRtpParameters(
"Attempted to set RtpParameters bitrate_priority to "
"an invalid number. bitrate_priority must be > 0.");
}
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
if (rtp_parameters.encodings[i].min_bitrate_bps &&
rtp_parameters.encodings[i].max_bitrate_bps) {
if (*rtp_parameters.encodings[i].max_bitrate_bps <
*rtp_parameters.encodings[i].min_bitrate_bps) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
"Attempted to set RtpParameters min bitrate "
"larger than max bitrate.");
}
}
}
return webrtc::RTCError::OK();
}
@ -1918,7 +1939,13 @@ WebRtcVideoChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig(
}
int stream_max_bitrate = parameters_.max_bitrate_bps;
if (rtp_parameters_.encodings[0].max_bitrate_bps) {
// When simulcast is enabled (when there are multiple encodings),
// encodings[i].max_bitrate_bps will be enforced by
// encoder_config.simulcast_layers[i].max_bitrate_bps. Otherwise, it's
// enforced by stream_max_bitrate, taking the minimum of the two maximums
// (one coming from SDP, the other coming from RtpParameters).
if (rtp_parameters_.encodings[0].max_bitrate_bps &&
rtp_parameters_.encodings.size() == 1) {
stream_max_bitrate =
webrtc::MinPositive(*(rtp_parameters_.encodings[0].max_bitrate_bps),
parameters_.max_bitrate_bps);
@ -1939,7 +1966,7 @@ WebRtcVideoChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig(
// Application-controlled state is held in the encoder_config's
// simulcast_layers. Currently this is used to control which simulcast layers
// are active.
// are active and for configuring the min/max bitrate.
RTC_DCHECK_GE(rtp_parameters_.encodings.size(),
encoder_config.number_of_streams);
RTC_DCHECK_GT(encoder_config.number_of_streams, 0);
@ -1947,6 +1974,14 @@ WebRtcVideoChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig(
for (size_t i = 0; i < encoder_config.simulcast_layers.size(); ++i) {
encoder_config.simulcast_layers[i].active =
rtp_parameters_.encodings[i].active;
if (rtp_parameters_.encodings[i].min_bitrate_bps) {
encoder_config.simulcast_layers[i].min_bitrate_bps =
*rtp_parameters_.encodings[i].min_bitrate_bps;
}
if (rtp_parameters_.encodings[i].max_bitrate_bps) {
encoder_config.simulcast_layers[i].max_bitrate_bps =
*rtp_parameters_.encodings[i].max_bitrate_bps;
}
}
int max_qp = kDefaultQpMax;
@ -2681,12 +2716,50 @@ std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
(CodecNamesEq(codec_name_, kVp8CodecName) && is_screenshare_ &&
screenshare_config_explicitly_enabled_)) {
layers = GetSimulcastConfig(encoder_config.number_of_streams, width, height,
encoder_config.max_bitrate_bps,
encoder_config.bitrate_priority, max_qp_,
max_framerate_, is_screenshare_);
// Update the active simulcast layers.
0 /*not used*/, encoder_config.bitrate_priority,
max_qp_, max_framerate_, is_screenshare_);
// Update the active simulcast layers and configured bitrates.
bool is_highest_layer_max_bitrate_configured = false;
for (size_t i = 0; i < layers.size(); ++i) {
layers[i].active = encoder_config.simulcast_layers[i].active;
// Update simulcast bitrates with configured min and max bitrate.
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
layers[i].min_bitrate_bps =
encoder_config.simulcast_layers[i].min_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
layers[i].max_bitrate_bps =
encoder_config.simulcast_layers[i].max_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0 &&
encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
// Min and max bitrate are configured.
// Set target to 3/4 of the max bitrate (or to max if below min).
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps * 3 / 4;
if (layers[i].target_bitrate_bps < layers[i].min_bitrate_bps)
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps;
} else if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
// Only min bitrate is configured, make sure target/max are above min.
layers[i].target_bitrate_bps =
std::max(layers[i].target_bitrate_bps, layers[i].min_bitrate_bps);
layers[i].max_bitrate_bps =
std::max(layers[i].max_bitrate_bps, layers[i].min_bitrate_bps);
} else if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
// Only max bitrate is configured, make sure min/target are below max.
layers[i].min_bitrate_bps =
std::min(layers[i].min_bitrate_bps, layers[i].max_bitrate_bps);
layers[i].target_bitrate_bps =
std::min(layers[i].target_bitrate_bps, layers[i].max_bitrate_bps);
}
if (i == layers.size() - 1) {
is_highest_layer_max_bitrate_configured =
encoder_config.simulcast_layers[i].max_bitrate_bps > 0;
}
}
if (!is_screenshare_ && !is_highest_layer_max_bitrate_configured) {
// No application-configured maximum for the largest layer.
// If there is bitrate leftover, give it to the largest layer.
BoostMaxSimulcastLayer(encoder_config.max_bitrate_bps, &layers);
}
return layers;
}

View File

@ -2212,6 +2212,21 @@ class WebRtcVideoChannelTest : public WebRtcVideoEngineTest {
EXPECT_EQ(expected_encoder_bitrate, GetMaxEncoderBitrate());
}
// Values from kSimulcastConfigs in simulcast.cc.
const std::vector<webrtc::VideoStream> GetSimulcastBitrates720p() const {
std::vector<webrtc::VideoStream> layers(3);
layers[0].min_bitrate_bps = 30000;
layers[0].target_bitrate_bps = 150000;
layers[0].max_bitrate_bps = 200000;
layers[1].min_bitrate_bps = 150000;
layers[1].target_bitrate_bps = 500000;
layers[1].max_bitrate_bps = 700000;
layers[2].min_bitrate_bps = 600000;
layers[2].target_bitrate_bps = 2500000;
layers[2].max_bitrate_bps = 2500000;
return layers;
}
std::unique_ptr<FakeCall> fake_call_;
std::unique_ptr<VideoMediaChannel> channel_;
cricket::VideoSendParameters send_parameters_;
@ -3980,6 +3995,31 @@ TEST_F(WebRtcVideoChannelTest, SetMaxSendBandwidthAndAddSendStream) {
stream->GetVideoStreams()[0].max_bitrate_bps);
}
TEST_F(WebRtcVideoChannelTest,
MaxBitrateIsMinimumOfMaxSendBandwidthAndMaxEncodingBitrate) {
send_parameters_.max_bandwidth_bps = 99999;
FakeVideoSendStream* stream = AddSendStream();
ExpectSetMaxBitrate(send_parameters_.max_bandwidth_bps);
ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
ASSERT_EQ(1u, stream->GetVideoStreams().size());
EXPECT_EQ(send_parameters_.max_bandwidth_bps,
stream->GetVideoStreams()[0].max_bitrate_bps);
// Get and set the rtp encoding parameters.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(1u, parameters.encodings.size());
parameters.encodings[0].max_bitrate_bps = 99999 - 1;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
EXPECT_EQ(parameters.encodings[0].max_bitrate_bps,
stream->GetVideoStreams()[0].max_bitrate_bps);
parameters.encodings[0].max_bitrate_bps = 99999 + 1;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
EXPECT_EQ(send_parameters_.max_bandwidth_bps,
stream->GetVideoStreams()[0].max_bitrate_bps);
}
TEST_F(WebRtcVideoChannelTest, SetMaxSendBitrateCanIncreaseSenderBitrate) {
cricket::VideoSendParameters parameters;
parameters.codecs.push_back(GetEngineCodec("VP8"));
@ -5371,6 +5411,325 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersPrioritySimulcastStreams) {
EXPECT_TRUE(channel_->SetVideoSend(primary_ssrc, nullptr, nullptr));
}
TEST_F(WebRtcVideoChannelTest, GetAndSetRtpSendParametersMinAndMaxBitrate) {
const size_t kNumSimulcastStreams = 3;
SetUpSimulcast(true, false);
// Get and set the rtp encoding parameters.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
for (const auto& encoding : parameters.encodings) {
EXPECT_FALSE(encoding.min_bitrate_bps);
EXPECT_FALSE(encoding.max_bitrate_bps);
}
// Change the value and set it on the VideoChannel.
parameters.encodings[0].min_bitrate_bps = 100000;
parameters.encodings[0].max_bitrate_bps = 200000;
parameters.encodings[1].min_bitrate_bps = 300000;
parameters.encodings[1].max_bitrate_bps = 400000;
parameters.encodings[2].min_bitrate_bps = 500000;
parameters.encodings[2].max_bitrate_bps = 600000;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
// Verify that the bitrates are set on the VideoChannel.
parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
EXPECT_EQ(100000, parameters.encodings[0].min_bitrate_bps);
EXPECT_EQ(200000, parameters.encodings[0].max_bitrate_bps);
EXPECT_EQ(300000, parameters.encodings[1].min_bitrate_bps);
EXPECT_EQ(400000, parameters.encodings[1].max_bitrate_bps);
EXPECT_EQ(500000, parameters.encodings[2].min_bitrate_bps);
EXPECT_EQ(600000, parameters.encodings[2].max_bitrate_bps);
}
TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersFailsWithIncorrectBitrate) {
const size_t kNumSimulcastStreams = 3;
SetUpSimulcast(true, false);
// Get and set the rtp encoding parameters.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
// Max bitrate lower than min bitrate should fail.
parameters.encodings[2].min_bitrate_bps = 100000;
parameters.encodings[2].max_bitrate_bps = 100000 - 1;
EXPECT_EQ(webrtc::RTCErrorType::INVALID_RANGE,
channel_->SetRtpSendParameters(last_ssrc_, parameters).type());
}
// Test that min and max bitrate values set via RtpParameters are correctly
// propagated to the underlying encoder, and that the target is set to 3/4 of
// the maximum (3/4 was chosen because it's similar to the simulcast defaults
// that are used if no min/max are specified).
TEST_F(WebRtcVideoChannelTest, MinAndMaxSimulcastBitratePropagatedToEncoder) {
const size_t kNumSimulcastStreams = 3;
FakeVideoSendStream* stream = SetUpSimulcast(true, false);
// Send a full size frame so all simulcast layers are used when reconfiguring.
FakeVideoCapturerWithTaskQueue capturer;
VideoOptions options;
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &capturer));
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
// Get and set the rtp encoding parameters.
// Change the value and set it on the VideoChannel.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
parameters.encodings[0].min_bitrate_bps = 100000;
parameters.encodings[0].max_bitrate_bps = 200000;
parameters.encodings[1].min_bitrate_bps = 300000;
parameters.encodings[1].max_bitrate_bps = 400000;
parameters.encodings[2].min_bitrate_bps = 500000;
parameters.encodings[2].max_bitrate_bps = 600000;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
// Verify that the new value propagated down to the encoder.
// Check that WebRtcVideoSendStream updates VideoEncoderConfig correctly.
EXPECT_EQ(2, stream->num_encoder_reconfigurations());
webrtc::VideoEncoderConfig encoder_config = stream->GetEncoderConfig().Copy();
EXPECT_EQ(kNumSimulcastStreams, encoder_config.number_of_streams);
EXPECT_EQ(kNumSimulcastStreams, encoder_config.simulcast_layers.size());
EXPECT_EQ(100000, encoder_config.simulcast_layers[0].min_bitrate_bps);
EXPECT_EQ(200000, encoder_config.simulcast_layers[0].max_bitrate_bps);
EXPECT_EQ(300000, encoder_config.simulcast_layers[1].min_bitrate_bps);
EXPECT_EQ(400000, encoder_config.simulcast_layers[1].max_bitrate_bps);
EXPECT_EQ(500000, encoder_config.simulcast_layers[2].min_bitrate_bps);
EXPECT_EQ(600000, encoder_config.simulcast_layers[2].max_bitrate_bps);
// FakeVideoSendStream calls CreateEncoderStreams, test that the vector of
// VideoStreams are created appropriately for the simulcast case.
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
// Target bitrate: 200000 * 3 / 4 = 150000.
EXPECT_EQ(100000, stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_EQ(150000, stream->GetVideoStreams()[0].target_bitrate_bps);
EXPECT_EQ(200000, stream->GetVideoStreams()[0].max_bitrate_bps);
// Target bitrate: 400000 * 3 / 4 = 300000.
EXPECT_EQ(300000, stream->GetVideoStreams()[1].min_bitrate_bps);
EXPECT_EQ(300000, stream->GetVideoStreams()[1].target_bitrate_bps);
EXPECT_EQ(400000, stream->GetVideoStreams()[1].max_bitrate_bps);
// Target bitrate: 600000 * 3 / 4 = 450000, less than min -> max.
EXPECT_EQ(500000, stream->GetVideoStreams()[2].min_bitrate_bps);
EXPECT_EQ(600000, stream->GetVideoStreams()[2].target_bitrate_bps);
EXPECT_EQ(600000, stream->GetVideoStreams()[2].max_bitrate_bps);
// No parameter changed, encoder should not be reconfigured.
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
EXPECT_EQ(2, stream->num_encoder_reconfigurations());
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
}
// Test to only specify the min or max bitrate value for a layer via
// RtpParameters. The unspecified min/max and target value should be set to the
// simulcast default that is used if no min/max are specified.
TEST_F(WebRtcVideoChannelTest, MinOrMaxSimulcastBitratePropagatedToEncoder) {
const size_t kNumSimulcastStreams = 3;
const std::vector<webrtc::VideoStream> kDefault = GetSimulcastBitrates720p();
FakeVideoSendStream* stream = SetUpSimulcast(true, false);
// Send a full size frame so all simulcast layers are used when reconfiguring.
FakeVideoCapturerWithTaskQueue capturer;
VideoOptions options;
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &capturer));
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
// Get and set the rtp encoding parameters.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
// Change the value and set it on the VideoChannel.
// Layer 0: only configure min bitrate.
const int kMinBpsLayer0 = kDefault[0].min_bitrate_bps + 1;
parameters.encodings[0].min_bitrate_bps = kMinBpsLayer0;
// Layer 1: only configure max bitrate.
const int kMaxBpsLayer1 = kDefault[1].max_bitrate_bps - 1;
parameters.encodings[1].max_bitrate_bps = kMaxBpsLayer1;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
// Verify that the new value propagated down to the encoder.
// Check that WebRtcVideoSendStream updates VideoEncoderConfig correctly.
webrtc::VideoEncoderConfig encoder_config = stream->GetEncoderConfig().Copy();
EXPECT_EQ(kNumSimulcastStreams, encoder_config.number_of_streams);
EXPECT_EQ(kNumSimulcastStreams, encoder_config.simulcast_layers.size());
EXPECT_EQ(kMinBpsLayer0, encoder_config.simulcast_layers[0].min_bitrate_bps);
EXPECT_EQ(-1, encoder_config.simulcast_layers[0].max_bitrate_bps);
EXPECT_EQ(-1, encoder_config.simulcast_layers[1].min_bitrate_bps);
EXPECT_EQ(kMaxBpsLayer1, encoder_config.simulcast_layers[1].max_bitrate_bps);
EXPECT_EQ(-1, encoder_config.simulcast_layers[2].min_bitrate_bps);
EXPECT_EQ(-1, encoder_config.simulcast_layers[2].max_bitrate_bps);
// FakeVideoSendStream calls CreateEncoderStreams, test that the vector of
// VideoStreams are created appropriately for the simulcast case.
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
// Layer 0: min configured bitrate should overwrite min default.
EXPECT_EQ(kMinBpsLayer0, stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_EQ(kDefault[0].target_bitrate_bps,
stream->GetVideoStreams()[0].target_bitrate_bps);
EXPECT_EQ(kDefault[0].max_bitrate_bps,
stream->GetVideoStreams()[0].max_bitrate_bps);
// Layer 1: max configured bitrate should overwrite max default.
EXPECT_EQ(kDefault[1].min_bitrate_bps,
stream->GetVideoStreams()[1].min_bitrate_bps);
EXPECT_EQ(kDefault[1].target_bitrate_bps,
stream->GetVideoStreams()[1].target_bitrate_bps);
EXPECT_EQ(kMaxBpsLayer1, stream->GetVideoStreams()[1].max_bitrate_bps);
// Layer 2: min and max bitrate not configured, default expected.
EXPECT_EQ(kDefault[2].min_bitrate_bps,
stream->GetVideoStreams()[2].min_bitrate_bps);
EXPECT_EQ(kDefault[2].target_bitrate_bps,
stream->GetVideoStreams()[2].target_bitrate_bps);
EXPECT_EQ(kDefault[2].max_bitrate_bps,
stream->GetVideoStreams()[2].max_bitrate_bps);
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
}
// Test that specifying the min (or max) bitrate value for a layer via
// RtpParameters above (or below) the simulcast default max (or min) adjusts the
// unspecified values accordingly.
TEST_F(WebRtcVideoChannelTest, SetMinAndMaxSimulcastBitrateAboveBelowDefault) {
const size_t kNumSimulcastStreams = 3;
const std::vector<webrtc::VideoStream> kDefault = GetSimulcastBitrates720p();
FakeVideoSendStream* stream = SetUpSimulcast(true, false);
// Send a full size frame so all simulcast layers are used when reconfiguring.
FakeVideoCapturerWithTaskQueue capturer;
VideoOptions options;
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &capturer));
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
// Get and set the rtp encoding parameters.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
// Change the value and set it on the VideoChannel.
// For layer 0, set the min bitrate above the default max.
const int kMinBpsLayer0 = kDefault[0].max_bitrate_bps + 1;
parameters.encodings[0].min_bitrate_bps = kMinBpsLayer0;
// For layer 1, set the max bitrate below the default min.
const int kMaxBpsLayer1 = kDefault[1].min_bitrate_bps - 1;
parameters.encodings[1].max_bitrate_bps = kMaxBpsLayer1;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
// Verify that the new value propagated down to the encoder.
// FakeVideoSendStream calls CreateEncoderStreams, test that the vector of
// VideoStreams are created appropriately for the simulcast case.
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
// Layer 0: Min bitrate above default max (target/max should be adjusted).
EXPECT_EQ(kMinBpsLayer0, stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_EQ(kMinBpsLayer0, stream->GetVideoStreams()[0].target_bitrate_bps);
EXPECT_EQ(kMinBpsLayer0, stream->GetVideoStreams()[0].max_bitrate_bps);
// Layer 1: Max bitrate below default min (min/target should be adjusted).
EXPECT_EQ(kMaxBpsLayer1, stream->GetVideoStreams()[1].min_bitrate_bps);
EXPECT_EQ(kMaxBpsLayer1, stream->GetVideoStreams()[1].target_bitrate_bps);
EXPECT_EQ(kMaxBpsLayer1, stream->GetVideoStreams()[1].max_bitrate_bps);
// Layer 2: min and max bitrate not configured, default expected.
EXPECT_EQ(kDefault[2].min_bitrate_bps,
stream->GetVideoStreams()[2].min_bitrate_bps);
EXPECT_EQ(kDefault[2].target_bitrate_bps,
stream->GetVideoStreams()[2].target_bitrate_bps);
EXPECT_EQ(kDefault[2].max_bitrate_bps,
stream->GetVideoStreams()[2].max_bitrate_bps);
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
}
TEST_F(WebRtcVideoChannelTest, BandwidthAboveTotalMaxBitrateGivenToMaxLayer) {
const size_t kNumSimulcastStreams = 3;
const std::vector<webrtc::VideoStream> kDefault = GetSimulcastBitrates720p();
FakeVideoSendStream* stream = SetUpSimulcast(true, false);
// Send a full size frame so all simulcast layers are used when reconfiguring.
FakeVideoCapturerWithTaskQueue capturer;
VideoOptions options;
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &capturer));
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
// Set max bitrate for all but the highest layer.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
parameters.encodings[0].max_bitrate_bps = kDefault[0].max_bitrate_bps;
parameters.encodings[1].max_bitrate_bps = kDefault[1].max_bitrate_bps;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
// Set max bandwidth equal to total max bitrate.
send_parameters_.max_bandwidth_bps =
GetTotalMaxBitrateBps(stream->GetVideoStreams());
ExpectSetMaxBitrate(send_parameters_.max_bandwidth_bps);
ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
// No bitrate above the total max to give to the highest layer.
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
EXPECT_EQ(kDefault[2].max_bitrate_bps,
stream->GetVideoStreams()[2].max_bitrate_bps);
// Set max bandwidth above the total max bitrate.
send_parameters_.max_bandwidth_bps =
GetTotalMaxBitrateBps(stream->GetVideoStreams()) + 1;
ExpectSetMaxBitrate(send_parameters_.max_bandwidth_bps);
ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
// The highest layer has no max bitrate set -> the bitrate above the total
// max should be given to the highest layer.
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
EXPECT_EQ(send_parameters_.max_bandwidth_bps,
GetTotalMaxBitrateBps(stream->GetVideoStreams()));
EXPECT_EQ(kDefault[2].max_bitrate_bps + 1,
stream->GetVideoStreams()[2].max_bitrate_bps);
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
}
TEST_F(WebRtcVideoChannelTest,
BandwidthAboveTotalMaxBitrateNotGivenToMaxLayerIfMaxBitrateSet) {
const size_t kNumSimulcastStreams = 3;
const std::vector<webrtc::VideoStream> kDefault = GetSimulcastBitrates720p();
EXPECT_EQ(kNumSimulcastStreams, kDefault.size());
FakeVideoSendStream* stream = SetUpSimulcast(true, false);
// Send a full size frame so all simulcast layers are used when reconfiguring.
FakeVideoCapturerWithTaskQueue capturer;
VideoOptions options;
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &capturer));
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
channel_->SetSend(true);
EXPECT_TRUE(capturer.CaptureFrame());
// Set max bitrate for the highest layer.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(last_ssrc_);
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
parameters.encodings[2].max_bitrate_bps = kDefault[2].max_bitrate_bps;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
// Set max bandwidth above the total max bitrate.
send_parameters_.max_bandwidth_bps =
GetTotalMaxBitrateBps(stream->GetVideoStreams()) + 1;
ExpectSetMaxBitrate(send_parameters_.max_bandwidth_bps);
ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
// The highest layer has the max bitrate set -> the bitrate above the total
// max should not be given to the highest layer.
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
EXPECT_EQ(*parameters.encodings[2].max_bitrate_bps,
stream->GetVideoStreams()[2].max_bitrate_bps);
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
}
// Test that a stream will not be sending if its encoding is made inactive
// through SetRtpSendParameters.
TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersOneEncodingActive) {

View File

@ -58,8 +58,7 @@ bool UnimplementedRtpEncodingParameterHasValue(
// layer.
bool PerSenderRtpEncodingParameterHasValue(
const RtpEncodingParameters& encoding_params) {
if (encoding_params.max_bitrate_bps.has_value() ||
encoding_params.bitrate_priority != kDefaultBitratePriority) {
if (encoding_params.bitrate_priority != kDefaultBitratePriority) {
return true;
}
return false;

View File

@ -959,31 +959,31 @@ TEST_F(RtpSenderReceiverTest, VideoSenderCantSetPerSenderEncodingParameters) {
video_rtp_sender_->SetParameters(params).type());
params = video_rtp_sender_->GetParameters();
params.encodings[1].max_bitrate_bps = 200000;
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
video_rtp_sender_->SetParameters(params).type());
DestroyVideoRtpSender();
}
TEST_F(RtpSenderReceiverTest, SetVideoMaxSendBitrate) {
TEST_F(RtpSenderReceiverTest, SetVideoMinMaxSendBitrate) {
CreateVideoRtpSender();
EXPECT_EQ(-1, video_media_channel_->max_bps());
webrtc::RtpParameters params = video_rtp_sender_->GetParameters();
EXPECT_EQ(1, params.encodings.size());
EXPECT_FALSE(params.encodings[0].min_bitrate_bps);
EXPECT_FALSE(params.encodings[0].max_bitrate_bps);
params.encodings[0].min_bitrate_bps = 100;
params.encodings[0].max_bitrate_bps = 1000;
EXPECT_TRUE(video_rtp_sender_->SetParameters(params).ok());
// Read back the parameters and verify they have been changed.
params = video_rtp_sender_->GetParameters();
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(100, params.encodings[0].min_bitrate_bps);
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
// Verify that the video channel received the new parameters.
params = video_media_channel_->GetRtpSendParameters(kVideoSsrc);
EXPECT_EQ(1, params.encodings.size());
EXPECT_EQ(100, params.encodings[0].min_bitrate_bps);
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
// Verify that the global bitrate limit has not been changed.
@ -992,6 +992,34 @@ TEST_F(RtpSenderReceiverTest, SetVideoMaxSendBitrate) {
DestroyVideoRtpSender();
}
TEST_F(RtpSenderReceiverTest, SetVideoMinMaxSendBitrateSimulcast) {
// Add a simulcast specific send stream that contains 2 encoding parameters.
std::vector<uint32_t> ssrcs({1, 2});
cricket::StreamParams stream_params =
cricket::CreateSimStreamParams("cname", ssrcs);
video_media_channel_->AddSendStream(stream_params);
uint32_t primary_ssrc = stream_params.first_ssrc();
CreateVideoRtpSender(primary_ssrc);
RtpParameters params = video_rtp_sender_->GetParameters();
EXPECT_EQ(ssrcs.size(), params.encodings.size());
params.encodings[0].min_bitrate_bps = 100;
params.encodings[0].max_bitrate_bps = 1000;
params.encodings[1].min_bitrate_bps = 200;
params.encodings[1].max_bitrate_bps = 2000;
EXPECT_TRUE(video_rtp_sender_->SetParameters(params).ok());
// Verify that the video channel received the new parameters.
params = video_media_channel_->GetRtpSendParameters(primary_ssrc);
EXPECT_EQ(ssrcs.size(), params.encodings.size());
EXPECT_EQ(100, params.encodings[0].min_bitrate_bps);
EXPECT_EQ(1000, params.encodings[0].max_bitrate_bps);
EXPECT_EQ(200, params.encodings[1].min_bitrate_bps);
EXPECT_EQ(2000, params.encodings[1].max_bitrate_bps);
DestroyVideoRtpSender();
}
TEST_F(RtpSenderReceiverTest, SetVideoBitratePriority) {
CreateVideoRtpSender();