1 /*
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 <memory>
14 #include <utility>
15 
16 #include "absl/strings/match.h"
17 #include "api/test/create_frame_generator.h"
18 #include "api/test/frame_generator_interface.h"
19 #include "api/test/video/function_video_encoder_factory.h"
20 #include "api/video/builtin_video_bitrate_allocator_factory.h"
21 #include "media/base/media_constants.h"
22 #include "media/engine/internal_decoder_factory.h"
23 #include "media/engine/internal_encoder_factory.h"
24 #include "media/engine/webrtc_video_engine.h"
25 #include "test/call_test.h"
26 #include "test/fake_encoder.h"
27 #include "test/scenario/hardware_codecs.h"
28 #include "test/testsupport/file_utils.h"
29 
30 namespace webrtc {
31 namespace test {
32 namespace {
33 enum : int {  // The first valid value is 1.
34   kTransportSequenceNumberExtensionId = 1,
35   kAbsSendTimeExtensionId,
36   kVideoContentTypeExtensionId,
37   kVideoRotationRtpExtensionId,
38 };
39 
40 constexpr int kDefaultMaxQp = cricket::WebRtcVideoChannel::kDefaultQpMax;
CodecTypeToPayloadType(VideoCodecType codec_type)41 uint8_t CodecTypeToPayloadType(VideoCodecType codec_type) {
42   switch (codec_type) {
43     case VideoCodecType::kVideoCodecGeneric:
44       return CallTest::kFakeVideoSendPayloadType;
45     case VideoCodecType::kVideoCodecVP8:
46       return CallTest::kPayloadTypeVP8;
47     case VideoCodecType::kVideoCodecVP9:
48       return CallTest::kPayloadTypeVP9;
49     case VideoCodecType::kVideoCodecH264:
50       return CallTest::kPayloadTypeH264;
51     default:
52       RTC_NOTREACHED();
53   }
54   return {};
55 }
CodecTypeToCodecName(VideoCodecType codec_type)56 std::string CodecTypeToCodecName(VideoCodecType codec_type) {
57   switch (codec_type) {
58     case VideoCodecType::kVideoCodecGeneric:
59       return "";
60     case VideoCodecType::kVideoCodecVP8:
61       return cricket::kVp8CodecName;
62     case VideoCodecType::kVideoCodecVP9:
63       return cricket::kVp9CodecName;
64     case VideoCodecType::kVideoCodecH264:
65       return cricket::kH264CodecName;
66     default:
67       RTC_NOTREACHED();
68   }
69   return {};
70 }
ConvertContentType(VideoStreamConfig::Encoder::ContentType content_type)71 VideoEncoderConfig::ContentType ConvertContentType(
72     VideoStreamConfig::Encoder::ContentType content_type) {
73   switch (content_type) {
74     case VideoStreamConfig::Encoder::ContentType::kVideo:
75       return VideoEncoderConfig::ContentType::kRealtimeVideo;
76       break;
77     case VideoStreamConfig::Encoder::ContentType::kScreen:
78       return VideoEncoderConfig::ContentType::kScreen;
79   }
80 }
ToInterLayerPredMode(VideoStreamConfig::Encoder::Layers::Prediction value)81 InterLayerPredMode ToInterLayerPredMode(
82     VideoStreamConfig::Encoder::Layers::Prediction value) {
83   using Pred = VideoStreamConfig::Encoder::Layers::Prediction;
84   switch (value) {
85     case Pred::kTemporalOnly:
86       return InterLayerPredMode::kOff;
87     case Pred::kSpatialOnKey:
88       return InterLayerPredMode::kOnKeyPic;
89     case Pred::kFull:
90       return InterLayerPredMode::kOn;
91   }
92 }
GetVideoRtpExtensions(const VideoStreamConfig config)93 std::vector<RtpExtension> GetVideoRtpExtensions(
94     const VideoStreamConfig config) {
95   std::vector<RtpExtension> res = {
96       RtpExtension(RtpExtension::kVideoContentTypeUri,
97                    kVideoContentTypeExtensionId),
98       RtpExtension(RtpExtension::kVideoRotationUri,
99                    kVideoRotationRtpExtensionId)};
100   if (config.stream.packet_feedback) {
101     res.push_back(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
102                                kTransportSequenceNumberExtensionId));
103   }
104   if (config.stream.abs_send_time) {
105     res.push_back(
106         RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
107   }
108   return res;
109 }
110 
TransformFilePath(std::string path)111 std::string TransformFilePath(std::string path) {
112   static const std::string resource_prefix = "res://";
113   int ext_pos = path.rfind(".");
114   if (ext_pos < 0) {
115     return test::ResourcePath(path, "yuv");
116   } else if (absl::StartsWith(path, resource_prefix)) {
117     std::string name = path.substr(resource_prefix.length(), ext_pos);
118     std::string ext = path.substr(ext_pos, path.size());
119     return test::ResourcePath(name, ext);
120   }
121   return path;
122 }
123 
CreateVideoSendStreamConfig(VideoStreamConfig config,std::vector<uint32_t> ssrcs,std::vector<uint32_t> rtx_ssrcs,Transport * send_transport)124 VideoSendStream::Config CreateVideoSendStreamConfig(
125     VideoStreamConfig config,
126     std::vector<uint32_t> ssrcs,
127     std::vector<uint32_t> rtx_ssrcs,
128     Transport* send_transport) {
129   VideoSendStream::Config send_config(send_transport);
130   send_config.rtp.payload_name = CodecTypeToPayloadString(config.encoder.codec);
131   send_config.rtp.payload_type = CodecTypeToPayloadType(config.encoder.codec);
132   send_config.rtp.nack.rtp_history_ms =
133       config.stream.nack_history_time.ms<int>();
134 
135   send_config.rtp.ssrcs = ssrcs;
136   send_config.rtp.extensions = GetVideoRtpExtensions(config);
137 
138   if (config.stream.use_rtx) {
139     send_config.rtp.rtx.payload_type = CallTest::kSendRtxPayloadType;
140     send_config.rtp.rtx.ssrcs = rtx_ssrcs;
141   }
142   if (config.stream.use_flexfec) {
143     send_config.rtp.flexfec.payload_type = CallTest::kFlexfecPayloadType;
144     send_config.rtp.flexfec.ssrc = CallTest::kFlexfecSendSsrc;
145     send_config.rtp.flexfec.protected_media_ssrcs = ssrcs;
146   }
147   if (config.stream.use_ulpfec) {
148     send_config.rtp.ulpfec.red_payload_type = CallTest::kRedPayloadType;
149     send_config.rtp.ulpfec.ulpfec_payload_type = CallTest::kUlpfecPayloadType;
150     send_config.rtp.ulpfec.red_rtx_payload_type = CallTest::kRtxRedPayloadType;
151   }
152   return send_config;
153 }
154 rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateVp9SpecificSettings(VideoStreamConfig video_config)155 CreateVp9SpecificSettings(VideoStreamConfig video_config) {
156   constexpr auto kScreen = VideoStreamConfig::Encoder::ContentType::kScreen;
157   VideoStreamConfig::Encoder conf = video_config.encoder;
158   VideoCodecVP9 vp9 = VideoEncoder::GetDefaultVp9Settings();
159   vp9.frameDroppingOn = conf.frame_dropping;
160   vp9.keyFrameInterval = conf.key_frame_interval.value_or(0);
161   vp9.numberOfTemporalLayers = static_cast<uint8_t>(conf.layers.temporal);
162   vp9.numberOfSpatialLayers = static_cast<uint8_t>(conf.layers.spatial);
163   vp9.interLayerPred = ToInterLayerPredMode(conf.layers.prediction);
164 
165   if (conf.content_type == kScreen &&
166       (video_config.source.framerate > 5 || conf.layers.spatial >= 3)) {
167     vp9.flexibleMode = true;
168   }
169 
170   if (conf.content_type == kScreen ||
171       conf.layers.temporal * conf.layers.spatial) {
172     vp9.automaticResizeOn = false;
173     vp9.denoisingOn = false;
174   } else {
175     vp9.automaticResizeOn = conf.single.automatic_scaling;
176     vp9.denoisingOn = conf.single.denoising;
177   }
178   return new rtc::RefCountedObject<
179       VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9);
180 }
181 
182 rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateVp8SpecificSettings(VideoStreamConfig config)183 CreateVp8SpecificSettings(VideoStreamConfig config) {
184   VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
185   vp8_settings.frameDroppingOn = config.encoder.frame_dropping;
186   vp8_settings.keyFrameInterval = config.encoder.key_frame_interval.value_or(0);
187   vp8_settings.numberOfTemporalLayers = config.encoder.layers.temporal;
188   if (config.encoder.layers.spatial * config.encoder.layers.temporal > 1) {
189     vp8_settings.automaticResizeOn = false;
190     vp8_settings.denoisingOn = false;
191   } else {
192     vp8_settings.automaticResizeOn = config.encoder.single.automatic_scaling;
193     vp8_settings.denoisingOn = config.encoder.single.denoising;
194   }
195   return new rtc::RefCountedObject<
196       VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
197 }
198 
199 rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateH264SpecificSettings(VideoStreamConfig config)200 CreateH264SpecificSettings(VideoStreamConfig config) {
201   RTC_DCHECK_EQ(config.encoder.layers.temporal, 1);
202   RTC_DCHECK_EQ(config.encoder.layers.spatial, 1);
203 
204   VideoCodecH264 h264_settings = VideoEncoder::GetDefaultH264Settings();
205   h264_settings.frameDroppingOn = config.encoder.frame_dropping;
206   h264_settings.keyFrameInterval =
207       config.encoder.key_frame_interval.value_or(0);
208   return new rtc::RefCountedObject<
209       VideoEncoderConfig::H264EncoderSpecificSettings>(h264_settings);
210 }
211 
212 rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
CreateEncoderSpecificSettings(VideoStreamConfig config)213 CreateEncoderSpecificSettings(VideoStreamConfig config) {
214   using Codec = VideoStreamConfig::Encoder::Codec;
215   switch (config.encoder.codec) {
216     case Codec::kVideoCodecH264:
217       return CreateH264SpecificSettings(config);
218     case Codec::kVideoCodecVP8:
219       return CreateVp8SpecificSettings(config);
220     case Codec::kVideoCodecVP9:
221       return CreateVp9SpecificSettings(config);
222     case Codec::kVideoCodecGeneric:
223     case Codec::kVideoCodecAV1:
224       return nullptr;
225     case Codec::kVideoCodecMultiplex:
226       RTC_NOTREACHED();
227       return nullptr;
228   }
229 }
230 
CreateVideoEncoderConfig(VideoStreamConfig config)231 VideoEncoderConfig CreateVideoEncoderConfig(VideoStreamConfig config) {
232   VideoEncoderConfig encoder_config;
233   encoder_config.codec_type = config.encoder.codec;
234   encoder_config.content_type = ConvertContentType(config.encoder.content_type);
235   encoder_config.video_format =
236       SdpVideoFormat(CodecTypeToPayloadString(config.encoder.codec), {});
237 
238   encoder_config.number_of_streams = 1;
239   if (config.encoder.codec == VideoStreamConfig::Encoder::Codec::kVideoCodecVP8)
240     encoder_config.number_of_streams =
241         static_cast<size_t>(config.encoder.layers.spatial);
242   encoder_config.simulcast_layers =
243       std::vector<VideoStream>(config.encoder.layers.spatial);
244   encoder_config.min_transmit_bitrate_bps = config.stream.pad_to_rate.bps();
245 
246   std::string cricket_codec = CodecTypeToCodecName(config.encoder.codec);
247   if (!cricket_codec.empty()) {
248     bool screenshare = config.encoder.content_type ==
249                        VideoStreamConfig::Encoder::ContentType::kScreen;
250     encoder_config.video_stream_factory =
251         new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
252             cricket_codec, kDefaultMaxQp, screenshare, screenshare);
253   } else {
254     encoder_config.video_stream_factory =
255         new rtc::RefCountedObject<DefaultVideoStreamFactory>();
256   }
257 
258   // TODO(srte): Base this on encoder capabilities.
259   encoder_config.max_bitrate_bps =
260       config.encoder.max_data_rate.value_or(DataRate::KilobitsPerSec(10000))
261           .bps();
262 
263   encoder_config.encoder_specific_settings =
264       CreateEncoderSpecificSettings(config);
265   if (config.encoder.max_framerate) {
266     for (auto& layer : encoder_config.simulcast_layers) {
267       layer.max_framerate = *config.encoder.max_framerate;
268       layer.min_bitrate_bps = config.encoder.min_data_rate->bps_or(-1);
269     }
270   }
271 
272   return encoder_config;
273 }
274 
CreateImageSlideGenerator(Clock * clock,VideoStreamConfig::Source::Slides slides,int framerate)275 std::unique_ptr<FrameGeneratorInterface> CreateImageSlideGenerator(
276     Clock* clock,
277     VideoStreamConfig::Source::Slides slides,
278     int framerate) {
279   std::vector<std::string> paths = slides.images.paths;
280   for (std::string& path : paths)
281     path = TransformFilePath(path);
282   if (slides.images.crop.width || slides.images.crop.height) {
283     TimeDelta pause_duration =
284         slides.change_interval - slides.images.crop.scroll_duration;
285     RTC_CHECK_GE(pause_duration, TimeDelta::Zero());
286     int crop_width = slides.images.crop.width.value_or(slides.images.width);
287     int crop_height = slides.images.crop.height.value_or(slides.images.height);
288     RTC_CHECK_LE(crop_width, slides.images.width);
289     RTC_CHECK_LE(crop_height, slides.images.height);
290     return CreateScrollingInputFromYuvFilesFrameGenerator(
291         clock, paths, slides.images.width, slides.images.height, crop_width,
292         crop_height, slides.images.crop.scroll_duration.ms(),
293         pause_duration.ms());
294   } else {
295     return CreateFromYuvFileFrameGenerator(
296         paths, slides.images.width, slides.images.height,
297         slides.change_interval.seconds<double>() * framerate);
298   }
299 }
300 
CreateFrameGenerator(Clock * clock,VideoStreamConfig::Source source)301 std::unique_ptr<FrameGeneratorInterface> CreateFrameGenerator(
302     Clock* clock,
303     VideoStreamConfig::Source source) {
304   using Capture = VideoStreamConfig::Source::Capture;
305   switch (source.capture) {
306     case Capture::kGenerator:
307       return CreateSquareFrameGenerator(
308           source.generator.width, source.generator.height,
309           source.generator.pixel_format, /*num_squares*/ absl::nullopt);
310     case Capture::kVideoFile:
311       RTC_CHECK(source.video_file.width && source.video_file.height);
312       return CreateFromYuvFileFrameGenerator(
313           {TransformFilePath(source.video_file.name)}, source.video_file.width,
314           source.video_file.height, /*frame_repeat_count*/ 1);
315     case Capture::kGenerateSlides:
316       return CreateSlideFrameGenerator(
317           source.slides.generator.width, source.slides.generator.height,
318           source.slides.change_interval.seconds<double>() * source.framerate);
319     case Capture::kImageSlides:
320       return CreateImageSlideGenerator(clock, source.slides, source.framerate);
321   }
322 }
323 
CreateVideoReceiveStreamConfig(VideoStreamConfig config,Transport * feedback_transport,VideoDecoderFactory * decoder_factory,VideoReceiveStream::Decoder decoder,rtc::VideoSinkInterface<VideoFrame> * renderer,uint32_t local_ssrc,uint32_t ssrc,uint32_t rtx_ssrc)324 VideoReceiveStream::Config CreateVideoReceiveStreamConfig(
325     VideoStreamConfig config,
326     Transport* feedback_transport,
327     VideoDecoderFactory* decoder_factory,
328     VideoReceiveStream::Decoder decoder,
329     rtc::VideoSinkInterface<VideoFrame>* renderer,
330     uint32_t local_ssrc,
331     uint32_t ssrc,
332     uint32_t rtx_ssrc) {
333   VideoReceiveStream::Config recv(feedback_transport);
334   recv.rtp.transport_cc = config.stream.packet_feedback;
335   recv.rtp.local_ssrc = local_ssrc;
336   recv.rtp.extensions = GetVideoRtpExtensions(config);
337 
338   RTC_DCHECK(!config.stream.use_rtx ||
339              config.stream.nack_history_time > TimeDelta::Zero());
340   recv.rtp.nack.rtp_history_ms = config.stream.nack_history_time.ms();
341   recv.rtp.protected_by_flexfec = config.stream.use_flexfec;
342   recv.rtp.remote_ssrc = ssrc;
343   recv.decoder_factory = decoder_factory;
344   recv.decoders.push_back(decoder);
345   recv.renderer = renderer;
346   if (config.stream.use_rtx) {
347     recv.rtp.rtx_ssrc = rtx_ssrc;
348     recv.rtp.rtx_associated_payload_types[CallTest::kSendRtxPayloadType] =
349         CodecTypeToPayloadType(config.encoder.codec);
350   }
351   if (config.stream.use_ulpfec) {
352     recv.rtp.red_payload_type = CallTest::kRedPayloadType;
353     recv.rtp.ulpfec_payload_type = CallTest::kUlpfecPayloadType;
354     recv.rtp.rtx_associated_payload_types[CallTest::kRtxRedPayloadType] =
355         CallTest::kRedPayloadType;
356   }
357   recv.sync_group = config.render.sync_group;
358   return recv;
359 }
360 }  // namespace
361 
SendVideoStream(CallClient * sender,VideoStreamConfig config,Transport * send_transport,VideoFrameMatcher * matcher)362 SendVideoStream::SendVideoStream(CallClient* sender,
363                                  VideoStreamConfig config,
364                                  Transport* send_transport,
365                                  VideoFrameMatcher* matcher)
366     : sender_(sender), config_(config) {
367   video_capturer_ = std::make_unique<FrameGeneratorCapturer>(
368       sender_->clock_, CreateFrameGenerator(sender_->clock_, config.source),
369       config.source.framerate,
370       *sender->time_controller_->GetTaskQueueFactory());
371   video_capturer_->Init();
372 
373   using Encoder = VideoStreamConfig::Encoder;
374   using Codec = VideoStreamConfig::Encoder::Codec;
375   switch (config.encoder.implementation) {
376     case Encoder::Implementation::kFake:
377       encoder_factory_ =
378           std::make_unique<FunctionVideoEncoderFactory>([this]() {
379             MutexLock lock(&mutex_);
380             std::unique_ptr<FakeEncoder> encoder;
381             if (config_.encoder.codec == Codec::kVideoCodecVP8) {
382               encoder = std::make_unique<test::FakeVp8Encoder>(sender_->clock_);
383             } else if (config_.encoder.codec == Codec::kVideoCodecGeneric) {
384               encoder = std::make_unique<test::FakeEncoder>(sender_->clock_);
385             } else {
386               RTC_NOTREACHED();
387             }
388             fake_encoders_.push_back(encoder.get());
389             if (config_.encoder.fake.max_rate.IsFinite())
390               encoder->SetMaxBitrate(config_.encoder.fake.max_rate.kbps());
391             return encoder;
392           });
393       break;
394     case VideoStreamConfig::Encoder::Implementation::kSoftware:
395       encoder_factory_.reset(new InternalEncoderFactory());
396       break;
397     case VideoStreamConfig::Encoder::Implementation::kHardware:
398       encoder_factory_ = CreateHardwareEncoderFactory();
399       break;
400   }
401   RTC_CHECK(encoder_factory_);
402 
403   bitrate_allocator_factory_ = CreateBuiltinVideoBitrateAllocatorFactory();
404   RTC_CHECK(bitrate_allocator_factory_);
405 
406   VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config);
407   for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
408     ssrcs_.push_back(sender->GetNextVideoSsrc());
409     rtx_ssrcs_.push_back(sender->GetNextRtxSsrc());
410   }
411   VideoSendStream::Config send_config =
412       CreateVideoSendStreamConfig(config, ssrcs_, rtx_ssrcs_, send_transport);
413   send_config.encoder_settings.encoder_factory = encoder_factory_.get();
414   send_config.encoder_settings.bitrate_allocator_factory =
415       bitrate_allocator_factory_.get();
416   send_config.suspend_below_min_bitrate =
417       config.encoder.suspend_below_min_bitrate;
418 
419   sender_->SendTask([&] {
420     if (config.stream.fec_controller_factory) {
421       send_stream_ = sender_->call_->CreateVideoSendStream(
422           std::move(send_config), std::move(encoder_config),
423           config.stream.fec_controller_factory->CreateFecController());
424     } else {
425       send_stream_ = sender_->call_->CreateVideoSendStream(
426           std::move(send_config), std::move(encoder_config));
427     }
428 
429     if (matcher->Active()) {
430       frame_tap_ = std::make_unique<ForwardingCapturedFrameTap>(
431           sender_->clock_, matcher, video_capturer_.get());
432       send_stream_->SetSource(frame_tap_.get(),
433                               config.encoder.degradation_preference);
434     } else {
435       send_stream_->SetSource(video_capturer_.get(),
436                               config.encoder.degradation_preference);
437     }
438   });
439 }
440 
~SendVideoStream()441 SendVideoStream::~SendVideoStream() {
442   sender_->SendTask(
443       [this] { sender_->call_->DestroyVideoSendStream(send_stream_); });
444 }
445 
Start()446 void SendVideoStream::Start() {
447   sender_->SendTask([this] {
448     send_stream_->Start();
449     sender_->call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
450   });
451 }
452 
Stop()453 void SendVideoStream::Stop() {
454   sender_->SendTask([this] { send_stream_->Stop(); });
455 }
456 
UpdateConfig(std::function<void (VideoStreamConfig *)> modifier)457 void SendVideoStream::UpdateConfig(
458     std::function<void(VideoStreamConfig*)> modifier) {
459   sender_->SendTask([&] {
460     MutexLock lock(&mutex_);
461     VideoStreamConfig prior_config = config_;
462     modifier(&config_);
463     if (prior_config.encoder.fake.max_rate != config_.encoder.fake.max_rate) {
464       for (auto* encoder : fake_encoders_) {
465         encoder->SetMaxBitrate(config_.encoder.fake.max_rate.kbps());
466       }
467     }
468     // TODO(srte): Add more conditions that should cause reconfiguration.
469     if (prior_config.encoder.max_framerate != config_.encoder.max_framerate ||
470         prior_config.encoder.max_data_rate != config_.encoder.max_data_rate) {
471       VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config_);
472       send_stream_->ReconfigureVideoEncoder(std::move(encoder_config));
473     }
474     if (prior_config.source.framerate != config_.source.framerate) {
475       SetCaptureFramerate(config_.source.framerate);
476     }
477   });
478 }
479 
UpdateActiveLayers(std::vector<bool> active_layers)480 void SendVideoStream::UpdateActiveLayers(std::vector<bool> active_layers) {
481   sender_->task_queue_.PostTask([=] {
482     MutexLock lock(&mutex_);
483     if (config_.encoder.codec ==
484         VideoStreamConfig::Encoder::Codec::kVideoCodecVP8) {
485       send_stream_->UpdateActiveSimulcastLayers(active_layers);
486     }
487     VideoEncoderConfig encoder_config = CreateVideoEncoderConfig(config_);
488     RTC_CHECK_EQ(encoder_config.simulcast_layers.size(), active_layers.size());
489     for (size_t i = 0; i < encoder_config.simulcast_layers.size(); ++i)
490       encoder_config.simulcast_layers[i].active = active_layers[i];
491     send_stream_->ReconfigureVideoEncoder(std::move(encoder_config));
492   });
493 }
494 
UsingSsrc(uint32_t ssrc) const495 bool SendVideoStream::UsingSsrc(uint32_t ssrc) const {
496   for (uint32_t owned : ssrcs_) {
497     if (owned == ssrc)
498       return true;
499   }
500   return false;
501 }
502 
UsingRtxSsrc(uint32_t ssrc) const503 bool SendVideoStream::UsingRtxSsrc(uint32_t ssrc) const {
504   for (uint32_t owned : rtx_ssrcs_) {
505     if (owned == ssrc)
506       return true;
507   }
508   return false;
509 }
510 
SetCaptureFramerate(int framerate)511 void SendVideoStream::SetCaptureFramerate(int framerate) {
512   sender_->SendTask([&] { video_capturer_->ChangeFramerate(framerate); });
513 }
514 
GetStats() const515 VideoSendStream::Stats SendVideoStream::GetStats() const {
516   return send_stream_->GetStats();
517 }
518 
StatsPrinter()519 ColumnPrinter SendVideoStream::StatsPrinter() {
520   return ColumnPrinter::Lambda(
521       "video_target_rate video_sent_rate width height",
522       [this](rtc::SimpleStringBuilder& sb) {
523         VideoSendStream::Stats video_stats = send_stream_->GetStats();
524         int width = 0;
525         int height = 0;
526         for (const auto& stream_stat : video_stats.substreams) {
527           width = std::max(width, stream_stat.second.width);
528           height = std::max(height, stream_stat.second.height);
529         }
530         sb.AppendFormat("%.0lf %.0lf %i %i",
531                         video_stats.target_media_bitrate_bps / 8.0,
532                         video_stats.media_bitrate_bps / 8.0, width, height);
533       },
534       64);
535 }
536 
ReceiveVideoStream(CallClient * receiver,VideoStreamConfig config,SendVideoStream * send_stream,size_t chosen_stream,Transport * feedback_transport,VideoFrameMatcher * matcher)537 ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver,
538                                        VideoStreamConfig config,
539                                        SendVideoStream* send_stream,
540                                        size_t chosen_stream,
541                                        Transport* feedback_transport,
542                                        VideoFrameMatcher* matcher)
543     : receiver_(receiver), config_(config) {
544   if (config.encoder.codec ==
545           VideoStreamConfig::Encoder::Codec::kVideoCodecGeneric ||
546       config.encoder.implementation == VideoStreamConfig::Encoder::kFake) {
547     decoder_factory_ = std::make_unique<FunctionVideoDecoderFactory>(
548         []() { return std::make_unique<FakeDecoder>(); });
549   } else {
550     decoder_factory_ = std::make_unique<InternalDecoderFactory>();
551   }
552 
553   VideoReceiveStream::Decoder decoder =
554       CreateMatchingDecoder(CodecTypeToPayloadType(config.encoder.codec),
555                             CodecTypeToPayloadString(config.encoder.codec));
556   size_t num_streams = 1;
557   if (config.encoder.codec == VideoStreamConfig::Encoder::Codec::kVideoCodecVP8)
558     num_streams = config.encoder.layers.spatial;
559   for (size_t i = 0; i < num_streams; ++i) {
560     rtc::VideoSinkInterface<VideoFrame>* renderer = &fake_renderer_;
561     if (matcher->Active()) {
562       render_taps_.emplace_back(
563           std::make_unique<DecodedFrameTap>(receiver_->clock_, matcher, i));
564       renderer = render_taps_.back().get();
565     }
566     auto recv_config = CreateVideoReceiveStreamConfig(
567         config, feedback_transport, decoder_factory_.get(), decoder, renderer,
568         receiver_->GetNextVideoLocalSsrc(), send_stream->ssrcs_[i],
569         send_stream->rtx_ssrcs_[i]);
570     if (config.stream.use_flexfec) {
571       RTC_DCHECK(num_streams == 1);
572       FlexfecReceiveStream::Config flexfec(feedback_transport);
573       flexfec.payload_type = CallTest::kFlexfecPayloadType;
574       flexfec.remote_ssrc = CallTest::kFlexfecSendSsrc;
575       flexfec.protected_media_ssrcs = send_stream->rtx_ssrcs_;
576       flexfec.local_ssrc = recv_config.rtp.local_ssrc;
577       receiver_->ssrc_media_types_[flexfec.remote_ssrc] = MediaType::VIDEO;
578 
579       receiver_->SendTask([this, &flexfec] {
580         flecfec_stream_ = receiver_->call_->CreateFlexfecReceiveStream(flexfec);
581       });
582     }
583     receiver_->ssrc_media_types_[recv_config.rtp.remote_ssrc] =
584         MediaType::VIDEO;
585     if (config.stream.use_rtx)
586       receiver_->ssrc_media_types_[recv_config.rtp.rtx_ssrc] = MediaType::VIDEO;
587     receiver_->SendTask([this, &recv_config] {
588       receive_streams_.push_back(
589           receiver_->call_->CreateVideoReceiveStream(std::move(recv_config)));
590     });
591   }
592 }
593 
~ReceiveVideoStream()594 ReceiveVideoStream::~ReceiveVideoStream() {
595   receiver_->SendTask([this] {
596     for (auto* recv_stream : receive_streams_)
597       receiver_->call_->DestroyVideoReceiveStream(recv_stream);
598     if (flecfec_stream_)
599       receiver_->call_->DestroyFlexfecReceiveStream(flecfec_stream_);
600   });
601 }
602 
Start()603 void ReceiveVideoStream::Start() {
604   receiver_->SendTask([this] {
605     for (auto* recv_stream : receive_streams_)
606       recv_stream->Start();
607     receiver_->call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
608   });
609 }
610 
Stop()611 void ReceiveVideoStream::Stop() {
612   receiver_->SendTask([this] {
613     for (auto* recv_stream : receive_streams_)
614       recv_stream->Stop();
615   });
616 }
617 
GetStats() const618 VideoReceiveStream::Stats ReceiveVideoStream::GetStats() const {
619   if (receive_streams_.empty())
620     return VideoReceiveStream::Stats();
621   // TODO(srte): Handle multiple receive streams.
622   return receive_streams_.back()->GetStats();
623 }
624 
625 VideoStreamPair::~VideoStreamPair() = default;
626 
VideoStreamPair(CallClient * sender,CallClient * receiver,VideoStreamConfig config)627 VideoStreamPair::VideoStreamPair(CallClient* sender,
628                                  CallClient* receiver,
629                                  VideoStreamConfig config)
630     : config_(config),
631       matcher_(config.hooks.frame_pair_handlers),
632       send_stream_(sender, config, sender->transport_.get(), &matcher_),
633       receive_stream_(receiver,
634                       config,
635                       &send_stream_,
636                       /*chosen_stream=*/0,
637                       receiver->transport_.get(),
638                       &matcher_) {}
639 
640 }  // namespace test
641 }  // namespace webrtc
642