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