Implement the encoding RtpParameter scaleResolutionDownBy
Support varies by codec, especially in the simulcast case, but using
the EncoderSimulcastProxy codec should fix this.
Bug: webrtc:10069
Change-Id: Idb6a5f400ffda1cdb139004f540961a9cf85d224
Reviewed-on: https://webrtc-review.googlesource.com/c/119400
Commit-Queue: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Seth Hampson <shampson@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26449}
diff --git a/api/video_codecs/video_encoder_config.cc b/api/video_codecs/video_encoder_config.cc
index 66ff7c9..2b1adc0 100644
--- a/api/video_codecs/video_encoder_config.cc
+++ b/api/video_codecs/video_encoder_config.cc
@@ -22,6 +22,7 @@
min_bitrate_bps(-1),
target_bitrate_bps(-1),
max_bitrate_bps(-1),
+ scale_resolution_down_by(-1.),
max_qp(-1),
active(true) {}
VideoStream::VideoStream(const VideoStream& other) = default;
diff --git a/api/video_codecs/video_encoder_config.h b/api/video_codecs/video_encoder_config.h
index 78f2db4..0c69b93 100644
--- a/api/video_codecs/video_encoder_config.h
+++ b/api/video_codecs/video_encoder_config.h
@@ -36,13 +36,15 @@
int min_bitrate_bps;
int target_bitrate_bps;
int max_bitrate_bps;
+ // Scaling factor applied to the stream size.
+ // |width| and |height| values are already scaled down.
+ double scale_resolution_down_by;
int max_qp;
absl::optional<size_t> num_temporal_layers;
absl::optional<double> bitrate_priority;
- // TODO(bugs.webrtc.org/8653): Support active per-simulcast layer.
bool active;
};
diff --git a/media/base/fake_media_engine.h b/media/base/fake_media_engine.h
index 564b0da..a41d4e4 100644
--- a/media/base/fake_media_engine.h
+++ b/media/base/fake_media_engine.h
@@ -146,8 +146,8 @@
const webrtc::RtpParameters& parameters) {
auto parameters_iterator = rtp_send_parameters_.find(ssrc);
if (parameters_iterator != rtp_send_parameters_.end()) {
- auto result =
- ValidateRtpParameters(parameters_iterator->second, parameters);
+ auto result = CheckRtpParametersInvalidModificationAndValues(
+ parameters_iterator->second, parameters);
if (!result.ok())
return result;
diff --git a/media/base/media_engine.cc b/media/base/media_engine.cc
index 91fcc1e..62c3cec 100644
--- a/media/base/media_engine.cc
+++ b/media/base/media_engine.cc
@@ -46,39 +46,23 @@
return parameters;
}
-webrtc::RTCError ValidateRtpParameters(
- const webrtc::RtpParameters& old_rtp_parameters,
+webrtc::RTCError CheckRtpParametersValues(
const webrtc::RtpParameters& rtp_parameters) {
using webrtc::RTCErrorType;
- if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
- LOG_AND_RETURN_ERROR(
- RTCErrorType::INVALID_MODIFICATION,
- "Attempted to set RtpParameters with different encoding count");
- }
- if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
- LOG_AND_RETURN_ERROR(
- RTCErrorType::INVALID_MODIFICATION,
- "Attempted to set RtpParameters with modified RTCP parameters");
- }
- if (rtp_parameters.header_extensions !=
- old_rtp_parameters.header_extensions) {
- LOG_AND_RETURN_ERROR(
- RTCErrorType::INVALID_MODIFICATION,
- "Attempted to set RtpParameters with modified header extensions");
- }
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
- if (rtp_parameters.encodings[i].ssrc !=
- old_rtp_parameters.encodings[i].ssrc) {
- LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
- "Attempted to set RtpParameters with modified SSRC");
- }
if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
"Attempted to set RtpParameters bitrate_priority to "
"an invalid number. bitrate_priority must be > 0.");
}
-
+ if (rtp_parameters.encodings[i].scale_resolution_down_by &&
+ *rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) {
+ LOG_AND_RETURN_ERROR(
+ RTCErrorType::INVALID_RANGE,
+ "Attempted to set RtpParameters scale_resolution_down_by to an "
+ "invalid number. scale_resolution_down_by must be >= 1.0");
+ }
if (rtp_parameters.encodings[i].min_bitrate_bps &&
rtp_parameters.encodings[i].max_bitrate_bps) {
if (*rtp_parameters.encodings[i].max_bitrate_bps <
@@ -107,9 +91,42 @@
" to a different value than other encoding layers.");
}
}
+
return webrtc::RTCError::OK();
}
+webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
+ const webrtc::RtpParameters& old_rtp_parameters,
+ const webrtc::RtpParameters& rtp_parameters) {
+ using webrtc::RTCErrorType;
+ if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
+ LOG_AND_RETURN_ERROR(
+ RTCErrorType::INVALID_MODIFICATION,
+ "Attempted to set RtpParameters with different encoding count");
+ }
+ if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
+ LOG_AND_RETURN_ERROR(
+ RTCErrorType::INVALID_MODIFICATION,
+ "Attempted to set RtpParameters with modified RTCP parameters");
+ }
+ if (rtp_parameters.header_extensions !=
+ old_rtp_parameters.header_extensions) {
+ LOG_AND_RETURN_ERROR(
+ RTCErrorType::INVALID_MODIFICATION,
+ "Attempted to set RtpParameters with modified header extensions");
+ }
+
+ for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
+ if (rtp_parameters.encodings[i].ssrc !=
+ old_rtp_parameters.encodings[i].ssrc) {
+ LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
+ "Attempted to set RtpParameters with modified SSRC");
+ }
+ }
+
+ return CheckRtpParametersValues(rtp_parameters);
+}
+
CompositeMediaEngine::CompositeMediaEngine(
std::unique_ptr<VoiceEngineInterface> voice_engine,
std::unique_ptr<VideoEngineInterface> video_engine)
diff --git a/media/base/media_engine.h b/media/base/media_engine.h
index 40c9ecc..5867c9e 100644
--- a/media/base/media_engine.h
+++ b/media/base/media_engine.h
@@ -38,7 +38,10 @@
namespace cricket {
-webrtc::RTCError ValidateRtpParameters(
+webrtc::RTCError CheckRtpParametersValues(
+ const webrtc::RtpParameters& new_parameters);
+
+webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
const webrtc::RtpParameters& old_parameters,
const webrtc::RtpParameters& new_parameters);
diff --git a/media/engine/simulcast.h b/media/engine/simulcast.h
index 97cb196..0e5afc2 100644
--- a/media/engine/simulcast.h
+++ b/media/engine/simulcast.h
@@ -26,6 +26,9 @@
void BoostMaxSimulcastLayer(int max_bitrate_bps,
std::vector<webrtc::VideoStream>* layers);
+// Round size to nearest simulcast-friendly size
+int NormalizeSimulcastSize(int size, size_t simulcast_layers);
+
// Gets simulcast settings.
// TODO(asapersson): Remove max_bitrate_bps and max_framerate.
std::vector<webrtc::VideoStream> GetSimulcastConfig(
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 756bc56..fc74a38 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -38,6 +38,8 @@
namespace {
+const int kMinLayerSize = 16;
+
// If this field trial is enabled, we will enable sending FlexFEC and disable
// sending ULPFEC whenever the former has been negotiated in the SDPs.
bool IsFlexfecFieldTrialEnabled() {
@@ -1794,8 +1796,8 @@
webrtc::RTCError WebRtcVideoChannel::WebRtcVideoSendStream::SetRtpParameters(
const webrtc::RtpParameters& new_parameters) {
RTC_DCHECK_RUN_ON(&thread_checker_);
- webrtc::RTCError error =
- ValidateRtpParameters(rtp_parameters_, new_parameters);
+ webrtc::RTCError error = CheckRtpParametersInvalidModificationAndValues(
+ rtp_parameters_, new_parameters);
if (!error.ok()) {
return error;
}
@@ -1808,6 +1810,8 @@
rtp_parameters_.encodings[i].max_bitrate_bps) ||
(new_parameters.encodings[i].max_framerate !=
rtp_parameters_.encodings[i].max_framerate) ||
+ (new_parameters.encodings[i].scale_resolution_down_by !=
+ rtp_parameters_.encodings[i].scale_resolution_down_by) ||
(new_parameters.encodings[i].num_temporal_layers !=
rtp_parameters_.encodings[i].num_temporal_layers)) {
new_param = true;
@@ -1979,6 +1983,10 @@
encoder_config.simulcast_layers[i].max_framerate =
*rtp_parameters_.encodings[i].max_framerate;
}
+ if (rtp_parameters_.encodings[i].scale_resolution_down_by) {
+ encoder_config.simulcast_layers[i].scale_resolution_down_by =
+ *rtp_parameters_.encodings[i].scale_resolution_down_by;
+ }
if (rtp_parameters_.encodings[i].num_temporal_layers) {
encoder_config.simulcast_layers[i].num_temporal_layers =
*rtp_parameters_.encodings[i].num_temporal_layers;
@@ -2694,6 +2702,12 @@
int max_framerate = GetMaxFramerate(encoder_config, layers.size());
// Update the active simulcast layers and configured bitrates.
bool is_highest_layer_max_bitrate_configured = false;
+ bool has_scale_resolution_down_by =
+ std::any_of(encoder_config.simulcast_layers.begin(),
+ encoder_config.simulcast_layers.end(),
+ [](const webrtc::VideoStream& layer) {
+ return layer.scale_resolution_down_by != -1.;
+ });
for (size_t i = 0; i < layers.size(); ++i) {
layers[i].active = encoder_config.simulcast_layers[i].active;
if (!is_screenshare_) {
@@ -2706,6 +2720,18 @@
*encoder_config.simulcast_layers[i].num_temporal_layers;
}
}
+ if (has_scale_resolution_down_by) {
+ double scale_resolution_down_by = std::max(
+ encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
+ layers[i].width =
+ std::max(NormalizeSimulcastSize(width / scale_resolution_down_by,
+ encoder_config.number_of_streams),
+ kMinLayerSize);
+ layers[i].height =
+ std::max(NormalizeSimulcastSize(height / scale_resolution_down_by,
+ encoder_config.number_of_streams),
+ kMinLayerSize);
+ }
// Update simulcast bitrates with configured min and max bitrate.
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
layers[i].min_bitrate_bps =
@@ -2771,6 +2797,17 @@
layer.height = height;
layer.max_framerate = max_framerate;
+ if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) {
+ layer.width = std::max<size_t>(
+ layer.width /
+ encoder_config.simulcast_layers[0].scale_resolution_down_by,
+ kMinLayerSize);
+ layer.height = std::max<size_t>(
+ layer.height /
+ encoder_config.simulcast_layers[0].scale_resolution_down_by,
+ kMinLayerSize);
+ }
+
// In the case that the application sets a max bitrate that's lower than the
// min bitrate, we adjust it down (see bugs.webrtc.org/9141).
layer.min_bitrate_bps = std::min(min_bitrate_bps, max_bitrate_bps);
diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc
index 14b4232..ac2bf4b 100644
--- a/media/engine/webrtc_video_engine_unittest.cc
+++ b/media/engine/webrtc_video_engine_unittest.cc
@@ -5547,6 +5547,218 @@
}
}
+TEST_F(WebRtcVideoChannelTest,
+ GetAndSetRtpSendParametersScaleResolutionDownByVP8) {
+ cricket::VideoSendParameters parameters;
+ parameters.codecs.push_back(cricket::VideoCodec("VP8"));
+ ASSERT_TRUE(channel_->SetSendParameters(parameters));
+ FakeVideoSendStream* stream = SetUpSimulcast(true, false);
+
+ webrtc::test::FrameForwarder frame_forwarder;
+ cricket::FakeFrameSource frame_source(1280, 720,
+ rtc::kNumMicrosecsPerSec / 30);
+
+ VideoOptions options;
+ EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &frame_forwarder));
+ channel_->SetSend(true);
+
+ // Try layers in natural order (smallest to largest).
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 4.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by = 2.0;
+ rtp_parameters.encodings[2].scale_resolution_down_by = 1.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(320u, video_streams[0].width);
+ EXPECT_EQ(180u, video_streams[0].height);
+ EXPECT_EQ(640u, video_streams[1].width);
+ EXPECT_EQ(360u, video_streams[1].height);
+ EXPECT_EQ(1280u, video_streams[2].width);
+ EXPECT_EQ(720u, video_streams[2].height);
+ }
+
+ // Try layers in reverse natural order (largest to smallest).
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 1.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by = 2.0;
+ rtp_parameters.encodings[2].scale_resolution_down_by = 4.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(1280u, video_streams[0].width);
+ EXPECT_EQ(720u, video_streams[0].height);
+ EXPECT_EQ(640u, video_streams[1].width);
+ EXPECT_EQ(360u, video_streams[1].height);
+ EXPECT_EQ(320u, video_streams[2].width);
+ EXPECT_EQ(180u, video_streams[2].height);
+ }
+
+ // Try layers in mixed order.
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 10.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by = 2.0;
+ rtp_parameters.encodings[2].scale_resolution_down_by = 4.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(128u, video_streams[0].width);
+ EXPECT_EQ(72u, video_streams[0].height);
+ EXPECT_EQ(640u, video_streams[1].width);
+ EXPECT_EQ(360u, video_streams[1].height);
+ EXPECT_EQ(320u, video_streams[2].width);
+ EXPECT_EQ(180u, video_streams[2].height);
+ }
+
+ // Try with a missing scale setting, defaults to 1.0 if any other is set.
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 1.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by.reset();
+ rtp_parameters.encodings[2].scale_resolution_down_by = 4.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(1280u, video_streams[0].width);
+ EXPECT_EQ(720u, video_streams[0].height);
+ EXPECT_EQ(1280u, video_streams[1].width);
+ EXPECT_EQ(720u, video_streams[1].height);
+ EXPECT_EQ(320u, video_streams[2].width);
+ EXPECT_EQ(180u, video_streams[2].height);
+ }
+
+ EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
+}
+
+TEST_F(WebRtcVideoChannelTest,
+ GetAndSetRtpSendParametersScaleResolutionDownByH264) {
+ encoder_factory_->AddSupportedVideoCodecType("H264");
+ cricket::VideoSendParameters parameters;
+ parameters.codecs.push_back(cricket::VideoCodec("H264"));
+ ASSERT_TRUE(channel_->SetSendParameters(parameters));
+ FakeVideoSendStream* stream = SetUpSimulcast(true, false);
+
+ webrtc::test::FrameForwarder frame_forwarder;
+ cricket::FakeFrameSource frame_source(1280, 720,
+ rtc::kNumMicrosecsPerSec / 30);
+
+ VideoOptions options;
+ EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &frame_forwarder));
+ channel_->SetSend(true);
+
+ // Try layers in natural order (smallest to largest).
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 4.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by = 2.0;
+ rtp_parameters.encodings[2].scale_resolution_down_by = 1.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(320u, video_streams[0].width);
+ EXPECT_EQ(180u, video_streams[0].height);
+ EXPECT_EQ(640u, video_streams[1].width);
+ EXPECT_EQ(360u, video_streams[1].height);
+ EXPECT_EQ(1280u, video_streams[2].width);
+ EXPECT_EQ(720u, video_streams[2].height);
+ }
+
+ // Try layers in reverse natural order (largest to smallest).
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 1.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by = 2.0;
+ rtp_parameters.encodings[2].scale_resolution_down_by = 4.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(1280u, video_streams[0].width);
+ EXPECT_EQ(720u, video_streams[0].height);
+ EXPECT_EQ(640u, video_streams[1].width);
+ EXPECT_EQ(360u, video_streams[1].height);
+ EXPECT_EQ(320u, video_streams[2].width);
+ EXPECT_EQ(180u, video_streams[2].height);
+ }
+
+ // Try layers in mixed order.
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 10.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by = 2.0;
+ rtp_parameters.encodings[2].scale_resolution_down_by = 4.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(128u, video_streams[0].width);
+ EXPECT_EQ(72u, video_streams[0].height);
+ EXPECT_EQ(640u, video_streams[1].width);
+ EXPECT_EQ(360u, video_streams[1].height);
+ EXPECT_EQ(320u, video_streams[2].width);
+ EXPECT_EQ(180u, video_streams[2].height);
+ }
+
+ // Try with a missing scale setting, defaults to 1.0 if any other is set.
+ {
+ auto rtp_parameters = channel_->GetRtpSendParameters(last_ssrc_);
+ ASSERT_EQ(3u, rtp_parameters.encodings.size());
+ rtp_parameters.encodings[0].scale_resolution_down_by = 1.0;
+ rtp_parameters.encodings[1].scale_resolution_down_by.reset();
+ rtp_parameters.encodings[2].scale_resolution_down_by = 4.0;
+ auto result = channel_->SetRtpSendParameters(last_ssrc_, rtp_parameters);
+ ASSERT_TRUE(result.ok());
+
+ frame_forwarder.IncomingCapturedFrame(frame_source.GetFrame());
+
+ std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
+ ASSERT_EQ(3u, video_streams.size());
+ EXPECT_EQ(1280u, video_streams[0].width);
+ EXPECT_EQ(720u, video_streams[0].height);
+ EXPECT_EQ(1280u, video_streams[1].width);
+ EXPECT_EQ(720u, video_streams[1].height);
+ EXPECT_EQ(320u, video_streams[2].width);
+ EXPECT_EQ(180u, video_streams[2].height);
+ }
+ EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
+}
+
TEST_F(WebRtcVideoChannelTest, GetAndSetRtpSendParametersMaxFramerate) {
const size_t kNumSimulcastStreams = 3;
SetUpSimulcast(true, false);
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc
index 67d89fd..4dec78e 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -920,7 +920,8 @@
}
webrtc::RTCError SetRtpParameters(const webrtc::RtpParameters& parameters) {
- webrtc::RTCError error = ValidateRtpParameters(rtp_parameters_, parameters);
+ webrtc::RTCError error = CheckRtpParametersInvalidModificationAndValues(
+ rtp_parameters_, parameters);
if (!error.ok()) {
return error;
}
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 22cd60a..1090149 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -1485,6 +1485,11 @@
"Attempted to set an unimplemented parameter of RtpParameters.");
}
+ auto result = cricket::CheckRtpParametersValues(parameters);
+ if (!result.ok()) {
+ LOG_AND_RETURN_ERROR(result.type(), result.message());
+ }
+
RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
<< " transceiver in response to a call to AddTransceiver.";
// Set the sender ID equal to the track ID if the track is specified unless
diff --git a/pc/peer_connection_rtp_unittest.cc b/pc/peer_connection_rtp_unittest.cc
index 2321ada..e80c95c 100644
--- a/pc/peer_connection_rtp_unittest.cc
+++ b/pc/peer_connection_rtp_unittest.cc
@@ -1452,8 +1452,7 @@
auto default_send_encodings = init.send_encodings;
// Unimplemented RtpParameters: ssrc, codec_payload_type, fec, rtx, dtx,
- // ptime, scale_resolution_down_by, scale_framerate_down_by, rid,
- // dependency_rids.
+ // ptime, scale_framerate_down_by, rid, dependency_rids.
init.send_encodings[0].ssrc = 1;
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
caller->pc()
@@ -1502,14 +1501,6 @@
.type());
init.send_encodings = default_send_encodings;
- init.send_encodings[0].scale_resolution_down_by = 2.0;
- EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
- caller->pc()
- ->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init)
- .error()
- .type());
- init.send_encodings = default_send_encodings;
-
init.send_encodings[0].rid = "dummy_rid";
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
caller->pc()
@@ -1526,6 +1517,58 @@
.type());
}
+// Test that AddTransceiver fails if trying to use invalid RTP encoding
+// parameters with the send_encodings parameters.
+TEST_F(PeerConnectionRtpTestUnifiedPlan, CheckForInvalidEncodingParameters) {
+ auto caller = CreatePeerConnection();
+
+ RtpTransceiverInit init;
+ init.send_encodings.emplace_back();
+
+ auto default_send_encodings = init.send_encodings;
+
+ init.send_encodings[0].scale_resolution_down_by = 0.5;
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE,
+ caller->pc()
+ ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
+ .error()
+ .type());
+ init.send_encodings = default_send_encodings;
+
+ init.send_encodings[0].bitrate_priority = 0;
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE,
+ caller->pc()
+ ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
+ .error()
+ .type());
+ init.send_encodings = default_send_encodings;
+
+ init.send_encodings[0].min_bitrate_bps = 200000;
+ init.send_encodings[0].max_bitrate_bps = 100000;
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE,
+ caller->pc()
+ ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
+ .error()
+ .type());
+ init.send_encodings = default_send_encodings;
+
+ init.send_encodings[0].num_temporal_layers = 0;
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE,
+ caller->pc()
+ ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
+ .error()
+ .type());
+ init.send_encodings = default_send_encodings;
+
+ init.send_encodings[0].num_temporal_layers = 5;
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE,
+ caller->pc()
+ ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
+ .error()
+ .type());
+ init.send_encodings = default_send_encodings;
+}
+
// Test that AddTransceiver transfers the send_encodings to the sender and they
// are retained after SetLocalDescription().
TEST_F(PeerConnectionRtpTestUnifiedPlan, SendEncodingsPassedToSender) {
diff --git a/pc/rtp_sender.cc b/pc/rtp_sender.cc
index b97b876..d88b1fc 100644
--- a/pc/rtp_sender.cc
+++ b/pc/rtp_sender.cc
@@ -42,7 +42,6 @@
encoding_params.fec.has_value() || encoding_params.rtx.has_value() ||
encoding_params.dtx.has_value() || encoding_params.ptime.has_value() ||
!encoding_params.rid.empty() ||
- encoding_params.scale_resolution_down_by.has_value() ||
encoding_params.scale_framerate_down_by.has_value() ||
!encoding_params.dependency_rids.empty()) {
return true;
@@ -290,7 +289,8 @@
"Attempted to set an unimplemented parameter of RtpParameters.");
}
if (!media_channel_) {
- auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
+ auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
+ init_parameters_, parameters);
if (result.ok()) {
init_parameters_ = parameters;
}
@@ -544,7 +544,8 @@
"Attempted to set an unimplemented parameter of RtpParameters.");
}
if (!media_channel_) {
- auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
+ auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
+ init_parameters_, parameters);
if (result.ok()) {
init_parameters_ = parameters;
}
diff --git a/pc/rtp_sender_receiver_unittest.cc b/pc/rtp_sender_receiver_unittest.cc
index 69d0c74..83f06c6 100644
--- a/pc/rtp_sender_receiver_unittest.cc
+++ b/pc/rtp_sender_receiver_unittest.cc
@@ -810,7 +810,7 @@
EXPECT_EQ(1u, params.encodings.size());
// Unimplemented RtpParameters: codec_payload_type, fec, rtx, dtx, ptime,
- // scale_resolution_down_by, scale_framerate_down_by, rid, dependency_rids.
+ // scale_framerate_down_by, rid, dependency_rids.
params.encodings[0].codec_payload_type = 1;
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
audio_rtp_sender_->SetParameters(params).type());
@@ -836,11 +836,6 @@
audio_rtp_sender_->SetParameters(params).type());
params = audio_rtp_sender_->GetParameters();
- params.encodings[0].scale_resolution_down_by = 2.0;
- EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
- audio_rtp_sender_->SetParameters(params).type());
- params = audio_rtp_sender_->GetParameters();
-
params.encodings[0].rid = "dummy_rid";
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
audio_rtp_sender_->SetParameters(params).type());
@@ -1087,7 +1082,7 @@
EXPECT_EQ(1u, params.encodings.size());
// Unimplemented RtpParameters: codec_payload_type, fec, rtx, dtx, ptime,
- // scale_resolution_down_by, scale_framerate_down_by, rid, dependency_rids.
+ // scale_framerate_down_by, rid, dependency_rids.
params.encodings[0].codec_payload_type = 1;
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
video_rtp_sender_->SetParameters(params).type());
@@ -1113,11 +1108,6 @@
video_rtp_sender_->SetParameters(params).type());
params = video_rtp_sender_->GetParameters();
- params.encodings[0].scale_resolution_down_by = 2.0;
- EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
- video_rtp_sender_->SetParameters(params).type());
- params = video_rtp_sender_->GetParameters();
-
params.encodings[0].rid = "dummy_rid";
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
video_rtp_sender_->SetParameters(params).type());
@@ -1130,6 +1120,30 @@
DestroyVideoRtpSender();
}
+TEST_F(RtpSenderReceiverTest, VideoSenderCanSetScaleResolutionDownBy) {
+ CreateVideoRtpSender();
+
+ RtpParameters params = video_rtp_sender_->GetParameters();
+ params.encodings[0].scale_resolution_down_by = 2;
+
+ EXPECT_TRUE(video_rtp_sender_->SetParameters(params).ok());
+ params = video_rtp_sender_->GetParameters();
+ EXPECT_EQ(2, params.encodings[0].scale_resolution_down_by);
+
+ DestroyVideoRtpSender();
+}
+
+TEST_F(RtpSenderReceiverTest, VideoSenderDetectInvalidScaleResolutionDownBy) {
+ CreateVideoRtpSender();
+
+ RtpParameters params = video_rtp_sender_->GetParameters();
+ params.encodings[0].scale_resolution_down_by = 0.5;
+ RTCError result = video_rtp_sender_->SetParameters(params);
+ EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.type());
+
+ DestroyVideoRtpSender();
+}
+
TEST_F(RtpSenderReceiverTest,
VideoSenderCantSetUnimplementedEncodingParametersWithSimulcast) {
CreateVideoRtpSenderWithSimulcast();
@@ -1137,7 +1151,7 @@
EXPECT_EQ(kVideoSimulcastLayerCount, params.encodings.size());
// Unimplemented RtpParameters: codec_payload_type, fec, rtx, dtx, ptime,
- // scale_resolution_down_by, scale_framerate_down_by, rid, dependency_rids.
+ // scale_framerate_down_by, rid, dependency_rids.
for (size_t i = 0; i < params.encodings.size(); i++) {
params.encodings[i].codec_payload_type = 1;
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
@@ -1164,11 +1178,6 @@
video_rtp_sender_->SetParameters(params).type());
params = video_rtp_sender_->GetParameters();
- params.encodings[i].scale_resolution_down_by = 2.0;
- EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
- video_rtp_sender_->SetParameters(params).type());
- params = video_rtp_sender_->GetParameters();
-
params.encodings[i].rid = "dummy_rid";
EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
video_rtp_sender_->SetParameters(params).type());