blob: 46e26470abba76573f1aa93df2608bbb441f344b [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 {
22static const char* kVp8PayloadName = "VP8";
23static const int kVp8PayloadType = 100;
24static 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
40/*
41 * static bool SetupCodec(
42 const VideoEncoderConfig& config,
43 const VideoSendStream::Config::EncoderSettings settings,
44 const std::vector<VideoStream>& streams,
45 bool nack_enabled,
46 VideoCodec* codec,
47 std::unique_ptr<VideoBitrateAllocator>* bitrate_allocator);
48
49 // Create a bitrate allocator for the specified codec. |tl_factory| is
50 // optional, if it is populated, ownership of that instance will be
51 // transferred to the VideoBitrateAllocator instance.
52 static std::unique_ptr<VideoBitrateAllocator> CreateBitrateAllocator(
53 const VideoCodec& codec,
54 std::unique_ptr<TemporalLayersFactory> tl_factory);
55 */
56
57// TODO(sprang): Extend coverage to handle the rest of the codec initializer.
58class VideoCodecInitializerTest : public ::testing::Test {
59 public:
60 VideoCodecInitializerTest() : nack_enabled_(false) {}
61 virtual ~VideoCodecInitializerTest() {}
62
63 protected:
64 void SetUpFor(VideoCodecType type,
65 int num_spatial_streams,
66 int num_temporal_streams,
67 bool screenshare) {
68 config_ = VideoEncoderConfig();
69 if (screenshare) {
70 config_.min_transmit_bitrate_bps = kDefaultMinTransmitBitrateBps;
71 config_.content_type = VideoEncoderConfig::ContentType::kScreen;
72 }
73
74 if (type == VideoCodecType::kVideoCodecVP8) {
75 config_.number_of_streams = num_spatial_streams;
76 VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
77 vp8_settings.numberOfTemporalLayers = num_temporal_streams;
78 config_.encoder_specific_settings = new rtc::RefCountedObject<
79 webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
80 settings_.payload_name = kVp8PayloadName;
81 settings_.payload_type = kVp8PayloadType;
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080082 } else if (type == VideoCodecType::kVideoCodecMultiplex) {
sprang429600d2017-01-26 06:12:26 -080083 } else {
84 ADD_FAILURE() << "Unexpected codec type: " << type;
85 }
86 }
87
88 bool InitializeCodec() {
89 codec_out_ = VideoCodec();
90 bitrate_allocator_out_.reset();
91 temporal_layers_.clear();
92 if (!VideoCodecInitializer::SetupCodec(config_, settings_, streams_,
93 nack_enabled_, &codec_out_,
94 &bitrate_allocator_out_)) {
95 return false;
96 }
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -080097 if (codec_out_.codecType == VideoCodecType::kVideoCodecMultiplex)
Emircan Uysaler0a375472017-12-11 12:21:02 +053098 return true;
sprang429600d2017-01-26 06:12:26 -080099 // Make sure temporal layers instances have been created.
100 if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
101 if (!codec_out_.VP8()->tl_factory)
102 return false;
103
104 for (int i = 0; i < codec_out_.numberOfSimulcastStreams; ++i) {
105 temporal_layers_.emplace_back(codec_out_.VP8()->tl_factory->Create(
Sergey Silkina796a7e2018-03-01 15:11:29 +0100106 i, *streams_[i].num_temporal_layers, 0));
sprang429600d2017-01-26 06:12:26 -0800107 }
108 }
109 return true;
110 }
111
112 VideoStream DefaultStream() {
113 VideoStream stream;
114 stream.width = kDefaultWidth;
115 stream.height = kDefaultHeight;
116 stream.max_framerate = kDefaultFrameRate;
117 stream.min_bitrate_bps = kDefaultMinBitrateBps;
118 stream.target_bitrate_bps = kDefaultTargetBitrateBps;
119 stream.max_bitrate_bps = kDefaultMaxBitrateBps;
120 stream.max_qp = kDefaultMaxQp;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100121 stream.num_temporal_layers = 1;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800122 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800123 return stream;
124 }
125
126 VideoStream DefaultScreenshareStream() {
127 VideoStream stream = DefaultStream();
128 stream.min_bitrate_bps = 30000;
129 stream.target_bitrate_bps = kScreenshareTl0BitrateBps;
130 stream.max_bitrate_bps = 1000000;
131 stream.max_framerate = kScreenshareDefaultFramerate;
Sergey Silkina796a7e2018-03-01 15:11:29 +0100132 stream.num_temporal_layers = 2;
Seth Hampson46e31ba2018-01-18 10:39:54 -0800133 stream.active = true;
sprang429600d2017-01-26 06:12:26 -0800134 return stream;
135 }
136
137 // Input settings.
138 VideoEncoderConfig config_;
139 VideoSendStream::Config::EncoderSettings settings_;
140 std::vector<VideoStream> streams_;
141 bool nack_enabled_;
142
143 // Output.
144 VideoCodec codec_out_;
145 std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_out_;
146 std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_;
147};
148
149TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
150 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
151 streams_.push_back(DefaultStream());
152 EXPECT_TRUE(InitializeCodec());
153
154 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
155 kDefaultTargetBitrateBps, kDefaultFrameRate);
156 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
157 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
158 EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
159}
160
Seth Hampson46e31ba2018-01-18 10:39:54 -0800161TEST_F(VideoCodecInitializerTest, SingleStreamVp8ScreenshareInactive) {
162 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
163 VideoStream inactive_stream = DefaultStream();
164 inactive_stream.active = false;
165 streams_.push_back(inactive_stream);
166 EXPECT_TRUE(InitializeCodec());
167
168 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
169 kDefaultTargetBitrateBps, kDefaultFrameRate);
170 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
171 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
172 EXPECT_EQ(0U, bitrate_allocation.get_sum_bps());
173}
174
sprang429600d2017-01-26 06:12:26 -0800175TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
176 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
177 streams_.push_back(DefaultScreenshareStream());
178 EXPECT_TRUE(InitializeCodec());
179
180 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
181 EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
182 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
183 kScreenshareCodecTargetBitrateBps, kScreenshareDefaultFramerate);
184 EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
185 bitrate_allocation.get_sum_bps());
186 EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
187}
188
Seth Hampson46e31ba2018-01-18 10:39:54 -0800189TEST_F(VideoCodecInitializerTest, SimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800190 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
191 streams_.push_back(DefaultScreenshareStream());
192 VideoStream video_stream = DefaultStream();
193 video_stream.max_framerate = kScreenshareDefaultFramerate;
194 streams_.push_back(video_stream);
195 EXPECT_TRUE(InitializeCodec());
196
197 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
198 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
199 const uint32_t max_bitrate_bps =
200 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
201 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
202 max_bitrate_bps, kScreenshareDefaultFramerate);
203 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
204 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
205 bitrate_allocation.GetSpatialLayerSum(0));
206 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
207 bitrate_allocation.GetSpatialLayerSum(1));
208}
209
Seth Hampson46e31ba2018-01-18 10:39:54 -0800210// Tests that when a video stream is inactive, then the bitrate allocation will
211// be 0 for that stream.
212TEST_F(VideoCodecInitializerTest, SimulcastVp8ScreenshareInactive) {
213 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
214 streams_.push_back(DefaultScreenshareStream());
215 VideoStream inactive_video_stream = DefaultStream();
216 inactive_video_stream.active = false;
217 inactive_video_stream.max_framerate = kScreenshareDefaultFramerate;
218 streams_.push_back(inactive_video_stream);
219 EXPECT_TRUE(InitializeCodec());
220
221 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
222 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
223 const uint32_t target_bitrate =
224 streams_[0].target_bitrate_bps + streams_[1].target_bitrate_bps;
225 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
226 target_bitrate, kScreenshareDefaultFramerate);
227 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
228 bitrate_allocation.get_sum_bps());
229 EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
230 bitrate_allocation.GetSpatialLayerSum(0));
231 EXPECT_EQ(0U, bitrate_allocation.GetSpatialLayerSum(1));
232}
233
234TEST_F(VideoCodecInitializerTest, HighFpsSimulcastVp8Screenshare) {
sprang429600d2017-01-26 06:12:26 -0800235 // Two simulcast streams, the lower one using legacy settings (two temporal
236 // streams, 5fps), the higher one using 3 temporal streams and 30fps.
237 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
238 streams_.push_back(DefaultScreenshareStream());
239 VideoStream video_stream = DefaultStream();
Sergey Silkina796a7e2018-03-01 15:11:29 +0100240 video_stream.num_temporal_layers = 3;
sprang429600d2017-01-26 06:12:26 -0800241 streams_.push_back(video_stream);
242 EXPECT_TRUE(InitializeCodec());
243
244 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
245 EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
246 const uint32_t max_bitrate_bps =
247 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
248 BitrateAllocation bitrate_allocation =
249 bitrate_allocator_out_->GetAllocation(max_bitrate_bps, kDefaultFrameRate);
250 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
251 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
252 bitrate_allocation.GetSpatialLayerSum(0));
253 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
254 bitrate_allocation.GetSpatialLayerSum(1));
255 EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
256 EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
257 bitrate_allocation.GetBitrate(1, 1));
258}
259
Emircan Uysalerd7ae3c32018-01-25 13:01:09 -0800260TEST_F(VideoCodecInitializerTest, SingleStreamMultiplexCodec) {
261 SetUpFor(VideoCodecType::kVideoCodecMultiplex, 1, 1, true);
Emircan Uysaler0a375472017-12-11 12:21:02 +0530262 streams_.push_back(DefaultStream());
263 EXPECT_TRUE(InitializeCodec());
264}
265
sprang429600d2017-01-26 06:12:26 -0800266} // namespace webrtc