blob: 99239c59ec75f802256b464a0ec46b85189b83c8 [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"
16#include "test/gtest.h"
sprang429600d2017-01-26 06:12:26 -080017
18namespace webrtc {
19
20namespace {
21static const char* kVp8PayloadName = "VP8";
22static const int kVp8PayloadType = 100;
23static 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
39/*
40 * static bool SetupCodec(
41 const VideoEncoderConfig& config,
42 const VideoSendStream::Config::EncoderSettings settings,
43 const std::vector<VideoStream>& streams,
44 bool nack_enabled,
45 VideoCodec* codec,
46 std::unique_ptr<VideoBitrateAllocator>* bitrate_allocator);
47
48 // Create a bitrate allocator for the specified codec. |tl_factory| is
49 // optional, if it is populated, ownership of that instance will be
50 // transferred to the VideoBitrateAllocator instance.
51 static std::unique_ptr<VideoBitrateAllocator> CreateBitrateAllocator(
52 const VideoCodec& codec,
53 std::unique_ptr<TemporalLayersFactory> tl_factory);
54 */
55
56// TODO(sprang): Extend coverage to handle the rest of the codec initializer.
57class VideoCodecInitializerTest : public ::testing::Test {
58 public:
59 VideoCodecInitializerTest() : nack_enabled_(false) {}
60 virtual ~VideoCodecInitializerTest() {}
61
62 protected:
63 void SetUpFor(VideoCodecType type,
64 int num_spatial_streams,
65 int num_temporal_streams,
66 bool screenshare) {
67 config_ = VideoEncoderConfig();
68 if (screenshare) {
69 config_.min_transmit_bitrate_bps = kDefaultMinTransmitBitrateBps;
70 config_.content_type = VideoEncoderConfig::ContentType::kScreen;
71 }
72
73 if (type == VideoCodecType::kVideoCodecVP8) {
74 config_.number_of_streams = num_spatial_streams;
75 VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
76 vp8_settings.numberOfTemporalLayers = num_temporal_streams;
77 config_.encoder_specific_settings = new rtc::RefCountedObject<
78 webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
79 settings_.payload_name = kVp8PayloadName;
80 settings_.payload_type = kVp8PayloadType;
81 } else {
82 ADD_FAILURE() << "Unexpected codec type: " << type;
83 }
84 }
85
86 bool InitializeCodec() {
87 codec_out_ = VideoCodec();
88 bitrate_allocator_out_.reset();
89 temporal_layers_.clear();
90 if (!VideoCodecInitializer::SetupCodec(config_, settings_, streams_,
91 nack_enabled_, &codec_out_,
92 &bitrate_allocator_out_)) {
93 return false;
94 }
95
96 // Make sure temporal layers instances have been created.
97 if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
98 if (!codec_out_.VP8()->tl_factory)
99 return false;
100
101 for (int i = 0; i < codec_out_.numberOfSimulcastStreams; ++i) {
102 temporal_layers_.emplace_back(codec_out_.VP8()->tl_factory->Create(
103 i, streams_[i].temporal_layer_thresholds_bps.size() + 1, 0));
104 }
105 }
106 return true;
107 }
108
109 VideoStream DefaultStream() {
110 VideoStream stream;
111 stream.width = kDefaultWidth;
112 stream.height = kDefaultHeight;
113 stream.max_framerate = kDefaultFrameRate;
114 stream.min_bitrate_bps = kDefaultMinBitrateBps;
115 stream.target_bitrate_bps = kDefaultTargetBitrateBps;
116 stream.max_bitrate_bps = kDefaultMaxBitrateBps;
117 stream.max_qp = kDefaultMaxQp;
118 return stream;
119 }
120
121 VideoStream DefaultScreenshareStream() {
122 VideoStream stream = DefaultStream();
123 stream.min_bitrate_bps = 30000;
124 stream.target_bitrate_bps = kScreenshareTl0BitrateBps;
125 stream.max_bitrate_bps = 1000000;
126 stream.max_framerate = kScreenshareDefaultFramerate;
127 stream.temporal_layer_thresholds_bps.push_back(kScreenshareTl0BitrateBps);
128 return stream;
129 }
130
131 // Input settings.
132 VideoEncoderConfig config_;
133 VideoSendStream::Config::EncoderSettings settings_;
134 std::vector<VideoStream> streams_;
135 bool nack_enabled_;
136
137 // Output.
138 VideoCodec codec_out_;
139 std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_out_;
140 std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_;
141};
142
143TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
144 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
145 streams_.push_back(DefaultStream());
146 EXPECT_TRUE(InitializeCodec());
147
148 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
149 kDefaultTargetBitrateBps, kDefaultFrameRate);
150 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
151 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
152 EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
153}
154
155TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
156 SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
157 streams_.push_back(DefaultScreenshareStream());
158 EXPECT_TRUE(InitializeCodec());
159
160 EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
161 EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
162 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
163 kScreenshareCodecTargetBitrateBps, kScreenshareDefaultFramerate);
164 EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
165 bitrate_allocation.get_sum_bps());
166 EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
167}
168
169TEST_F(VideoCodecInitializerTest, SimlucastVp8Screenshare) {
170 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
171 streams_.push_back(DefaultScreenshareStream());
172 VideoStream video_stream = DefaultStream();
173 video_stream.max_framerate = kScreenshareDefaultFramerate;
174 streams_.push_back(video_stream);
175 EXPECT_TRUE(InitializeCodec());
176
177 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
178 EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
179 const uint32_t max_bitrate_bps =
180 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
181 BitrateAllocation bitrate_allocation = bitrate_allocator_out_->GetAllocation(
182 max_bitrate_bps, kScreenshareDefaultFramerate);
183 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
184 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
185 bitrate_allocation.GetSpatialLayerSum(0));
186 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
187 bitrate_allocation.GetSpatialLayerSum(1));
188}
189
190TEST_F(VideoCodecInitializerTest, HighFpsSimlucastVp8Screenshare) {
191 // Two simulcast streams, the lower one using legacy settings (two temporal
192 // streams, 5fps), the higher one using 3 temporal streams and 30fps.
193 SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
194 streams_.push_back(DefaultScreenshareStream());
195 VideoStream video_stream = DefaultStream();
196 video_stream.temporal_layer_thresholds_bps.push_back(kHighScreenshareTl0Bps);
197 video_stream.temporal_layer_thresholds_bps.push_back(kHighScreenshareTl1Bps);
198 streams_.push_back(video_stream);
199 EXPECT_TRUE(InitializeCodec());
200
201 EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
202 EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
203 const uint32_t max_bitrate_bps =
204 streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
205 BitrateAllocation bitrate_allocation =
206 bitrate_allocator_out_->GetAllocation(max_bitrate_bps, kDefaultFrameRate);
207 EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
208 EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
209 bitrate_allocation.GetSpatialLayerSum(0));
210 EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
211 bitrate_allocation.GetSpatialLayerSum(1));
212 EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
213 EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
214 bitrate_allocation.GetBitrate(1, 1));
215}
216
217} // namespace webrtc