Move EncoderStreamFactory into own file

This cl/ is a NOP refactoring,
moving the EncoderStreamFactory from within webrtc_video_engine.cc
into own file in video/. simulcast.cc is collateral.

Bug: webrtc:14451
Change-Id: Ia69b9241d8cd8a12be6628d887701f2e244c07cc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/276861
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38224}
This commit is contained in:
Jonas Oreland 2022-09-27 16:53:04 +02:00 committed by WebRTC LUCI CQ
parent 2d0ba28e25
commit 1262eb5ebc
25 changed files with 577 additions and 433 deletions

View File

@ -331,6 +331,7 @@ rtc_library("rtc_audio_video") {
"../rtc_base/third_party/base64",
"../system_wrappers",
"../system_wrappers:metrics",
"../video/config:streams_config",
]
absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
@ -344,8 +345,6 @@ rtc_library("rtc_audio_video") {
"engine/null_webrtc_video_engine.h",
"engine/payload_type_mapper.cc",
"engine/payload_type_mapper.h",
"engine/simulcast.cc",
"engine/simulcast.h",
"engine/unhandled_packets_buffer.cc",
"engine/unhandled_packets_buffer.h",
"engine/webrtc_media_engine.cc",
@ -654,6 +653,7 @@ if (rtc_include_tests) {
"../test:test_support",
"../test:video_test_common",
"../test/time_controller",
"../video/config:streams_config",
]
if (enable_libaom) {
@ -683,7 +683,6 @@ if (rtc_include_tests) {
"engine/null_webrtc_video_engine_unittest.cc",
"engine/payload_type_mapper_unittest.cc",
"engine/simulcast_encoder_adapter_unittest.cc",
"engine/simulcast_unittest.cc",
"engine/unhandled_packets_buffer_unittest.cc",
"engine/webrtc_media_engine_unittest.cc",
"engine/webrtc_video_engine_unittest.cc",

View File

@ -22,4 +22,10 @@ specific_include_rules = {
"win32devicemanager\.cc": [
"+third_party/logitech/files/logitechquickcam.h",
],
".*webrtc_video_engine\.h": [
"+video/config",
],
".*webrtc_video_engine_unittest\.cc": [
"+video/config",
],
}

View File

@ -20,7 +20,6 @@
#include "absl/algorithm/container.h"
#include "absl/strings/match.h"
#include "api/media_stream_interface.h"
#include "api/units/data_rate.h"
#include "api/video/video_codec_constants.h"
#include "api/video/video_codec_type.h"
#include "api/video_codecs/sdp_video_format.h"
@ -28,7 +27,6 @@
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "call/call.h"
#include "media/engine/simulcast.h"
#include "media/engine/webrtc_media_engine.h"
#include "media/engine/webrtc_voice_engine.h"
#include "modules/rtp_rtcp/source/rtp_util.h"
@ -37,8 +35,6 @@
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/field_trial_units.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/experiments/normalize_simulcast_size_experiment.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/strings/string_builder.h"
@ -52,25 +48,12 @@ namespace {
using ::webrtc::ParseRtpPayloadType;
using ::webrtc::ParseRtpSsrc;
const int kMinLayerSize = 16;
constexpr int64_t kUnsignaledSsrcCooldownMs = rtc::kNumMillisecsPerSec / 2;
// TODO(bugs.webrtc.org/13166): Remove AV1X when backwards compatibility is not
// needed.
constexpr char kAv1xCodecName[] = "AV1X";
int ScaleDownResolution(int resolution,
double scale_down_by,
int min_resolution) {
// Resolution is never scalied down to smaller than min_resolution.
// If the input resolution is already smaller than min_resolution,
// no scaling should be done at all.
if (resolution <= min_resolution)
return resolution;
return std::max(static_cast<int>(resolution / scale_down_by + 0.5),
min_resolution);
}
const char* StreamTypeToString(
webrtc::VideoSendStream::StreamStats::StreamType type) {
switch (type) {
@ -92,20 +75,6 @@ bool IsDisabled(const webrtc::FieldTrialsView& trials, absl::string_view name) {
return absl::StartsWith(trials.Lookup(name), "Disabled");
}
bool PowerOfTwo(int value) {
return (value > 0) && ((value & (value - 1)) == 0);
}
bool IsScaleFactorsPowerOfTwo(const webrtc::VideoEncoderConfig& config) {
for (const auto& layer : config.simulcast_layers) {
double scale = std::max(layer.scale_resolution_down_by, 1.0);
if (std::round(scale) != scale || !PowerOfTwo(scale)) {
return false;
}
}
return true;
}
void AddDefaultFeedbackParams(VideoCodec* codec,
const webrtc::FieldTrialsView& trials) {
// Don't add any feedback params for RED and ULPFEC.
@ -269,12 +238,6 @@ std::vector<VideoCodec> GetPayloadTypesAndDefaultCodecs(
return output_codecs;
}
bool IsTemporalLayersSupported(const std::string& codec_name) {
return absl::EqualsIgnoreCase(codec_name, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name, kVp9CodecName) ||
absl::EqualsIgnoreCase(codec_name, kAv1CodecName);
}
static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
rtc::StringBuilder out;
out << "{";
@ -356,26 +319,6 @@ bool IsCodecDisabledForSimulcast(const std::string& codec_name,
return false;
}
// The selected thresholds for QVGA and VGA corresponded to a QP around 10.
// The change in QP declined above the selected bitrates.
static int GetMaxDefaultVideoBitrateKbps(int width,
int height,
bool is_screenshare) {
int max_bitrate;
if (width * height <= 320 * 240) {
max_bitrate = 600;
} else if (width * height <= 640 * 480) {
max_bitrate = 1700;
} else if (width * height <= 960 * 540) {
max_bitrate = 2000;
} else {
max_bitrate = 2500;
}
if (is_screenshare)
max_bitrate = std::max(max_bitrate, 1200);
return max_bitrate;
}
// Returns its smallest positive argument. If neither argument is positive,
// returns an arbitrary nonpositive value.
int MinPositive(int a, int b) {
@ -394,17 +337,6 @@ bool IsLayerActive(const webrtc::RtpEncodingParameters& layer) {
(!layer.max_framerate || *layer.max_framerate > 0);
}
size_t FindRequiredActiveLayers(
const webrtc::VideoEncoderConfig& encoder_config) {
// Need enough layers so that at least the first active one is present.
for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
if (encoder_config.simulcast_layers[i].active) {
return i + 1;
}
}
return 0;
}
int NumActiveStreams(const webrtc::RtpParameters& rtp_parameters) {
int res = 0;
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
@ -3636,309 +3568,4 @@ void WebRtcVideoChannel::SetDepacketizerToDecoderFrameTransformer(
}
}
// TODO(bugs.webrtc.org/8785): Consider removing max_qp as member of
// EncoderStreamFactory and instead set this value individually for each stream
// in the VideoEncoderConfig.simulcast_layers.
EncoderStreamFactory::EncoderStreamFactory(
std::string codec_name,
int max_qp,
bool is_screenshare,
bool conference_mode,
const webrtc::FieldTrialsView* trials)
: codec_name_(codec_name),
max_qp_(max_qp),
is_screenshare_(is_screenshare),
conference_mode_(conference_mode),
trials_(trials ? *trials : fallback_trials_) {}
std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config) {
RTC_DCHECK_GT(encoder_config.number_of_streams, 0);
RTC_DCHECK_GE(encoder_config.simulcast_layers.size(),
encoder_config.number_of_streams);
const absl::optional<webrtc::DataRate> experimental_min_bitrate =
GetExperimentalMinVideoBitrate(encoder_config.codec_type);
if (encoder_config.number_of_streams > 1 ||
((absl::EqualsIgnoreCase(codec_name_, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name_, kH264CodecName)) &&
is_screenshare_ && conference_mode_)) {
return CreateSimulcastOrConferenceModeScreenshareStreams(
width, height, encoder_config, experimental_min_bitrate);
}
return CreateDefaultVideoStreams(width, height, encoder_config,
experimental_min_bitrate);
}
std::vector<webrtc::VideoStream>
EncoderStreamFactory::CreateDefaultVideoStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const {
std::vector<webrtc::VideoStream> layers;
// For unset max bitrates set default bitrate for non-simulcast.
int max_bitrate_bps =
(encoder_config.max_bitrate_bps > 0)
? encoder_config.max_bitrate_bps
: GetMaxDefaultVideoBitrateKbps(width, height, is_screenshare_) *
1000;
int min_bitrate_bps =
experimental_min_bitrate
? rtc::saturated_cast<int>(experimental_min_bitrate->bps())
: webrtc::kDefaultMinVideoBitrateBps;
if (encoder_config.simulcast_layers[0].min_bitrate_bps > 0) {
// Use set min bitrate.
min_bitrate_bps = encoder_config.simulcast_layers[0].min_bitrate_bps;
// If only min bitrate is configured, make sure max is above min.
if (encoder_config.max_bitrate_bps <= 0)
max_bitrate_bps = std::max(min_bitrate_bps, max_bitrate_bps);
}
int max_framerate = (encoder_config.simulcast_layers[0].max_framerate > 0)
? encoder_config.simulcast_layers[0].max_framerate
: kDefaultVideoMaxFramerate;
webrtc::VideoStream layer;
layer.width = width;
layer.height = height;
layer.max_framerate = max_framerate;
// Note: VP9 seems to have be sending if any layer is active,
// (see `UpdateSendState`) and still use parameters only from
// encoder_config.simulcast_layers[0].
layer.active = absl::c_any_of(encoder_config.simulcast_layers,
[](const auto& layer) { return layer.active; });
if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) {
layer.width = ScaleDownResolution(
layer.width,
encoder_config.simulcast_layers[0].scale_resolution_down_by,
kMinLayerSize);
layer.height = ScaleDownResolution(
layer.height,
encoder_config.simulcast_layers[0].scale_resolution_down_by,
kMinLayerSize);
}
if (absl::EqualsIgnoreCase(codec_name_, kVp9CodecName)) {
RTC_DCHECK(encoder_config.encoder_specific_settings);
// Use VP9 SVC layering from codec settings which might be initialized
// though field trial in ConfigureVideoEncoderSettings.
webrtc::VideoCodecVP9 vp9_settings;
encoder_config.encoder_specific_settings->FillVideoCodecVp9(&vp9_settings);
layer.num_temporal_layers = vp9_settings.numberOfTemporalLayers;
// Number of spatial layers is signalled differently from different call
// sites (sigh), pick the max as we are interested in the upper bound.
int num_spatial_layers =
std::max({encoder_config.simulcast_layers.size(),
encoder_config.spatial_layers.size(),
size_t{vp9_settings.numberOfSpatialLayers}});
if (width * height > 0 &&
(layer.num_temporal_layers > 1u || num_spatial_layers > 1)) {
// In SVC mode, the VP9 max bitrate is determined by SvcConfig, instead of
// GetMaxDefaultVideoBitrateKbps().
std::vector<webrtc::SpatialLayer> svc_layers =
webrtc::GetSvcConfig(width, height, max_framerate,
/*first_active_layer=*/0, num_spatial_layers,
*layer.num_temporal_layers, is_screenshare_);
int sum_max_bitrates_kbps = 0;
for (const webrtc::SpatialLayer& spatial_layer : svc_layers) {
sum_max_bitrates_kbps += spatial_layer.maxBitrate;
}
RTC_DCHECK_GE(sum_max_bitrates_kbps, 0);
if (encoder_config.max_bitrate_bps <= 0) {
max_bitrate_bps = sum_max_bitrates_kbps * 1000;
} else {
max_bitrate_bps =
std::min(max_bitrate_bps, sum_max_bitrates_kbps * 1000);
}
max_bitrate_bps = std::max(min_bitrate_bps, max_bitrate_bps);
}
}
// 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);
if (encoder_config.simulcast_layers[0].target_bitrate_bps <= 0) {
layer.target_bitrate_bps = max_bitrate_bps;
} else {
layer.target_bitrate_bps = std::min(
encoder_config.simulcast_layers[0].target_bitrate_bps, max_bitrate_bps);
}
layer.max_bitrate_bps = max_bitrate_bps;
layer.max_qp = max_qp_;
layer.bitrate_priority = encoder_config.bitrate_priority;
if (IsTemporalLayersSupported(codec_name_)) {
// Use configured number of temporal layers if set.
if (encoder_config.simulcast_layers[0].num_temporal_layers) {
layer.num_temporal_layers =
*encoder_config.simulcast_layers[0].num_temporal_layers;
}
}
layer.scalability_mode = encoder_config.simulcast_layers[0].scalability_mode;
layers.push_back(layer);
return layers;
}
std::vector<webrtc::VideoStream>
EncoderStreamFactory::CreateSimulcastOrConferenceModeScreenshareStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const {
std::vector<webrtc::VideoStream> layers;
const bool temporal_layers_supported =
absl::EqualsIgnoreCase(codec_name_, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name_, kH264CodecName);
// Use legacy simulcast screenshare if conference mode is explicitly enabled
// or use the regular simulcast configuration path which is generic.
layers = GetSimulcastConfig(FindRequiredActiveLayers(encoder_config),
encoder_config.number_of_streams, width, height,
encoder_config.bitrate_priority, max_qp_,
is_screenshare_ && conference_mode_,
temporal_layers_supported, trials_);
// Allow an experiment to override the minimum bitrate for the lowest
// spatial layer. The experiment's configuration has the lowest priority.
if (experimental_min_bitrate) {
layers[0].min_bitrate_bps =
rtc::saturated_cast<int>(experimental_min_bitrate->bps());
}
// Update the active simulcast layers and configured bitrates.
bool is_highest_layer_max_bitrate_configured = false;
const bool has_scale_resolution_down_by = absl::c_any_of(
encoder_config.simulcast_layers, [](const webrtc::VideoStream& layer) {
return layer.scale_resolution_down_by != -1.;
});
bool default_scale_factors_used = true;
if (has_scale_resolution_down_by) {
default_scale_factors_used = IsScaleFactorsPowerOfTwo(encoder_config);
}
const bool norm_size_configured =
webrtc::NormalizeSimulcastSizeExperiment::GetBase2Exponent().has_value();
const int normalized_width =
(default_scale_factors_used || norm_size_configured) &&
(width >= kMinLayerSize)
? NormalizeSimulcastSize(width, encoder_config.number_of_streams)
: width;
const int normalized_height =
(default_scale_factors_used || norm_size_configured) &&
(height >= kMinLayerSize)
? NormalizeSimulcastSize(height, encoder_config.number_of_streams)
: height;
for (size_t i = 0; i < layers.size(); ++i) {
layers[i].active = encoder_config.simulcast_layers[i].active;
layers[i].scalability_mode =
encoder_config.simulcast_layers[i].scalability_mode;
// Update with configured num temporal layers if supported by codec.
if (encoder_config.simulcast_layers[i].num_temporal_layers &&
IsTemporalLayersSupported(codec_name_)) {
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) {
const double scale_resolution_down_by = std::max(
encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
layers[i].width = ScaleDownResolution(
normalized_width, scale_resolution_down_by, kMinLayerSize);
layers[i].height = ScaleDownResolution(
normalized_height, scale_resolution_down_by, 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 =
encoder_config.simulcast_layers[i].min_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
layers[i].max_bitrate_bps =
encoder_config.simulcast_layers[i].max_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].target_bitrate_bps > 0) {
layers[i].target_bitrate_bps =
encoder_config.simulcast_layers[i].target_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0 &&
encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
// Min and max bitrate are configured.
// Set target to 3/4 of the max bitrate (or to max if below min).
if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0)
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps * 3 / 4;
if (layers[i].target_bitrate_bps < layers[i].min_bitrate_bps)
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps;
} else if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
// Only min bitrate is configured, make sure target/max are above min.
layers[i].target_bitrate_bps =
std::max(layers[i].target_bitrate_bps, layers[i].min_bitrate_bps);
layers[i].max_bitrate_bps =
std::max(layers[i].max_bitrate_bps, layers[i].min_bitrate_bps);
} else if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
// Only max bitrate is configured, make sure min/target are below max.
// Keep target bitrate if it is set explicitly in encoding config.
// Otherwise set target bitrate to 3/4 of the max bitrate
// or the one calculated from GetSimulcastConfig() which is larger.
layers[i].min_bitrate_bps =
std::min(layers[i].min_bitrate_bps, layers[i].max_bitrate_bps);
if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0) {
layers[i].target_bitrate_bps = std::max(
layers[i].target_bitrate_bps, layers[i].max_bitrate_bps * 3 / 4);
}
layers[i].target_bitrate_bps = std::max(
std::min(layers[i].target_bitrate_bps, layers[i].max_bitrate_bps),
layers[i].min_bitrate_bps);
}
if (i == layers.size() - 1) {
is_highest_layer_max_bitrate_configured =
encoder_config.simulcast_layers[i].max_bitrate_bps > 0;
}
}
if (!is_screenshare_ && !is_highest_layer_max_bitrate_configured &&
encoder_config.max_bitrate_bps > 0) {
// No application-configured maximum for the largest layer.
// If there is bitrate leftover, give it to the largest layer.
BoostMaxSimulcastLayer(
webrtc::DataRate::BitsPerSec(encoder_config.max_bitrate_bps), &layers);
}
// Sort the layers by max_bitrate_bps, they might not always be from
// smallest to biggest
std::vector<size_t> index(layers.size());
std::iota(index.begin(), index.end(), 0);
std::stable_sort(index.begin(), index.end(), [&layers](size_t a, size_t b) {
return layers[a].max_bitrate_bps < layers[b].max_bitrate_bps;
});
if (!layers[index[0]].active) {
// Adjust min bitrate of the first active layer to allow it to go as low as
// the lowest (now inactive) layer could.
// Otherwise, if e.g. a single HD stream is active, it would have 600kbps
// min bitrate, which would always be allocated to the stream.
// This would lead to congested network, dropped frames and overall bad
// experience.
const int min_configured_bitrate = layers[index[0]].min_bitrate_bps;
for (size_t i = 0; i < layers.size(); ++i) {
if (layers[index[i]].active) {
layers[index[i]].min_bitrate_bps = min_configured_bitrate;
break;
}
}
}
return layers;
}
} // namespace cricket

View File

@ -37,6 +37,7 @@
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/system/no_unique_address.h"
#include "rtc_base/thread_annotations.h"
#include "video/config/encoder_stream_factory.h"
namespace webrtc {
class VideoDecoderFactory;
@ -683,54 +684,6 @@ class WebRtcVideoChannel : public VideoMediaChannel,
bool allow_codec_switching_ = false;
};
class EncoderStreamFactory
: public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
public:
EncoderStreamFactory(std::string codec_name,
int max_qp,
bool is_screenshare,
bool conference_mode)
: EncoderStreamFactory(codec_name,
max_qp,
is_screenshare,
conference_mode,
nullptr) {}
EncoderStreamFactory(std::string codec_name,
int max_qp,
bool is_screenshare,
bool conference_mode,
const webrtc::FieldTrialsView* trials);
private:
std::vector<webrtc::VideoStream> CreateEncoderStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config) override;
std::vector<webrtc::VideoStream> CreateDefaultVideoStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const;
std::vector<webrtc::VideoStream>
CreateSimulcastOrConferenceModeScreenshareStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const;
const std::string codec_name_;
const int max_qp_;
const bool is_screenshare_;
// Allows a screenshare specific configuration, which enables temporal
// layering and various settings.
const bool conference_mode_;
const webrtc::FieldTrialBasedConfig fallback_trials_;
const webrtc::FieldTrialsView& trials_;
};
} // namespace cricket
#endif // MEDIA_ENGINE_WEBRTC_VIDEO_ENGINE_H_

