blob: 335ca6b33219b63f25f9d12dedea84d2033e0624 [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"
Jiawei Ou4206a0a2018-07-20 15:49:43 -070012#include "api/video/video_bitrate_allocator.h"
Erik Språng4529fbc2018-10-12 10:30:31 +020013#include "api/video_codecs/create_vp8_temporal_layers.h"
Sergey Silkin86684962018-03-28 19:32:37 +020014#include "api/video_codecs/video_encoder.h"
Erik Språng4529fbc2018-10-12 10:30:31 +020015#include "api/video_codecs/vp8_temporal_layers.h"
Sergey Silkin86684962018-03-28 19:32:37 +020016#include "common_types.h" // NOLINT(build/include)
Sergey Silkin86684962018-03-28 19:32:37 +020017#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
Niels Möller84255bb2017-10-06 13:43:23 +020018#include "rtc_base/refcountedobject.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gtest.h"
sprang429600d2017-01-26 06:12:26 -080020
21namespace webrtc {
22
23namespace {
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;
Erik Språng5e898d62018-07-06 16:32:20 +020032static const uint32_t kScreenshareTl0BitrateBps = 200000;
sprang429600d2017-01-26 06:12:26 -080033static 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:
Niels Möllerf1338562018-04-26 09:51:47 +020043 VideoCodecInitializerTest() {}
sprang429600d2017-01-26 06:12:26 -080044 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();
Niels Möller259a4972018-04-05 15:36:51 +020052 config_.codec_type = type;
53
sprang429600d2017-01-26 06:12:26 -080054 if (screenshare) {
55 config_.min_transmit_bitrate_bps = kDefaultMinTransmitBitrateBps;
56 config_.content_type = VideoEncoderConfig::ContentType::kScreen;
57 }
58
59 if (type == VideoCodecType::kVideoCodecVP8) {
60 config_.number_of_streams = num_spatial_streams;
61 VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
62 vp8_settings.numberOfTemporalLayers = num_temporal_streams;
63 config_.encoder_specific_settings = new rtc::RefCountedObject<
64 webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
Sergey Silkin86684962018-03-28 19:32:37 +020065 } else if (type == VideoCodecType::kVideoCodecVP9) {
66 VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
67 vp9_settings.numberOfSpatialLayers = num_spatial_streams;
68 vp9_settings.numberOfTemporalLayers = num_temporal_streams;
69 config_.encoder_specific_settings = new rtc::RefCountedObject<
70 webrtc::VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
71 } else if (type != VideoCodecType::kVideoCodecMultiplex) {
sprang429600d2017-01-26 06:12:26 -080072 ADD_FAILURE() << "Unexpected codec type: " << type;
73 }
74 }
75
76 bool InitializeCodec() {
77 codec_out_ = VideoCodec();
78 bitrate_allocator_out_.reset();
79 temporal_layers_.clear();
Yves Gerey665174f2018-06-19 15:03:05 +020080 if (!VideoCodecInitializer::SetupCodec(config_, streams_, &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ång4529fbc2018-10-12 10:30:31 +020090 temporal_layers_.emplace_back(
91 CreateVp8TemporalLayers(Vp8TemporalLayersType::kFixedPattern,
92 codec_out_.VP8()->numberOfTemporalLayers));
sprang429600d2017-01-26 06:12:26 -080093 }
94 }
95 return true;
96 }
97
98 VideoStream DefaultStream() {
99 VideoStream stream;
100 stream.width = kDefaultWidth;
101 stream.height = kDefaultHeight;
102 stream.max_framerate = kDefaultFrameRate;
103 stream.min_bitrate_bps = kDefaultMinBitrateBps;
104 stream.target_bitrate_bps = kDefaultTargetBitrateBps;
105 stream.max_bitrate_bps = kDefaultMaxBitrateBps;
106 stream.max_qp = kDefaultMaxQp;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100107 stream.num_temporal_layers = 1;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800108 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800109 return stream;
110 }
111
112 VideoStream DefaultScreenshareStream() {
113 VideoStream stream = DefaultStream();
114 stream.min_bitrate_bps = 30000;
115 stream.target_bitrate_bps = kScreenshareTl0BitrateBps;
116 stream.max_bitrate_bps = 1000000;
117 stream.max_framerate = kScreenshareDefaultFramerate;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100118 stream.num_temporal_layers = 2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800119 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800120 return stream;
121 }
122
123 // Input settings.
124 VideoEncoderConfig config_;
sprang429600d2017-01-26 06:12:26 -0800125 std::vector<VideoStream> streams_;
sprang429600d2017-01-26 06:12:26 -0800126
127 // Output.
128 VideoCodec codec_out_;
129 std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_out_;
Erik Språng4529fbc2018-10-12 10:30:31 +0200130 std::vector<std::unique_ptr<Vp8TemporalLayers>> temporal_layers_;
sprang429600d2017-01-26 06:12:26 -0800131};
132
133TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
134 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
135 streams_.push_back(DefaultStream());
136 EXPECT_TRUE(InitializeCodec());
137
Erik Språng566124a2018-04-23 12:32:22 +0200138 VideoBitrateAllocation bitrate_allocation =
139 bitrate_allocator_out_->GetAllocation(kDefaultTargetBitrateBps,
140 kDefaultFrameRate);
sprang429600d2017-01-26 06:12:26 -0800141 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
142 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
143 EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
144}
145
Seth Hampson46e31ba2018-01-18 10:39:54 -0800146TEST_F(VideoCodecInitializerTest, SingleStreamVp8ScreenshareInactive) {
147 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
148 VideoStream inactive_stream = DefaultStream();
149 inactive_stream.active = false;
150 streams_.push_back(inactive_stream);
151 EXPECT_TRUE(InitializeCodec());
152
Erik Språng566124a2018-04-23 12:32:22 +0200153 VideoBitrateAllocation bitrate_allocation =
154 bitrate_allocator_out_->GetAllocation(kDefaultTargetBitrateBps,
155 kDefaultFrameRate);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800156 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
157 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
158 EXPECT_EQ(0U, bitrate_allocation.get_sum_bps());
159}
160
sprang429600d2017-01-26 06:12:26 -0800161TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
162 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
163 streams_.push_back(DefaultScreenshareStream());
164 EXPECT_TRUE(InitializeCodec());
165
166 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
167 EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
Erik Språng566124a2018-04-23 12:32:22 +0200168 VideoBitrateAllocation bitrate_allocation =
169 bitrate_allocator_out_->GetAllocation(kScreenshareCodecTargetBitrateBps,
170 kScreenshareDefaultFramerate);
sprang429600d2017-01-26 06:12:26 -0800171 EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
172 bitrate_allocation.get_sum_bps());
173 EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
174}
175
Seth Hampson46e31ba2018-01-18 10:39:54 -0800176TEST_F(VideoCodecInitializerTest, SimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800177 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
178 streams_.push_back(DefaultScreenshareStream());
179 VideoStream video_stream = DefaultStream();
180 video_stream.max_framerate = kScreenshareDefaultFramerate;
181 streams_.push_back(video_stream);
182 EXPECT_TRUE(InitializeCodec());
183
184 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
185 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
186 const uint32_t max_bitrate_bps =
187 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
Erik Språng566124a2018-04-23 12:32:22 +0200188 VideoBitrateAllocation bitrate_allocation =
189 bitrate_allocator_out_->GetAllocation(max_bitrate_bps,
190 kScreenshareDefaultFramerate);
sprang429600d2017-01-26 06:12:26 -0800191 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
192 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
193 bitrate_allocation.GetSpatialLayerSum(0));
194 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
195 bitrate_allocation.GetSpatialLayerSum(1));
196}
197
Seth Hampson46e31ba2018-01-18 10:39:54 -0800198// Tests that when a video stream is inactive, then the bitrate allocation will
199// be 0 for that stream.
200TEST_F(VideoCodecInitializerTest, SimulcastVp8ScreenshareInactive) {
201 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
202 streams_.push_back(DefaultScreenshareStream());
203 VideoStream inactive_video_stream = DefaultStream();
204 inactive_video_stream.active = false;
205 inactive_video_stream.max_framerate = kScreenshareDefaultFramerate;
206 streams_.push_back(inactive_video_stream);
207 EXPECT_TRUE(InitializeCodec());
208
209 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
210 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
211 const uint32_t target_bitrate =
212 streams_[0].target_bitrate_bps + streams_[1].target_bitrate_bps;
Erik Språng566124a2018-04-23 12:32:22 +0200213 VideoBitrateAllocation bitrate_allocation =
214 bitrate_allocator_out_->GetAllocation(target_bitrate,
215 kScreenshareDefaultFramerate);
Seth Hampson46e31ba2018-01-18 10:39:54 -0800216 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
217 bitrate_allocation.get_sum_bps());
218 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
219 bitrate_allocation.GetSpatialLayerSum(0));
220 EXPECT_EQ(0U, bitrate_allocation.GetSpatialLayerSum(1));
221}
222
223TEST_F(VideoCodecInitializerTest, HighFpsSimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800224 // Two simulcast streams, the lower one using legacy settings (two temporal
225 // streams, 5fps), the higher one using 3 temporal streams and 30fps.
226 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
227 streams_.push_back(DefaultScreenshareStream());
228 VideoStream video_stream = DefaultStream();
Sergey Silkina796a7e2018-03-01 15:11:29 +0100229 video_stream.num_temporal_layers = 3;
sprang429600d2017-01-26 06:12:26 -0800230 streams_.push_back(video_stream);
231 EXPECT_TRUE(InitializeCodec());
232
233 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
234 EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
235 const uint32_t max_bitrate_bps =
236 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
Erik Språng566124a2018-04-23 12:32:22 +0200237 VideoBitrateAllocation bitrate_allocation =
sprang429600d2017-01-26 06:12:26 -0800238 bitrate_allocator_out_->GetAllocation(max_bitrate_bps, kDefaultFrameRate);
239 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
240 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
241 bitrate_allocation.GetSpatialLayerSum(0));
242 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
243 bitrate_allocation.GetSpatialLayerSum(1));
244 EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
245 EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
246 bitrate_allocation.GetBitrate(1, 1));
247}
248
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -0800249TEST_F(VideoCodecInitializerTest, SingleStreamMultiplexCodec) {
250 SetUpFor(VideoCodecType::kVideoCodecMultiplex, 1, 1, true);
Emircan Uysaler0a375472017-12-11 12:21:02 +0530251 streams_.push_back(DefaultStream());
252 EXPECT_TRUE(InitializeCodec());
253}
254
Sergey Silkin86684962018-03-28 19:32:37 +0200255TEST_F(VideoCodecInitializerTest, Vp9SvcDefaultLayering) {
256 SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
257 VideoStream stream = DefaultStream();
258 stream.num_temporal_layers = 3;
259 streams_.push_back(stream);
260
261 EXPECT_TRUE(InitializeCodec());
262 EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3u);
263 EXPECT_EQ(codec_out_.VP9()->numberOfTemporalLayers, 3u);
264}
265
266TEST_F(VideoCodecInitializerTest, Vp9SvcAdjustedLayering) {
267 SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
268 VideoStream stream = DefaultStream();
269 stream.num_temporal_layers = 3;
270 // Set resolution which is only enough to produce 2 spatial layers.
271 stream.width = kMinVp9SpatialLayerWidth * 2;
272 stream.height = kMinVp9SpatialLayerHeight * 2;
273
274 streams_.push_back(stream);
275
276 EXPECT_TRUE(InitializeCodec());
277 EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 2u);
278}
279
Sergey Silkinfafeac32018-04-13 16:36:39 +0200280TEST_F(VideoCodecInitializerTest,
281 Vp9SingleSpatialLayerMaxBitrateIsEqualToCodecMaxBitrate) {
282 SetUpFor(VideoCodecType::kVideoCodecVP9, 1, 3, false);
283 VideoStream stream = DefaultStream();
284 stream.num_temporal_layers = 3;
285 streams_.push_back(stream);
286
287 EXPECT_TRUE(InitializeCodec());
288 EXPECT_EQ(codec_out_.spatialLayers[0].maxBitrate,
289 kDefaultMaxBitrateBps / 1000);
290}
291
sprang429600d2017-01-26 06:12:26 -0800292} // namespace webrtc