Reland "Refactor handling of configuration overrides from Vp8FrameBufferController"
This is a reland of 4d6795f828bc4f2b050405b0ff73d4020b2a2963
Original change's description:
> Refactor handling of configuration overrides from Vp8FrameBufferController
>
> Make Vp8FrameBufferController::UpdateConfiguration return a set
> of desired overrides. These overrides are cumulative with
> previously returned override sets.
>
> Bug: webrtc:10382
> Change-Id: I1aa9544ae0cf6c57115e80963b3bbcdc3101db5e
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/134649
> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Commit-Queue: Elad Alon <eladalon@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27835}
TBR=brandtr@webrtc.org,sprang@webrtc.org
Bug: webrtc:10382
Change-Id: I0b313d19843edf429aeeaa4deafc5426c434a0fd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135942
Commit-Queue: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27904}
diff --git a/api/video_codecs/vp8_frame_buffer_controller.h b/api/video_codecs/vp8_frame_buffer_controller.h
index f71740e..bcfbd97 100644
--- a/api/video_codecs/vp8_frame_buffer_controller.h
+++ b/api/video_codecs/vp8_frame_buffer_controller.h
@@ -11,6 +11,7 @@
#ifndef API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_
#define API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_
+#include <array>
#include <memory>
#include <vector>
@@ -46,34 +47,48 @@
struct CodecSpecificInfo;
-// TODO(eladalon): This configuration is temporal-layers specific; refactor.
+// Each member represents an override of the VPX configuration if the optional
+// value is set.
struct Vp8EncoderConfig {
- static constexpr size_t kMaxPeriodicity = 16;
- static constexpr size_t kMaxLayers = 5;
+ struct TemporalLayerConfig {
+ bool operator!=(const TemporalLayerConfig& other) const {
+ return ts_number_layers != other.ts_number_layers ||
+ ts_target_bitrate != other.ts_target_bitrate ||
+ ts_rate_decimator != other.ts_rate_decimator ||
+ ts_periodicity != other.ts_periodicity ||
+ ts_layer_id != other.ts_layer_id;
+ }
- // Number of active temporal layers. Set to 0 if not used.
- uint32_t ts_number_layers;
- // Arrays of length |ts_number_layers|, indicating (cumulative) target bitrate
- // and rate decimator (e.g. 4 if every 4th frame is in the given layer) for
- // each active temporal layer, starting with temporal id 0.
- uint32_t ts_target_bitrate[kMaxLayers];
- uint32_t ts_rate_decimator[kMaxLayers];
+ static constexpr size_t kMaxPeriodicity = 16;
+ static constexpr size_t kMaxLayers = 5;
- // The periodicity of the temporal pattern. Set to 0 if not used.
- uint32_t ts_periodicity;
- // Array of length |ts_periodicity| indicating the sequence of temporal id's
- // to assign to incoming frames.
- uint32_t ts_layer_id[kMaxPeriodicity];
+ // Number of active temporal layers. Set to 0 if not used.
+ uint32_t ts_number_layers;
+
+ // Arrays of length |ts_number_layers|, indicating (cumulative) target
+ // bitrate and rate decimator (e.g. 4 if every 4th frame is in the given
+ // layer) for each active temporal layer, starting with temporal id 0.
+ std::array<uint32_t, kMaxLayers> ts_target_bitrate;
+ std::array<uint32_t, kMaxLayers> ts_rate_decimator;
+
+ // The periodicity of the temporal pattern. Set to 0 if not used.
+ uint32_t ts_periodicity;
+
+ // Array of length |ts_periodicity| indicating the sequence of temporal id's
+ // to assign to incoming frames.
+ std::array<uint32_t, kMaxPeriodicity> ts_layer_id;
+ };
+
+ absl::optional<TemporalLayerConfig> temporal_layer_config;
// Target bitrate, in bps.
- uint32_t rc_target_bitrate;
+ absl::optional<uint32_t> rc_target_bitrate;
- // Clamp QP to min/max. Use 0 to disable clamping.
- uint32_t rc_min_quantizer;
- uint32_t rc_max_quantizer;
+ // Clamp QP to max. Use 0 to disable clamping.
+ absl::optional<uint32_t> rc_max_quantizer;
- // If has_value(), override error resilience to value().
- absl::optional<uint32_t> error_resilient;
+ // Error resilience mode.
+ absl::optional<uint32_t> g_error_resilient;
};
// This interface defines a way of delegating the logic of buffer management.
@@ -83,6 +98,10 @@
public:
virtual ~Vp8FrameBufferController() = default;
+ // Set limits on QP.
+ // The limits are suggestion-only; the controller is allowed to exceed them.
+ virtual void SetQpLimits(size_t stream_index, int min_qp, int max_qp) = 0;
+
// Number of streamed controlled by |this|.
virtual size_t StreamCount() const = 0;
@@ -103,12 +122,13 @@
const std::vector<uint32_t>& bitrates_bps,
int framerate_fps) = 0;
- // Called by the encoder before encoding a frame. |cfg| contains the current
- // configuration. If the encoder wishes any part of that to be changed before
- // the encode step, |cfg| should be changed and then return true. If false is
- // returned, the encoder will proceed without updating the configuration.
- virtual bool UpdateConfiguration(size_t stream_index,
- Vp8EncoderConfig* cfg) = 0;
+ // Called by the encoder before encoding a frame. Returns a set of overrides
+ // the controller wishes to enact in the encoder's configuration.
+ // If a value is not overridden, previous overrides are still in effect.
+ // (It is therefore not possible to go from a specific override to
+ // no-override. Once the controller takes responsibility over a value, it
+ // must maintain responsibility for it.)
+ virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;
// Returns the recommended VP8 encode flags needed.
// The timestamp may be used as both a time and a unique identifier, and so
diff --git a/api/video_codecs/vp8_temporal_layers.cc b/api/video_codecs/vp8_temporal_layers.cc
index 7f7d8ad..22916a7 100644
--- a/api/video_codecs/vp8_temporal_layers.cc
+++ b/api/video_codecs/vp8_temporal_layers.cc
@@ -28,6 +28,13 @@
}));
}
+void Vp8TemporalLayers::SetQpLimits(size_t stream_index,
+ int min_qp,
+ int max_qp) {
+ RTC_DCHECK_LT(stream_index, controllers_.size());
+ return controllers_[stream_index]->SetQpLimits(0, min_qp, max_qp);
+}
+
size_t Vp8TemporalLayers::StreamCount() const {
return controllers_.size();
}
@@ -47,10 +54,9 @@
framerate_fps);
}
-bool Vp8TemporalLayers::UpdateConfiguration(size_t stream_index,
- Vp8EncoderConfig* cfg) {
+Vp8EncoderConfig Vp8TemporalLayers::UpdateConfiguration(size_t stream_index) {
RTC_DCHECK_LT(stream_index, controllers_.size());
- return controllers_[stream_index]->UpdateConfiguration(0, cfg);
+ return controllers_[stream_index]->UpdateConfiguration(0);
}
Vp8FrameConfig Vp8TemporalLayers::NextFrameConfig(size_t stream_index,
diff --git a/api/video_codecs/vp8_temporal_layers.h b/api/video_codecs/vp8_temporal_layers.h
index 3864705..4194352 100644
--- a/api/video_codecs/vp8_temporal_layers.h
+++ b/api/video_codecs/vp8_temporal_layers.h
@@ -35,6 +35,8 @@
std::vector<std::unique_ptr<Vp8FrameBufferController>>&& controllers);
~Vp8TemporalLayers() override = default;
+ void SetQpLimits(size_t stream_index, int min_qp, int max_qp) override;
+
size_t StreamCount() const override;
bool SupportsEncoderFrameDropping(size_t stream_index) const override;
@@ -43,7 +45,7 @@
const std::vector<uint32_t>& bitrates_bps,
int framerate_fps) override;
- bool UpdateConfiguration(size_t stream_index, Vp8EncoderConfig* cfg) override;
+ Vp8EncoderConfig UpdateConfiguration(size_t stream_index) override;
Vp8FrameConfig NextFrameConfig(size_t stream_index,
uint32_t rtp_timestamp) override;
diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers.cc b/modules/video_coding/codecs/vp8/default_temporal_layers.cc
index 8fa8f0d..339e81d 100644
--- a/modules/video_coding/codecs/vp8/default_temporal_layers.cc
+++ b/modules/video_coding/codecs/vp8/default_temporal_layers.cc
@@ -10,7 +10,6 @@
#include "modules/video_coding/codecs/vp8/default_temporal_layers.h"
#include <stdlib.h>
-#include <string.h>
#include <algorithm>
#include <array>
@@ -251,6 +250,13 @@
DefaultTemporalLayers::~DefaultTemporalLayers() = default;
+void DefaultTemporalLayers::SetQpLimits(size_t stream_index,
+ int min_qp,
+ int max_qp) {
+ RTC_DCHECK_LT(stream_index, StreamCount());
+ // Ignore.
+}
+
size_t DefaultTemporalLayers::StreamCount() const {
return 1;
}
@@ -278,28 +284,34 @@
}
}
-bool DefaultTemporalLayers::UpdateConfiguration(size_t stream_index,
- Vp8EncoderConfig* cfg) {
+Vp8EncoderConfig DefaultTemporalLayers::UpdateConfiguration(
+ size_t stream_index) {
RTC_DCHECK_LT(stream_index, StreamCount());
+ Vp8EncoderConfig config;
+
if (!new_bitrates_bps_) {
- return false;
+ return config;
}
+ config.temporal_layer_config.emplace();
+ Vp8EncoderConfig::TemporalLayerConfig& ts_config =
+ config.temporal_layer_config.value();
+
for (size_t i = 0; i < num_layers_; ++i) {
- cfg->ts_target_bitrate[i] = (*new_bitrates_bps_)[i] / 1000;
+ ts_config.ts_target_bitrate[i] = (*new_bitrates_bps_)[i] / 1000;
// ..., 4, 2, 1
- cfg->ts_rate_decimator[i] = 1 << (num_layers_ - i - 1);
+ ts_config.ts_rate_decimator[i] = 1 << (num_layers_ - i - 1);
}
- cfg->ts_number_layers = num_layers_;
- cfg->ts_periodicity = temporal_ids_.size();
- memcpy(cfg->ts_layer_id, &temporal_ids_[0],
- sizeof(unsigned int) * temporal_ids_.size());
+ ts_config.ts_number_layers = num_layers_;
+ ts_config.ts_periodicity = temporal_ids_.size();
+ std::copy(temporal_ids_.begin(), temporal_ids_.end(),
+ ts_config.ts_layer_id.begin());
new_bitrates_bps_.reset();
- return true;
+ return config;
}
bool DefaultTemporalLayers::IsSyncFrame(const Vp8FrameConfig& config) const {
diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers.h b/modules/video_coding/codecs/vp8/default_temporal_layers.h
index 34ed711..cb1cbbe 100644
--- a/modules/video_coding/codecs/vp8/default_temporal_layers.h
+++ b/modules/video_coding/codecs/vp8/default_temporal_layers.h
@@ -34,6 +34,8 @@
explicit DefaultTemporalLayers(int number_of_temporal_layers);
~DefaultTemporalLayers() override;
+ void SetQpLimits(size_t stream_index, int min_qp, int max_qp) override;
+
size_t StreamCount() const override;
bool SupportsEncoderFrameDropping(size_t stream_index) const override;
@@ -48,7 +50,7 @@
const std::vector<uint32_t>& bitrates_bps,
int framerate_fps) override;
- bool UpdateConfiguration(size_t stream_index, Vp8EncoderConfig* cfg) override;
+ Vp8EncoderConfig UpdateConfiguration(size_t stream_index) override;
void OnEncodeDone(size_t stream_index,
uint32_t rtp_timestamp,
diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc b/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc
index 8f01e59..2c419da 100644
--- a/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc
+++ b/modules/video_coding/codecs/vp8/default_temporal_layers_unittest.cc
@@ -23,6 +23,8 @@
#include "test/gtest.h"
#include "vpx/vp8cx.h"
+// TODO(bugs.webrtc.org/10582): Test the behavior of UpdateConfiguration().
+
namespace webrtc {
namespace test {
namespace {
@@ -119,12 +121,11 @@
constexpr int kNumLayers = 2;
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
constexpr size_t kPatternSize = 4;
constexpr size_t kRepetitions = 4;
@@ -162,12 +163,11 @@
constexpr int kNumLayers = 3;
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
int expected_flags[16] = {
kTemporalUpdateLast,
@@ -217,12 +217,11 @@
ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
int expected_flags[8] = {kTemporalUpdateLast,
kTemporalUpdateAltrefWithoutDependency,
@@ -260,12 +259,11 @@
ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
// Use a repeating pattern of tl 0, 2, 1, 2.
// Tl 0, 1, 2 update last, golden, altref respectively.
@@ -304,12 +302,11 @@
ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
// Use a repeating pattern of tl 0, 2, 1, 2.
// Tl 0, 1, 2 update last, golden, altref respectively.
@@ -344,12 +341,11 @@
constexpr int kNumLayers = 4;
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
int expected_flags[16] = {
kTemporalUpdateLast,
kTemporalUpdateNoneNoRefGoldenAltRef,
@@ -400,12 +396,11 @@
ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
// Start with a keyframe.
uint32_t timestamp = 0;
@@ -487,12 +482,11 @@
// Tl 0, 1 updates last, golden respectively. Altref is always last keyframe.
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
// Start with a keyframe.
uint32_t timestamp = 0;
@@ -557,12 +551,11 @@
ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
// Start with a keyframe.
uint32_t timestamp = 0;
@@ -618,12 +611,11 @@
constexpr int kNumLayers = 3;
DefaultTemporalLayers tl(kNumLayers);
DefaultTemporalLayersChecker checker(kNumLayers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(0,
GetTemporalLayerRates(kDefaultBytesPerFrame,
kDefaultFramerate, kNumLayers),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
int expected_flags[8] = {
kTemporalUpdateLastRefAltRef,
@@ -735,11 +727,10 @@
TEST_P(TemporalLayersReferenceTest, ValidFrameConfigs) {
const int num_layers = GetParam();
DefaultTemporalLayers tl(num_layers);
- Vp8EncoderConfig cfg;
tl.OnRatesUpdated(
0, GetTemporalLayerRates(kDefaultBytesPerFrame, kDefaultFramerate, 1),
kDefaultFramerate);
- tl.UpdateConfiguration(0, &cfg);
+ tl.UpdateConfiguration(0);
// Run through the pattern and store the frame dependencies, plus keep track
// of the buffer state; which buffers references which temporal layers (if
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index 86da3a7..d35ec29 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -15,6 +15,7 @@
#include <algorithm>
#include <cstdint>
+#include <iterator>
#include <memory>
#include <string>
#include <utility>
@@ -145,58 +146,74 @@
config->rc_dropframe_thresh = new_settings.rc_dropframe_thresh;
}
-static_assert(Vp8EncoderConfig::kMaxPeriodicity == VPX_TS_MAX_PERIODICITY,
+static_assert(Vp8EncoderConfig::TemporalLayerConfig::kMaxPeriodicity ==
+ VPX_TS_MAX_PERIODICITY,
"Vp8EncoderConfig::kMaxPeriodicity must be kept in sync with the "
"constant in libvpx.");
-static_assert(Vp8EncoderConfig::kMaxLayers == VPX_TS_MAX_LAYERS,
+static_assert(Vp8EncoderConfig::TemporalLayerConfig::kMaxLayers ==
+ VPX_TS_MAX_LAYERS,
"Vp8EncoderConfig::kMaxLayers must be kept in sync with the "
"constant in libvpx.");
-static Vp8EncoderConfig GetEncoderConfig(vpx_codec_enc_cfg* vpx_config) {
- Vp8EncoderConfig config;
-
- config.ts_number_layers = vpx_config->ts_number_layers;
- memcpy(config.ts_target_bitrate, vpx_config->ts_target_bitrate,
- sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
- memcpy(config.ts_rate_decimator, vpx_config->ts_rate_decimator,
- sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
- config.ts_periodicity = vpx_config->ts_periodicity;
- memcpy(config.ts_layer_id, vpx_config->ts_layer_id,
- sizeof(unsigned int) * Vp8EncoderConfig::kMaxPeriodicity);
- config.rc_target_bitrate = vpx_config->rc_target_bitrate;
- config.rc_min_quantizer = vpx_config->rc_min_quantizer;
- config.rc_max_quantizer = vpx_config->rc_max_quantizer;
-
- return config;
-}
-
-static void FillInEncoderConfig(vpx_codec_enc_cfg* vpx_config,
- const Vp8EncoderConfig& config) {
- vpx_config->ts_number_layers = config.ts_number_layers;
- memcpy(vpx_config->ts_target_bitrate, config.ts_target_bitrate,
- sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
- memcpy(vpx_config->ts_rate_decimator, config.ts_rate_decimator,
- sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
- vpx_config->ts_periodicity = config.ts_periodicity;
- memcpy(vpx_config->ts_layer_id, config.ts_layer_id,
- sizeof(unsigned int) * Vp8EncoderConfig::kMaxPeriodicity);
- vpx_config->rc_target_bitrate = config.rc_target_bitrate;
- vpx_config->rc_min_quantizer = config.rc_min_quantizer;
- vpx_config->rc_max_quantizer = config.rc_max_quantizer;
- if (config.error_resilient.has_value()) {
- vpx_config->g_error_resilient = config.error_resilient.value();
+// Allow a newer value to override a current value only if the new value
+// is set.
+template <typename T>
+bool MaybeSetNewValue(const absl::optional<T>& new_value,
+ absl::optional<T>* base_value) {
+ if (new_value.has_value() && new_value != *base_value) {
+ *base_value = new_value;
+ return true;
+ } else {
+ return false;
}
}
-bool UpdateVpxConfiguration(size_t stream_index,
- Vp8FrameBufferController* frame_buffer_controller,
- vpx_codec_enc_cfg_t* cfg) {
- Vp8EncoderConfig config = GetEncoderConfig(cfg);
- const bool res =
- frame_buffer_controller->UpdateConfiguration(stream_index, &config);
- if (res)
- FillInEncoderConfig(cfg, config);
- return res;
+// Adds configuration from |new_config| to |base_config|. Both configs consist
+// of optionals, and only optionals which are set in |new_config| can have
+// an effect. (That is, set values in |base_config| cannot be unset.)
+// Returns |true| iff any changes were made to |base_config|.
+bool MaybeExtendVp8EncoderConfig(const Vp8EncoderConfig& new_config,
+ Vp8EncoderConfig* base_config) {
+ bool changes_made = false;
+ changes_made |= MaybeSetNewValue(new_config.temporal_layer_config,
+ &base_config->temporal_layer_config);
+ changes_made |= MaybeSetNewValue(new_config.rc_target_bitrate,
+ &base_config->rc_target_bitrate);
+ changes_made |= MaybeSetNewValue(new_config.rc_max_quantizer,
+ &base_config->rc_max_quantizer);
+ changes_made |= MaybeSetNewValue(new_config.g_error_resilient,
+ &base_config->g_error_resilient);
+ return changes_made;
+}
+
+void ApplyVp8EncoderConfigToVpxConfig(const Vp8EncoderConfig& encoder_config,
+ vpx_codec_enc_cfg_t* vpx_config) {
+ if (encoder_config.temporal_layer_config.has_value()) {
+ const Vp8EncoderConfig::TemporalLayerConfig& ts_config =
+ encoder_config.temporal_layer_config.value();
+ vpx_config->ts_number_layers = ts_config.ts_number_layers;
+ std::copy(ts_config.ts_target_bitrate.begin(),
+ ts_config.ts_target_bitrate.end(),
+ std::begin(vpx_config->ts_target_bitrate));
+ std::copy(ts_config.ts_rate_decimator.begin(),
+ ts_config.ts_rate_decimator.end(),
+ std::begin(vpx_config->ts_rate_decimator));
+ vpx_config->ts_periodicity = ts_config.ts_periodicity;
+ std::copy(ts_config.ts_layer_id.begin(), ts_config.ts_layer_id.end(),
+ std::begin(vpx_config->ts_layer_id));
+ }
+
+ if (encoder_config.rc_target_bitrate.has_value()) {
+ vpx_config->rc_target_bitrate = encoder_config.rc_target_bitrate.value();
+ }
+
+ if (encoder_config.rc_max_quantizer.has_value()) {
+ vpx_config->rc_max_quantizer = encoder_config.rc_max_quantizer.value();
+ }
+
+ if (encoder_config.g_error_resilient.has_value()) {
+ vpx_config->g_error_resilient = encoder_config.g_error_resilient.value();
+ }
}
} // namespace
@@ -282,6 +299,7 @@
cpu_speed_.assign(kMaxSimulcastStreams, cpu_speed_default_);
encoders_.reserve(kMaxSimulcastStreams);
configurations_.reserve(kMaxSimulcastStreams);
+ config_overrides_.reserve(kMaxSimulcastStreams);
downsampling_factors_.reserve(kMaxSimulcastStreams);
}
@@ -304,6 +322,7 @@
encoders_.clear();
configurations_.clear();
+ config_overrides_.clear();
send_stream_.clear();
cpu_speed_.clear();
@@ -367,8 +386,9 @@
}
}
- size_t stream_idx = encoders_.size() - 1;
- for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) {
+ for (size_t i = 0; i < encoders_.size(); ++i) {
+ const size_t stream_idx = encoders_.size() - 1 - i;
+
unsigned int target_bitrate_kbps =
parameters.bitrate.GetSpatialLayerSum(stream_idx) / 1000;
@@ -383,8 +403,7 @@
static_cast<int>(parameters.framerate_fps + 0.5));
}
- UpdateVpxConfiguration(stream_idx, frame_buffer_controller_.get(),
- &configurations_[i]);
+ UpdateVpxConfiguration(stream_idx);
if (rate_control_settings_.Vp8DynamicRateSettings()) {
// Tweak rate control settings based on available network headroom.
@@ -486,6 +505,7 @@
encoded_images_.resize(number_of_streams);
encoders_.resize(number_of_streams);
configurations_.resize(number_of_streams);
+ config_overrides_.resize(number_of_streams);
downsampling_factors_.resize(number_of_streams);
raw_images_.resize(number_of_streams);
send_stream_.resize(number_of_streams);
@@ -600,7 +620,7 @@
// Note the order we use is different from webm, we have lowest resolution
// at position 0 and they have highest resolution at position 0.
- int stream_idx = encoders_.size() - 1;
+ const size_t stream_idx_cfg_0 = encoders_.size() - 1;
SimulcastRateAllocator init_allocator(codec_);
VideoBitrateAllocation allocation = init_allocator.GetAllocation(
inst->startBitrate * 1000, inst->maxFramerate);
@@ -610,18 +630,21 @@
stream_bitrates.push_back(bitrate);
}
- configurations_[0].rc_target_bitrate = stream_bitrates[stream_idx];
- if (stream_bitrates[stream_idx] > 0) {
+ configurations_[0].rc_target_bitrate = stream_bitrates[stream_idx_cfg_0];
+ if (stream_bitrates[stream_idx_cfg_0] > 0) {
frame_buffer_controller_->OnRatesUpdated(
- stream_idx, allocation.GetTemporalLayerAllocation(stream_idx),
+ stream_idx_cfg_0,
+ allocation.GetTemporalLayerAllocation(stream_idx_cfg_0),
inst->maxFramerate);
}
- UpdateVpxConfiguration(stream_idx, frame_buffer_controller_.get(),
- &configurations_[0]);
- configurations_[0].rc_dropframe_thresh = FrameDropThreshold(stream_idx);
+ frame_buffer_controller_->SetQpLimits(stream_idx_cfg_0,
+ configurations_[0].rc_min_quantizer,
+ configurations_[0].rc_max_quantizer);
+ UpdateVpxConfiguration(stream_idx_cfg_0);
+ configurations_[0].rc_dropframe_thresh = FrameDropThreshold(stream_idx_cfg_0);
- --stream_idx;
- for (size_t i = 1; i < encoders_.size(); ++i, --stream_idx) {
+ for (size_t i = 1; i < encoders_.size(); ++i) {
+ const size_t stream_idx = encoders_.size() - 1 - i;
memcpy(&configurations_[i], &configurations_[0],
sizeof(configurations_[0]));
@@ -647,8 +670,10 @@
stream_idx, allocation.GetTemporalLayerAllocation(stream_idx),
inst->maxFramerate);
}
- UpdateVpxConfiguration(stream_idx, frame_buffer_controller_.get(),
- &configurations_[i]);
+ frame_buffer_controller_->SetQpLimits(stream_idx,
+ configurations_[i].rc_min_quantizer,
+ configurations_[i].rc_max_quantizer);
+ UpdateVpxConfiguration(stream_idx);
}
return InitAndSetControlSettings();
@@ -856,6 +881,27 @@
0.5);
}
+bool LibvpxVp8Encoder::UpdateVpxConfiguration(size_t stream_index) {
+ RTC_DCHECK(frame_buffer_controller_);
+
+ const size_t config_index = configurations_.size() - 1 - stream_index;
+
+ RTC_DCHECK_LT(config_index, config_overrides_.size());
+ Vp8EncoderConfig* config = &config_overrides_[config_index];
+
+ const Vp8EncoderConfig new_config =
+ frame_buffer_controller_->UpdateConfiguration(stream_index);
+
+ const bool changes_made = MaybeExtendVp8EncoderConfig(new_config, config);
+
+ // Note that overrides must be applied even if they haven't changed.
+ RTC_DCHECK_LT(config_index, configurations_.size());
+ vpx_codec_enc_cfg_t* vpx_config = &configurations_[config_index];
+ ApplyVp8EncoderConfigToVpxConfig(*config, vpx_config);
+
+ return changes_made;
+}
+
int LibvpxVp8Encoder::Encode(const VideoFrame& frame,
const std::vector<VideoFrameType>* frame_types) {
RTC_DCHECK_EQ(frame.width(), codec_.width);
@@ -977,16 +1023,11 @@
// Note that streams are defined starting from lowest resolution at
// position 0 to highest resolution at position |encoders_.size() - 1|,
// whereas |encoder_| is from highest to lowest resolution.
- size_t stream_idx = encoders_.size() - 1;
- for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) {
- // Allow the layers adapter to temporarily modify the configuration. This
- // change isn't stored in configurations_ so change will be discarded at
- // the next update.
- vpx_codec_enc_cfg_t temp_config;
- memcpy(&temp_config, &configurations_[i], sizeof(vpx_codec_enc_cfg_t));
- if (UpdateVpxConfiguration(stream_idx, frame_buffer_controller_.get(),
- &temp_config)) {
- if (libvpx_->codec_enc_config_set(&encoders_[i], &temp_config))
+ for (size_t i = 0; i < encoders_.size(); ++i) {
+ const size_t stream_idx = encoders_.size() - 1 - i;
+
+ if (UpdateVpxConfiguration(stream_idx)) {
+ if (libvpx_->codec_enc_config_set(&encoders_[i], &configurations_[i]))
return WEBRTC_VIDEO_CODEC_ERROR;
}
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
index 0913f5b..1e17096 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
@@ -93,6 +93,8 @@
size_t SteadyStateSize(int sid, int tid);
+ bool UpdateVpxConfiguration(size_t stream_index);
+
const std::unique_ptr<LibvpxInterface> libvpx_;
const absl::optional<std::vector<CpuSpeedExperiment::Config>>
@@ -117,6 +119,7 @@
std::vector<EncodedImage> encoded_images_;
std::vector<vpx_codec_ctx_t> encoders_;
std::vector<vpx_codec_enc_cfg_t> configurations_;
+ std::vector<Vp8EncoderConfig> config_overrides_;
std::vector<vpx_rational_t> downsampling_factors_;
// Variable frame-rate screencast related fields and methods.
diff --git a/modules/video_coding/codecs/vp8/screenshare_layers.cc b/modules/video_coding/codecs/vp8/screenshare_layers.cc
index 2f4b482..c8ea6ca 100644
--- a/modules/video_coding/codecs/vp8/screenshare_layers.cc
+++ b/modules/video_coding/codecs/vp8/screenshare_layers.cc
@@ -55,8 +55,6 @@
last_sync_timestamp_(-1),
last_emitted_tl0_timestamp_(-1),
last_frame_time_ms_(-1),
- min_qp_(-1),
- max_qp_(-1),
max_debt_bytes_(0),
encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale.
bitrate_updated_(false),
@@ -71,6 +69,24 @@
UpdateHistograms();
}
+void ScreenshareLayers::SetQpLimits(size_t stream_index,
+ int min_qp,
+ int max_qp) {
+ RTC_DCHECK_LT(stream_index, StreamCount());
+ // 0 < min_qp <= max_qp
+ RTC_DCHECK_LT(0, min_qp);
+ RTC_DCHECK_LE(min_qp, max_qp);
+
+ RTC_DCHECK_EQ(min_qp_.has_value(), max_qp_.has_value());
+ if (!min_qp_.has_value()) {
+ min_qp_ = min_qp;
+ max_qp_ = max_qp;
+ } else {
+ RTC_DCHECK_EQ(min_qp, min_qp_.value());
+ RTC_DCHECK_EQ(max_qp, max_qp_.value());
+ }
+}
+
size_t ScreenshareLayers::StreamCount() const {
return 1;
}
@@ -478,19 +494,12 @@
return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
}
-bool ScreenshareLayers::UpdateConfiguration(size_t stream_index,
- Vp8EncoderConfig* cfg) {
+Vp8EncoderConfig ScreenshareLayers::UpdateConfiguration(size_t stream_index) {
RTC_DCHECK_LT(stream_index, StreamCount());
+ RTC_DCHECK(min_qp_.has_value());
+ RTC_DCHECK(max_qp_.has_value());
- if (min_qp_ == -1 || max_qp_ == -1) {
- // Store the valid qp range. This must not change during the lifetime of
- // this class.
- min_qp_ = cfg->rc_min_quantizer;
- max_qp_ = cfg->rc_max_quantizer;
- }
-
- bool cfg_updated = false;
- uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
+ const uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
// TODO(sprang): We _really_ need to make an overhaul of this class. :(
// If we're dropping frames in order to meet a target framerate, adjust the
@@ -503,12 +512,16 @@
}
if (bitrate_updated_ ||
- cfg->rc_target_bitrate != encoder_config_bitrate_kbps) {
- cfg->rc_target_bitrate = encoder_config_bitrate_kbps;
+ encoder_config_.rc_target_bitrate !=
+ absl::make_optional(encoder_config_bitrate_kbps)) {
+ encoder_config_.rc_target_bitrate = encoder_config_bitrate_kbps;
// Don't reconfigure qp limits during quality boost frames.
if (active_layer_ == -1 ||
layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
+ const int min_qp = min_qp_.value();
+ const int max_qp = max_qp_.value();
+
// After a dropped frame, a frame with max qp will be encoded and the
// quality will then ramp up from there. To boost the speed of recovery,
// encode the next frame with lower max qp, if there is sufficient
@@ -517,10 +530,8 @@
// will propagate to TL1.
// Currently, reduce max qp by 20% for TL0 and 15% for TL1.
if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
- layers_[0].enhanced_max_qp =
- min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
- layers_[1].enhanced_max_qp =
- min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
+ layers_[0].enhanced_max_qp = min_qp + (((max_qp - min_qp) * 80) / 100);
+ layers_[1].enhanced_max_qp = min_qp + (((max_qp - min_qp) * 85) / 100);
} else {
layers_[0].enhanced_max_qp = -1;
layers_[1].enhanced_max_qp = -1;
@@ -538,20 +549,19 @@
}
bitrate_updated_ = false;
- cfg_updated = true;
}
// Don't try to update boosts state if not active yet.
if (active_layer_ == -1)
- return cfg_updated;
+ return encoder_config_;
- if (max_qp_ == -1 || number_of_temporal_layers_ <= 1)
- return cfg_updated;
+ if (number_of_temporal_layers_ <= 1)
+ return encoder_config_;
// If layer is in the quality boost state (following a dropped frame), update
// the configuration with the adjusted (lower) qp and set the state back to
// normal.
- unsigned int adjusted_max_qp = max_qp_; // Set the normal max qp.
+ unsigned int adjusted_max_qp = max_qp_.value(); // Set the normal max qp.
if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost) {
if (layers_[active_layer_].enhanced_max_qp != -1) {
// Bitrate is high enough for quality boost, update max qp.
@@ -560,14 +570,9 @@
// Regardless of qp, reset the boost state for the next frame.
layers_[active_layer_].state = TemporalLayer::State::kNormal;
}
+ encoder_config_.rc_max_quantizer = adjusted_max_qp;
- if (adjusted_max_qp == cfg->rc_max_quantizer)
- return cfg_updated;
-
- cfg->rc_max_quantizer = adjusted_max_qp;
- cfg_updated = true;
-
- return cfg_updated;
+ return encoder_config_;
}
void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
diff --git a/modules/video_coding/codecs/vp8/screenshare_layers.h b/modules/video_coding/codecs/vp8/screenshare_layers.h
index 06d4553..d7de527 100644
--- a/modules/video_coding/codecs/vp8/screenshare_layers.h
+++ b/modules/video_coding/codecs/vp8/screenshare_layers.h
@@ -36,6 +36,8 @@
explicit ScreenshareLayers(int num_temporal_layers);
~ScreenshareLayers() override;
+ void SetQpLimits(size_t stream_index, int min_qp, int max_qp) override;
+
size_t StreamCount() const override;
bool SupportsEncoderFrameDropping(size_t stream_index) const override;
@@ -50,9 +52,7 @@
const std::vector<uint32_t>& bitrates_bps,
int framerate_fps) override;
- // Update the encoder configuration with target bitrates or other parameters.
- // Returns true iff the configuration was actually modified.
- bool UpdateConfiguration(size_t stream_index, Vp8EncoderConfig* cfg) override;
+ Vp8EncoderConfig UpdateConfiguration(size_t stream_index) override;
void OnEncodeDone(size_t stream_index,
uint32_t rtp_timestamp,
@@ -89,15 +89,18 @@
bool TimeToSync(int64_t timestamp) const;
uint32_t GetCodecTargetBitrateKbps() const;
- int number_of_temporal_layers_;
+ const int number_of_temporal_layers_;
+
+ // TODO(eladalon/sprang): These should be made into const-int set in the ctor.
+ absl::optional<int> min_qp_;
+ absl::optional<int> max_qp_;
+
int active_layer_;
int64_t last_timestamp_;
int64_t last_sync_timestamp_;
int64_t last_emitted_tl0_timestamp_;
int64_t last_frame_time_ms_;
rtc::TimestampWrapAroundHandler time_wrap_handler_;
- int min_qp_;
- int max_qp_;
uint32_t max_debt_bytes_;
std::map<uint32_t, DependencyInfo> pending_frame_configs_;
@@ -152,6 +155,8 @@
int64_t tl1_target_bitrate_sum_ = 0;
} stats_;
+ Vp8EncoderConfig encoder_config_;
+
// Optional utility used to verify reference validity.
std::unique_ptr<TemporalLayersChecker> checker_;
};
diff --git a/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc b/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
index 032c528..1f85cb6 100644
--- a/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
+++ b/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
@@ -30,7 +30,6 @@
using ::testing::_;
using ::testing::ElementsAre;
using ::testing::NiceMock;
-using ::testing::Return;
namespace webrtc {
namespace {
@@ -93,7 +92,19 @@
if (tl_config_.drop_frame) {
return -1;
}
- config_updated_ = layers_->UpdateConfiguration(0, &cfg_);
+ const uint32_t prev_rc_target_bitrate = cfg_.rc_target_bitrate.value_or(-1);
+ const uint32_t prev_rc_max_quantizer = cfg_.rc_max_quantizer.value_or(-1);
+
+ cfg_ = layers_->UpdateConfiguration(0);
+
+ config_updated_ =
+ cfg_.temporal_layer_config.has_value() ||
+ (cfg_.rc_target_bitrate.has_value() &&
+ cfg_.rc_target_bitrate.value() != prev_rc_target_bitrate) ||
+ (cfg_.rc_max_quantizer.has_value() &&
+ cfg_.rc_max_quantizer.value() != prev_rc_max_quantizer) ||
+ cfg_.g_error_resilient.has_value();
+
int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
EXPECT_NE(-1, frame_size_);
return flags;
@@ -110,13 +121,11 @@
}
Vp8EncoderConfig ConfigureBitrates() {
- Vp8EncoderConfig vp8_cfg;
- memset(&vp8_cfg, 0, sizeof(Vp8EncoderConfig));
- vp8_cfg.rc_min_quantizer = min_qp_;
- vp8_cfg.rc_max_quantizer = max_qp_;
+ layers_->SetQpLimits(0, min_qp_, max_qp_);
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
- EXPECT_TRUE(layers_->UpdateConfiguration(0, &vp8_cfg));
- frame_size_ = FrameSizeForBitrate(vp8_cfg.rc_target_bitrate);
+ const Vp8EncoderConfig vp8_cfg = layers_->UpdateConfiguration(0);
+ EXPECT_TRUE(vp8_cfg.rc_target_bitrate.has_value());
+ frame_size_ = FrameSizeForBitrate(vp8_cfg.rc_target_bitrate.value());
return vp8_cfg;
}
@@ -246,7 +255,7 @@
CodecSpecificInfo info;
tl_config_ = NextFrameConfig(0, timestamp_);
- config_updated_ = layers_->UpdateConfiguration(0, &cfg_);
+ cfg_ = layers_->UpdateConfiguration(0);
// Simulate TL1 being at least 8 qp steps better.
if (tl_config_.packetizer_temporal_idx == 0) {
@@ -394,7 +403,7 @@
const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
(kTl1_kbps - kTl0_kbps) * 1000};
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
- EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
+ cfg_ = layers_->UpdateConfiguration(0);
EXPECT_EQ(static_cast<unsigned int>(
ScreenshareLayers::kMaxTL0FpsReduction * kTl0_kbps + 0.5),
@@ -407,7 +416,7 @@
const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
(kTl1_kbps - kTl0_kbps) * 1000};
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
- EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
+ cfg_ = layers_->UpdateConfiguration(0);
EXPECT_EQ(static_cast<unsigned int>(
kTl1_kbps / ScreenshareLayers::kAcceptableTargetOvershoot),
@@ -418,7 +427,7 @@
const int kTl0_kbps = 100;
const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000};
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
- EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
+ cfg_ = layers_->UpdateConfiguration(0);
EXPECT_EQ(static_cast<uint32_t>(kTl0_kbps), cfg_.rc_target_bitrate);
}
@@ -484,7 +493,7 @@
const std::vector<uint32_t> layer_rates = {kLowBitrateKbps * 1000};
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
- layers_->UpdateConfiguration(0, &cfg_);
+ cfg_ = layers_->UpdateConfiguration(0);
EXPECT_EQ(kTl0Flags,
LibvpxVp8Encoder::EncodeFlags(NextFrameConfig(0, kStartTimestamp)));
@@ -527,7 +536,7 @@
}
int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
if (flags != -1)
- layers_->UpdateConfiguration(0, &cfg_);
+ cfg_ = layers_->UpdateConfiguration(0);
if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) {
// Simulate one overshoot.
@@ -592,13 +601,6 @@
kDefaultTl1BitrateKbps));
}
-TEST_F(ScreenshareLayerTest, AllowsUpdateConfigBeforeSetRates) {
- layers_.reset(new ScreenshareLayers(2));
- // New layer instance, OnRatesUpdated() never called.
- // UpdateConfiguration() call should not cause crash.
- layers_->UpdateConfiguration(0, &cfg_);
-}
-
TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
int64_t kTestSpanMs = 2000;
int64_t kFrameIntervalsMs = 1000 / kFrameRate;
@@ -654,7 +656,7 @@
// Simulate overshoot of this frame.
layers_->OnEncodeDone(0, timestamp_, 0, false, 0, nullptr);
- config_updated_ = layers_->UpdateConfiguration(0, &cfg_);
+ cfg_ = layers_->UpdateConfiguration(0);
EXPECT_EQ(kTl1SyncFlags, LibvpxVp8Encoder::EncodeFlags(tl_config_));
CodecSpecificInfo new_info;
@@ -687,7 +689,8 @@
TEST_F(ScreenshareLayerTest, AdjustsBitrateWhenDroppingFrames) {
const uint32_t kTimestampDelta10Fps = kTimestampDelta5Fps / 2;
const int kNumFrames = 30;
- uint32_t default_bitrate = cfg_.rc_target_bitrate;
+ ASSERT_TRUE(cfg_.rc_target_bitrate.has_value());
+ const uint32_t default_bitrate = cfg_.rc_target_bitrate.value();
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, 10);
int num_dropped_frames = 0;
@@ -696,7 +699,7 @@
++num_dropped_frames;
timestamp_ += kTimestampDelta10Fps;
}
- layers_->UpdateConfiguration(0, &cfg_);
+ cfg_ = layers_->UpdateConfiguration(0);
EXPECT_EQ(num_dropped_frames, kNumFrames / 2);
EXPECT_EQ(cfg_.rc_target_bitrate, default_bitrate * 2);
@@ -705,20 +708,20 @@
TEST_F(ScreenshareLayerTest, UpdatesConfigurationAfterRateChange) {
// Set inital rate again, no need to update configuration.
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
- EXPECT_FALSE(layers_->UpdateConfiguration(0, &cfg_));
+ cfg_ = layers_->UpdateConfiguration(0);
// Rate changed, now update config.
std::vector<uint32_t> bitrates = kDefault2TlBitratesBps;
bitrates[1] -= 100000;
layers_->OnRatesUpdated(0, bitrates, 5);
- EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
+ cfg_ = layers_->UpdateConfiguration(0);
// Changed rate, but then set changed rate again before trying to update
// configuration, update should still apply.
bitrates[1] -= 100000;
layers_->OnRatesUpdated(0, bitrates, 5);
layers_->OnRatesUpdated(0, bitrates, 5);
- EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
+ cfg_ = layers_->UpdateConfiguration(0);
}
TEST_F(ScreenshareLayerTest, MaxQpRestoredAfterDoubleDrop) {
@@ -744,7 +747,8 @@
EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
- uint32_t adjusted_qp = cfg_.rc_max_quantizer;
+ ASSERT_TRUE(cfg_.rc_max_quantizer.has_value());
+ const uint32_t adjusted_qp = cfg_.rc_max_quantizer.value();
// Simulate overshoot of this frame.
layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
diff --git a/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc b/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
index eefb743..471fcd0 100644
--- a/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
+++ b/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
@@ -15,6 +15,7 @@
#include <utility>
#include <vector>
+#include "api/video_codecs/vp8_frame_buffer_controller.h"
#include "api/video_codecs/vp8_frame_config.h"
#include "api/video_codecs/vp8_temporal_layers.h"
#include "rtc_base/checks.h"
@@ -39,7 +40,7 @@
public:
MOCK_METHOD2(NextFrameConfig, Vp8FrameConfig(size_t, uint32_t));
MOCK_METHOD3(OnRatesUpdated, void(size_t, const std::vector<uint32_t>&, int));
- MOCK_METHOD2(UpdateConfiguration, bool(size_t, Vp8EncoderConfig*));
+ MOCK_METHOD1(UpdateConfiguration, Vp8EncoderConfig(size_t));
MOCK_METHOD6(OnEncodeDone,
void(size_t, uint32_t, size_t, bool, int, CodecSpecificInfo*));
MOCK_METHOD4(FrameEncoded, void(size_t, uint32_t, size_t, int));
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 491fee1..d935ea0 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -711,9 +711,7 @@
}
// Reset (release existing encoder) if one exists and anything except
- // start bitrate or max framerate has changed. Don't call Release() if
- // |pending_encoder_creation_| as that means this is a new encoder
- // that has not yet been initialized.
+ // start bitrate or max framerate has changed.
const bool reset_required = RequiresEncoderReset(codec, send_codec_);
send_codec_ = codec;