blob: fe87a6deeeb21320ef4ca6c990dc72129432e418 [file] [log] [blame]
Sebastian Jansson98b07e912018-09-27 11:47:011/*
2 * Copyright 2018 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#include "test/scenario/video_stream.h"
11
12#include <algorithm>
13#include <utility>
14
15#include "media/base/mediaconstants.h"
16#include "media/engine/internaldecoderfactory.h"
17#include "media/engine/internalencoderfactory.h"
18#include "media/engine/webrtcvideoengine.h"
19#include "test/call_test.h"
20#include "test/fake_encoder.h"
21#include "test/function_video_encoder_factory.h"
22
23#include "test/scenario/hardware_codecs.h"
24#include "test/testsupport/fileutils.h"
25
26namespace webrtc {
27namespace test {
28namespace {
29constexpr int kDefaultMaxQp = cricket::WebRtcVideoChannel::kDefaultQpMax;
30const int kVideoRotationRtpExtensionId = 4;
31uint8_t CodecTypeToPayloadType(VideoCodecType codec_type) {
32 switch (codec_type) {
33 case VideoCodecType::kVideoCodecGeneric:
34 return CallTest::kFakeVideoSendPayloadType;
35 case VideoCodecType::kVideoCodecVP8:
36 return CallTest::kPayloadTypeVP8;
37 case VideoCodecType::kVideoCodecVP9:
38 return CallTest::kPayloadTypeVP9;
39 case VideoCodecType::kVideoCodecH264:
40 return CallTest::kPayloadTypeH264;
41 default:
42 RTC_NOTREACHED();
43 }
44 return {};
45}
46std::string CodecTypeToCodecName(VideoCodecType codec_type) {
47 switch (codec_type) {
48 case VideoCodecType::kVideoCodecGeneric:
49 return "";
50 case VideoCodecType::kVideoCodecVP8:
51 return cricket::kVp8CodecName;
52 case VideoCodecType::kVideoCodecVP9:
53 return cricket::kVp9CodecName;
54 case VideoCodecType::kVideoCodecH264:
55 return cricket::kH264CodecName;
56 default:
57 RTC_NOTREACHED();
58 }
59 return {};
60}
61std::vector<RtpExtension> GetVideoRtpExtensions(
62 const VideoStreamConfig config) {
63 return {RtpExtension(RtpExtension::kTransportSequenceNumberUri,
64 kTransportSequenceNumberExtensionId),
65 RtpExtension(RtpExtension::kVideoContentTypeUri,
66 kVideoContentTypeExtensionId),
67 RtpExtension(RtpExtension::kVideoRotationUri,
68 kVideoRotationRtpExtensionId)};
69}
70
71VideoSendStream::Config CreateVideoSendStreamConfig(VideoStreamConfig config,
72 std::vector<uint32_t> ssrcs,
73 Transport* send_transport) {
74 VideoSendStream::Config send_config(send_transport);
75 send_config.rtp.payload_name = CodecTypeToPayloadString(config.encoder.codec);
76 send_config.rtp.payload_type = CodecTypeToPayloadType(config.encoder.codec);
77
78 send_config.rtp.ssrcs = ssrcs;
79 send_config.rtp.extensions = GetVideoRtpExtensions(config);
80
81 if (config.stream.use_flexfec) {
82 send_config.rtp.flexfec.payload_type = CallTest::kFlexfecPayloadType;
83 send_config.rtp.flexfec.ssrc = CallTest::kFlexfecSendSsrc;
84 send_config.rtp.flexfec.protected_media_ssrcs = ssrcs;
85 }
86 if (config.stream.use_ulpfec) {
87 send_config.rtp.ulpfec.red_payload_type = CallTest::kRedPayloadType;
88 send_config.rtp.ulpfec.ulpfec_payload_type = CallTest::kUlpfecPayloadType;
89 send_config.rtp.ulpfec.red_rtx_payload_type = CallTest::kRtxRedPayloadType;
90 }
91 return send_config;
92}
93rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
94CreateEncoderSpecificSettings(VideoStreamConfig config) {
95 using Codec = VideoStreamConfig::Encoder::Codec;
96 switch (config.encoder.codec) {
97 case Codec::kVideoCodecH264: {
98 VideoCodecH264 h264_settings = VideoEncoder::GetDefaultH264Settings();
99 h264_settings.frameDroppingOn = true;
100 h264_settings.keyFrameInterval =
101 config.encoder.key_frame_interval.value_or(0);
102 return new rtc::RefCountedObject<
103 VideoEncoderConfig::H264EncoderSpecificSettings>(h264_settings);
104 }
105 case Codec::kVideoCodecVP8: {
106 VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
107 vp8_settings.frameDroppingOn = true;
108 vp8_settings.keyFrameInterval =
109 config.encoder.key_frame_interval.value_or(0);
110 vp8_settings.automaticResizeOn = true;
111 vp8_settings.denoisingOn = config.encoder.denoising;
112 return new rtc::RefCountedObject<
113 VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
114 }
115 case Codec::kVideoCodecVP9: {
116 VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
117 vp9_settings.frameDroppingOn = true;
118 vp9_settings.keyFrameInterval =
119 config.encoder.key_frame_interval.value_or(0);
120 vp9_settings.automaticResizeOn = true;
121 vp9_settings.denoisingOn = config.encoder.denoising;
122 vp9_settings.interLayerPred = InterLayerPredMode::kOnKeyPic;
123 return new rtc::RefCountedObject<
124 VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
125 }
126 default:
127 return nullptr;
128 }
129}
130
131VideoEncoderConfig CreateVideoEncoderConfig(VideoStreamConfig config) {
132 size_t num_streams = config.encoder.num_simulcast_streams;
133 VideoEncoderConfig encoder_config;
134 encoder_config.codec_type = config.encoder.codec;
135 encoder_config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
136 encoder_config.video_format =
137 SdpVideoFormat(CodecTypeToPayloadString(config.encoder.codec), {});
138 encoder_config.number_of_streams = num_streams;
139 encoder_config.simulcast_layers = std::vector<VideoStream>(num_streams);
140
141 std::string cricket_codec = CodecTypeToCodecName(config.encoder.codec);
142 if (!cricket_codec.empty()) {
143 encoder_config.video_stream_factory =
144 new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
145 cricket_codec, kDefaultMaxQp, false, false);
146 } else {
147 encoder_config.video_stream_factory =
148 new rtc::RefCountedObject<DefaultVideoStreamFactory>();
149 }
150 if (config.encoder.max_data_rate) {
151 encoder_config.max_bitrate_bps = config.encoder.max_data_rate->bps();
152 } else {
153 encoder_config.max_bitrate_bps = 10000000; // 10 mbit
154 }
155 encoder_config.encoder_specific_settings =
156 CreateEncoderSpecificSettings(config);
157 return encoder_config;
158}
159} // namespace
160
161SendVideoStream::SendVideoStream(CallClient* sender,
162 VideoStreamConfig config,
163 Transport* send_transport)
164 : sender_(sender), config_(config) {
165 for (size_t i = 0; i < config.encoder.num_simulcast_streams; ++i) {
166 ssrcs_.push_back(sender->GetNextVideoSsrc());
167 rtx_ssrcs_.push_back(sender->GetNextRtxSsrc());
168 }
169
170 using Capture = VideoStreamConfig::Source::Capture;
171 switch (config.source.capture) {
172 case Capture::kGenerator:
173 frame_generator_ = test::FrameGeneratorCapturer::Create(
174 config.source.width, config.source.height,
175 config.source.generator.pixel_format, absl::nullopt,
176 config.source.framerate, sender_->clock_);
177 video_capturer_.reset(frame_generator_);
178 break;
179 case Capture::kVideoFile:
180 frame_generator_ = test::FrameGeneratorCapturer::CreateFromYuvFile(
181 test::ResourcePath(config.source.video_file.name, "yuv"),
182 config.source.width, config.source.height, config.source.framerate,
183 sender_->clock_);
184 RTC_CHECK(frame_generator_)
185 << "Could not create capturer for " << config.source.video_file.name
186 << ".yuv. Is this resource file present?";
187 video_capturer_.reset(frame_generator_);
188 break;
189 }
190
191 using Encoder = VideoStreamConfig::Encoder;
192 using Codec = VideoStreamConfig::Encoder::Codec;
193 switch (config.encoder.implementation) {
194 case Encoder::Implementation::kFake:
195 if (config.encoder.codec == Codec::kVideoCodecGeneric) {
196 encoder_factory_ =
197 absl::make_unique<FunctionVideoEncoderFactory>([this, config]() {
198 auto encoder =
199 absl::make_unique<test::FakeEncoder>(sender_->clock_);
200 if (config.encoder.fake.max_rate.IsFinite())
201 encoder->SetMaxBitrate(config.encoder.fake.max_rate.kbps());
202 return encoder;
203 });
204 } else {
205 RTC_NOTREACHED();
206 }
207 break;
208 case VideoStreamConfig::Encoder::Implementation::kSoftware:
209 encoder_factory_.reset(new InternalEncoderFactory());
210 break;
211 case VideoStreamConfig::Encoder::Implementation::kHardware:
212 encoder_factory_ = CreateHardwareEncoderFactory();
213 break;
214 }
215 RTC_CHECK(encoder_factory_);
216
217 VideoSendStream::Config send_config =
218 CreateVideoSendStreamConfig(config, ssrcs_, send_transport);
219 send_config.encoder_settings.encoder_factory = encoder_factory_.get();
220 VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config);
221
222 send_stream_ = sender_->call_->CreateVideoSendStream(
223 std::move(send_config), std::move(encoder_config));
224
225 send_stream_->SetSource(video_capturer_.get(),
226 config.encoder.degradation_preference);
227}
228
229SendVideoStream::~SendVideoStream() {
230 sender_->call_->DestroyVideoSendStream(send_stream_);
231}
232
233void SendVideoStream::Start() {
234 send_stream_->Start();
235 video_capturer_->Start();
236}
237
238bool SendVideoStream::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
239 uint64_t receiver,
240 Timestamp at_time) {
241 // Removes added overhead before delivering RTCP packet to sender.
242 RTC_DCHECK_GE(packet.size(), config_.stream.packet_overhead.bytes());
243 packet.SetSize(packet.size() - config_.stream.packet_overhead.bytes());
244 sender_->DeliverPacket(MediaType::VIDEO, packet, at_time);
245 return true;
246}
247
248void SendVideoStream::SetCaptureFramerate(int framerate) {
249 RTC_CHECK(frame_generator_)
250 << "Framerate change only implemented for generators";
251 frame_generator_->ChangeFramerate(framerate);
252}
253
254void SendVideoStream::SetMaxFramerate(absl::optional<int> max_framerate) {
255 VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config_);
256 RTC_DCHECK_EQ(encoder_config.simulcast_layers.size(), 1);
257 encoder_config.simulcast_layers[0].max_framerate = max_framerate.value_or(-1);
258 send_stream_->ReconfigureVideoEncoder(std::move(encoder_config));
259}
260
261VideoSendStream::Stats SendVideoStream::GetStats() const {
262 return send_stream_->GetStats();
263}
264
265ColumnPrinter SendVideoStream::StatsPrinter() {
266 return ColumnPrinter::Lambda(
267 "video_target_rate video_sent_rate width height",
268 [this](rtc::SimpleStringBuilder& sb) {
269 VideoSendStream::Stats video_stats = send_stream_->GetStats();
270 int width = 0;
271 int height = 0;
272 for (auto stream_stat : video_stats.substreams) {
273 width = std::max(width, stream_stat.second.width);
274 height = std::max(height, stream_stat.second.height);
275 }
276 sb.AppendFormat("%.0lf %.0lf %i %i",
277 video_stats.target_media_bitrate_bps / 8.0,
278 video_stats.media_bitrate_bps / 8.0, width, height);
279 },
280 64);
281}
282
283ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver,
284 VideoStreamConfig config,
285 SendVideoStream* send_stream,
286 size_t chosen_stream,
287 Transport* feedback_transport)
288 : receiver_(receiver),
289 config_(config),
290 decoder_factory_(absl::make_unique<InternalDecoderFactory>()) {
291 renderer_ = absl::make_unique<FakeVideoRenderer>();
292 VideoReceiveStream::Config recv_config(feedback_transport);
293 recv_config.rtp.remb = !config.stream.packet_feedback;
294 recv_config.rtp.transport_cc = config.stream.packet_feedback;
295 recv_config.rtp.local_ssrc = CallTest::kReceiverLocalVideoSsrc;
296 recv_config.rtp.extensions = GetVideoRtpExtensions(config);
297 RTC_DCHECK(!config.stream.use_rtx ||
298 config.stream.nack_history_time > TimeDelta::Zero());
299 recv_config.rtp.nack.rtp_history_ms = config.stream.nack_history_time.ms();
300 recv_config.rtp.protected_by_flexfec = config.stream.use_flexfec;
301 recv_config.renderer = renderer_.get();
302 if (config.stream.use_rtx) {
303 recv_config.rtp.rtx_ssrc = send_stream->rtx_ssrcs_[chosen_stream];
304 recv_config.rtp
305 .rtx_associated_payload_types[CallTest::kSendRtxPayloadType] =
306 CodecTypeToPayloadType(config.encoder.codec);
307 }
308 recv_config.rtp.remote_ssrc = send_stream->ssrcs_[chosen_stream];
309 VideoReceiveStream::Decoder decoder =
310 CreateMatchingDecoder(CodecTypeToPayloadType(config.encoder.codec),
311 CodecTypeToPayloadString(config.encoder.codec));
312 decoder.decoder_factory = decoder_factory_.get();
313 recv_config.decoders.push_back(decoder);
314
315 if (config.stream.use_flexfec) {
316 RTC_CHECK_EQ(config.encoder.num_simulcast_streams, 1);
317 FlexfecReceiveStream::Config flexfec_config(feedback_transport);
318 flexfec_config.payload_type = CallTest::kFlexfecPayloadType;
319 flexfec_config.remote_ssrc = CallTest::kFlexfecSendSsrc;
320 flexfec_config.protected_media_ssrcs = send_stream->rtx_ssrcs_;
321 flexfec_config.local_ssrc = recv_config.rtp.local_ssrc;
322 flecfec_stream_ =
323 receiver_->call_->CreateFlexfecReceiveStream(flexfec_config);
324 }
325 if (config.stream.use_ulpfec) {
326 recv_config.rtp.red_payload_type = CallTest::kRedPayloadType;
327 recv_config.rtp.ulpfec_payload_type = CallTest::kUlpfecPayloadType;
328 recv_config.rtp.rtx_associated_payload_types[CallTest::kRtxRedPayloadType] =
329 CallTest::kRedPayloadType;
330 }
331 receive_stream_ =
332 receiver_->call_->CreateVideoReceiveStream(std::move(recv_config));
333}
334
335ReceiveVideoStream::~ReceiveVideoStream() {
336 receiver_->call_->DestroyVideoReceiveStream(receive_stream_);
337 if (flecfec_stream_)
338 receiver_->call_->DestroyFlexfecReceiveStream(flecfec_stream_);
339}
340
341bool ReceiveVideoStream::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
342 uint64_t receiver,
343 Timestamp at_time) {
344 RTC_DCHECK_GE(packet.size(), config_.stream.packet_overhead.bytes());
345 packet.SetSize(packet.size() - config_.stream.packet_overhead.bytes());
346 receiver_->DeliverPacket(MediaType::VIDEO, packet, at_time);
347 return true;
348}
349
350VideoStreamPair::~VideoStreamPair() = default;
351
352VideoStreamPair::VideoStreamPair(CallClient* sender,
353 std::vector<NetworkNode*> send_link,
354 uint64_t send_receiver_id,
355 CallClient* receiver,
356 std::vector<NetworkNode*> return_link,
357 uint64_t return_receiver_id,
358 VideoStreamConfig config)
359 : config_(config),
360 send_link_(send_link),
361 return_link_(return_link),
362 send_transport_(sender,
363 send_link.front(),
364 send_receiver_id,
365 config.stream.packet_overhead),
366 return_transport_(receiver,
367 return_link.front(),
368 return_receiver_id,
369 config.stream.packet_overhead),
370 send_stream_(sender, config, &send_transport_),
371 receive_stream_(receiver,
372 config,
373 &send_stream_,
374 /*chosen_stream=*/0,
375 &return_transport_) {
376 NetworkNode::Route(send_transport_.ReceiverId(), send_link_,
377 &receive_stream_);
378 NetworkNode::Route(return_transport_.ReceiverId(), return_link_,
379 &send_stream_);
380}
381
382} // namespace test
383} // namespace webrtc