Bug 1924098 - Vendor libwebrtc from 26146bbce0

Upstream commit: https://webrtc.googlesource.com/src/+/26146bbce01c4ea67e6f1569defa3863f5867d7a
    Add support for screencast with temporal layering to SvcRateAllocator

    SvcRateAllocator assumed no temporal layering for screencast content and allocated all bitrate to base temporal layer. Now it distributes bitrate to spatial and temporal layers (if configured) no matter of content type.

    Bug: webrtc:351644568, b/364190191
    Change-Id: I445f0157d2c14cad033648693dc0564ae97023e9
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/362080
    Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
    Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#42979}
This commit is contained in:
Michael Froman 2024-10-15 18:22:34 -05:00
parent 6ae07b9942
commit 32451c7bab
6 changed files with 165 additions and 91 deletions

View File

@ -32724,3 +32724,6 @@ c9aaf11985
# MOZ_LIBWEBRTC_SRC=/home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh # MOZ_LIBWEBRTC_SRC=/home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
# base of lastest vendoring # base of lastest vendoring
405f343099 405f343099
# MOZ_LIBWEBRTC_SRC=/home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
# base of lastest vendoring
26146bbce0

View File

@ -21840,3 +21840,5 @@ libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-15T23:17:14.271773. libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-15T23:17:14.271773.
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-15T23:21:29.177608. libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-15T23:21:29.177608.
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-15T23:22:24.165846.

View File

