aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/video_codecs/video_encoder.cc11
-rw-r--r--api/video_codecs/video_encoder.h3
-rw-r--r--video/video_stream_encoder.cc53
-rw-r--r--video/video_stream_encoder.h3
-rw-r--r--video/video_stream_encoder_unittest.cc78
5 files changed, 121 insertions, 27 deletions
diff --git a/api/video_codecs/video_encoder.cc b/api/video_codecs/video_encoder.cc
index d3f16a0053..3a848f39ed 100644
--- a/api/video_codecs/video_encoder.cc
+++ b/api/video_codecs/video_encoder.cc
@@ -116,6 +116,17 @@ VideoEncoder::RateControlParameters::RateControlParameters(
framerate_fps(framerate_fps),
bandwidth_allocation(bandwidth_allocation) {}
+bool VideoEncoder::RateControlParameters::operator==(
+ const VideoEncoder::RateControlParameters& rhs) const {
+ return std::tie(bitrate, framerate_fps, bandwidth_allocation) ==
+ std::tie(rhs.bitrate, rhs.framerate_fps, rhs.bandwidth_allocation);
+}
+
+bool VideoEncoder::RateControlParameters::operator!=(
+ const VideoEncoder::RateControlParameters& rhs) const {
+ return !(rhs == *this);
+}
+
VideoEncoder::RateControlParameters::~RateControlParameters() = default;
void VideoEncoder::SetFecControllerOverride(
diff --git a/api/video_codecs/video_encoder.h b/api/video_codecs/video_encoder.h
index 0ee5521b95..766ea75712 100644
--- a/api/video_codecs/video_encoder.h
+++ b/api/video_codecs/video_encoder.h
@@ -239,6 +239,9 @@ class RTC_EXPORT VideoEncoder {
// |bitrate.get_sum_bps()|, but may be higher if the application is not
// network constrained.
DataRate bandwidth_allocation;
+
+ bool operator==(const RateControlParameters& rhs) const;
+ bool operator!=(const RateControlParameters& rhs) const;
};
struct LossNotification {
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 8b576e8c75..9257f93ad3 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -441,7 +441,7 @@ class VideoStreamEncoder::VideoSourceProxy {
};
VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings()
- : VideoEncoder::RateControlParameters(),
+ : rate_control(),
encoder_target(DataRate::Zero()),
stable_encoder_target(DataRate::Zero()) {}
@@ -451,16 +451,13 @@ VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings(
DataRate bandwidth_allocation,
DataRate encoder_target,
DataRate stable_encoder_target)
- : VideoEncoder::RateControlParameters(bitrate,
- framerate_fps,
- bandwidth_allocation),
+ : rate_control(bitrate, framerate_fps, bandwidth_allocation),
encoder_target(encoder_target),
stable_encoder_target(stable_encoder_target) {}
bool VideoStreamEncoder::EncoderRateSettings::operator==(
const EncoderRateSettings& rhs) const {
- return bitrate == rhs.bitrate && framerate_fps == rhs.framerate_fps &&
- bandwidth_allocation == rhs.bandwidth_allocation &&
+ return rate_control == rhs.rate_control &&
encoder_target == rhs.encoder_target &&
stable_encoder_target == rhs.stable_encoder_target;
}
@@ -948,7 +945,8 @@ void VideoStreamEncoder::ReconfigureEncoder() {
if (rate_allocator_ && last_encoder_rate_settings_) {
// We have a new rate allocator instance and already configured target
// bitrate. Update the rate allocation and notify observers.
- last_encoder_rate_settings_->framerate_fps = GetInputFramerateFps();
+ last_encoder_rate_settings_->rate_control.framerate_fps =
+ GetInputFramerateFps();
SetEncoderRates(
UpdateBitrateAllocationAndNotifyObserver(*last_encoder_rate_settings_));
}
@@ -1149,7 +1147,7 @@ VideoStreamEncoder::UpdateBitrateAllocationAndNotifyObserver(
if (rate_allocator_ && rate_settings.encoder_target > DataRate::Zero()) {
new_allocation = rate_allocator_->Allocate(VideoBitrateAllocationParameters(
rate_settings.encoder_target, rate_settings.stable_encoder_target,
- rate_settings.framerate_fps));
+ rate_settings.rate_control.framerate_fps));
}
if (bitrate_observer_ && new_allocation.get_sum_bps() > 0) {
@@ -1170,27 +1168,27 @@ VideoStreamEncoder::UpdateBitrateAllocationAndNotifyObserver(
}
EncoderRateSettings new_rate_settings = rate_settings;
- new_rate_settings.bitrate = new_allocation;
+ new_rate_settings.rate_control.bitrate = new_allocation;
// VideoBitrateAllocator subclasses may allocate a bitrate higher than the
// target in order to sustain the min bitrate of the video codec. In this
// case, make sure the bandwidth allocation is at least equal the allocation
// as that is part of the document contract for that field.
- new_rate_settings.bandwidth_allocation =
- std::max(new_rate_settings.bandwidth_allocation,
- DataRate::bps(new_rate_settings.bitrate.get_sum_bps()));
+ new_rate_settings.rate_control.bandwidth_allocation = std::max(
+ new_rate_settings.rate_control.bandwidth_allocation,
+ DataRate::bps(new_rate_settings.rate_control.bitrate.get_sum_bps()));
if (bitrate_adjuster_) {
VideoBitrateAllocation adjusted_allocation =
- bitrate_adjuster_->AdjustRateAllocation(new_rate_settings);
+ bitrate_adjuster_->AdjustRateAllocation(new_rate_settings.rate_control);
RTC_LOG(LS_VERBOSE) << "Adjusting allocation, fps = "
- << rate_settings.framerate_fps << ", from "
+ << rate_settings.rate_control.framerate_fps << ", from "
<< new_allocation.ToString() << ", to "
<< adjusted_allocation.ToString();
- new_rate_settings.bitrate = adjusted_allocation;
+ new_rate_settings.rate_control.bitrate = adjusted_allocation;
}
encoder_stats_observer_->OnBitrateAllocationUpdated(
- send_codec_, new_rate_settings.bitrate);
+ send_codec_, new_rate_settings.rate_control.bitrate);
return new_rate_settings;
}
@@ -1207,10 +1205,11 @@ uint32_t VideoStreamEncoder::GetInputFramerateFps() {
void VideoStreamEncoder::SetEncoderRates(
const EncoderRateSettings& rate_settings) {
- RTC_DCHECK_GT(rate_settings.framerate_fps, 0.0);
- const bool settings_changes = !last_encoder_rate_settings_ ||
- rate_settings != *last_encoder_rate_settings_;
- if (settings_changes) {
+ RTC_DCHECK_GT(rate_settings.rate_control.framerate_fps, 0.0);
+ bool rate_control_changed =
+ (!last_encoder_rate_settings_.has_value() ||
+ last_encoder_rate_settings_->rate_control != rate_settings.rate_control);
+ if (last_encoder_rate_settings_ != rate_settings) {
last_encoder_rate_settings_ = rate_settings;
}
@@ -1226,15 +1225,16 @@ void VideoStreamEncoder::SetEncoderRates(
// bitrate.
// TODO(perkj): Make sure all known encoder implementations handle zero
// target bitrate and remove this check.
- if (!HasInternalSource() && rate_settings.bitrate.get_sum_bps() == 0) {
+ if (!HasInternalSource() &&
+ rate_settings.rate_control.bitrate.get_sum_bps() == 0) {
return;
}
- if (settings_changes) {
- encoder_->SetRates(rate_settings);
+ if (rate_control_changed) {
+ encoder_->SetRates(rate_settings.rate_control);
frame_encode_metadata_writer_.OnSetRates(
- rate_settings.bitrate,
- static_cast<uint32_t>(rate_settings.framerate_fps + 0.5));
+ rate_settings.rate_control.bitrate,
+ static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
}
}
@@ -1283,7 +1283,8 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
// |last_encoder_rate_setings_|, triggering the call to SetRate() on the
// encoder.
EncoderRateSettings new_rate_settings = *last_encoder_rate_settings_;
- new_rate_settings.framerate_fps = static_cast<double>(framerate_fps);
+ new_rate_settings.rate_control.framerate_fps =
+ static_cast<double>(framerate_fps);
SetEncoderRates(
UpdateBitrateAllocationAndNotifyObserver(new_rate_settings));
}
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index 4db92f5fa6..46df362ebd 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -121,7 +121,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
int pixel_count() const { return width * height; }
};
- struct EncoderRateSettings : public VideoEncoder::RateControlParameters {
+ struct EncoderRateSettings {
EncoderRateSettings();
EncoderRateSettings(const VideoBitrateAllocation& bitrate,
double framerate_fps,
@@ -131,6 +131,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
bool operator==(const EncoderRateSettings& rhs) const;
bool operator!=(const EncoderRateSettings& rhs) const;
+ VideoEncoder::RateControlParameters rate_control;
// This is the scalar target bitrate before the VideoBitrateAllocator, i.e.
// the |target_bitrate| argument of the OnBitrateUpdated() method. This is
// needed because the bitrate allocator may truncate the total bitrate and a
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 6f19edcbb1..6eba930405 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -782,6 +782,11 @@ class VideoStreamEncoderTest : public ::testing::Test {
return num_encoder_initializations_;
}
+ int GetNumSetRates() const {
+ rtc::CritScope lock(&local_crit_sect_);
+ return num_set_rates_;
+ }
+
private:
int32_t Encode(const VideoFrame& input_image,
const std::vector<VideoFrameType>* frame_types) override {
@@ -848,6 +853,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
void SetRates(const RateControlParameters& parameters) {
rtc::CritScope lock(&local_crit_sect_);
+ num_set_rates_++;
VideoBitrateAllocation adjusted_rate_allocation;
for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
@@ -901,6 +907,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
int num_encoder_initializations_ RTC_GUARDED_BY(local_crit_sect_) = 0;
std::vector<ResolutionBitrateLimits> resolution_bitrate_limits_
RTC_GUARDED_BY(local_crit_sect_);
+ int num_set_rates_ RTC_GUARDED_BY(local_crit_sect_) = 0;
};
class TestSink : public VideoStreamEncoder::EncoderSink {
@@ -4875,4 +4882,75 @@ TEST_F(VideoStreamEncoderTest, ResolutionEncoderSwitch) {
video_stream_encoder_->Stop();
}
+TEST_F(VideoStreamEncoderTest,
+ AllocationPropegratedToEncoderWhenTargetRateChanged) {
+ const int kFrameWidth = 320;
+ const int kFrameHeight = 180;
+
+ // Set initial rate.
+ auto rate = DataRate::kbps(100);
+ video_stream_encoder_->OnBitrateUpdated(
+ /*target_bitrate=*/rate,
+ /*stable_target_bitrate=*/rate,
+ /*link_allocation=*/rate,
+ /*fraction_lost=*/0,
+ /*rtt_ms=*/0);
+
+ // Insert a first video frame so that encoder gets configured.
+ int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
+ VideoFrame frame = CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight);
+ frame.set_rotation(kVideoRotation_270);
+ video_source_.IncomingCapturedFrame(frame);
+ WaitForEncodedFrame(timestamp_ms);
+ EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
+
+ // Change of target bitrate propagates to the encoder.
+ auto new_stable_rate = rate - DataRate::kbps(5);
+ video_stream_encoder_->OnBitrateUpdated(
+ /*target_bitrate=*/new_stable_rate,
+ /*stable_target_bitrate=*/new_stable_rate,
+ /*link_allocation=*/rate,
+ /*fraction_lost=*/0,
+ /*rtt_ms=*/0);
+ video_stream_encoder_->WaitUntilTaskQueueIsIdle();
+ EXPECT_EQ(2, fake_encoder_.GetNumSetRates());
+ video_stream_encoder_->Stop();
+}
+
+TEST_F(VideoStreamEncoderTest,
+ AllocationNotPropegratedToEncoderWhenTargetRateUnchanged) {
+ const int kFrameWidth = 320;
+ const int kFrameHeight = 180;
+
+ // Set initial rate.
+ auto rate = DataRate::kbps(100);
+ video_stream_encoder_->OnBitrateUpdated(
+ /*target_bitrate=*/rate,
+ /*stable_target_bitrate=*/rate,
+ /*link_allocation=*/rate,
+ /*fraction_lost=*/0,
+ /*rtt_ms=*/0);
+
+ // Insert a first video frame so that encoder gets configured.
+ int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
+ VideoFrame frame = CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight);
+ frame.set_rotation(kVideoRotation_270);
+ video_source_.IncomingCapturedFrame(frame);
+ WaitForEncodedFrame(timestamp_ms);
+ EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
+
+ // Set a higher target rate without changing the link_allocation. Should not
+ // reset encoder's rate.
+ auto new_stable_rate = rate - DataRate::kbps(5);
+ video_stream_encoder_->OnBitrateUpdated(
+ /*target_bitrate=*/rate,
+ /*stable_target_bitrate=*/new_stable_rate,
+ /*link_allocation=*/rate,
+ /*fraction_lost=*/0,
+ /*rtt_ms=*/0);
+ video_stream_encoder_->WaitUntilTaskQueueIsIdle();
+ EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
+ video_stream_encoder_->Stop();
+}
+
} // namespace webrtc