Add unit tests for simulcast layer configurations.

Bug: webrtc:9341
Change-Id: I82b164bd1faca2042be6176463c930b693d951eb
Reviewed-on: https://webrtc-review.googlesource.com/83321
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23922}
This commit is contained in:
Åsa Persson 2018-06-27 10:44:56 +02:00 committed by Commit Bot
parent b661c658da
commit 31cb8f9a50
4 changed files with 201 additions and 23 deletions

View File

@ -518,6 +518,7 @@ if (rtc_include_tests) {
"engine/nullwebrtcvideoengine_unittest.cc",
"engine/payload_type_mapper_unittest.cc",
"engine/simulcast_encoder_adapter_unittest.cc",
"engine/simulcast_unittest.cc",
"engine/vp8_encoder_simulcast_proxy_unittest.cc",
"engine/webrtcmediaengine_unittest.cc",
"engine/webrtcvideocapturer_unittest.cc",

View File

@ -11,16 +11,12 @@
#ifndef MEDIA_ENGINE_SIMULCAST_H_
#define MEDIA_ENGINE_SIMULCAST_H_
#include <string>
#include <vector>
#include "api/video_codecs/video_encoder_config.h"
namespace cricket {
// TODO(pthatcher): Write unit tests just for these functions,
// independent of WebrtcVideoEngine.
// Gets the total maximum bitrate for the |streams|.
int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& streams);

View File

@ -0,0 +1,189 @@
/*
* Copyright 2018 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 "media/engine/simulcast.h"
#include "media/engine/constants.h"
#include "test/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
constexpr int kQpMax = 55;
constexpr double kBitratePriority = 2.0;
constexpr int kMaxFps = 33;
constexpr int kMaxBitrateBps = 0;
constexpr bool kScreenshare = true;
constexpr int kDefaultTemporalLayers = 3; // Value from simulcast.cc.
// Values from kSimulcastConfigs in simulcast.cc.
const std::vector<VideoStream> GetSimulcastBitrates720p() {
std::vector<VideoStream> streams(3);
streams[0].min_bitrate_bps = 30000;
streams[0].target_bitrate_bps = 150000;
streams[0].max_bitrate_bps = 200000;
streams[1].min_bitrate_bps = 150000;
streams[1].target_bitrate_bps = 500000;
streams[1].max_bitrate_bps = 700000;
streams[2].min_bitrate_bps = 600000;
streams[2].target_bitrate_bps = 2500000;
streams[2].max_bitrate_bps = 2500000;
return streams;
}
} // namespace
TEST(SimulcastTest, TotalMaxBitrateIsZeroForNoStreams) {
std::vector<VideoStream> streams;
EXPECT_EQ(0, cricket::GetTotalMaxBitrateBps(streams));
}
TEST(SimulcastTest, GetTotalMaxBitrateForSingleStream) {
std::vector<VideoStream> streams(1);
streams[0].max_bitrate_bps = 100000;
EXPECT_EQ(100000, cricket::GetTotalMaxBitrateBps(streams));
}
TEST(SimulcastTest, GetTotalMaxBitrateForMultipleStreams) {
std::vector<VideoStream> streams(3);
streams[0].target_bitrate_bps = 100000;
streams[1].target_bitrate_bps = 200000;
streams[2].max_bitrate_bps = 400000;
EXPECT_EQ(700000, cricket::GetTotalMaxBitrateBps(streams));
}
TEST(SimulcastTest, BandwidthAboveTotalMaxBitrateGivenToHighestStream) {
std::vector<VideoStream> streams(3);
streams[0].target_bitrate_bps = 100000;
streams[1].target_bitrate_bps = 200000;
streams[2].max_bitrate_bps = 400000;
// No bitrate above the total max to give to the highest stream.
const int kMaxTotalBps = cricket::GetTotalMaxBitrateBps(streams);
cricket::BoostMaxSimulcastLayer(kMaxTotalBps, &streams);
EXPECT_EQ(400000, streams[2].max_bitrate_bps);
EXPECT_EQ(kMaxTotalBps, cricket::GetTotalMaxBitrateBps(streams));
// The bitrate above the total max should be given to the highest stream.
cricket::BoostMaxSimulcastLayer(kMaxTotalBps + 1, &streams);
EXPECT_EQ(400000 + 1, streams[2].max_bitrate_bps);
EXPECT_EQ(kMaxTotalBps + 1, cricket::GetTotalMaxBitrateBps(streams));
}
TEST(SimulcastTest, GetConfig) {
const std::vector<VideoStream> kExpected = GetSimulcastBitrates720p();
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 1280, 720, kMaxBitrateBps, kBitratePriority, kQpMax, kMaxFps,
!kScreenshare);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(320u, streams[0].width);
EXPECT_EQ(180u, streams[0].height);
EXPECT_EQ(640u, streams[1].width);
EXPECT_EQ(360u, streams[1].height);
EXPECT_EQ(1280u, streams[2].width);
EXPECT_EQ(720u, streams[2].height);
for (size_t i = 0; i < streams.size(); ++i) {
EXPECT_EQ(kDefaultTemporalLayers, streams[i].num_temporal_layers);
EXPECT_EQ(kMaxFps, streams[i].max_framerate);
EXPECT_EQ(kQpMax, streams[i].max_qp);
EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps);
EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps);
EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps);
EXPECT_TRUE(streams[i].active);
}
// Currently set on lowest stream.
EXPECT_EQ(kBitratePriority, streams[0].bitrate_priority);
EXPECT_FALSE(streams[1].bitrate_priority);
EXPECT_FALSE(streams[2].bitrate_priority);
}
TEST(SimulcastTest, GetConfigWithLimitedMaxLayers) {
const size_t kMaxLayers = 2;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 1280, 720, kMaxBitrateBps, kBitratePriority, kQpMax, kMaxFps,
!kScreenshare);
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(320u, streams[0].width);
EXPECT_EQ(180u, streams[0].height);
EXPECT_EQ(640u, streams[1].width);
EXPECT_EQ(360u, streams[1].height);
}
TEST(SimulcastTest, GetConfigWithNormalizedResolution) {
const size_t kMaxLayers = 2;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 640 + 1, 360 + 1, kMaxBitrateBps, kBitratePriority, kQpMax,
kMaxFps, !kScreenshare);
// Must be dividable by |2 ^ (num_layers - 1)|.
EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(320u, streams[0].width);
EXPECT_EQ(180u, streams[0].height);
EXPECT_EQ(640u, streams[1].width);
EXPECT_EQ(360u, streams[1].height);
}
TEST(SimulcastTest, GetConfigForScreenshare) {
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 1400, 800, kMaxBitrateBps, kBitratePriority, kQpMax, kMaxFps,
kScreenshare);
EXPECT_EQ(1u, streams.size()) << "No simulcast.";
EXPECT_EQ(1400u, streams[0].width);
EXPECT_EQ(800u, streams[0].height);
EXPECT_EQ(kQpMax, streams[0].max_qp);
EXPECT_EQ(kBitratePriority, streams[0].bitrate_priority);
EXPECT_TRUE(streams[0].active);
EXPECT_GT(streams[0].num_temporal_layers, 1);
EXPECT_GT(streams[0].max_framerate, 0);
EXPECT_EQ(cricket::kMinVideoBitrateBps, streams[0].min_bitrate_bps);
EXPECT_GT(streams[0].target_bitrate_bps, streams[0].min_bitrate_bps);
EXPECT_GT(streams[0].max_bitrate_bps, streams[0].target_bitrate_bps);
}
TEST(SimulcastTest, GetConfigForScreenshareSimulcast) {
test::ScopedFieldTrials field_trials("WebRTC-SimulcastScreenshare/Enabled/");
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 1400, 800, kMaxBitrateBps, kBitratePriority, kQpMax, kMaxFps,
kScreenshare);
EXPECT_GT(streams.size(), 1u);
for (size_t i = 0; i < streams.size(); ++i) {
EXPECT_EQ(1400u, streams[i].width) << "Screen content never scaled.";
EXPECT_EQ(800u, streams[i].height) << "Screen content never scaled.";
EXPECT_EQ(kQpMax, streams[i].max_qp);
EXPECT_TRUE(streams[i].active);
EXPECT_GT(streams[i].num_temporal_layers, 1);
EXPECT_GT(streams[i].max_framerate, 0);
EXPECT_GT(streams[i].min_bitrate_bps, 0);
EXPECT_GT(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
EXPECT_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
}
}
TEST(SimulcastTest, GetConfigForScreenshareSimulcastWithLimitedMaxLayers) {
test::ScopedFieldTrials field_trials("WebRTC-SimulcastScreenshare/Enabled/");
const size_t kMaxLayers = 1;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 1400, 800, kMaxBitrateBps, kBitratePriority, kQpMax, kMaxFps,
kScreenshare);
EXPECT_EQ(kMaxLayers, streams.size());
}
} // namespace webrtc

View File

@ -5344,7 +5344,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersPriorityOneStream) {
// streams.
TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersPrioritySimulcastStreams) {
// Create the stream params with multiple ssrcs for simulcast.
const int kNumSimulcastStreams = 3;
const size_t kNumSimulcastStreams = 3;
std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
StreamParams stream_params = CreateSimStreamParams("cname", ssrcs);
AddSendStream(stream_params);
@ -5365,8 +5365,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersPrioritySimulcastStreams) {
// Get and set the rtp encoding parameters.
webrtc::RtpParameters parameters =
channel_->GetRtpSendParameters(primary_ssrc);
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
parameters.encodings.size());
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
EXPECT_EQ(webrtc::kDefaultBitratePriority,
parameters.encodings[0].bitrate_priority);
// Change the value and set it on the VideoChannel.
@ -5376,8 +5375,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersPrioritySimulcastStreams) {
// Verify that the encoding parameters priority is set on the VideoChannel.
parameters = channel_->GetRtpSendParameters(primary_ssrc);
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
parameters.encodings.size());
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
EXPECT_EQ(new_bitrate_priority, parameters.encodings[0].bitrate_priority);
// Verify that the new value propagated down to the encoder.
@ -5387,15 +5385,14 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersPrioritySimulcastStreams) {
FakeVideoSendStream* video_send_stream = video_send_streams.front();
// Check that the WebRtcVideoSendStream updated the VideoEncoderConfig
// appropriately.
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
EXPECT_EQ(kNumSimulcastStreams,
video_send_stream->GetEncoderConfig().number_of_streams);
EXPECT_EQ(new_bitrate_priority,
video_send_stream->GetEncoderConfig().bitrate_priority);
// Check that the vector of VideoStreams also propagated correctly. The
// FakeVideoSendStream calls CreateEncoderStreams, and we are testing that
// these are created appropriately for the simulcast case.
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
video_send_stream->GetVideoStreams().size());
EXPECT_EQ(kNumSimulcastStreams, video_send_stream->GetVideoStreams().size());
EXPECT_EQ(absl::optional<double>(new_bitrate_priority),
video_send_stream->GetVideoStreams()[0].bitrate_priority);
// Since we are only setting bitrate priority per-sender, the other
@ -5807,7 +5804,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersOneEncodingActive) {
// new appropriate active simulcast streams.
TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersMultipleEncodingsActive) {
// Create the stream params with multiple ssrcs for simulcast.
const int kNumSimulcastStreams = 3;
const size_t kNumSimulcastStreams = 3;
std::vector<uint32_t> ssrcs = MAKE_VECTOR(kSsrcs3);
StreamParams stream_params = CreateSimStreamParams("cname", ssrcs);
FakeVideoSendStream* fake_video_send_stream = AddSendStream(stream_params);
@ -5829,8 +5826,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersMultipleEncodingsActive) {
// Check that all encodings are initially active.
webrtc::RtpParameters parameters =
channel_->GetRtpSendParameters(primary_ssrc);
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
parameters.encodings.size());
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
EXPECT_TRUE(parameters.encodings[0].active);
EXPECT_TRUE(parameters.encodings[1].active);
EXPECT_TRUE(parameters.encodings[2].active);
@ -5843,8 +5839,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersMultipleEncodingsActive) {
EXPECT_TRUE(channel_->SetRtpSendParameters(primary_ssrc, parameters).ok());
// Verify that the active fields are set on the VideoChannel.
parameters = channel_->GetRtpSendParameters(primary_ssrc);
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
parameters.encodings.size());
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
EXPECT_FALSE(parameters.encodings[0].active);
EXPECT_TRUE(parameters.encodings[1].active);
EXPECT_FALSE(parameters.encodings[2].active);
@ -5853,8 +5848,7 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersMultipleEncodingsActive) {
EXPECT_TRUE(fake_video_send_stream->IsSending());
std::vector<webrtc::VideoStream> simulcast_streams =
fake_video_send_stream->GetVideoStreams();
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
simulcast_streams.size());
EXPECT_EQ(kNumSimulcastStreams, simulcast_streams.size());
EXPECT_FALSE(simulcast_streams[0].active);
EXPECT_TRUE(simulcast_streams[1].active);
EXPECT_FALSE(simulcast_streams[2].active);
@ -5866,16 +5860,14 @@ TEST_F(WebRtcVideoChannelTest, SetRtpSendParametersMultipleEncodingsActive) {
EXPECT_TRUE(channel_->SetRtpSendParameters(primary_ssrc, parameters).ok());
// Verify that the active fields are set on the VideoChannel.
parameters = channel_->GetRtpSendParameters(primary_ssrc);
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
parameters.encodings.size());
EXPECT_EQ(kNumSimulcastStreams, parameters.encodings.size());
EXPECT_FALSE(parameters.encodings[0].active);
EXPECT_FALSE(parameters.encodings[1].active);
EXPECT_FALSE(parameters.encodings[2].active);
// Check that the VideoSendStream is off.
EXPECT_FALSE(fake_video_send_stream->IsSending());
simulcast_streams = fake_video_send_stream->GetVideoStreams();
EXPECT_EQ(rtc::checked_cast<size_t>(kNumSimulcastStreams),
simulcast_streams.size());
EXPECT_EQ(kNumSimulcastStreams, simulcast_streams.size());
EXPECT_FALSE(simulcast_streams[0].active);
EXPECT_FALSE(simulcast_streams[1].active);
EXPECT_FALSE(simulcast_streams[2].active);