mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00
Add support for RtpEncodingParameters::max_framerate
This adds the framework support for the max_framerate parameter. It doesn't implement it in any encoder yet. Bug: webrtc:11117 Change-Id: I329624cc0205c828498d3623a2e13dd3f97e1629 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160184 Reviewed-by: Steve Anton <steveanton@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Reviewed-by: Åsa Persson <asapersson@webrtc.org> Commit-Queue: Florent Castelli <orphis@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29907}
This commit is contained in:
parent
f534a64047
commit
15be5282e9
9 changed files with 75 additions and 82 deletions
|
@ -447,10 +447,7 @@ struct RTC_EXPORT RtpEncodingParameters {
|
||||||
absl::optional<int> min_bitrate_bps;
|
absl::optional<int> min_bitrate_bps;
|
||||||
|
|
||||||
// Specifies the maximum framerate in fps for video.
|
// Specifies the maximum framerate in fps for video.
|
||||||
// TODO(asapersson): Different framerates are not supported per simulcast
|
absl::optional<double> max_framerate;
|
||||||
// layer. If set, the maximum |max_framerate| is currently used.
|
|
||||||
// Not supported for screencast.
|
|
||||||
absl::optional<int> max_framerate;
|
|
||||||
|
|
||||||
// Specifies the number of temporal layers for video (if the feature is
|
// Specifies the number of temporal layers for video (if the feature is
|
||||||
// supported by the codec implementation).
|
// supported by the codec implementation).
|
||||||
|
|
|
@ -48,6 +48,7 @@ bool VideoCodecH264::operator==(const VideoCodecH264& other) const {
|
||||||
|
|
||||||
bool SpatialLayer::operator==(const SpatialLayer& other) const {
|
bool SpatialLayer::operator==(const SpatialLayer& other) const {
|
||||||
return (width == other.width && height == other.height &&
|
return (width == other.width && height == other.height &&
|
||||||
|
maxFramerate == other.maxFramerate &&
|
||||||
numberOfTemporalLayers == other.numberOfTemporalLayers &&
|
numberOfTemporalLayers == other.numberOfTemporalLayers &&
|
||||||
maxBitrate == other.maxBitrate &&
|
maxBitrate == other.maxBitrate &&
|
||||||
targetBitrate == other.targetBitrate &&
|
targetBitrate == other.targetBitrate &&
|
||||||
|
|
|
@ -70,7 +70,13 @@ webrtc::RTCError CheckRtpParametersValues(
|
||||||
LOG_AND_RETURN_ERROR(
|
LOG_AND_RETURN_ERROR(
|
||||||
RTCErrorType::INVALID_RANGE,
|
RTCErrorType::INVALID_RANGE,
|
||||||
"Attempted to set RtpParameters scale_resolution_down_by to an "
|
"Attempted to set RtpParameters scale_resolution_down_by to an "
|
||||||
"invalid number. scale_resolution_down_by must be >= 1.0");
|
"invalid value. scale_resolution_down_by must be >= 1.0");
|
||||||
|
}
|
||||||
|
if (rtp_parameters.encodings[i].max_framerate &&
|
||||||
|
*rtp_parameters.encodings[i].max_framerate < 0.0) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
|
||||||
|
"Attempted to set RtpParameters max_framerate to an "
|
||||||
|
"invalid value. max_framerate must be >= 0.0");
|
||||||
}
|
}
|
||||||
if (rtp_parameters.encodings[i].min_bitrate_bps &&
|
if (rtp_parameters.encodings[i].min_bitrate_bps &&
|
||||||
rtp_parameters.encodings[i].max_bitrate_bps) {
|
rtp_parameters.encodings[i].max_bitrate_bps) {
|
||||||
|
|
|
@ -146,18 +146,6 @@ std::vector<VideoCodec> AssignPayloadTypesAndDefaultCodecs(
|
||||||
: std::vector<VideoCodec>();
|
: std::vector<VideoCodec>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMaxFramerate(const webrtc::VideoEncoderConfig& encoder_config,
|
|
||||||
size_t num_layers) {
|
|
||||||
int max_fps = -1;
|
|
||||||
for (size_t i = 0; i < num_layers; ++i) {
|
|
||||||
int fps = (encoder_config.simulcast_layers[i].max_framerate > 0)
|
|
||||||
? encoder_config.simulcast_layers[i].max_framerate
|
|
||||||
: kDefaultVideoMaxFramerate;
|
|
||||||
max_fps = std::max(fps, max_fps);
|
|
||||||
}
|
|
||||||
return max_fps;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsTemporalLayersSupported(const std::string& codec_name) {
|
bool IsTemporalLayersSupported(const std::string& codec_name) {
|
||||||
return absl::EqualsIgnoreCase(codec_name, kVp8CodecName) ||
|
return absl::EqualsIgnoreCase(codec_name, kVp8CodecName) ||
|
||||||
absl::EqualsIgnoreCase(codec_name, kVp9CodecName);
|
absl::EqualsIgnoreCase(codec_name, kVp9CodecName);
|
||||||
|
@ -308,6 +296,12 @@ int MinPositive(int a, int b) {
|
||||||
return std::min(a, b);
|
return std::min(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsLayerActive(const webrtc::RtpEncodingParameters& layer) {
|
||||||
|
return layer.active &&
|
||||||
|
(!layer.max_bitrate_bps || *layer.max_bitrate_bps > 0) &&
|
||||||
|
(!layer.max_framerate || *layer.max_framerate > 0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// This constant is really an on/off, lower-level configurable NACK history
|
// This constant is really an on/off, lower-level configurable NACK history
|
||||||
|
@ -2089,8 +2083,9 @@ webrtc::RTCError WebRtcVideoChannel::WebRtcVideoSendStream::SetRtpParameters(
|
||||||
// allocator and the video bitrate allocator.
|
// allocator and the video bitrate allocator.
|
||||||
bool new_send_state = false;
|
bool new_send_state = false;
|
||||||
for (size_t i = 0; i < rtp_parameters_.encodings.size(); ++i) {
|
for (size_t i = 0; i < rtp_parameters_.encodings.size(); ++i) {
|
||||||
if (new_parameters.encodings[i].active !=
|
bool new_active = IsLayerActive(new_parameters.encodings[i]);
|
||||||
rtp_parameters_.encodings[i].active) {
|
bool old_active = IsLayerActive(rtp_parameters_.encodings[i]);
|
||||||
|
if (new_active != old_active) {
|
||||||
new_send_state = true;
|
new_send_state = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2138,7 +2133,7 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::UpdateSendState() {
|
||||||
}
|
}
|
||||||
std::vector<bool> active_layers(num_layers);
|
std::vector<bool> active_layers(num_layers);
|
||||||
for (size_t i = 0; i < num_layers; ++i) {
|
for (size_t i = 0; i < num_layers; ++i) {
|
||||||
active_layers[i] = rtp_parameters_.encodings[i].active;
|
active_layers[i] = IsLayerActive(rtp_parameters_.encodings[i]);
|
||||||
}
|
}
|
||||||
// This updates what simulcast layers are sending, and possibly starts
|
// This updates what simulcast layers are sending, and possibly starts
|
||||||
// or stops the VideoSendStream.
|
// or stops the VideoSendStream.
|
||||||
|
@ -3063,8 +3058,6 @@ std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
|
||||||
layers[0].min_bitrate_bps =
|
layers[0].min_bitrate_bps =
|
||||||
rtc::saturated_cast<int>(experimental_min_bitrate->bps());
|
rtc::saturated_cast<int>(experimental_min_bitrate->bps());
|
||||||
}
|
}
|
||||||
// The maximum |max_framerate| is currently used for video.
|
|
||||||
const int max_framerate = GetMaxFramerate(encoder_config, layers.size());
|
|
||||||
// Update the active simulcast layers and configured bitrates.
|
// Update the active simulcast layers and configured bitrates.
|
||||||
bool is_highest_layer_max_bitrate_configured = false;
|
bool is_highest_layer_max_bitrate_configured = false;
|
||||||
const bool has_scale_resolution_down_by = absl::c_any_of(
|
const bool has_scale_resolution_down_by = absl::c_any_of(
|
||||||
|
@ -3077,16 +3070,16 @@ std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
|
||||||
NormalizeSimulcastSize(height, encoder_config.number_of_streams);
|
NormalizeSimulcastSize(height, encoder_config.number_of_streams);
|
||||||
for (size_t i = 0; i < layers.size(); ++i) {
|
for (size_t i = 0; i < layers.size(); ++i) {
|
||||||
layers[i].active = encoder_config.simulcast_layers[i].active;
|
layers[i].active = encoder_config.simulcast_layers[i].active;
|
||||||
if (!is_screenshare_) {
|
|
||||||
// Update simulcast framerates with max configured max framerate.
|
|
||||||
layers[i].max_framerate = max_framerate;
|
|
||||||
}
|
|
||||||
// Update with configured num temporal layers if supported by codec.
|
// Update with configured num temporal layers if supported by codec.
|
||||||
if (encoder_config.simulcast_layers[i].num_temporal_layers &&
|
if (encoder_config.simulcast_layers[i].num_temporal_layers &&
|
||||||
IsTemporalLayersSupported(codec_name_)) {
|
IsTemporalLayersSupported(codec_name_)) {
|
||||||
layers[i].num_temporal_layers =
|
layers[i].num_temporal_layers =
|
||||||
*encoder_config.simulcast_layers[i].num_temporal_layers;
|
*encoder_config.simulcast_layers[i].num_temporal_layers;
|
||||||
}
|
}
|
||||||
|
if (encoder_config.simulcast_layers[i].max_framerate > 0) {
|
||||||
|
layers[i].max_framerate =
|
||||||
|
encoder_config.simulcast_layers[i].max_framerate;
|
||||||
|
}
|
||||||
if (has_scale_resolution_down_by) {
|
if (has_scale_resolution_down_by) {
|
||||||
const double scale_resolution_down_by = std::max(
|
const double scale_resolution_down_by = std::max(
|
||||||
encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
|
encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
|
||||||
|
|
|
@ -6643,47 +6643,6 @@ TEST_F(WebRtcVideoChannelTest,
|
||||||
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WebRtcVideoChannelTest, MaxSimulcastFrameratePropagatedToEncoder) {
|
|
||||||
const size_t kNumSimulcastStreams = 3;
|
|
||||||
FakeVideoSendStream* stream = SetUpSimulcast(true, false);
|
|
||||||
|
|
||||||
// Send a full size frame so all simulcast layers are used when reconfiguring.
|
|
||||||
webrtc::test::FrameForwarder frame_forwarder;
|
|
||||||
VideoOptions options;
|
|
||||||
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, &options, &frame_forwarder));
|
|
||||||
channel_->SetSend(true);
|
|
||||||
frame_forwarder.IncomingCapturedFrame(frame_source_.GetFrame());
|
|
||||||
|
|
||||||
// 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].max_framerate = 15;
|
|
||||||
parameters.encodings[1].max_framerate = 25;
|
|
||||||
parameters.encodings[2].max_framerate = 20;
|
|
||||||
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(15, encoder_config.simulcast_layers[0].max_framerate);
|
|
||||||
EXPECT_EQ(25, encoder_config.simulcast_layers[1].max_framerate);
|
|
||||||
EXPECT_EQ(20, encoder_config.simulcast_layers[2].max_framerate);
|
|
||||||
|
|
||||||
// FakeVideoSendStream calls CreateEncoderStreams, test that the vector of
|
|
||||||
// VideoStreams are created appropriately for the simulcast case.
|
|
||||||
// Currently the maximum |max_framerate| is used.
|
|
||||||
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
|
|
||||||
EXPECT_EQ(25, stream->GetVideoStreams()[0].max_framerate);
|
|
||||||
EXPECT_EQ(25, stream->GetVideoStreams()[1].max_framerate);
|
|
||||||
EXPECT_EQ(25, stream->GetVideoStreams()[2].max_framerate);
|
|
||||||
|
|
||||||
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(WebRtcVideoChannelTest,
|
TEST_F(WebRtcVideoChannelTest,
|
||||||
DefaultValuePropagatedToEncoderForUnsetFramerate) {
|
DefaultValuePropagatedToEncoderForUnsetFramerate) {
|
||||||
const size_t kNumSimulcastStreams = 3;
|
const size_t kNumSimulcastStreams = 3;
|
||||||
|
@ -6718,12 +6677,10 @@ TEST_F(WebRtcVideoChannelTest,
|
||||||
// VideoStreams are created appropriately for the simulcast case.
|
// VideoStreams are created appropriately for the simulcast case.
|
||||||
// The maximum |max_framerate| is used, kDefaultVideoMaxFramerate: 60.
|
// The maximum |max_framerate| is used, kDefaultVideoMaxFramerate: 60.
|
||||||
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
|
EXPECT_EQ(kNumSimulcastStreams, stream->GetVideoStreams().size());
|
||||||
EXPECT_EQ(kDefaultVideoMaxFramerate,
|
EXPECT_EQ(15, stream->GetVideoStreams()[0].max_framerate);
|
||||||
stream->GetVideoStreams()[0].max_framerate);
|
|
||||||
EXPECT_EQ(kDefaultVideoMaxFramerate,
|
EXPECT_EQ(kDefaultVideoMaxFramerate,
|
||||||
stream->GetVideoStreams()[1].max_framerate);
|
stream->GetVideoStreams()[1].max_framerate);
|
||||||
EXPECT_EQ(kDefaultVideoMaxFramerate,
|
EXPECT_EQ(20, stream->GetVideoStreams()[2].max_framerate);
|
||||||
stream->GetVideoStreams()[2].max_framerate);
|
|
||||||
|
|
||||||
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
EXPECT_TRUE(channel_->SetVideoSend(last_ssrc_, nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ const int kColorV = 33;
|
||||||
const int kMaxBitrates[kNumberOfSimulcastStreams] = {150, 600, 1200};
|
const int kMaxBitrates[kNumberOfSimulcastStreams] = {150, 600, 1200};
|
||||||
const int kMinBitrates[kNumberOfSimulcastStreams] = {50, 150, 600};
|
const int kMinBitrates[kNumberOfSimulcastStreams] = {50, 150, 600};
|
||||||
const int kTargetBitrates[kNumberOfSimulcastStreams] = {100, 450, 1000};
|
const int kTargetBitrates[kNumberOfSimulcastStreams] = {100, 450, 1000};
|
||||||
|
const float kMaxFramerates[kNumberOfSimulcastStreams] = {30, 30, 30};
|
||||||
const int kDefaultTemporalLayerProfile[3] = {3, 3, 3};
|
const int kDefaultTemporalLayerProfile[3] = {3, 3, 3};
|
||||||
const int kNoTemporalLayerProfile[3] = {0, 0, 0};
|
const int kNoTemporalLayerProfile[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
@ -195,6 +196,7 @@ void ConfigureStream(int width,
|
||||||
int max_bitrate,
|
int max_bitrate,
|
||||||
int min_bitrate,
|
int min_bitrate,
|
||||||
int target_bitrate,
|
int target_bitrate,
|
||||||
|
float max_framerate,
|
||||||
SimulcastStream* stream,
|
SimulcastStream* stream,
|
||||||
int num_temporal_layers) {
|
int num_temporal_layers) {
|
||||||
assert(stream);
|
assert(stream);
|
||||||
|
@ -203,6 +205,7 @@ void ConfigureStream(int width,
|
||||||
stream->maxBitrate = max_bitrate;
|
stream->maxBitrate = max_bitrate;
|
||||||
stream->minBitrate = min_bitrate;
|
stream->minBitrate = min_bitrate;
|
||||||
stream->targetBitrate = target_bitrate;
|
stream->targetBitrate = target_bitrate;
|
||||||
|
stream->maxFramerate = max_framerate;
|
||||||
if (num_temporal_layers >= 0) {
|
if (num_temporal_layers >= 0) {
|
||||||
stream->numberOfTemporalLayers = num_temporal_layers;
|
stream->numberOfTemporalLayers = num_temporal_layers;
|
||||||
}
|
}
|
||||||
|
@ -239,15 +242,15 @@ void SimulcastTestFixtureImpl::DefaultSettings(
|
||||||
settings->timing_frame_thresholds = {kDefaultTimingFramesDelayMs,
|
settings->timing_frame_thresholds = {kDefaultTimingFramesDelayMs,
|
||||||
kDefaultOutlierFrameSizePercent};
|
kDefaultOutlierFrameSizePercent};
|
||||||
ConfigureStream(kDefaultWidth / 4, kDefaultHeight / 4, kMaxBitrates[0],
|
ConfigureStream(kDefaultWidth / 4, kDefaultHeight / 4, kMaxBitrates[0],
|
||||||
kMinBitrates[0], kTargetBitrates[0],
|
kMinBitrates[0], kTargetBitrates[0], kMaxFramerates[0],
|
||||||
&settings->simulcastStream[layer_order[0]],
|
&settings->simulcastStream[layer_order[0]],
|
||||||
temporal_layer_profile[0]);
|
temporal_layer_profile[0]);
|
||||||
ConfigureStream(kDefaultWidth / 2, kDefaultHeight / 2, kMaxBitrates[1],
|
ConfigureStream(kDefaultWidth / 2, kDefaultHeight / 2, kMaxBitrates[1],
|
||||||
kMinBitrates[1], kTargetBitrates[1],
|
kMinBitrates[1], kTargetBitrates[1], kMaxFramerates[1],
|
||||||
&settings->simulcastStream[layer_order[1]],
|
&settings->simulcastStream[layer_order[1]],
|
||||||
temporal_layer_profile[1]);
|
temporal_layer_profile[1]);
|
||||||
ConfigureStream(kDefaultWidth, kDefaultHeight, kMaxBitrates[2],
|
ConfigureStream(kDefaultWidth, kDefaultHeight, kMaxBitrates[2],
|
||||||
kMinBitrates[2], kTargetBitrates[2],
|
kMinBitrates[2], kTargetBitrates[2], kMaxFramerates[2],
|
||||||
&settings->simulcastStream[layer_order[2]],
|
&settings->simulcastStream[layer_order[2]],
|
||||||
temporal_layer_profile[2]);
|
temporal_layer_profile[2]);
|
||||||
if (codec_type == kVideoCodecVP8) {
|
if (codec_type == kVideoCodecVP8) {
|
||||||
|
|
|
@ -89,17 +89,13 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
|
||||||
kDefaultOutlierFrameSizePercent};
|
kDefaultOutlierFrameSizePercent};
|
||||||
RTC_DCHECK_LE(streams.size(), kMaxSimulcastStreams);
|
RTC_DCHECK_LE(streams.size(), kMaxSimulcastStreams);
|
||||||
|
|
||||||
|
int max_framerate = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < streams.size(); ++i) {
|
for (size_t i = 0; i < streams.size(); ++i) {
|
||||||
SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
|
SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
|
||||||
RTC_DCHECK_GT(streams[i].width, 0);
|
RTC_DCHECK_GT(streams[i].width, 0);
|
||||||
RTC_DCHECK_GT(streams[i].height, 0);
|
RTC_DCHECK_GT(streams[i].height, 0);
|
||||||
RTC_DCHECK_GT(streams[i].max_framerate, 0);
|
RTC_DCHECK_GT(streams[i].max_framerate, 0);
|
||||||
// Different framerates not supported per stream at the moment, unless it's
|
|
||||||
// screenshare where there is an exception and a simulcast encoder adapter,
|
|
||||||
// which supports different framerates, is used instead.
|
|
||||||
if (config.content_type != VideoEncoderConfig::ContentType::kScreen) {
|
|
||||||
RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
|
|
||||||
}
|
|
||||||
RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
|
RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
|
||||||
RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
|
RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
|
||||||
RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
|
RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
|
||||||
|
@ -126,6 +122,7 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
|
||||||
video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
|
video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
|
||||||
video_codec.qpMax = std::max(video_codec.qpMax,
|
video_codec.qpMax = std::max(video_codec.qpMax,
|
||||||
static_cast<unsigned int>(streams[i].max_qp));
|
static_cast<unsigned int>(streams[i].max_qp));
|
||||||
|
max_framerate = std::max(max_framerate, streams[i].max_framerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_codec.maxBitrate == 0) {
|
if (video_codec.maxBitrate == 0) {
|
||||||
|
@ -137,8 +134,7 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
|
||||||
if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
|
if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
|
||||||
video_codec.maxBitrate = kEncoderMinBitrateKbps;
|
video_codec.maxBitrate = kEncoderMinBitrateKbps;
|
||||||
|
|
||||||
RTC_DCHECK_GT(streams[0].max_framerate, 0);
|
video_codec.maxFramerate = max_framerate;
|
||||||
video_codec.maxFramerate = streams[0].max_framerate;
|
|
||||||
|
|
||||||
// Set codec specific options
|
// Set codec specific options
|
||||||
if (config.encoder_specific_settings)
|
if (config.encoder_specific_settings)
|
||||||
|
|
|
@ -1309,6 +1309,43 @@ TEST_F(RtpSenderReceiverTest, VideoSenderDetectInvalidScaleResolutionDownBy) {
|
||||||
DestroyVideoRtpSender();
|
DestroyVideoRtpSender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpSenderReceiverTest, VideoSenderCanSetMaxFramerate) {
|
||||||
|
CreateVideoRtpSender();
|
||||||
|
|
||||||
|
RtpParameters params = video_rtp_sender_->GetParameters();
|
||||||
|
params.encodings[0].max_framerate = 20;
|
||||||
|
|
||||||
|
EXPECT_TRUE(video_rtp_sender_->SetParameters(params).ok());
|
||||||
|
params = video_rtp_sender_->GetParameters();
|
||||||
|
EXPECT_EQ(20., params.encodings[0].max_framerate);
|
||||||
|
|
||||||
|
DestroyVideoRtpSender();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpSenderReceiverTest, VideoSenderCanSetMaxFramerateZero) {
|
||||||
|
CreateVideoRtpSender();
|
||||||
|
|
||||||
|
RtpParameters params = video_rtp_sender_->GetParameters();
|
||||||
|
params.encodings[0].max_framerate = 0.;
|
||||||
|
|
||||||
|
EXPECT_TRUE(video_rtp_sender_->SetParameters(params).ok());
|
||||||
|
params = video_rtp_sender_->GetParameters();
|
||||||
|
EXPECT_EQ(0., params.encodings[0].max_framerate);
|
||||||
|
|
||||||
|
DestroyVideoRtpSender();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpSenderReceiverTest, VideoSenderDetectInvalidMaxFramerate) {
|
||||||
|
CreateVideoRtpSender();
|
||||||
|
|
||||||
|
RtpParameters params = video_rtp_sender_->GetParameters();
|
||||||
|
params.encodings[0].max_framerate = -5.;
|
||||||
|
RTCError result = video_rtp_sender_->SetParameters(params);
|
||||||
|
EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.type());
|
||||||
|
|
||||||
|
DestroyVideoRtpSender();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(RtpSenderReceiverTest,
|
TEST_F(RtpSenderReceiverTest,
|
||||||
VideoSenderCantSetUnimplementedEncodingParametersWithSimulcast) {
|
VideoSenderCantSetUnimplementedEncodingParametersWithSimulcast) {
|
||||||
CreateVideoRtpSenderWithSimulcast();
|
CreateVideoRtpSenderWithSimulcast();
|
||||||
|
|
|
@ -151,6 +151,8 @@ bool RequiresEncoderReset(const VideoCodec& prev_send_codec,
|
||||||
prev_send_codec.simulcastStream[i].width ||
|
prev_send_codec.simulcastStream[i].width ||
|
||||||
new_send_codec.simulcastStream[i].height !=
|
new_send_codec.simulcastStream[i].height !=
|
||||||
prev_send_codec.simulcastStream[i].height ||
|
prev_send_codec.simulcastStream[i].height ||
|
||||||
|
new_send_codec.simulcastStream[i].maxFramerate !=
|
||||||
|
prev_send_codec.simulcastStream[i].maxFramerate ||
|
||||||
new_send_codec.simulcastStream[i].numberOfTemporalLayers !=
|
new_send_codec.simulcastStream[i].numberOfTemporalLayers !=
|
||||||
prev_send_codec.simulcastStream[i].numberOfTemporalLayers ||
|
prev_send_codec.simulcastStream[i].numberOfTemporalLayers ||
|
||||||
new_send_codec.simulcastStream[i].qpMax !=
|
new_send_codec.simulcastStream[i].qpMax !=
|
||||||
|
@ -813,6 +815,7 @@ void VideoStreamEncoder::ReconfigureEncoder() {
|
||||||
<< " min_bps: " << codec.simulcastStream[i].minBitrate
|
<< " min_bps: " << codec.simulcastStream[i].minBitrate
|
||||||
<< " target_bps: " << codec.simulcastStream[i].targetBitrate
|
<< " target_bps: " << codec.simulcastStream[i].targetBitrate
|
||||||
<< " max_bps: " << codec.simulcastStream[i].maxBitrate
|
<< " max_bps: " << codec.simulcastStream[i].maxBitrate
|
||||||
|
<< " max_fps: " << codec.simulcastStream[i].maxFramerate
|
||||||
<< " max_qp: " << codec.simulcastStream[i].qpMax
|
<< " max_qp: " << codec.simulcastStream[i].qpMax
|
||||||
<< " num_tl: " << codec.simulcastStream[i].numberOfTemporalLayers
|
<< " num_tl: " << codec.simulcastStream[i].numberOfTemporalLayers
|
||||||
<< " active: "
|
<< " active: "
|
||||||
|
|
Loading…
Reference in a new issue