View File

@ -51,7 +51,6 @@
#include "media/base/test_utils.h"
#include "media/engine/fake_webrtc_call.h"
#include "media/engine/fake_webrtc_video_engine.h"
#include "media/engine/simulcast.h"
#include "media/engine/webrtc_voice_engine.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
#include "rtc_base/arraysize.h"
@ -66,6 +65,7 @@
#include "test/gmock.h"
#include "test/scoped_key_value_config.h"
#include "test/time_controller/simulated_time_controller.h"
#include "video/config/simulcast.h"
using ::testing::_;
using ::testing::Contains;

View File

@ -989,6 +989,7 @@ if (rtc_include_tests) {
"../../test:test_support",
"../../test:video_test_common",
"../../test:video_test_support",
"../../video/config:streams_config",
]
absl_deps = [
"//third_party/abseil-cpp/absl/strings:strings",

View File

@ -19,5 +19,6 @@ specific_include_rules = {
".*test.*\.cc": [
"+media/base",
"+media/engine",
"+video/config",
],
}

View File

@ -46,7 +46,6 @@
#include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h"
#include "common_video/h264/h264_common.h"
#include "media/base/media_constants.h"
#include "media/engine/simulcast.h"
#include "modules/video_coding/codecs/h264/include/h264_globals.h"
#include "modules/video_coding/codecs/vp9/svc_config.h"
#include "modules/video_coding/utility/ivf_file_writer.h"
@ -61,6 +60,7 @@
#include "test/testsupport/file_utils.h"
#include "test/testsupport/frame_writer.h"
#include "test/video_codec_settings.h"
#include "video/config/simulcast.h"
namespace webrtc {
namespace test {

View File

@ -218,6 +218,7 @@ if (!is_component_build) {
"../test:fileutils",
"../test:rtp_test_utils",
"../test:video_test_common",
"../video/config:streams_config",
"//third_party/abseil-cpp/absl/flags:flag",
"//third_party/abseil-cpp/absl/flags:parse",
"//third_party/abseil-cpp/absl/flags:usage",

View File

@ -17,6 +17,7 @@ include_rules = [
"+system_wrappers",
"+p2p",
"+third_party/libyuv",
"+video/config",
]
specific_include_rules = {

View File

@ -25,6 +25,7 @@
#include "rtc_base/system/file_wrapper.h"
#include "rtc_base/thread.h"
#include "test/testsupport/file_utils.h"
#include "video/config/encoder_stream_factory.h"
namespace webrtc {
namespace {

View File

@ -22,6 +22,7 @@ include_rules = [
"+sdk",
"+system_wrappers",
"+third_party/libyuv",
"+video/config",
]
specific_include_rules = {

View File

@ -142,7 +142,7 @@ if (rtc_include_tests && !build_with_chromium) {
"../../rtc_base/task_utils:repeating_task",
"../../system_wrappers",
"../../system_wrappers:field_trial",
"../../video",
"../../video/config:streams_config",
"../logging:log_writer",
"../network:emulated_network",
"../time_controller",

View File

@ -27,6 +27,7 @@
#include "test/fake_encoder.h"
#include "test/scenario/hardware_codecs.h"
#include "test/testsupport/file_utils.h"
#include "video/config/encoder_stream_factory.h"
namespace webrtc {
namespace test {

View File

@ -71,6 +71,8 @@ rtc_library("video") {
"../api/crypto:options",
"../api/task_queue",
"../api/task_queue:pending_task_safety_flag",
"../api/transport:field_trial_based_config",
"../api/units:data_rate",
"../api/units:frequency",
"../api/units:time_delta",
"../api/units:timestamp",
@ -102,6 +104,7 @@ rtc_library("video") {
"../modules/video_coding:packet_buffer",
"../modules/video_coding:video_codec_interface",
"../modules/video_coding:video_coding_utility",
"../modules/video_coding:webrtc_vp9_helpers",
"../modules/video_coding/timing:timing_module",
"../rtc_base:checks",
"../rtc_base:event_tracer",
@ -125,6 +128,7 @@ rtc_library("video") {
"../rtc_base/experiments:field_trial_parser",
"../rtc_base/experiments:keyframe_interval_settings_experiment",
"../rtc_base/experiments:min_video_bitrate_experiment",
"../rtc_base/experiments:normalize_simulcast_size_experiment",
"../rtc_base/experiments:rate_control_settings",
"../rtc_base/synchronization:mutex",
"../rtc_base/system:no_unique_address",
@ -530,6 +534,7 @@ if (rtc_include_tests) {
"../test:test_support_test_artifacts",
"../test:video_test_common",
"../test:video_test_support",
"config:streams_config",
]
absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
@ -799,6 +804,7 @@ if (rtc_include_tests) {
"../api/test/metrics:global_metrics_logger_and_exporter",
"../api/test/metrics:metric",
"../api/test/video:function_video_factory",
"../api/transport:field_trial_based_config",
"../api/units:data_rate",
"../api/units:frequency",
"../api/units:time_delta",
@ -899,6 +905,7 @@ if (rtc_include_tests) {
"../test:video_test_common",
"../test/time_controller",
"adaptation:video_adaptation",
"config:streams_config",
]
absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",

68
video/config/BUILD.gn Normal file
View File

@ -0,0 +1,68 @@
# Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("../../webrtc.gni")
rtc_library("streams_config") {
sources = [
"encoder_stream_factory.cc",
"encoder_stream_factory.h",
"simulcast.cc",
"simulcast.h",
]
deps = [
"../../api:field_trials_view",
"../../api/transport:field_trial_based_config",
"../../api/units:data_rate",
"../../api/video:video_codec_constants",
"../../api/video_codecs:video_codecs_api",
"../../media:rtc_media_base",
"../../modules/video_coding:video_coding_utility",
"../../modules/video_coding:webrtc_vp9_helpers",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../rtc_base/experiments:field_trial_parser",
"../../rtc_base/experiments:min_video_bitrate_experiment",
"../../rtc_base/experiments:normalize_simulcast_size_experiment",
"../../rtc_base/experiments:rate_control_settings",
]
absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
}
if (rtc_include_tests) {
rtc_library("video_config_tests") {
testonly = true
defines = []
sources = [ "simulcast_unittest.cc" ]
deps = [
":streams_config",
"../../api/transport:field_trial_based_config",
"../../test:field_trial",
"../../test:test_support",
]
absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/functional:any_invocable",
"//third_party/abseil-cpp/absl/functional:bind_front",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
"//third_party/abseil-cpp/absl/types:variant",
]
if (!build_with_mozilla) {
deps += [ "../../media:rtc_media_base" ]
}
}
}

View File

@ -0,0 +1,401 @@
/*
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "video/config/encoder_stream_factory.h"
#include <algorithm>
#include <set>
#include <string>
#include <utility>
#include "absl/algorithm/container.h"
#include "absl/strings/match.h"
#include "api/video/video_codec_constants.h"
#include "media/base/media_constants.h"
#include "modules/video_coding/codecs/vp9/svc_config.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/experiments/normalize_simulcast_size_experiment.h"
#include "video/config/simulcast.h"
namespace cricket {
namespace {
const int kMinLayerSize = 16;
int ScaleDownResolution(int resolution,
double scale_down_by,
int min_resolution) {
// Resolution is never scalied down to smaller than min_resolution.
// If the input resolution is already smaller than min_resolution,
// no scaling should be done at all.
if (resolution <= min_resolution)
return resolution;
return std::max(static_cast<int>(resolution / scale_down_by + 0.5),
min_resolution);
}
bool PowerOfTwo(int value) {
return (value > 0) && ((value & (value - 1)) == 0);
}
bool IsScaleFactorsPowerOfTwo(const webrtc::VideoEncoderConfig& config) {
for (const auto& layer : config.simulcast_layers) {
double scale = std::max(layer.scale_resolution_down_by, 1.0);
if (std::round(scale) != scale || !PowerOfTwo(scale)) {
return false;
}
}
return true;
}
bool IsTemporalLayersSupported(const std::string& codec_name) {
return absl::EqualsIgnoreCase(codec_name, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name, kVp9CodecName) ||
absl::EqualsIgnoreCase(codec_name, kAv1CodecName);
}
size_t FindRequiredActiveLayers(
const webrtc::VideoEncoderConfig& encoder_config) {
// Need enough layers so that at least the first active one is present.
for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
if (encoder_config.simulcast_layers[i].active) {
return i + 1;
}
}
return 0;
}
// The selected thresholds for QVGA and VGA corresponded to a QP around 10.
// The change in QP declined above the selected bitrates.
static int GetMaxDefaultVideoBitrateKbps(int width,
int height,
bool is_screenshare) {
int max_bitrate;
if (width * height <= 320 * 240) {
max_bitrate = 600;
} else if (width * height <= 640 * 480) {
max_bitrate = 1700;
} else if (width * height <= 960 * 540) {
max_bitrate = 2000;
} else {
max_bitrate = 2500;
}
if (is_screenshare)
max_bitrate = std::max(max_bitrate, 1200);
return max_bitrate;
}
} // namespace
// TODO(bugs.webrtc.org/8785): Consider removing max_qp as member of
// EncoderStreamFactory and instead set this value individually for each stream
// in the VideoEncoderConfig.simulcast_layers.
EncoderStreamFactory::EncoderStreamFactory(
std::string codec_name,
int max_qp,
bool is_screenshare,
bool conference_mode,
const webrtc::FieldTrialsView* trials)
: codec_name_(codec_name),
max_qp_(max_qp),
is_screenshare_(is_screenshare),
conference_mode_(conference_mode),
trials_(trials ? *trials : fallback_trials_) {}
std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config) {
RTC_DCHECK_GT(encoder_config.number_of_streams, 0);
RTC_DCHECK_GE(encoder_config.simulcast_layers.size(),
encoder_config.number_of_streams);
const absl::optional<webrtc::DataRate> experimental_min_bitrate =
GetExperimentalMinVideoBitrate(encoder_config.codec_type);
if (encoder_config.number_of_streams > 1 ||
((absl::EqualsIgnoreCase(codec_name_, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name_, kH264CodecName)) &&
is_screenshare_ && conference_mode_)) {
return CreateSimulcastOrConferenceModeScreenshareStreams(
width, height, encoder_config, experimental_min_bitrate);
}
return CreateDefaultVideoStreams(width, height, encoder_config,
experimental_min_bitrate);
}
std::vector<webrtc::VideoStream>
EncoderStreamFactory::CreateDefaultVideoStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const {
std::vector<webrtc::VideoStream> layers;
// For unset max bitrates set default bitrate for non-simulcast.
int max_bitrate_bps =
(encoder_config.max_bitrate_bps > 0)
? encoder_config.max_bitrate_bps
: GetMaxDefaultVideoBitrateKbps(width, height, is_screenshare_) *
1000;
int min_bitrate_bps =
experimental_min_bitrate
? rtc::saturated_cast<int>(experimental_min_bitrate->bps())
: webrtc::kDefaultMinVideoBitrateBps;
if (encoder_config.simulcast_layers[0].min_bitrate_bps > 0) {
// Use set min bitrate.
min_bitrate_bps = encoder_config.simulcast_layers[0].min_bitrate_bps;
// If only min bitrate is configured, make sure max is above min.
if (encoder_config.max_bitrate_bps <= 0)
max_bitrate_bps = std::max(min_bitrate_bps, max_bitrate_bps);
}
int max_framerate = (encoder_config.simulcast_layers[0].max_framerate > 0)
? encoder_config.simulcast_layers[0].max_framerate
: kDefaultVideoMaxFramerate;
webrtc::VideoStream layer;
layer.width = width;
layer.height = height;
layer.max_framerate = max_framerate;
// Note: VP9 seems to have be sending if any layer is active,
// (see `UpdateSendState`) and still use parameters only from
// encoder_config.simulcast_layers[0].
layer.active = absl::c_any_of(encoder_config.simulcast_layers,
[](const auto& layer) { return layer.active; });
if (encoder_config.simulcast_layers[0].scale_resolution_down_by > 1.) {
layer.width = ScaleDownResolution(
layer.width,
encoder_config.simulcast_layers[0].scale_resolution_down_by,
kMinLayerSize);
layer.height = ScaleDownResolution(
layer.height,
encoder_config.simulcast_layers[0].scale_resolution_down_by,
kMinLayerSize);
}
if (absl::EqualsIgnoreCase(codec_name_, kVp9CodecName)) {
RTC_DCHECK(encoder_config.encoder_specific_settings);
// Use VP9 SVC layering from codec settings which might be initialized
// though field trial in ConfigureVideoEncoderSettings.
webrtc::VideoCodecVP9 vp9_settings;
encoder_config.encoder_specific_settings->FillVideoCodecVp9(&vp9_settings);
layer.num_temporal_layers = vp9_settings.numberOfTemporalLayers;
// Number of spatial layers is signalled differently from different call
// sites (sigh), pick the max as we are interested in the upper bound.
int num_spatial_layers =
std::max({encoder_config.simulcast_layers.size(),
encoder_config.spatial_layers.size(),
size_t{vp9_settings.numberOfSpatialLayers}});
if (width * height > 0 &&
(layer.num_temporal_layers > 1u || num_spatial_layers > 1)) {
// In SVC mode, the VP9 max bitrate is determined by SvcConfig, instead of
// GetMaxDefaultVideoBitrateKbps().
std::vector<webrtc::SpatialLayer> svc_layers =
webrtc::GetSvcConfig(width, height, max_framerate,
/*first_active_layer=*/0, num_spatial_layers,
*layer.num_temporal_layers, is_screenshare_);
int sum_max_bitrates_kbps = 0;
for (const webrtc::SpatialLayer& spatial_layer : svc_layers) {
sum_max_bitrates_kbps += spatial_layer.maxBitrate;
}
RTC_DCHECK_GE(sum_max_bitrates_kbps, 0);
if (encoder_config.max_bitrate_bps <= 0) {
max_bitrate_bps = sum_max_bitrates_kbps * 1000;
} else {
max_bitrate_bps =
std::min(max_bitrate_bps, sum_max_bitrates_kbps * 1000);
}
max_bitrate_bps = std::max(min_bitrate_bps, max_bitrate_bps);
}
}
// 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);
if (encoder_config.simulcast_layers[0].target_bitrate_bps <= 0) {
layer.target_bitrate_bps = max_bitrate_bps;
} else {
layer.target_bitrate_bps = std::min(
encoder_config.simulcast_layers[0].target_bitrate_bps, max_bitrate_bps);
}
layer.max_bitrate_bps = max_bitrate_bps;
layer.max_qp = max_qp_;
layer.bitrate_priority = encoder_config.bitrate_priority;
if (IsTemporalLayersSupported(codec_name_)) {
// Use configured number of temporal layers if set.
if (encoder_config.simulcast_layers[0].num_temporal_layers) {
layer.num_temporal_layers =
*encoder_config.simulcast_layers[0].num_temporal_layers;
}
}
layer.scalability_mode = encoder_config.simulcast_layers[0].scalability_mode;
layers.push_back(layer);
return layers;
}
std::vector<webrtc::VideoStream>
EncoderStreamFactory::CreateSimulcastOrConferenceModeScreenshareStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const {
std::vector<webrtc::VideoStream> layers;
const bool temporal_layers_supported =
absl::EqualsIgnoreCase(codec_name_, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name_, kH264CodecName);
// Use legacy simulcast screenshare if conference mode is explicitly enabled
// or use the regular simulcast configuration path which is generic.
layers = GetSimulcastConfig(FindRequiredActiveLayers(encoder_config),
encoder_config.number_of_streams, width, height,
encoder_config.bitrate_priority, max_qp_,
is_screenshare_ && conference_mode_,
temporal_layers_supported, trials_);
// Allow an experiment to override the minimum bitrate for the lowest
// spatial layer. The experiment's configuration has the lowest priority.
if (experimental_min_bitrate) {
layers[0].min_bitrate_bps =
rtc::saturated_cast<int>(experimental_min_bitrate->bps());
}
// Update the active simulcast layers and configured bitrates.
bool is_highest_layer_max_bitrate_configured = false;
const bool has_scale_resolution_down_by = absl::c_any_of(
encoder_config.simulcast_layers, [](const webrtc::VideoStream& layer) {
return layer.scale_resolution_down_by != -1.;
});
bool default_scale_factors_used = true;
if (has_scale_resolution_down_by) {
default_scale_factors_used = IsScaleFactorsPowerOfTwo(encoder_config);
}
const bool norm_size_configured =
webrtc::NormalizeSimulcastSizeExperiment::GetBase2Exponent().has_value();
const int normalized_width =
(default_scale_factors_used || norm_size_configured) &&
(width >= kMinLayerSize)
? NormalizeSimulcastSize(width, encoder_config.number_of_streams)
: width;
const int normalized_height =
(default_scale_factors_used || norm_size_configured) &&
(height >= kMinLayerSize)
? NormalizeSimulcastSize(height, encoder_config.number_of_streams)
: height;
for (size_t i = 0; i < layers.size(); ++i) {
layers[i].active = encoder_config.simulcast_layers[i].active;
layers[i].scalability_mode =
encoder_config.simulcast_layers[i].scalability_mode;
// Update with configured num temporal layers if supported by codec.
if (encoder_config.simulcast_layers[i].num_temporal_layers &&
IsTemporalLayersSupported(codec_name_)) {
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) {
const double scale_resolution_down_by = std::max(
encoder_config.simulcast_layers[i].scale_resolution_down_by, 1.0);
layers[i].width = ScaleDownResolution(
normalized_width, scale_resolution_down_by, kMinLayerSize);
layers[i].height = ScaleDownResolution(
normalized_height, scale_resolution_down_by, 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 =
encoder_config.simulcast_layers[i].min_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
layers[i].max_bitrate_bps =
encoder_config.simulcast_layers[i].max_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].target_bitrate_bps > 0) {
layers[i].target_bitrate_bps =
encoder_config.simulcast_layers[i].target_bitrate_bps;
}
if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0 &&
encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
// Min and max bitrate are configured.
// Set target to 3/4 of the max bitrate (or to max if below min).
if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0)
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps * 3 / 4;
if (layers[i].target_bitrate_bps < layers[i].min_bitrate_bps)
layers[i].target_bitrate_bps = layers[i].max_bitrate_bps;
} else if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
// Only min bitrate is configured, make sure target/max are above min.
layers[i].target_bitrate_bps =
std::max(layers[i].target_bitrate_bps, layers[i].min_bitrate_bps);
layers[i].max_bitrate_bps =
std::max(layers[i].max_bitrate_bps, layers[i].min_bitrate_bps);
} else if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
// Only max bitrate is configured, make sure min/target are below max.
// Keep target bitrate if it is set explicitly in encoding config.
// Otherwise set target bitrate to 3/4 of the max bitrate
// or the one calculated from GetSimulcastConfig() which is larger.
layers[i].min_bitrate_bps =
std::min(layers[i].min_bitrate_bps, layers[i].max_bitrate_bps);
if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0) {
layers[i].target_bitrate_bps = std::max(
layers[i].target_bitrate_bps, layers[i].max_bitrate_bps * 3 / 4);
}
layers[i].target_bitrate_bps = std::max(
std::min(layers[i].target_bitrate_bps, layers[i].max_bitrate_bps),
layers[i].min_bitrate_bps);
}
if (i == layers.size() - 1) {
is_highest_layer_max_bitrate_configured =
encoder_config.simulcast_layers[i].max_bitrate_bps > 0;
}
}
if (!is_screenshare_ && !is_highest_layer_max_bitrate_configured &&
encoder_config.max_bitrate_bps > 0) {
// No application-configured maximum for the largest layer.
// If there is bitrate leftover, give it to the largest layer.
BoostMaxSimulcastLayer(
webrtc::DataRate::BitsPerSec(encoder_config.max_bitrate_bps), &layers);
}
// Sort the layers by max_bitrate_bps, they might not always be from
// smallest to biggest
std::vector<size_t> index(layers.size());
std::iota(index.begin(), index.end(), 0);
std::stable_sort(index.begin(), index.end(), [&layers](size_t a, size_t b) {
return layers[a].max_bitrate_bps < layers[b].max_bitrate_bps;
});
if (!layers[index[0]].active) {
// Adjust min bitrate of the first active layer to allow it to go as low as
// the lowest (now inactive) layer could.
// Otherwise, if e.g. a single HD stream is active, it would have 600kbps
// min bitrate, which would always be allocated to the stream.
// This would lead to congested network, dropped frames and overall bad
// experience.
const int min_configured_bitrate = layers[index[0]].min_bitrate_bps;
for (size_t i = 0; i < layers.size(); ++i) {
if (layers[index[i]].active) {
layers[index[i]].min_bitrate_bps = min_configured_bitrate;
break;
}
}
}
return layers;
}
} // namespace cricket

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VIDEO_CONFIG_ENCODER_STREAM_FACTORY_H_
#define VIDEO_CONFIG_ENCODER_STREAM_FACTORY_H_
#include <string>
#include <vector>
#include "api/transport/field_trial_based_config.h"
#include "api/units/data_rate.h"
#include "api/video_codecs/video_encoder_config.h"
namespace cricket {
class EncoderStreamFactory
: public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface {
public:
EncoderStreamFactory(std::string codec_name,
int max_qp,
bool is_screenshare,
bool conference_mode)
: EncoderStreamFactory(codec_name,
max_qp,
is_screenshare,
conference_mode,
nullptr) {}
EncoderStreamFactory(std::string codec_name,
int max_qp,
bool is_screenshare,
bool conference_mode,
const webrtc::FieldTrialsView* trials);
private:
std::vector<webrtc::VideoStream> CreateEncoderStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config) override;
std::vector<webrtc::VideoStream> CreateDefaultVideoStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const;
std::vector<webrtc::VideoStream>
CreateSimulcastOrConferenceModeScreenshareStreams(
int width,
int height,
const webrtc::VideoEncoderConfig& encoder_config,
const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const;
const std::string codec_name_;
const int max_qp_;
const bool is_screenshare_;
// Allows a screenshare specific configuration, which enables temporal
// layering and various settings.
const bool conference_mode_;
const webrtc::FieldTrialBasedConfig fallback_trials_;
const webrtc::FieldTrialsView& trials_;
};
} // namespace cricket
#endif // VIDEO_CONFIG_ENCODER_STREAM_FACTORY_H_

View File

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "media/engine/simulcast.h"
#include "video/config/simulcast.h"
#include <stdint.h>
#include <stdio.h>

View File

@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MEDIA_ENGINE_SIMULCAST_H_
#define MEDIA_ENGINE_SIMULCAST_H_
#ifndef VIDEO_CONFIG_SIMULCAST_H_
#define VIDEO_CONFIG_SIMULCAST_H_
#include <stddef.h>
@ -69,4 +69,4 @@ std::vector<webrtc::VideoStream> GetScreenshareLayers(
} // namespace cricket
#endif // MEDIA_ENGINE_SIMULCAST_H_
#endif // VIDEO_CONFIG_SIMULCAST_H_

View File

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "media/engine/simulcast.h"
#include "video/config/simulcast.h"
#include "api/transport/field_trial_based_config.h"
#include "media/base/media_constants.h"

View File

@ -18,6 +18,7 @@
#include "test/field_trial.h"
#include "test/gtest.h"
#include "test/video_encoder_proxy_factory.h"
#include "video/config/encoder_stream_factory.h"
namespace webrtc {
namespace test {

View File

@ -54,6 +54,7 @@
#ifdef WEBRTC_WIN
#include "modules/audio_device/include/audio_device_factory.h"
#endif
#include "video/config/encoder_stream_factory.h"
namespace webrtc {

View File

@ -69,6 +69,7 @@
#include "test/null_transport.h"
#include "test/rtcp_packet_parser.h"
#include "test/video_encoder_proxy_factory.h"
#include "video/config/encoder_stream_factory.h"
#include "video/send_statistics_proxy.h"
#include "video/transport_adapter.h"
#include "video/video_send_stream.h"

View File

@ -1,3 +1,4 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
@ -7,7 +8,6 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "video/video_stream_encoder.h"
#include <algorithm>
@ -70,6 +70,7 @@
#include "test/time_controller/simulated_time_controller.h"
#include "test/video_encoder_nullable_proxy_factory.h"
#include "test/video_encoder_proxy_factory.h"
#include "video/config/encoder_stream_factory.h"
#include "video/frame_cadence_adapter.h"
#include "video/send_statistics_proxy.h"