From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../libwebrtc/test/fuzzers/utils/rtp_replayer.cc | 202 +++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 third_party/libwebrtc/test/fuzzers/utils/rtp_replayer.cc (limited to 'third_party/libwebrtc/test/fuzzers/utils/rtp_replayer.cc') diff --git a/third_party/libwebrtc/test/fuzzers/utils/rtp_replayer.cc b/third_party/libwebrtc/test/fuzzers/utils/rtp_replayer.cc new file mode 100644 index 0000000000..f6d7119338 --- /dev/null +++ b/third_party/libwebrtc/test/fuzzers/utils/rtp_replayer.cc @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2019 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/fuzzers/utils/rtp_replayer.h" + +#include +#include +#include +#include + +#include "absl/memory/memory.h" +#include "api/task_queue/default_task_queue_factory.h" +#include "api/transport/field_trial_based_config.h" +#include "api/units/timestamp.h" +#include "modules/rtp_rtcp/source/rtp_packet.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "rtc_base/strings/json.h" +#include "system_wrappers/include/clock.h" +#include "test/call_config_utils.h" +#include "test/encoder_settings.h" +#include "test/fake_decoder.h" +#include "test/rtp_file_reader.h" +#include "test/run_loop.h" + +namespace webrtc { +namespace test { + +void RtpReplayer::Replay(const std::string& replay_config_filepath, + const uint8_t* rtp_dump_data, + size_t rtp_dump_size) { + auto stream_state = std::make_unique(); + std::vector receive_stream_configs = + ReadConfigFromFile(replay_config_filepath, &(stream_state->transport)); + return Replay(std::move(stream_state), std::move(receive_stream_configs), + rtp_dump_data, rtp_dump_size); +} + +void RtpReplayer::Replay( + std::unique_ptr stream_state, + std::vector receive_stream_configs, + const uint8_t* rtp_dump_data, + size_t rtp_dump_size) { + RunLoop loop; + rtc::ScopedBaseFakeClock fake_clock; + + // Work around: webrtc calls webrtc::Random(clock.TimeInMicroseconds()) + // everywhere and Random expects non-zero seed. Let's set the clock non-zero + // to make them happy. + fake_clock.SetTime(webrtc::Timestamp::Millis(1)); + + // Attempt to create an RtpReader from the input file. + auto rtp_reader = CreateRtpReader(rtp_dump_data, rtp_dump_size); + if (rtp_reader == nullptr) { + RTC_LOG(LS_ERROR) << "Failed to create the rtp_reader"; + return; + } + + RtpHeaderExtensionMap extensions(/*extmap_allow_mixed=*/true); + // Skip i = 0 since it maps to kRtpExtensionNone. + for (int i = 1; i < kRtpExtensionNumberOfExtensions; i++) { + RTPExtensionType extension_type = static_cast(i); + // Extensions are registered with an ID, which you signal to the + // peer so they know what to expect. This code only cares about + // parsing so the value of the ID isn't relevant. + extensions.RegisterByType(i, extension_type); + } + + // Setup the video streams based on the configuration. + webrtc::RtcEventLogNull event_log; + std::unique_ptr task_queue_factory = + CreateDefaultTaskQueueFactory(); + CallConfig call_config(&event_log); + call_config.task_queue_factory = task_queue_factory.get(); + FieldTrialBasedConfig field_trials; + call_config.trials = &field_trials; + std::unique_ptr call(Call::Create(call_config)); + SetupVideoStreams(&receive_stream_configs, stream_state.get(), call.get()); + + // Start replaying the provided stream now that it has been configured. + for (const auto& receive_stream : stream_state->receive_streams) { + receive_stream->Start(); + } + + ReplayPackets(&fake_clock, call.get(), rtp_reader.get(), extensions); + + for (const auto& receive_stream : stream_state->receive_streams) { + call->DestroyVideoReceiveStream(receive_stream); + } +} + +std::vector +RtpReplayer::ReadConfigFromFile(const std::string& replay_config, + Transport* transport) { + Json::CharReaderBuilder factory; + std::unique_ptr json_reader = + absl::WrapUnique(factory.newCharReader()); + Json::Value json_configs; + Json::String errors; + if (!json_reader->parse(replay_config.data(), + replay_config.data() + replay_config.length(), + &json_configs, &errors)) { + RTC_LOG(LS_ERROR) + << "Error parsing JSON replay configuration for the fuzzer: " << errors; + return {}; + } + + std::vector receive_stream_configs; + receive_stream_configs.reserve(json_configs.size()); + for (const auto& json : json_configs) { + receive_stream_configs.push_back( + ParseVideoReceiveStreamJsonConfig(transport, json)); + } + return receive_stream_configs; +} + +void RtpReplayer::SetupVideoStreams( + std::vector* receive_stream_configs, + StreamState* stream_state, + Call* call) { + stream_state->decoder_factory = std::make_unique(); + for (auto& receive_config : *receive_stream_configs) { + // Attach the decoder for the corresponding payload type in the config. + for (auto& decoder : receive_config.decoders) { + decoder = test::CreateMatchingDecoder(decoder.payload_type, + decoder.video_format.name); + } + + // Create the window to display the rendered video. + stream_state->sinks.emplace_back( + test::VideoRenderer::Create("Fuzzing WebRTC Video Config", 640, 480)); + // Create a receive stream for this config. + receive_config.renderer = stream_state->sinks.back().get(); + receive_config.decoder_factory = stream_state->decoder_factory.get(); + stream_state->receive_streams.emplace_back( + call->CreateVideoReceiveStream(std::move(receive_config))); + } +} + +std::unique_ptr RtpReplayer::CreateRtpReader( + const uint8_t* rtp_dump_data, + size_t rtp_dump_size) { + std::unique_ptr rtp_reader(test::RtpFileReader::Create( + test::RtpFileReader::kRtpDump, rtp_dump_data, rtp_dump_size, {})); + if (!rtp_reader) { + RTC_LOG(LS_ERROR) << "Unable to open input file with any supported format"; + return nullptr; + } + return rtp_reader; +} + +void RtpReplayer::ReplayPackets( + rtc::FakeClock* clock, + Call* call, + test::RtpFileReader* rtp_reader, + const RtpPacketReceived::ExtensionManager& extensions) { + int64_t replay_start_ms = -1; + + while (true) { + int64_t now_ms = rtc::TimeMillis(); + if (replay_start_ms == -1) { + replay_start_ms = now_ms; + } + + test::RtpPacket packet; + if (!rtp_reader->NextPacket(&packet)) { + break; + } + + int64_t deliver_in_ms = replay_start_ms + packet.time_ms - now_ms; + if (deliver_in_ms > 0) { + // StatsCounter::ReportMetricToAggregatedCounter is O(elapsed time). + // Set an upper limit to prevent waste time. + clock->AdvanceTime(webrtc::TimeDelta::Millis( + std::min(deliver_in_ms, static_cast(100)))); + } + + RtpPacketReceived received_packet( + &extensions, Timestamp::Micros(clock->TimeNanos() / 1000)); + if (!received_packet.Parse(packet.data, packet.length)) { + RTC_LOG(LS_ERROR) << "Packet error, corrupt packets or incorrect setup?"; + break; + } + // Set the clock rate - always 90K for video + received_packet.set_payload_type_frequency(kVideoPayloadTypeFrequency); + + call->Receiver()->DeliverRtpPacket( + MediaType::VIDEO, std::move(received_packet), + [&](const RtpPacketReceived& parsed_packet) { + RTC_LOG(LS_ERROR) << "Unknown SSRC: " << parsed_packet.Ssrc(); + return false; + }); + } +} +} // namespace test +} // namespace webrtc -- cgit v1.2.3