@ -134,6 +134,8 @@ if (rtc_include_tests) {
deps = [ deps = [
":svc_rate_allocator", ":svc_rate_allocator",
"..:webrtc_vp9_helpers", "..:webrtc_vp9_helpers",
"../../../api/video:video_frame",
"../../../modules/video_coding/codecs/av1:av1_svc_config",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../test:field_trial", "../../../test:field_trial",
"../../../test:test_support", "../../../test:test_support",

View File

@ -117,6 +117,46 @@ static std::vector<DataRate> SplitBitrate(size_t num_layers,
return bitrates; return bitrates;
} }
VideoBitrateAllocation DistributeAllocationToTemporalLayers(
std::vector<DataRate> spatial_layer_birates,
size_t first_active_layer,
size_t num_temporal_layers) {
// Distribute rate across temporal layers. Allocate more bits to lower
// layers since they are used for prediction of higher layers and their
// references are far apart.
VideoBitrateAllocation bitrate_allocation;
for (size_t sl_idx = 0; sl_idx < spatial_layer_birates.size(); ++sl_idx) {
std::vector<DataRate> temporal_layer_bitrates =
SplitBitrate(num_temporal_layers, spatial_layer_birates[sl_idx],
kTemporalLayeringRateScalingFactor);
if (num_temporal_layers == 1) {
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
temporal_layer_bitrates[0].bps());
} else if (num_temporal_layers == 2) {
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
temporal_layer_bitrates[1].bps());
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
temporal_layer_bitrates[0].bps());
} else {
RTC_CHECK_EQ(num_temporal_layers, 3);
// In case of three temporal layers the high layer has two frames and the
// middle layer has one frame within GOP (in between two consecutive low
// layer frames). Thus high layer requires more bits (comparing pure
// bitrate of layer, excluding bitrate of base layers) to keep quality on
// par with lower layers.
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
temporal_layer_bitrates[2].bps());
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
temporal_layer_bitrates[0].bps());
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 2,
temporal_layer_bitrates[1].bps());
}
}
return bitrate_allocation;
}
// Returns the minimum bitrate needed for `num_active_layers` spatial layers to // Returns the minimum bitrate needed for `num_active_layers` spatial layers to
// become active using the configuration specified by `codec`. // become active using the configuration specified by `codec`.
DataRate FindLayerTogglingThreshold(const VideoCodec& codec, DataRate FindLayerTogglingThreshold(const VideoCodec& codec,
@ -269,19 +309,24 @@ VideoBitrateAllocation SvcRateAllocator::Allocate(
} }
last_active_layer_count_ = num_spatial_layers; last_active_layer_count_ = num_spatial_layers;
VideoBitrateAllocation allocation; std::vector<DataRate> spatial_layer_bitrates;
if (codec_.mode == VideoCodecMode::kRealtimeVideo) { if (codec_.mode == VideoCodecMode::kRealtimeVideo) {
allocation = GetAllocationNormalVideo(total_bitrate, active_layers.first, spatial_layer_bitrates = DistributeAllocationToSpatialLayersNormalVideo(
num_spatial_layers); total_bitrate, active_layers.first, num_spatial_layers);
} else { } else {
allocation = GetAllocationScreenSharing(total_bitrate, active_layers.first, spatial_layer_bitrates = DistributeAllocationToSpatialLayersScreenSharing(
num_spatial_layers); total_bitrate, active_layers.first, num_spatial_layers);
} }
VideoBitrateAllocation allocation = DistributeAllocationToTemporalLayers(
spatial_layer_bitrates, active_layers.first, num_layers_.temporal);
allocation.set_bw_limited(num_spatial_layers < active_layers.num); allocation.set_bw_limited(num_spatial_layers < active_layers.num);
return allocation; return allocation;
} }
VideoBitrateAllocation SvcRateAllocator::GetAllocationNormalVideo( std::vector<DataRate>
SvcRateAllocator::DistributeAllocationToSpatialLayersNormalVideo(
DataRate total_bitrate, DataRate total_bitrate,
size_t first_active_layer, size_t first_active_layer,
size_t num_spatial_layers) const { size_t num_spatial_layers) const {
@ -291,67 +336,33 @@ VideoBitrateAllocation SvcRateAllocator::GetAllocationNormalVideo(
// bitrate anyway. // bitrate anyway.
num_spatial_layers = 1; num_spatial_layers = 1;
spatial_layer_rates.push_back(total_bitrate); spatial_layer_rates.push_back(total_bitrate);
} else { return spatial_layer_rates;
spatial_layer_rates =
AdjustAndVerify(codec_, first_active_layer,
SplitBitrate(num_spatial_layers, total_bitrate,
kSpatialLayeringRateScalingFactor));
RTC_DCHECK_EQ(spatial_layer_rates.size(), num_spatial_layers);
} }
VideoBitrateAllocation bitrate_allocation; spatial_layer_rates =
AdjustAndVerify(codec_, first_active_layer,
for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) { SplitBitrate(num_spatial_layers, total_bitrate,
std::vector<DataRate> temporal_layer_rates = kSpatialLayeringRateScalingFactor));
SplitBitrate(num_layers_.temporal, spatial_layer_rates[sl_idx], RTC_DCHECK_EQ(spatial_layer_rates.size(), num_spatial_layers);
kTemporalLayeringRateScalingFactor); return spatial_layer_rates;
// Distribute rate across temporal layers. Allocate more bits to lower
// layers since they are used for prediction of higher layers and their
// references are far apart.
if (num_layers_.temporal == 1) {
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
temporal_layer_rates[0].bps());
} else if (num_layers_.temporal == 2) {
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
temporal_layer_rates[1].bps());
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
temporal_layer_rates[0].bps());
} else {
RTC_CHECK_EQ(num_layers_.temporal, 3);
// In case of three temporal layers the high layer has two frames and the
// middle layer has one frame within GOP (in between two consecutive low
// layer frames). Thus high layer requires more bits (comparing pure
// bitrate of layer, excluding bitrate of base layers) to keep quality on
// par with lower layers.
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
temporal_layer_rates[2].bps());
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
temporal_layer_rates[0].bps());
bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 2,
temporal_layer_rates[1].bps());
}
}
return bitrate_allocation;
} }
// Bit-rate is allocated in such a way, that the highest enabled layer will have // Bit-rate is allocated in such a way, that the highest enabled layer will have
// between min and max bitrate, and all others will have exactly target // between min and max bitrate, and all others will have exactly target
// bit-rate allocated. // bit-rate allocated.
VideoBitrateAllocation SvcRateAllocator::GetAllocationScreenSharing( std::vector<DataRate>
SvcRateAllocator::DistributeAllocationToSpatialLayersScreenSharing(
DataRate total_bitrate, DataRate total_bitrate,
size_t first_active_layer, size_t first_active_layer,
size_t num_spatial_layers) const { size_t num_spatial_layers) const {
VideoBitrateAllocation bitrate_allocation; std::vector<DataRate> spatial_layer_rates;
if (num_spatial_layers == 0 || if (num_spatial_layers == 0 ||
total_bitrate < total_bitrate <
DataRate::KilobitsPerSec( DataRate::KilobitsPerSec(
codec_.spatialLayers[first_active_layer].minBitrate)) { codec_.spatialLayers[first_active_layer].minBitrate)) {
// Always enable at least one layer. // Always enable at least one layer.
bitrate_allocation.SetBitrate(first_active_layer, 0, total_bitrate.bps()); spatial_layer_rates.push_back(total_bitrate);
return bitrate_allocation; return spatial_layer_rates;
} }
DataRate allocated_rate = DataRate::Zero(); DataRate allocated_rate = DataRate::Zero();
@ -370,7 +381,7 @@ VideoBitrateAllocation SvcRateAllocator::GetAllocationScreenSharing(
} }
top_layer_rate = std::min(target_rate, total_bitrate - allocated_rate); top_layer_rate = std::min(target_rate, total_bitrate - allocated_rate);
bitrate_allocation.SetBitrate(sl_idx, 0, top_layer_rate.bps()); spatial_layer_rates.push_back(top_layer_rate);
allocated_rate += top_layer_rate; allocated_rate += top_layer_rate;
} }
@ -379,10 +390,10 @@ VideoBitrateAllocation SvcRateAllocator::GetAllocationScreenSharing(
top_layer_rate = std::min( top_layer_rate = std::min(
top_layer_rate + (total_bitrate - allocated_rate), top_layer_rate + (total_bitrate - allocated_rate),
DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx - 1].maxBitrate)); DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx - 1].maxBitrate));
bitrate_allocation.SetBitrate(sl_idx - 1, 0, top_layer_rate.bps()); spatial_layer_rates.back() = top_layer_rate;
} }
return bitrate_allocation; return spatial_layer_rates;
} }
size_t SvcRateAllocator::FindNumEnabledLayers(DataRate target_rate) const { size_t SvcRateAllocator::FindNumEnabledLayers(DataRate target_rate) const {

View File

@ -14,6 +14,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <vector>
#include "absl/container/inlined_vector.h" #include "absl/container/inlined_vector.h"
#include "api/video/video_bitrate_allocation.h" #include "api/video/video_bitrate_allocation.h"
#include "api/video/video_bitrate_allocator.h" #include "api/video/video_bitrate_allocator.h"
@ -42,12 +44,12 @@ class SvcRateAllocator : public VideoBitrateAllocator {
}; };
static NumLayers GetNumLayers(const VideoCodec& codec); static NumLayers GetNumLayers(const VideoCodec& codec);
VideoBitrateAllocation GetAllocationNormalVideo( std::vector<DataRate> DistributeAllocationToSpatialLayersNormalVideo(
DataRate total_bitrate, DataRate total_bitrate,
size_t first_active_layer, size_t first_active_layer,
size_t num_spatial_layers) const; size_t num_spatial_layers) const;
VideoBitrateAllocation GetAllocationScreenSharing( std::vector<DataRate> DistributeAllocationToSpatialLayersScreenSharing(
DataRate total_bitrate, DataRate total_bitrate,
size_t first_active_layer, size_t first_active_layer,
size_t num_spatial_layers) const; size_t num_spatial_layers) const;

View File

@ -13,6 +13,8 @@
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include "api/video/video_codec_type.h"
#include "modules/video_coding/codecs/av1/av1_svc_config.h"
#include "modules/video_coding/codecs/vp9/svc_config.h" #include "modules/video_coding/codecs/vp9/svc_config.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "test/field_trial.h" #include "test/field_trial.h"
@ -21,7 +23,11 @@
namespace webrtc { namespace webrtc {
namespace test { namespace test {
namespace { namespace {
static VideoCodec Configure(size_t width, using ::testing::Bool;
using ::testing::TestWithParam;
static VideoCodec Configure(VideoCodecType codecType,
size_t width,
size_t height, size_t height,
size_t num_spatial_layers, size_t num_spatial_layers,
size_t num_temporal_layers, size_t num_temporal_layers,
@ -29,31 +35,47 @@ static VideoCodec Configure(size_t width,
VideoCodec codec; VideoCodec codec;
codec.width = width; codec.width = width;
codec.height = height; codec.height = height;
codec.codecType = kVideoCodecVP9; codec.codecType = codecType;
codec.mode = is_screen_sharing ? VideoCodecMode::kScreensharing codec.mode = is_screen_sharing ? VideoCodecMode::kScreensharing
: VideoCodecMode::kRealtimeVideo; : VideoCodecMode::kRealtimeVideo;
std::vector<SpatialLayer> spatial_layers = std::vector<SpatialLayer> spatial_layers;
GetSvcConfig(width, height, 30, /*first_active_layer=*/0, if (codecType == kVideoCodecVP9) {
num_spatial_layers, num_temporal_layers, is_screen_sharing); spatial_layers = GetSvcConfig(width, height, 30, /*first_active_layer=*/0,
RTC_CHECK_LE(spatial_layers.size(), kMaxSpatialLayers); num_spatial_layers, num_temporal_layers,
is_screen_sharing);
RTC_CHECK_LE(spatial_layers.size(), kMaxSpatialLayers);
codec.VP9()->numberOfSpatialLayers = codec.VP9()->numberOfSpatialLayers =
std::min<unsigned char>(num_spatial_layers, spatial_layers.size()); std::min<unsigned char>(num_spatial_layers, spatial_layers.size());
codec.VP9()->numberOfTemporalLayers = std::min<unsigned char>( codec.VP9()->numberOfTemporalLayers = std::min<unsigned char>(
num_temporal_layers, spatial_layers.back().numberOfTemporalLayers); num_temporal_layers, spatial_layers.back().numberOfTemporalLayers);
for (size_t sl_idx = 0; sl_idx < spatial_layers.size(); ++sl_idx) { for (size_t sl_idx = 0; sl_idx < spatial_layers.size(); ++sl_idx) {
codec.spatialLayers[sl_idx] = spatial_layers[sl_idx]; codec.spatialLayers[sl_idx] = spatial_layers[sl_idx];
}
return codec;
} }
RTC_DCHECK_EQ(codecType, kVideoCodecAV1);
if (num_spatial_layers == 1) {
// SetAv1SvcConfig expects bitrate limits for be set when single spatial
// layer is requested.
codec.minBitrate = 30;
codec.maxBitrate = 5000;
}
SetAv1SvcConfig(codec, num_temporal_layers, num_spatial_layers);
return codec; return codec;
} }
} // namespace } // namespace
TEST(SvcRateAllocatorTest, SingleLayerFor320x180Input) { TEST(SvcRateAllocatorTest, SingleLayerFor320x180Input) {
VideoCodec codec = Configure(320, 180, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 320, 180, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
VideoBitrateAllocation allocation = VideoBitrateAllocation allocation =
@ -64,7 +86,7 @@ TEST(SvcRateAllocatorTest, SingleLayerFor320x180Input) {
} }
TEST(SvcRateAllocatorTest, TwoLayersFor640x360Input) { TEST(SvcRateAllocatorTest, TwoLayersFor640x360Input) {
VideoCodec codec = Configure(640, 360, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 640, 360, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
VideoBitrateAllocation allocation = VideoBitrateAllocation allocation =
@ -76,7 +98,7 @@ TEST(SvcRateAllocatorTest, TwoLayersFor640x360Input) {
} }
TEST(SvcRateAllocatorTest, ThreeLayersFor1280x720Input) { TEST(SvcRateAllocatorTest, ThreeLayersFor1280x720Input) {
VideoCodec codec = Configure(1280, 720, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
VideoBitrateAllocation allocation = VideoBitrateAllocation allocation =
@ -89,7 +111,7 @@ TEST(SvcRateAllocatorTest, ThreeLayersFor1280x720Input) {
TEST(SvcRateAllocatorTest, TEST(SvcRateAllocatorTest,
BaseLayerNonZeroBitrateEvenIfTotalIfLessThanMinimum) { BaseLayerNonZeroBitrateEvenIfTotalIfLessThanMinimum) {
VideoCodec codec = Configure(1280, 720, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
const SpatialLayer* layers = codec.spatialLayers; const SpatialLayer* layers = codec.spatialLayers;
@ -103,7 +125,7 @@ TEST(SvcRateAllocatorTest,
} }
TEST(SvcRateAllocatorTest, Disable640x360Layer) { TEST(SvcRateAllocatorTest, Disable640x360Layer) {
VideoCodec codec = Configure(1280, 720, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
const SpatialLayer* layers = codec.spatialLayers; const SpatialLayer* layers = codec.spatialLayers;
@ -120,7 +142,7 @@ TEST(SvcRateAllocatorTest, Disable640x360Layer) {
} }
TEST(SvcRateAllocatorTest, Disable1280x720Layer) { TEST(SvcRateAllocatorTest, Disable1280x720Layer) {
VideoCodec codec = Configure(1280, 720, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
const SpatialLayer* layers = codec.spatialLayers; const SpatialLayer* layers = codec.spatialLayers;
@ -138,7 +160,7 @@ TEST(SvcRateAllocatorTest, Disable1280x720Layer) {
} }
TEST(SvcRateAllocatorTest, BitrateIsCapped) { TEST(SvcRateAllocatorTest, BitrateIsCapped) {
VideoCodec codec = Configure(1280, 720, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 3, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
const SpatialLayer* layers = codec.spatialLayers; const SpatialLayer* layers = codec.spatialLayers;
@ -155,7 +177,7 @@ TEST(SvcRateAllocatorTest, BitrateIsCapped) {
} }
TEST(SvcRateAllocatorTest, MinBitrateToGetQualityLayer) { TEST(SvcRateAllocatorTest, MinBitrateToGetQualityLayer) {
VideoCodec codec = Configure(1280, 720, 3, 1, true); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 1, true);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
const SpatialLayer* layers = codec.spatialLayers; const SpatialLayer* layers = codec.spatialLayers;
@ -175,7 +197,7 @@ TEST(SvcRateAllocatorTest, MinBitrateToGetQualityLayer) {
TEST(SvcRateAllocatorTest, DeactivateHigherLayers) { TEST(SvcRateAllocatorTest, DeactivateHigherLayers) {
for (int deactivated_idx = 2; deactivated_idx >= 0; --deactivated_idx) { for (int deactivated_idx = 2; deactivated_idx >= 0; --deactivated_idx) {
VideoCodec codec = Configure(1280, 720, 3, 1, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 1, false);
EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U); EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U);
for (int i = deactivated_idx; i < 3; ++i) for (int i = deactivated_idx; i < 3; ++i)
@ -200,7 +222,7 @@ TEST(SvcRateAllocatorTest, DeactivateHigherLayers) {
TEST(SvcRateAllocatorTest, DeactivateLowerLayers) { TEST(SvcRateAllocatorTest, DeactivateLowerLayers) {
for (int deactivated_idx = 0; deactivated_idx < 3; ++deactivated_idx) { for (int deactivated_idx = 0; deactivated_idx < 3; ++deactivated_idx) {
VideoCodec codec = Configure(1280, 720, 3, 1, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 1, false);
EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U); EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U);
for (int i = deactivated_idx; i >= 0; --i) for (int i = deactivated_idx; i >= 0; --i)
@ -225,7 +247,7 @@ TEST(SvcRateAllocatorTest, DeactivateLowerLayers) {
} }
TEST(SvcRateAllocatorTest, SignalsBwLimited) { TEST(SvcRateAllocatorTest, SignalsBwLimited) {
VideoCodec codec = Configure(1280, 720, 3, 1, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 1, false);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
// Rough estimate calculated by hand. // Rough estimate calculated by hand.
@ -243,7 +265,7 @@ TEST(SvcRateAllocatorTest, SignalsBwLimited) {
} }
TEST(SvcRateAllocatorTest, NoPaddingIfAllLayersAreDeactivated) { TEST(SvcRateAllocatorTest, NoPaddingIfAllLayersAreDeactivated) {
VideoCodec codec = Configure(1280, 720, 3, 1, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 1, false);
EXPECT_EQ(codec.VP9()->numberOfSpatialLayers, 3U); EXPECT_EQ(codec.VP9()->numberOfSpatialLayers, 3U);
// Deactivation of base layer deactivates all layers. // Deactivation of base layer deactivates all layers.
codec.spatialLayers[0].active = false; codec.spatialLayers[0].active = false;
@ -262,7 +284,7 @@ TEST(SvcRateAllocatorTest, FindLayerTogglingThreshold) {
const DataRate kTwoLayerMinRate = DataRate::BitsPerSec(299150); const DataRate kTwoLayerMinRate = DataRate::BitsPerSec(299150);
const DataRate kThreeLayerMinRate = DataRate::BitsPerSec(891052); const DataRate kThreeLayerMinRate = DataRate::BitsPerSec(891052);
VideoCodec codec = Configure(1280, 720, 3, 1, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 1, false);
absl::InlinedVector<DataRate, kMaxSpatialLayers> layer_start_bitrates = absl::InlinedVector<DataRate, kMaxSpatialLayers> layer_start_bitrates =
SvcRateAllocator::GetLayerStartBitrates(codec); SvcRateAllocator::GetLayerStartBitrates(codec);
ASSERT_EQ(layer_start_bitrates.size(), 3u); ASSERT_EQ(layer_start_bitrates.size(), 3u);
@ -362,7 +384,7 @@ TEST(SvcRateAllocatorTest, UsesScalabilityModeToGetNumberOfLayers) {
} }
TEST(SvcRateAllocatorTest, CapsAllocationToMaxBitrate) { TEST(SvcRateAllocatorTest, CapsAllocationToMaxBitrate) {
VideoCodec codec = Configure(1280, 720, 3, 3, false); VideoCodec codec = Configure(kVideoCodecVP9, 1280, 720, 3, 3, false);
codec.maxBitrate = 70; // Cap the overall max bitrate to 70kbps. codec.maxBitrate = 70; // Cap the overall max bitrate to 70kbps.
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
@ -376,9 +398,7 @@ TEST(SvcRateAllocatorTest, CapsAllocationToMaxBitrate) {
EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0u); EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0u);
} }
class SvcRateAllocatorTestParametrizedContentType class SvcRateAllocatorTestParametrizedContentType : public TestWithParam<bool> {
: public ::testing::Test,
public ::testing::WithParamInterface<bool> {
public: public:
SvcRateAllocatorTestParametrizedContentType() SvcRateAllocatorTestParametrizedContentType()
: is_screen_sharing_(GetParam()) {} : is_screen_sharing_(GetParam()) {}
@ -387,7 +407,8 @@ class SvcRateAllocatorTestParametrizedContentType
}; };
TEST_P(SvcRateAllocatorTestParametrizedContentType, MaxBitrate) { TEST_P(SvcRateAllocatorTestParametrizedContentType, MaxBitrate) {
VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_); VideoCodec codec =
Configure(kVideoCodecVP9, 1280, 720, 3, 1, is_screen_sharing_);
EXPECT_EQ(SvcRateAllocator::GetMaxBitrate(codec), EXPECT_EQ(SvcRateAllocator::GetMaxBitrate(codec),
DataRate::KilobitsPerSec(codec.spatialLayers[0].maxBitrate + DataRate::KilobitsPerSec(codec.spatialLayers[0].maxBitrate +
codec.spatialLayers[1].maxBitrate + codec.spatialLayers[1].maxBitrate +
@ -400,7 +421,8 @@ TEST_P(SvcRateAllocatorTestParametrizedContentType, MaxBitrate) {
} }
TEST_P(SvcRateAllocatorTestParametrizedContentType, PaddingBitrate) { TEST_P(SvcRateAllocatorTestParametrizedContentType, PaddingBitrate) {
VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_); VideoCodec codec =
Configure(kVideoCodecVP9, 1280, 720, 3, 1, is_screen_sharing_);
SvcRateAllocator allocator = SvcRateAllocator(codec); SvcRateAllocator allocator = SvcRateAllocator(codec);
DataRate padding_bitrate = SvcRateAllocator::GetPaddingBitrate(codec); DataRate padding_bitrate = SvcRateAllocator::GetPaddingBitrate(codec);
@ -449,7 +471,8 @@ TEST_P(SvcRateAllocatorTestParametrizedContentType, StableBitrate) {
"WebRTC-StableTargetRate/enabled:true,video_hysteresis_factor:1.0," "WebRTC-StableTargetRate/enabled:true,video_hysteresis_factor:1.0,"
"screenshare_hysteresis_factor:1.0/"); "screenshare_hysteresis_factor:1.0/");
const VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_); const VideoCodec codec =
Configure(kVideoCodecVP9, 1280, 720, 3, 1, is_screen_sharing_);
const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec); const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec);
const DataRate min_rate_two_layers = start_rates[1]; const DataRate min_rate_two_layers = start_rates[1];
const DataRate min_rate_three_layers = start_rates[2]; const DataRate min_rate_three_layers = start_rates[2];
@ -502,7 +525,8 @@ TEST_P(SvcRateAllocatorTestParametrizedContentType, StableBitrate) {
TEST_P(SvcRateAllocatorTestParametrizedContentType, TEST_P(SvcRateAllocatorTestParametrizedContentType,
StableBitrateWithHysteresis) { StableBitrateWithHysteresis) {
const VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_); const VideoCodec codec =
Configure(kVideoCodecVP9, 1280, 720, 3, 1, is_screen_sharing_);
const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec); const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec);
const DataRate min_rate_single_layer = start_rates[0]; const DataRate min_rate_single_layer = start_rates[0];
const DataRate min_rate_two_layers = start_rates[1]; const DataRate min_rate_two_layers = start_rates[1];
@ -591,9 +615,39 @@ TEST_P(SvcRateAllocatorTestParametrizedContentType,
EXPECT_FALSE(allocation.IsSpatialLayerUsed(2)); EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
} }
TEST_P(SvcRateAllocatorTestParametrizedContentType, TwoTemporalLayersAv1) {
VideoCodec codec =
Configure(kVideoCodecAV1, 1280, 720, 1, 2, is_screen_sharing_);
SvcRateAllocator allocator = SvcRateAllocator(codec);
VideoBitrateAllocation allocation =
allocator.Allocate(VideoBitrateAllocationParameters(
/*total_bitrate_bps=*/1024'000, /*framerate=*/30));
EXPECT_EQ(allocation.GetBitrate(/*spatial_index=*/0, /*temporal_index=*/0),
660645u);
EXPECT_EQ(allocation.GetBitrate(/*spatial_index=*/0, /*temporal_index=*/1),
363355u);
}
TEST_P(SvcRateAllocatorTestParametrizedContentType, ThreeTemporalLayersAv1) {
VideoCodec codec =
Configure(kVideoCodecAV1, 1280, 720, 1, 3, is_screen_sharing_);
SvcRateAllocator allocator = SvcRateAllocator(codec);
VideoBitrateAllocation allocation =
allocator.Allocate(VideoBitrateAllocationParameters(
/*total_bitrate_bps=*/1024'000, /*framerate=*/30));
EXPECT_EQ(allocation.GetBitrate(/*spatial_index=*/0, /*temporal_index=*/0),
552766u);
EXPECT_EQ(allocation.GetBitrate(/*spatial_index=*/0, /*temporal_index=*/1),
167212u);
EXPECT_EQ(allocation.GetBitrate(/*spatial_index=*/0, /*temporal_index=*/2),
304022u);
}
INSTANTIATE_TEST_SUITE_P(_, INSTANTIATE_TEST_SUITE_P(_,
SvcRateAllocatorTestParametrizedContentType, SvcRateAllocatorTestParametrizedContentType,
::testing::Bool()); Bool());
} // namespace test } // namespace test
} // namespace webrtc } // namespace webrtc