mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-19 08:37:54 +01:00
Consider frame orientation for number of spatial layers in VP9.
Addresses case where 540*960 would not get a 135*240 layer. Bug: webrtc:13469 Change-Id: Icc291c65114fb400cc71659d76a786e359e5996c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/239820 Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Konrad Hofbauer <hofbauer@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35507}
This commit is contained in:
parent
70f445e592
commit
d2cd8722cd
5 changed files with 55 additions and 28 deletions
|
@ -30,8 +30,8 @@ const size_t kMaxVp9RefPics = 3;
|
||||||
const size_t kMaxVp9FramesInGof = 0xFF; // 8 bits
|
const size_t kMaxVp9FramesInGof = 0xFF; // 8 bits
|
||||||
const size_t kMaxVp9NumberOfSpatialLayers = 8;
|
const size_t kMaxVp9NumberOfSpatialLayers = 8;
|
||||||
|
|
||||||
const size_t kMinVp9SpatialLayerWidth = 240;
|
const size_t kMinVp9SpatialLayerLongSideLength = 240;
|
||||||
const size_t kMinVp9SpatialLayerHeight = 135;
|
const size_t kMinVp9SpatialLayerShortSideLength = 135;
|
||||||
|
|
||||||
enum TemporalStructureMode {
|
enum TemporalStructureMode {
|
||||||
kTemporalStructureMode1, // 1 temporal layer structure - i.e., IPPP...
|
kTemporalStructureMode1, // 1 temporal layer structure - i.e., IPPP...
|
||||||
|
|
|
@ -69,12 +69,15 @@ std::vector<SpatialLayer> ConfigureSvcNormalVideo(size_t input_width,
|
||||||
std::vector<SpatialLayer> spatial_layers;
|
std::vector<SpatialLayer> spatial_layers;
|
||||||
|
|
||||||
// Limit number of layers for given resolution.
|
// Limit number of layers for given resolution.
|
||||||
|
const bool is_landscape = input_width >= input_height;
|
||||||
|
const size_t min_width = is_landscape ? kMinVp9SpatialLayerLongSideLength
|
||||||
|
: kMinVp9SpatialLayerShortSideLength;
|
||||||
|
const size_t min_height = is_landscape ? kMinVp9SpatialLayerShortSideLength
|
||||||
|
: kMinVp9SpatialLayerLongSideLength;
|
||||||
const size_t num_layers_fit_horz = static_cast<size_t>(std::floor(
|
const size_t num_layers_fit_horz = static_cast<size_t>(std::floor(
|
||||||
1 + std::max(0.0f,
|
1 + std::max(0.0f, std::log2(1.0f * input_width / min_width))));
|
||||||
std::log2(1.0f * input_width / kMinVp9SpatialLayerWidth))));
|
const size_t num_layers_fit_vert = static_cast<size_t>(std::floor(
|
||||||
const size_t num_layers_fit_vert = static_cast<size_t>(
|
1 + std::max(0.0f, std::log2(1.0f * input_height / min_height))));
|
||||||
std::floor(1 + std::max(0.0f, std::log2(1.0f * input_height /
|
|
||||||
kMinVp9SpatialLayerHeight))));
|
|
||||||
const size_t limited_num_spatial_layers =
|
const size_t limited_num_spatial_layers =
|
||||||
std::min(num_layers_fit_horz, num_layers_fit_vert);
|
std::min(num_layers_fit_horz, num_layers_fit_vert);
|
||||||
if (limited_num_spatial_layers < num_spatial_layers) {
|
if (limited_num_spatial_layers < num_spatial_layers) {
|
||||||
|
|
|
@ -22,10 +22,23 @@ TEST(SvcConfig, NumSpatialLayers) {
|
||||||
const size_t first_active_layer = 0;
|
const size_t first_active_layer = 0;
|
||||||
const size_t num_spatial_layers = 2;
|
const size_t num_spatial_layers = 2;
|
||||||
|
|
||||||
std::vector<SpatialLayer> spatial_layers =
|
std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
|
||||||
GetSvcConfig(kMinVp9SpatialLayerWidth << (num_spatial_layers - 1),
|
kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1),
|
||||||
kMinVp9SpatialLayerHeight << (num_spatial_layers - 1), 30,
|
kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1), 30,
|
||||||
first_active_layer, max_num_spatial_layers, 1, false);
|
first_active_layer, max_num_spatial_layers, 1, false);
|
||||||
|
|
||||||
|
EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SvcConfig, NumSpatialLayersPortrait) {
|
||||||
|
const size_t max_num_spatial_layers = 6;
|
||||||
|
const size_t first_active_layer = 0;
|
||||||
|
const size_t num_spatial_layers = 2;
|
||||||
|
|
||||||
|
std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
|
||||||
|
kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1),
|
||||||
|
kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1), 30,
|
||||||
|
first_active_layer, max_num_spatial_layers, 1, false);
|
||||||
|
|
||||||
EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
|
EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
|
||||||
}
|
}
|
||||||
|
@ -34,11 +47,22 @@ TEST(SvcConfig, AlwaysSendsAtLeastOneLayer) {
|
||||||
const size_t max_num_spatial_layers = 6;
|
const size_t max_num_spatial_layers = 6;
|
||||||
const size_t first_active_layer = 5;
|
const size_t first_active_layer = 5;
|
||||||
|
|
||||||
std::vector<SpatialLayer> spatial_layers =
|
std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
|
||||||
GetSvcConfig(kMinVp9SpatialLayerWidth, kMinVp9SpatialLayerHeight, 30,
|
kMinVp9SpatialLayerLongSideLength, kMinVp9SpatialLayerShortSideLength, 30,
|
||||||
first_active_layer, max_num_spatial_layers, 1, false);
|
first_active_layer, max_num_spatial_layers, 1, false);
|
||||||
EXPECT_EQ(spatial_layers.size(), 1u);
|
EXPECT_EQ(spatial_layers.size(), 1u);
|
||||||
EXPECT_EQ(spatial_layers.back().width, kMinVp9SpatialLayerWidth);
|
EXPECT_EQ(spatial_layers.back().width, kMinVp9SpatialLayerLongSideLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SvcConfig, AlwaysSendsAtLeastOneLayerPortrait) {
|
||||||
|
const size_t max_num_spatial_layers = 6;
|
||||||
|
const size_t first_active_layer = 5;
|
||||||
|
|
||||||
|
std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
|
||||||
|
kMinVp9SpatialLayerShortSideLength, kMinVp9SpatialLayerLongSideLength, 30,
|
||||||
|
first_active_layer, max_num_spatial_layers, 1, false);
|
||||||
|
EXPECT_EQ(spatial_layers.size(), 1u);
|
||||||
|
EXPECT_EQ(spatial_layers.back().width, kMinVp9SpatialLayerShortSideLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SvcConfig, EnforcesMinimalRequiredParity) {
|
TEST(SvcConfig, EnforcesMinimalRequiredParity) {
|
||||||
|
@ -71,22 +95,22 @@ TEST(SvcConfig, SkipsInactiveLayers) {
|
||||||
const size_t num_spatial_layers = 4;
|
const size_t num_spatial_layers = 4;
|
||||||
const size_t first_active_layer = 2;
|
const size_t first_active_layer = 2;
|
||||||
|
|
||||||
std::vector<SpatialLayer> spatial_layers =
|
std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
|
||||||
GetSvcConfig(kMinVp9SpatialLayerWidth << (num_spatial_layers - 1),
|
kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1),
|
||||||
kMinVp9SpatialLayerHeight << (num_spatial_layers - 1), 30,
|
kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1), 30,
|
||||||
first_active_layer, num_spatial_layers, 1, false);
|
first_active_layer, num_spatial_layers, 1, false);
|
||||||
EXPECT_EQ(spatial_layers.size(), 2u);
|
EXPECT_EQ(spatial_layers.size(), 2u);
|
||||||
EXPECT_EQ(spatial_layers.back().width,
|
EXPECT_EQ(spatial_layers.back().width,
|
||||||
kMinVp9SpatialLayerWidth << (num_spatial_layers - 1));
|
kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SvcConfig, BitrateThresholds) {
|
TEST(SvcConfig, BitrateThresholds) {
|
||||||
const size_t first_active_layer = 0;
|
const size_t first_active_layer = 0;
|
||||||
const size_t num_spatial_layers = 3;
|
const size_t num_spatial_layers = 3;
|
||||||
std::vector<SpatialLayer> spatial_layers =
|
std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
|
||||||
GetSvcConfig(kMinVp9SpatialLayerWidth << (num_spatial_layers - 1),
|
kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1),
|
||||||
kMinVp9SpatialLayerHeight << (num_spatial_layers - 1), 30,
|
kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1), 30,
|
||||||
first_active_layer, num_spatial_layers, 1, false);
|
first_active_layer, num_spatial_layers, 1, false);
|
||||||
|
|
||||||
EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
|
EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
|
||||||
|
|
||||||
|
|
|
@ -302,8 +302,8 @@ TEST_F(VideoCodecInitializerTest, Vp9SvcAdjustedLayering) {
|
||||||
VideoStream stream = DefaultStream();
|
VideoStream stream = DefaultStream();
|
||||||
stream.num_temporal_layers = 3;
|
stream.num_temporal_layers = 3;
|
||||||
// Set resolution which is only enough to produce 2 spatial layers.
|
// Set resolution which is only enough to produce 2 spatial layers.
|
||||||
stream.width = kMinVp9SpatialLayerWidth * 2;
|
stream.width = kMinVp9SpatialLayerLongSideLength * 2;
|
||||||
stream.height = kMinVp9SpatialLayerHeight * 2;
|
stream.height = kMinVp9SpatialLayerShortSideLength * 2;
|
||||||
|
|
||||||
streams_.push_back(stream);
|
streams_.push_back(stream);
|
||||||
|
|
||||||
|
|
|
@ -3316,8 +3316,8 @@ void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
|
||||||
// structures to verify temporal id reset on key frame.
|
// structures to verify temporal id reset on key frame.
|
||||||
static const int kKeyFrameInterval = 31;
|
static const int kKeyFrameInterval = 31;
|
||||||
|
|
||||||
static const int kWidth = kMinVp9SpatialLayerWidth;
|
static const int kWidth = kMinVp9SpatialLayerLongSideLength;
|
||||||
static const int kHeight = kMinVp9SpatialLayerHeight;
|
static const int kHeight = kMinVp9SpatialLayerShortSideLength;
|
||||||
static const float kGoodBitsPerPixel = 0.1f;
|
static const float kGoodBitsPerPixel = 0.1f;
|
||||||
class NonFlexibleMode : public Vp9HeaderObserver {
|
class NonFlexibleMode : public Vp9HeaderObserver {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue