diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/test/scenario/call_client.cc | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/test/scenario/call_client.cc')
-rw-r--r-- | third_party/libwebrtc/test/scenario/call_client.cc | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/scenario/call_client.cc b/third_party/libwebrtc/test/scenario/call_client.cc new file mode 100644 index 0000000000..fdf36dee08 --- /dev/null +++ b/third_party/libwebrtc/test/scenario/call_client.cc @@ -0,0 +1,388 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "test/scenario/call_client.h" + +#include <iostream> +#include <memory> +#include <utility> + +#include "api/media_types.h" +#include "api/rtc_event_log/rtc_event_log.h" +#include "api/rtc_event_log/rtc_event_log_factory.h" +#include "api/transport/network_types.h" +#include "call/call.h" +#include "call/rtp_transport_controller_send_factory.h" +#include "modules/audio_device/include/test_audio_device.h" +#include "modules/audio_mixer/audio_mixer_impl.h" +#include "modules/rtp_rtcp/include/rtp_header_extension_map.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "modules/rtp_rtcp/source/rtp_util.h" + +namespace webrtc { +namespace test { +namespace { +static constexpr size_t kNumSsrcs = 6; +const uint32_t kSendRtxSsrcs[kNumSsrcs] = {0xBADCAFD, 0xBADCAFE, 0xBADCAFF, + 0xBADCB00, 0xBADCB01, 0xBADCB02}; +const uint32_t kVideoSendSsrcs[kNumSsrcs] = {0xC0FFED, 0xC0FFEE, 0xC0FFEF, + 0xC0FFF0, 0xC0FFF1, 0xC0FFF2}; +const uint32_t kVideoRecvLocalSsrcs[kNumSsrcs] = {0xDAB001, 0xDAB002, 0xDAB003, + 0xDAB004, 0xDAB005, 0xDAB006}; +const uint32_t kAudioSendSsrc = 0xDEADBEEF; +const uint32_t kReceiverLocalAudioSsrc = 0x1234567; + +constexpr int kEventLogOutputIntervalMs = 5000; + +CallClientFakeAudio InitAudio(TimeController* time_controller) { + CallClientFakeAudio setup; + auto capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(256, 48000); + auto renderer = TestAudioDeviceModule::CreateDiscardRenderer(48000); + setup.fake_audio_device = TestAudioDeviceModule::Create( + time_controller->GetTaskQueueFactory(), std::move(capturer), + std::move(renderer), 1.f); + setup.apm = AudioProcessingBuilder().Create(); + setup.fake_audio_device->Init(); + AudioState::Config audio_state_config; + audio_state_config.audio_mixer = AudioMixerImpl::Create(); + audio_state_config.audio_processing = setup.apm; + audio_state_config.audio_device_module = setup.fake_audio_device; + setup.audio_state = AudioState::Create(audio_state_config); + setup.fake_audio_device->RegisterAudioCallback( + setup.audio_state->audio_transport()); + return setup; +} + +std::unique_ptr<Call> CreateCall( + TimeController* time_controller, + RtcEventLog* event_log, + CallClientConfig config, + LoggingNetworkControllerFactory* network_controller_factory, + rtc::scoped_refptr<AudioState> audio_state) { + CallConfig call_config(event_log); + call_config.bitrate_config.max_bitrate_bps = + config.transport.rates.max_rate.bps_or(-1); + call_config.bitrate_config.min_bitrate_bps = + config.transport.rates.min_rate.bps(); + call_config.bitrate_config.start_bitrate_bps = + config.transport.rates.start_rate.bps(); + call_config.task_queue_factory = time_controller->GetTaskQueueFactory(); + call_config.network_controller_factory = network_controller_factory; + call_config.audio_state = audio_state; + call_config.pacer_burst_interval = config.pacer_burst_interval; + call_config.trials = config.field_trials; + Clock* clock = time_controller->GetClock(); + return Call::Create(call_config, clock, + RtpTransportControllerSendFactory().Create( + call_config.ExtractTransportConfig(), clock)); +} + +std::unique_ptr<RtcEventLog> CreateEventLog( + TaskQueueFactory* task_queue_factory, + LogWriterFactoryInterface* log_writer_factory) { + if (!log_writer_factory) { + return std::make_unique<RtcEventLogNull>(); + } + auto event_log = RtcEventLogFactory(task_queue_factory) + .CreateRtcEventLog(RtcEventLog::EncodingType::NewFormat); + bool success = event_log->StartLogging(log_writer_factory->Create(".rtc.dat"), + kEventLogOutputIntervalMs); + RTC_CHECK(success); + return event_log; +} +} // namespace +NetworkControleUpdateCache::NetworkControleUpdateCache( + std::unique_ptr<NetworkControllerInterface> controller) + : controller_(std::move(controller)) {} +NetworkControlUpdate NetworkControleUpdateCache::OnNetworkAvailability( + NetworkAvailability msg) { + return Update(controller_->OnNetworkAvailability(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnNetworkRouteChange( + NetworkRouteChange msg) { + return Update(controller_->OnNetworkRouteChange(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnProcessInterval( + ProcessInterval msg) { + return Update(controller_->OnProcessInterval(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnRemoteBitrateReport( + RemoteBitrateReport msg) { + return Update(controller_->OnRemoteBitrateReport(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnRoundTripTimeUpdate( + RoundTripTimeUpdate msg) { + return Update(controller_->OnRoundTripTimeUpdate(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnSentPacket(SentPacket msg) { + return Update(controller_->OnSentPacket(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnReceivedPacket( + ReceivedPacket msg) { + return Update(controller_->OnReceivedPacket(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnStreamsConfig( + StreamsConfig msg) { + return Update(controller_->OnStreamsConfig(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnTargetRateConstraints( + TargetRateConstraints msg) { + return Update(controller_->OnTargetRateConstraints(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnTransportLossReport( + TransportLossReport msg) { + return Update(controller_->OnTransportLossReport(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnTransportPacketsFeedback( + TransportPacketsFeedback msg) { + return Update(controller_->OnTransportPacketsFeedback(msg)); +} +NetworkControlUpdate NetworkControleUpdateCache::OnNetworkStateEstimate( + NetworkStateEstimate msg) { + return Update(controller_->OnNetworkStateEstimate(msg)); +} + +NetworkControlUpdate NetworkControleUpdateCache::update_state() const { + return update_state_; +} +NetworkControlUpdate NetworkControleUpdateCache::Update( + NetworkControlUpdate update) { + if (update.target_rate) + update_state_.target_rate = update.target_rate; + if (update.pacer_config) + update_state_.pacer_config = update.pacer_config; + if (update.congestion_window) + update_state_.congestion_window = update.congestion_window; + if (!update.probe_cluster_configs.empty()) + update_state_.probe_cluster_configs = update.probe_cluster_configs; + return update; +} + +LoggingNetworkControllerFactory::LoggingNetworkControllerFactory( + LogWriterFactoryInterface* log_writer_factory, + TransportControllerConfig config) { + if (config.cc_factory) { + cc_factory_ = config.cc_factory; + if (log_writer_factory) + RTC_LOG(LS_WARNING) + << "Can't log controller state for injected network controllers"; + } else { + if (log_writer_factory) { + goog_cc_factory_.AttachWriter( + log_writer_factory->Create(".cc_state.txt")); + print_cc_state_ = true; + } + cc_factory_ = &goog_cc_factory_; + } +} + +LoggingNetworkControllerFactory::~LoggingNetworkControllerFactory() {} + +void LoggingNetworkControllerFactory::LogCongestionControllerStats( + Timestamp at_time) { + if (print_cc_state_) + goog_cc_factory_.PrintState(at_time); +} + +NetworkControlUpdate LoggingNetworkControllerFactory::GetUpdate() const { + if (last_controller_) + return last_controller_->update_state(); + return NetworkControlUpdate(); +} + +std::unique_ptr<NetworkControllerInterface> +LoggingNetworkControllerFactory::Create(NetworkControllerConfig config) { + auto controller = + std::make_unique<NetworkControleUpdateCache>(cc_factory_->Create(config)); + last_controller_ = controller.get(); + return controller; +} + +TimeDelta LoggingNetworkControllerFactory::GetProcessInterval() const { + return cc_factory_->GetProcessInterval(); +} + +void LoggingNetworkControllerFactory::SetRemoteBitrateEstimate( + RemoteBitrateReport msg) { + if (last_controller_) + last_controller_->OnRemoteBitrateReport(msg); +} + +CallClient::CallClient( + TimeController* time_controller, + std::unique_ptr<LogWriterFactoryInterface> log_writer_factory, + CallClientConfig config) + : time_controller_(time_controller), + clock_(time_controller->GetClock()), + log_writer_factory_(std::move(log_writer_factory)), + network_controller_factory_(log_writer_factory_.get(), config.transport), + task_queue_(time_controller->GetTaskQueueFactory()->CreateTaskQueue( + "CallClient", + TaskQueueFactory::Priority::NORMAL)) { + config.field_trials = &field_trials_; + SendTask([this, config] { + event_log_ = CreateEventLog(time_controller_->GetTaskQueueFactory(), + log_writer_factory_.get()); + fake_audio_setup_ = InitAudio(time_controller_); + + call_ = + CreateCall(time_controller_, event_log_.get(), config, + &network_controller_factory_, fake_audio_setup_.audio_state); + transport_ = std::make_unique<NetworkNodeTransport>(clock_, call_.get()); + }); +} + +CallClient::~CallClient() { + SendTask([&] { + call_.reset(); + fake_audio_setup_ = {}; + rtc::Event done; + event_log_->StopLogging([&done] { done.Set(); }); + done.Wait(rtc::Event::kForever); + event_log_.reset(); + }); +} + +ColumnPrinter CallClient::StatsPrinter() { + return ColumnPrinter::Lambda( + "pacer_delay call_send_bw", + [this](rtc::SimpleStringBuilder& sb) { + Call::Stats call_stats = call_->GetStats(); + sb.AppendFormat("%.3lf %.0lf", call_stats.pacer_delay_ms / 1000.0, + call_stats.send_bandwidth_bps / 8.0); + }, + 64); +} + +Call::Stats CallClient::GetStats() { + // This call needs to be made on the thread that `call_` was constructed on. + Call::Stats stats; + SendTask([this, &stats] { stats = call_->GetStats(); }); + return stats; +} + +DataRate CallClient::target_rate() const { + return network_controller_factory_.GetUpdate().target_rate->target_rate; +} + +DataRate CallClient::stable_target_rate() const { + return network_controller_factory_.GetUpdate() + .target_rate->stable_target_rate; +} + +DataRate CallClient::padding_rate() const { + return network_controller_factory_.GetUpdate().pacer_config->pad_rate(); +} + +void CallClient::SetRemoteBitrate(DataRate bitrate) { + RemoteBitrateReport msg; + msg.bandwidth = bitrate; + msg.receive_time = clock_->CurrentTime(); + network_controller_factory_.SetRemoteBitrateEstimate(msg); +} + +void CallClient::UpdateBitrateConstraints( + const BitrateConstraints& constraints) { + SendTask([this, &constraints]() { + call_->GetTransportControllerSend()->SetSdpBitrateParameters(constraints); + }); +} + +void CallClient::SetAudioReceiveRtpHeaderExtensions( + rtc::ArrayView<RtpExtension> extensions) { + SendTask([this, &extensions]() { + audio_extensions_ = RtpHeaderExtensionMap(extensions); + }); +} + +void CallClient::SetVideoReceiveRtpHeaderExtensions( + rtc::ArrayView<RtpExtension> extensions) { + SendTask([this, &extensions]() { + video_extensions_ = RtpHeaderExtensionMap(extensions); + }); +} + +void CallClient::OnPacketReceived(EmulatedIpPacket packet) { + MediaType media_type = MediaType::ANY; + if (IsRtpPacket(packet.data)) { + media_type = ssrc_media_types_[ParseRtpSsrc(packet.data)]; + task_queue_.PostTask([this, media_type, + packet = std::move(packet)]() mutable { + RtpHeaderExtensionMap& extension_map = media_type == MediaType::AUDIO + ? audio_extensions_ + : video_extensions_; + RtpPacketReceived received_packet(&extension_map, packet.arrival_time); + RTC_CHECK(received_packet.Parse(packet.data)); + call_->Receiver()->DeliverRtpPacket(media_type, received_packet, + /*undemuxable_packet_handler=*/ + [](const RtpPacketReceived& packet) { + RTC_CHECK_NOTREACHED(); + return false; + }); + }); + } else { + task_queue_.PostTask( + [call = call_.get(), packet = std::move(packet)]() mutable { + call->Receiver()->DeliverRtcpPacket(packet.data); + }); + } +} + +std::unique_ptr<RtcEventLogOutput> CallClient::GetLogWriter(std::string name) { + if (!log_writer_factory_ || name.empty()) + return nullptr; + return log_writer_factory_->Create(name); +} + +uint32_t CallClient::GetNextVideoSsrc() { + RTC_CHECK_LT(next_video_ssrc_index_, kNumSsrcs); + return kVideoSendSsrcs[next_video_ssrc_index_++]; +} + +uint32_t CallClient::GetNextVideoLocalSsrc() { + RTC_CHECK_LT(next_video_local_ssrc_index_, kNumSsrcs); + return kVideoRecvLocalSsrcs[next_video_local_ssrc_index_++]; +} + +uint32_t CallClient::GetNextAudioSsrc() { + RTC_CHECK_LT(next_audio_ssrc_index_, 1); + next_audio_ssrc_index_++; + return kAudioSendSsrc; +} + +uint32_t CallClient::GetNextAudioLocalSsrc() { + RTC_CHECK_LT(next_audio_local_ssrc_index_, 1); + next_audio_local_ssrc_index_++; + return kReceiverLocalAudioSsrc; +} + +uint32_t CallClient::GetNextRtxSsrc() { + RTC_CHECK_LT(next_rtx_ssrc_index_, kNumSsrcs); + return kSendRtxSsrcs[next_rtx_ssrc_index_++]; +} + +void CallClient::SendTask(std::function<void()> task) { + task_queue_.SendTask(std::move(task)); +} + +int16_t CallClient::Bind(EmulatedEndpoint* endpoint) { + uint16_t port = endpoint->BindReceiver(0, this).value(); + endpoints_.push_back({endpoint, port}); + return port; +} + +void CallClient::UnBind() { + for (auto ep_port : endpoints_) + ep_port.first->UnbindReceiver(ep_port.second); +} + +CallClientPair::~CallClientPair() = default; + +} // namespace test +} // namespace webrtc |