blob: 104b149c000ce0f3f181b5b4ae0451c96ae51640 [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 "modules/video_coding/include/video_codec_initializer.h"
Sergey Silkin86684962018-03-28 19:32:37 +020012#include "api/video_codecs/video_encoder.h"
13#include "common_types.h" // NOLINT(build/include)
14#include "common_video/include/video_bitrate_allocator.h"
15#include "modules/video_coding/codecs/vp8/temporal_layers.h"
16#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Niels Möller84255bb2017-10-06 13:43:23 +020017#include "rtc_base/refcountedobject.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "test/gtest.h"
sprang429600d2017-01-26 06:12:26 -080019
20namespace webrtc {
21
22namespace {
sprang429600d2017-01-26 06:12:26 -080023static const int kDefaultWidth = 1280;
24static const int kDefaultHeight = 720;
25static const int kDefaultFrameRate = 30;
26static const uint32_t kDefaultMinBitrateBps = 60000;
27static const uint32_t kDefaultTargetBitrateBps = 2000000;
28static const uint32_t kDefaultMaxBitrateBps = 2000000;
29static const uint32_t kDefaultMinTransmitBitrateBps = 400000;
30static const int kDefaultMaxQp = 48;
31static const uint32_t kScreenshareTl0BitrateBps = 100000;
32static const uint32_t kScreenshareCodecTargetBitrateBps = 200000;
33static const uint32_t kScreenshareDefaultFramerate = 5;
34// Bitrates for the temporal layers of the higher screenshare simulcast stream.
35static const uint32_t kHighScreenshareTl0Bps = 800000;
36static const uint32_t kHighScreenshareTl1Bps = 1200000;
37} // namespace
38
sprang429600d2017-01-26 06:12:26 -080039// TODO(sprang): Extend coverage to handle the rest of the codec initializer.
40class VideoCodecInitializerTest : public ::testing::Test {
41 public:
Niels Möllerf1338562018-04-26 09:51:47 +020042 VideoCodecInitializerTest() {}
sprang429600d2017-01-26 06:12:26 -080043 virtual ~VideoCodecInitializerTest() {}
44
45 protected:
46 void SetUpFor(VideoCodecType type,
47 int num_spatial_streams,
48 int num_temporal_streams,
49 bool screenshare) {
50 config_ = VideoEncoderConfig();
Niels Möller259a4972018-04-05 15:36:51 +020051 config_.codec_type = type;
52
sprang429600d2017-01-26 06:12:26 -080053 if (screenshare) {
54 config_.min_transmit_bitrate_bps = kDefaultMinTransmitBitrateBps;
55 config_.content_type = VideoEncoderConfig::ContentType::kScreen;
56 }
57
58 if (type == VideoCodecType::kVideoCodecVP8) {
59 config_.number_of_streams = num_spatial_streams;
60 VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
61 vp8_settings.numberOfTemporalLayers = num_temporal_streams;
62 config_.encoder_specific_settings = new rtc::RefCountedObject<
63 webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
Sergey Silkin86684962018-03-28 19:32:37 +020064 } else if (type == VideoCodecType::kVideoCodecVP9) {
65 VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
66 vp9_settings.numberOfSpatialLayers = num_spatial_streams;
67 vp9_settings.numberOfTemporalLayers = num_temporal_streams;
68 config_.encoder_specific_settings = new rtc::RefCountedObject<
69 webrtc::VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
70 } else if (type != VideoCodecType::kVideoCodecMultiplex) {
sprang429600d2017-01-26 06:12:26 -080071 ADD_FAILURE() << "Unexpected codec type: " << type;
72 }
73 }
74
75 bool InitializeCodec() {
76 codec_out_ = VideoCodec();
77 bitrate_allocator_out_.reset();
78 temporal_layers_.clear();
Niels Möllerf1338562018-04-26 09:51:47 +020079 if (!VideoCodecInitializer::SetupCodec(config_, streams_,
Niels Möller259a4972018-04-05 15:36:51 +020080 &codec_out_,
sprang429600d2017-01-26 06:12:26 -080081 &bitrate_allocator_out_)) {
82 return false;
83 }
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080084 if (codec_out_.codecType == VideoCodecType::kVideoCodecMultiplex)
Emircan Uysaler0a375472017-12-11 12:21:02 +053085 return true;
Erik Språng82fad3d2018-03-21 09:57:23 +010086
sprang429600d2017-01-26 06:12:26 -080087 // Make sure temporal layers instances have been created.
88 if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
sprang429600d2017-01-26 06:12:26 -080089 for (int i = 0; i < codec_out_.numberOfSimulcastStreams; ++i) {
Erik Språng82fad3d2018-03-21 09:57:23 +010090 temporal_layers_.emplace_back(
Niels Möller150dcb02018-03-27 14:16:55 +020091 TemporalLayers::CreateTemporalLayers(codec_out_, i));
sprang429600d2017-01-26 06:12:26 -080092 }
93 }
94 return true;
95 }
96
97 VideoStream DefaultStream() {
98 VideoStream stream;
99 stream.width = kDefaultWidth;
100 stream.height = kDefaultHeight;
101 stream.max_framerate = kDefaultFrameRate;
102 stream.min_bitrate_bps = kDefaultMinBitrateBps;
103 stream.target_bitrate_bps = kDefaultTargetBitrateBps;
104 stream.max_bitrate_bps = kDefaultMaxBitrateBps;
105 stream.max_qp = kDefaultMaxQp;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100106 stream.num_temporal_layers = 1;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800107 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800108 return stream;
109 }
110
111 VideoStream DefaultScreenshareStream() {
112 VideoStream stream = DefaultStream();
113 stream.min_bitrate_bps = 30000;
114 stream.target_bitrate_bps = kScreenshareTl0BitrateBps;
115 stream.max_bitrate_bps = 1000000;
116 stream.max_framerate = kScreenshareDefaultFramerate;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100117 stream.num_temporal_layers = 2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800118 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800119 return stream;
120 }
121
122 // Input settings.
123 VideoEncoderConfig config_;
sprang429600d2017-01-26 06:12:26 -0800124 std::vector<VideoStream> streams_;
sprang429600d2017-01-26 06:12:26 -0800125
126 // Output.
127 VideoCodec codec_out_;
128 std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_out_;
129 std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_;
130};
131
132TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
133 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
134 streams_.push_back(DefaultStream());
135 EXPECT_TRUE(InitializeCodec());
136
Erik Språng566124a2018-04-23 12:32:22 +0200137 VideoBitrateAllocation bitrate_allocation =
138 bitrate_allocator_out_->GetAllocation(kDefaultTargetBitrateBps,
139 kDefaultFrameRate);
sprang429600d2017-01-26 06:12:26 -0800140 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
141 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
142 EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
143}
144
Seth Hampson46e31ba2018-01-18 10:39:54 -0800145TEST_F(VideoCodecInitializerTest, SingleStreamVp8ScreenshareInactive) {
146 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
147 VideoStream inactive_stream = DefaultStream();
148 inactive_stream.active = false;
149 streams_.push_back(inactive_stream);
150 EXPECT_TRUE(InitializeCodec());
151
Erik Språng566124a2018-04-23 12:32:22 +0200152 VideoBitrateAllocation bitrate_allocation =
153 bitrate_allocator_out_->GetAllocation(kDefaultTargetBitrateBps,
154 kDefaultFrameRate);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800155 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
156 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
157 EXPECT_EQ(0U, bitrate_allocation.get_sum_bps());
158}
159
sprang429600d2017-01-26 06:12:26 -0800160TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
161 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
162 streams_.push_back(DefaultScreenshareStream());
163 EXPECT_TRUE(InitializeCodec());
164
165 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
166 EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
Erik Språng566124a2018-04-23 12:32:22 +0200167 VideoBitrateAllocation bitrate_allocation =
168 bitrate_allocator_out_->GetAllocation(kScreenshareCodecTargetBitrateBps,
169 kScreenshareDefaultFramerate);
sprang429600d2017-01-26 06:12:26 -0800170 EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
171 bitrate_allocation.get_sum_bps());
172 EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
173}
174
Seth Hampson46e31ba2018-01-18 10:39:54 -0800175TEST_F(VideoCodecInitializerTest, SimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800176 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
177 streams_.push_back(DefaultScreenshareStream());
178 VideoStream video_stream = DefaultStream();
179 video_stream.max_framerate = kScreenshareDefaultFramerate;
180 streams_.push_back(video_stream);
181 EXPECT_TRUE(InitializeCodec());
182
183 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
184 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
185 const uint32_t max_bitrate_bps =
186 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
Erik Språng566124a2018-04-23 12:32:22 +0200187 VideoBitrateAllocation bitrate_allocation =
188 bitrate_allocator_out_->GetAllocation(max_bitrate_bps,
189 kScreenshareDefaultFramerate);
sprang429600d2017-01-26 06:12:26 -0800190 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
191 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
192 bitrate_allocation.GetSpatialLayerSum(0));
193 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
194 bitrate_allocation.GetSpatialLayerSum(1));
195}
196
Seth Hampson46e31ba2018-01-18 10:39:54 -0800197// Tests that when a video stream is inactive, then the bitrate allocation will
198// be 0 for that stream.
199TEST_F(VideoCodecInitializerTest, SimulcastVp8ScreenshareInactive) {
200 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
201 streams_.push_back(DefaultScreenshareStream());
202 VideoStream inactive_video_stream = DefaultStream();
203 inactive_video_stream.active = false;
204 inactive_video_stream.max_framerate = kScreenshareDefaultFramerate;
205 streams_.push_back(inactive_video_stream);
206 EXPECT_TRUE(InitializeCodec());
207
208 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
209 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
210 const uint32_t target_bitrate =
211 streams_[0].target_bitrate_bps + streams_[1].target_bitrate_bps;
Erik Språng566124a2018-04-23 12:32:22 +0200212 VideoBitrateAllocation bitrate_allocation =
213 bitrate_allocator_out_->GetAllocation(target_bitrate,
214 kScreenshareDefaultFramerate);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800215 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
216 bitrate_allocation.get_sum_bps());
217 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
218 bitrate_allocation.GetSpatialLayerSum(0));
219 EXPECT_EQ(0U, bitrate_allocation.GetSpatialLayerSum(1));
220}
221
222TEST_F(VideoCodecInitializerTest, HighFpsSimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800223 // Two simulcast streams, the lower one using legacy settings (two temporal
224 // streams, 5fps), the higher one using 3 temporal streams and 30fps.
225 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
226 streams_.push_back(DefaultScreenshareStream());
227 VideoStream video_stream = DefaultStream();
Sergey Silkina796a7e2018-03-01 15:11:29 +0100228 video_stream.num_temporal_layers = 3;
sprang429600d2017-01-26 06:12:26 -0800229 streams_.push_back(video_stream);
230 EXPECT_TRUE(InitializeCodec());
231
232 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
233 EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
234 const uint32_t max_bitrate_bps =
235 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
Erik Språng566124a2018-04-23 12:32:22 +0200236 VideoBitrateAllocation bitrate_allocation =
sprang429600d2017-01-26 06:12:26 -0800237 bitrate_allocator_out_->GetAllocation(max_bitrate_bps, kDefaultFrameRate);
238 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
239 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
240 bitrate_allocation.GetSpatialLayerSum(0));
241 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
242 bitrate_allocation.GetSpatialLayerSum(1));
243 EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
244 EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
245 bitrate_allocation.GetBitrate(1, 1));
246}
247
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -0800248TEST_F(VideoCodecInitializerTest, SingleStreamMultiplexCodec) {
249 SetUpFor(VideoCodecType::kVideoCodecMultiplex, 1, 1, true);
Emircan Uysaler0a375472017-12-11 12:21:02 +0530250 streams_.push_back(DefaultStream());
251 EXPECT_TRUE(InitializeCodec());
252}
253
Sergey Silkin86684962018-03-28 19:32:37 +0200254TEST_F(VideoCodecInitializerTest, Vp9SvcDefaultLayering) {
255 SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
256 VideoStream stream = DefaultStream();
257 stream.num_temporal_layers = 3;
258 streams_.push_back(stream);
259
260 EXPECT_TRUE(InitializeCodec());
261 EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3u);
262 EXPECT_EQ(codec_out_.VP9()->numberOfTemporalLayers, 3u);
263}
264
265TEST_F(VideoCodecInitializerTest, Vp9SvcAdjustedLayering) {
266 SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
267 VideoStream stream = DefaultStream();
268 stream.num_temporal_layers = 3;
269 // Set resolution which is only enough to produce 2 spatial layers.
270 stream.width = kMinVp9SpatialLayerWidth * 2;
271 stream.height = kMinVp9SpatialLayerHeight * 2;
272
273 streams_.push_back(stream);
274
275 EXPECT_TRUE(InitializeCodec());
276 EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 2u);
277}
278
Sergey Silkinfafeac32018-04-13 16:36:39 +0200279TEST_F(VideoCodecInitializerTest,
280 Vp9SingleSpatialLayerMaxBitrateIsEqualToCodecMaxBitrate) {
281 SetUpFor(VideoCodecType::kVideoCodecVP9, 1, 3, false);
282 VideoStream stream = DefaultStream();
283 stream.num_temporal_layers = 3;
284 streams_.push_back(stream);
285
286 EXPECT_TRUE(InitializeCodec());
287 EXPECT_EQ(codec_out_.spatialLayers[0].maxBitrate,
288 kDefaultMaxBitrateBps / 1000);
289}
290
sprang429600d2017-01-26 06:12:26 -0800291} // namespace webrtc