blob: 3a69d999a537a0d7875dfda854eef43332618b4d [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 {
sprang429600d2017-01-26 06:12:26 -080022static const int kDefaultWidth = 1280;
23static const int kDefaultHeight = 720;
24static const int kDefaultFrameRate = 30;
25static const uint32_t kDefaultMinBitrateBps = 60000;
26static const uint32_t kDefaultTargetBitrateBps = 2000000;
27static const uint32_t kDefaultMaxBitrateBps = 2000000;
28static const uint32_t kDefaultMinTransmitBitrateBps = 400000;
29static const int kDefaultMaxQp = 48;
30static const uint32_t kScreenshareTl0BitrateBps = 100000;
31static const uint32_t kScreenshareCodecTargetBitrateBps = 200000;
32static const uint32_t kScreenshareDefaultFramerate = 5;
33// Bitrates for the temporal layers of the higher screenshare simulcast stream.
34static const uint32_t kHighScreenshareTl0Bps = 800000;
35static const uint32_t kHighScreenshareTl1Bps = 1200000;
36} // namespace
37
sprang429600d2017-01-26 06:12:26 -080038// TODO(sprang): Extend coverage to handle the rest of the codec initializer.
39class VideoCodecInitializerTest : public ::testing::Test {
40 public:
41 VideoCodecInitializerTest() : nack_enabled_(false) {}
42 virtual ~VideoCodecInitializerTest() {}
43
44 protected:
45 void SetUpFor(VideoCodecType type,
46 int num_spatial_streams,
47 int num_temporal_streams,
48 bool screenshare) {
49 config_ = VideoEncoderConfig();
Niels Möller04dd1762018-03-23 16:05:22 +010050 config_.codec_type = type;
51
sprang429600d2017-01-26 06:12:26 -080052 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);
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080063 } else if (type == VideoCodecType::kVideoCodecMultiplex) {
sprang429600d2017-01-26 06:12:26 -080064 } else {
65 ADD_FAILURE() << "Unexpected codec type: " << type;
66 }
67 }
68
69 bool InitializeCodec() {
70 codec_out_ = VideoCodec();
71 bitrate_allocator_out_.reset();
72 temporal_layers_.clear();
Niels Möller04dd1762018-03-23 16:05:22 +010073 if (!VideoCodecInitializer::SetupCodec(config_, streams_, nack_enabled_,
74 &codec_out_,
sprang429600d2017-01-26 06:12:26 -080075 &bitrate_allocator_out_)) {
76 return false;
77 }
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080078 if (codec_out_.codecType == VideoCodecType::kVideoCodecMultiplex)
Emircan Uysaler0a375472017-12-11 12:21:02 +053079 return true;
Erik Språng82fad3d2018-03-21 09:57:23 +010080
sprang429600d2017-01-26 06:12:26 -080081 // Make sure temporal layers instances have been created.
82 if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
sprang429600d2017-01-26 06:12:26 -080083 for (int i = 0; i < codec_out_.numberOfSimulcastStreams; ++i) {
Erik Språng82fad3d2018-03-21 09:57:23 +010084 temporal_layers_.emplace_back(
Niels Möller150dcb02018-03-27 14:16:55 +020085 TemporalLayers::CreateTemporalLayers(codec_out_, i));
sprang429600d2017-01-26 06:12:26 -080086 }
87 }
88 return true;
89 }
90
91 VideoStream DefaultStream() {
92 VideoStream stream;
93 stream.width = kDefaultWidth;
94 stream.height = kDefaultHeight;
95 stream.max_framerate = kDefaultFrameRate;
96 stream.min_bitrate_bps = kDefaultMinBitrateBps;
97 stream.target_bitrate_bps = kDefaultTargetBitrateBps;
98 stream.max_bitrate_bps = kDefaultMaxBitrateBps;
99 stream.max_qp = kDefaultMaxQp;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100100 stream.num_temporal_layers = 1;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800101 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800102 return stream;
103 }
104
105 VideoStream DefaultScreenshareStream() {
106 VideoStream stream = DefaultStream();
107 stream.min_bitrate_bps = 30000;
108 stream.target_bitrate_bps = kScreenshareTl0BitrateBps;
109 stream.max_bitrate_bps = 1000000;
110 stream.max_framerate = kScreenshareDefaultFramerate;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100111 stream.num_temporal_layers = 2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800112 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800113 return stream;
114 }
115
116 // Input settings.
117 VideoEncoderConfig config_;
sprang429600d2017-01-26 06:12:26 -0800118 std::vector<VideoStream> streams_;
119 bool nack_enabled_;
120
121 // Output.
122 VideoCodec codec_out_;
123 std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_out_;
124 std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_;
125};
126
127TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
128 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
129 streams_.push_back(DefaultStream());
130 EXPECT_TRUE(InitializeCodec());
131
132 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
133 kDefaultTargetBitrateBps, kDefaultFrameRate);
134 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
135 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
136 EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
137}
138
Seth Hampson46e31ba2018-01-18 10:39:54 -0800139TEST_F(VideoCodecInitializerTest, SingleStreamVp8ScreenshareInactive) {
140 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
141 VideoStream inactive_stream = DefaultStream();
142 inactive_stream.active = false;
143 streams_.push_back(inactive_stream);
144 EXPECT_TRUE(InitializeCodec());
145
146 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
147 kDefaultTargetBitrateBps, kDefaultFrameRate);
148 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
149 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
150 EXPECT_EQ(0U, bitrate_allocation.get_sum_bps());
151}
152
sprang429600d2017-01-26 06:12:26 -0800153TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
154 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
155 streams_.push_back(DefaultScreenshareStream());
156 EXPECT_TRUE(InitializeCodec());
157
158 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
159 EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
160 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
161 kScreenshareCodecTargetBitrateBps, kScreenshareDefaultFramerate);
162 EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
163 bitrate_allocation.get_sum_bps());
164 EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
165}
166
Seth Hampson46e31ba2018-01-18 10:39:54 -0800167TEST_F(VideoCodecInitializerTest, SimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800168 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
169 streams_.push_back(DefaultScreenshareStream());
170 VideoStream video_stream = DefaultStream();
171 video_stream.max_framerate = kScreenshareDefaultFramerate;
172 streams_.push_back(video_stream);
173 EXPECT_TRUE(InitializeCodec());
174
175 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
176 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
177 const uint32_t max_bitrate_bps =
178 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
179 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
180 max_bitrate_bps, kScreenshareDefaultFramerate);
181 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
182 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
183 bitrate_allocation.GetSpatialLayerSum(0));
184 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
185 bitrate_allocation.GetSpatialLayerSum(1));
186}
187
Seth Hampson46e31ba2018-01-18 10:39:54 -0800188// Tests that when a video stream is inactive, then the bitrate allocation will
189// be 0 for that stream.
190TEST_F(VideoCodecInitializerTest, SimulcastVp8ScreenshareInactive) {
191 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
192 streams_.push_back(DefaultScreenshareStream());
193 VideoStream inactive_video_stream = DefaultStream();
194 inactive_video_stream.active = false;
195 inactive_video_stream.max_framerate = kScreenshareDefaultFramerate;
196 streams_.push_back(inactive_video_stream);
197 EXPECT_TRUE(InitializeCodec());
198
199 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
200 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
201 const uint32_t target_bitrate =
202 streams_[0].target_bitrate_bps + streams_[1].target_bitrate_bps;
203 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
204 target_bitrate, kScreenshareDefaultFramerate);
205 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
206 bitrate_allocation.get_sum_bps());
207 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
208 bitrate_allocation.GetSpatialLayerSum(0));
209 EXPECT_EQ(0U, bitrate_allocation.GetSpatialLayerSum(1));
210}
211
212TEST_F(VideoCodecInitializerTest, HighFpsSimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800213 // Two simulcast streams, the lower one using legacy settings (two temporal
214 // streams, 5fps), the higher one using 3 temporal streams and 30fps.
215 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
216 streams_.push_back(DefaultScreenshareStream());
217 VideoStream video_stream = DefaultStream();
Sergey Silkina796a7e2018-03-01 15:11:29 +0100218 video_stream.num_temporal_layers = 3;
sprang429600d2017-01-26 06:12:26 -0800219 streams_.push_back(video_stream);
220 EXPECT_TRUE(InitializeCodec());
221
222 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
223 EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
224 const uint32_t max_bitrate_bps =
225 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
226 BitrateAllocation bitrate_allocation =
227 bitrate_allocator_out_->GetAllocation(max_bitrate_bps, kDefaultFrameRate);
228 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
229 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
230 bitrate_allocation.GetSpatialLayerSum(0));
231 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
232 bitrate_allocation.GetSpatialLayerSum(1));
233 EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
234 EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
235 bitrate_allocation.GetBitrate(1, 1));
236}
237
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -0800238TEST_F(VideoCodecInitializerTest, SingleStreamMultiplexCodec) {
239 SetUpFor(VideoCodecType::kVideoCodecMultiplex, 1, 1, true);
Emircan Uysaler0a375472017-12-11 12:21:02 +0530240 streams_.push_back(DefaultStream());
241 EXPECT_TRUE(InitializeCodec());
242}
243
sprang429600d2017-01-26 06:12:26 -0800244} // namespace webrtc