blob: 4e99fbbdedff723a8f209867d03e7ac5939b509c [file] [log] [blame]
sprang429600d2017-01-26 06:12:26 -08001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "api/video_codecs/video_encoder.h"
12#include "common_video/include/video_bitrate_allocator.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020013#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/video_coding/codecs/vp8/temporal_layers.h"
15#include "modules/video_coding/include/video_codec_initializer.h"
Niels Möller84255bb2017-10-06 13:43:23 +020016#include "rtc_base/refcountedobject.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "test/gtest.h"
sprang429600d2017-01-26 06:12:26 -080018
19namespace webrtc {
20
21namespace {
Niels Moller92be1ca2018-03-21 13:53:41 +000022static const char* kVp8PayloadName = "VP8";
23static const int kVp8PayloadType = 100;
sprang429600d2017-01-26 06:12:26 -080024static const int kDefaultWidth = 1280;
25static const int kDefaultHeight = 720;
26static const int kDefaultFrameRate = 30;
27static const uint32_t kDefaultMinBitrateBps = 60000;
28static const uint32_t kDefaultTargetBitrateBps = 2000000;
29static const uint32_t kDefaultMaxBitrateBps = 2000000;
30static const uint32_t kDefaultMinTransmitBitrateBps = 400000;
31static const int kDefaultMaxQp = 48;
32static const uint32_t kScreenshareTl0BitrateBps = 100000;
33static const uint32_t kScreenshareCodecTargetBitrateBps = 200000;
34static const uint32_t kScreenshareDefaultFramerate = 5;
35// Bitrates for the temporal layers of the higher screenshare simulcast stream.
36static const uint32_t kHighScreenshareTl0Bps = 800000;
37static const uint32_t kHighScreenshareTl1Bps = 1200000;
38} // namespace
39
sprang429600d2017-01-26 06:12:26 -080040// TODO(sprang): Extend coverage to handle the rest of the codec initializer.
41class VideoCodecInitializerTest : public ::testing::Test {
42 public:
43 VideoCodecInitializerTest() : nack_enabled_(false) {}
44 virtual ~VideoCodecInitializerTest() {}
45
46 protected:
47 void SetUpFor(VideoCodecType type,
48 int num_spatial_streams,
49 int num_temporal_streams,
50 bool screenshare) {
51 config_ = VideoEncoderConfig();
52 if (screenshare) {
53 config_.min_transmit_bitrate_bps = kDefaultMinTransmitBitrateBps;
54 config_.content_type = VideoEncoderConfig::ContentType::kScreen;
55 }
56
57 if (type == VideoCodecType::kVideoCodecVP8) {
58 config_.number_of_streams = num_spatial_streams;
59 VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
60 vp8_settings.numberOfTemporalLayers = num_temporal_streams;
61 config_.encoder_specific_settings = new rtc::RefCountedObject<
62 webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
Niels Moller92be1ca2018-03-21 13:53:41 +000063 settings_.payload_name = kVp8PayloadName;
64 settings_.payload_type = kVp8PayloadType;
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080065 } else if (type == VideoCodecType::kVideoCodecMultiplex) {
sprang429600d2017-01-26 06:12:26 -080066 } else {
67 ADD_FAILURE() << "Unexpected codec type: " << type;
68 }
69 }
70
71 bool InitializeCodec() {
72 codec_out_ = VideoCodec();
73 bitrate_allocator_out_.reset();
74 temporal_layers_.clear();
Niels Moller92be1ca2018-03-21 13:53:41 +000075 if (!VideoCodecInitializer::SetupCodec(config_, settings_, streams_,
76 nack_enabled_, &codec_out_,
sprang429600d2017-01-26 06:12:26 -080077 &bitrate_allocator_out_)) {
78 return false;
79 }
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080080 if (codec_out_.codecType == VideoCodecType::kVideoCodecMultiplex)
Emircan Uysaler0a375472017-12-11 12:21:02 +053081 return true;
Erik Språng82fad3d2018-03-21 09:57:23 +010082
sprang429600d2017-01-26 06:12:26 -080083 // Make sure temporal layers instances have been created.
84 if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
sprang429600d2017-01-26 06:12:26 -080085 for (int i = 0; i < codec_out_.numberOfSimulcastStreams; ++i) {
Erik Språng82fad3d2018-03-21 09:57:23 +010086 temporal_layers_.emplace_back(
87 TemporalLayers::CreateTemporalLayers(codec_out_, i, 0));
sprang429600d2017-01-26 06:12:26 -080088 }
89 }
90 return true;
91 }
92
93 VideoStream DefaultStream() {
94 VideoStream stream;
95 stream.width = kDefaultWidth;
96 stream.height = kDefaultHeight;
97 stream.max_framerate = kDefaultFrameRate;
98 stream.min_bitrate_bps = kDefaultMinBitrateBps;
99 stream.target_bitrate_bps = kDefaultTargetBitrateBps;
100 stream.max_bitrate_bps = kDefaultMaxBitrateBps;
101 stream.max_qp = kDefaultMaxQp;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100102 stream.num_temporal_layers = 1;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800103 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800104 return stream;
105 }
106
107 VideoStream DefaultScreenshareStream() {
108 VideoStream stream = DefaultStream();
109 stream.min_bitrate_bps = 30000;
110 stream.target_bitrate_bps = kScreenshareTl0BitrateBps;
111 stream.max_bitrate_bps = 1000000;
112 stream.max_framerate = kScreenshareDefaultFramerate;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100113 stream.num_temporal_layers = 2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800114 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800115 return stream;
116 }
117
118 // Input settings.
119 VideoEncoderConfig config_;
Niels Moller92be1ca2018-03-21 13:53:41 +0000120 VideoSendStream::Config::EncoderSettings settings_;
sprang429600d2017-01-26 06:12:26 -0800121 std::vector<VideoStream> streams_;
122 bool nack_enabled_;
123
124 // Output.
125 VideoCodec codec_out_;
126 std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_out_;
127 std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_;
128};
129
130TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
131 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
132 streams_.push_back(DefaultStream());
133 EXPECT_TRUE(InitializeCodec());
134
135 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
136 kDefaultTargetBitrateBps, kDefaultFrameRate);
137 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
138 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
139 EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
140}
141
Seth Hampson46e31ba2018-01-18 10:39:54 -0800142TEST_F(VideoCodecInitializerTest, SingleStreamVp8ScreenshareInactive) {
143 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
144 VideoStream inactive_stream = DefaultStream();
145 inactive_stream.active = false;
146 streams_.push_back(inactive_stream);
147 EXPECT_TRUE(InitializeCodec());
148
149 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
150 kDefaultTargetBitrateBps, kDefaultFrameRate);
151 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
152 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
153 EXPECT_EQ(0U, bitrate_allocation.get_sum_bps());
154}
155
sprang429600d2017-01-26 06:12:26 -0800156TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
157 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
158 streams_.push_back(DefaultScreenshareStream());
159 EXPECT_TRUE(InitializeCodec());
160
161 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
162 EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
163 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
164 kScreenshareCodecTargetBitrateBps, kScreenshareDefaultFramerate);
165 EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
166 bitrate_allocation.get_sum_bps());
167 EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
168}
169
Seth Hampson46e31ba2018-01-18 10:39:54 -0800170TEST_F(VideoCodecInitializerTest, SimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800171 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
172 streams_.push_back(DefaultScreenshareStream());
173 VideoStream video_stream = DefaultStream();
174 video_stream.max_framerate = kScreenshareDefaultFramerate;
175 streams_.push_back(video_stream);
176 EXPECT_TRUE(InitializeCodec());
177
178 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
179 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
180 const uint32_t max_bitrate_bps =
181 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
182 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
183 max_bitrate_bps, kScreenshareDefaultFramerate);
184 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
185 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
186 bitrate_allocation.GetSpatialLayerSum(0));
187 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
188 bitrate_allocation.GetSpatialLayerSum(1));
189}
190
Seth Hampson46e31ba2018-01-18 10:39:54 -0800191// Tests that when a video stream is inactive, then the bitrate allocation will
192// be 0 for that stream.
193TEST_F(VideoCodecInitializerTest, SimulcastVp8ScreenshareInactive) {
194 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
195 streams_.push_back(DefaultScreenshareStream());
196 VideoStream inactive_video_stream = DefaultStream();
197 inactive_video_stream.active = false;
198 inactive_video_stream.max_framerate = kScreenshareDefaultFramerate;
199 streams_.push_back(inactive_video_stream);
200 EXPECT_TRUE(InitializeCodec());
201
202 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
203 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
204 const uint32_t target_bitrate =
205 streams_[0].target_bitrate_bps + streams_[1].target_bitrate_bps;
206 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
207 target_bitrate, kScreenshareDefaultFramerate);
208 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
209 bitrate_allocation.get_sum_bps());
210 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
211 bitrate_allocation.GetSpatialLayerSum(0));
212 EXPECT_EQ(0U, bitrate_allocation.GetSpatialLayerSum(1));
213}
214
215TEST_F(VideoCodecInitializerTest, HighFpsSimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800216 // Two simulcast streams, the lower one using legacy settings (two temporal
217 // streams, 5fps), the higher one using 3 temporal streams and 30fps.
218 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
219 streams_.push_back(DefaultScreenshareStream());
220 VideoStream video_stream = DefaultStream();
Sergey Silkina796a7e2018-03-01 15:11:29 +0100221 video_stream.num_temporal_layers = 3;
sprang429600d2017-01-26 06:12:26 -0800222 streams_.push_back(video_stream);
223 EXPECT_TRUE(InitializeCodec());
224
225 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
226 EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
227 const uint32_t max_bitrate_bps =
228 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
229 BitrateAllocation bitrate_allocation =
230 bitrate_allocator_out_->GetAllocation(max_bitrate_bps, kDefaultFrameRate);
231 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
232 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
233 bitrate_allocation.GetSpatialLayerSum(0));
234 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
235 bitrate_allocation.GetSpatialLayerSum(1));
236 EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
237 EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
238 bitrate_allocation.GetBitrate(1, 1));
239}
240
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -0800241TEST_F(VideoCodecInitializerTest, SingleStreamMultiplexCodec) {
242 SetUpFor(VideoCodecType::kVideoCodecMultiplex, 1, 1, true);
Emircan Uysaler0a375472017-12-11 12:21:02 +0530243 streams_.push_back(DefaultStream());
244 EXPECT_TRUE(InitializeCodec());
245}
246
sprang429600d2017-01-26 06:12:26 -0800247} // namespace webrtc