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:
parent
b661c658da
commit
31cb8f9a50
@ -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",
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
189
media/engine/simulcast_unittest.cc
Normal file
189
media/engine/simulcast_unittest.cc
Normal 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
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user