blob: e430d40d8646730babf786ee2acc62875132e6ef [file] [log] [blame]
Benjamin Wright47dbcab2019-03-14 15:01:30 -07001/*
2 * Copyright (c) 2019 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
11#include "test/fuzzers/utils/rtp_replayer.h"
12
Benjamin Wright3295c012019-03-29 15:56:06 -070013#include <algorithm>
Benjamin Wright47dbcab2019-03-14 15:01:30 -070014#include <string>
15#include <utility>
16
17#include "absl/memory/memory.h"
Danil Chapovalov32b18342019-07-11 13:58:14 +020018#include "api/task_queue/default_task_queue_factory.h"
Benjamin Wright47dbcab2019-03-14 15:01:30 -070019#include "modules/rtp_rtcp/include/rtp_header_parser.h"
20#include "rtc_base/strings/json.h"
21#include "system_wrappers/include/clock.h"
22#include "system_wrappers/include/sleep.h"
23#include "test/call_config_utils.h"
24#include "test/encoder_settings.h"
25#include "test/fake_decoder.h"
26#include "test/rtp_file_reader.h"
27
28namespace webrtc {
29namespace test {
30
31void RtpReplayer::Replay(const std::string& replay_config_filepath,
32 const uint8_t* rtp_dump_data,
33 size_t rtp_dump_size) {
34 auto stream_state = absl::make_unique<StreamState>();
35 std::vector<VideoReceiveStream::Config> receive_stream_configs =
36 ReadConfigFromFile(replay_config_filepath, &(stream_state->transport));
37 return Replay(std::move(stream_state), std::move(receive_stream_configs),
38 rtp_dump_data, rtp_dump_size);
39}
40
41void RtpReplayer::Replay(
42 std::unique_ptr<StreamState> stream_state,
43 std::vector<VideoReceiveStream::Config> receive_stream_configs,
44 const uint8_t* rtp_dump_data,
45 size_t rtp_dump_size) {
46 // Attempt to create an RtpReader from the input file.
47 auto rtp_reader = CreateRtpReader(rtp_dump_data, rtp_dump_size);
48 if (rtp_reader == nullptr) {
49 RTC_LOG(LS_ERROR) << "Failed to create the rtp_reader";
50 return;
51 }
52
53 // Setup the video streams based on the configuration.
Danil Chapovalov83bbe912019-08-07 12:24:53 +020054 webrtc::RtcEventLogNull event_log;
Danil Chapovalov98793e52019-04-11 10:48:40 +020055 std::unique_ptr<TaskQueueFactory> task_queue_factory =
Danil Chapovalov32b18342019-07-11 13:58:14 +020056 CreateDefaultTaskQueueFactory();
Benjamin Wright47dbcab2019-03-14 15:01:30 -070057 Call::Config call_config(&event_log);
Danil Chapovalov98793e52019-04-11 10:48:40 +020058 call_config.task_queue_factory = task_queue_factory.get();
Benjamin Wright47dbcab2019-03-14 15:01:30 -070059 std::unique_ptr<Call> call(Call::Create(call_config));
60 SetupVideoStreams(&receive_stream_configs, stream_state.get(), call.get());
61
62 // Start replaying the provided stream now that it has been configured.
63 for (const auto& receive_stream : stream_state->receive_streams) {
64 receive_stream->Start();
65 }
66
67 ReplayPackets(call.get(), rtp_reader.get());
68
69 for (const auto& receive_stream : stream_state->receive_streams) {
70 call->DestroyVideoReceiveStream(receive_stream);
71 }
72}
73
74std::vector<VideoReceiveStream::Config> RtpReplayer::ReadConfigFromFile(
75 const std::string& replay_config,
76 Transport* transport) {
77 Json::Reader json_reader;
78 Json::Value json_configs;
79 if (!json_reader.parse(replay_config, json_configs)) {
80 RTC_LOG(LS_ERROR)
81 << "Error parsing JSON replay configuration for the fuzzer"
82 << json_reader.getFormatedErrorMessages();
83 return {};
84 }
85
86 std::vector<VideoReceiveStream::Config> receive_stream_configs;
87 receive_stream_configs.reserve(json_configs.size());
88 for (const auto& json : json_configs) {
89 receive_stream_configs.push_back(
90 ParseVideoReceiveStreamJsonConfig(transport, json));
91 }
92 return receive_stream_configs;
93}
94
95void RtpReplayer::SetupVideoStreams(
96 std::vector<VideoReceiveStream::Config>* receive_stream_configs,
97 StreamState* stream_state,
98 Call* call) {
99 stream_state->decoder_factory = absl::make_unique<InternalDecoderFactory>();
100 for (auto& receive_config : *receive_stream_configs) {
101 // Attach the decoder for the corresponding payload type in the config.
102 for (auto& decoder : receive_config.decoders) {
103 decoder = test::CreateMatchingDecoder(decoder.payload_type,
104 decoder.video_format.name);
105 decoder.decoder_factory = stream_state->decoder_factory.get();
106 }
107
108 // Create the window to display the rendered video.
109 stream_state->sinks.emplace_back(
110 test::VideoRenderer::Create("Fuzzing WebRTC Video Config", 640, 480));
111 // Create a receive stream for this config.
112 receive_config.renderer = stream_state->sinks.back().get();
113 stream_state->receive_streams.emplace_back(
114 call->CreateVideoReceiveStream(std::move(receive_config)));
115 }
116}
117
118std::unique_ptr<test::RtpFileReader> RtpReplayer::CreateRtpReader(
119 const uint8_t* rtp_dump_data,
120 size_t rtp_dump_size) {
121 std::unique_ptr<test::RtpFileReader> rtp_reader(test::RtpFileReader::Create(
122 test::RtpFileReader::kRtpDump, rtp_dump_data, rtp_dump_size, {}));
123 if (!rtp_reader) {
124 RTC_LOG(LS_ERROR) << "Unable to open input file with any supported format";
125 return nullptr;
126 }
127 return rtp_reader;
128}
129
130void RtpReplayer::ReplayPackets(Call* call, test::RtpFileReader* rtp_reader) {
131 int64_t replay_start_ms = -1;
132 int num_packets = 0;
133 std::map<uint32_t, int> unknown_packets;
134
135 while (true) {
136 int64_t now_ms = rtc::TimeMillis();
137 if (replay_start_ms == -1) {
138 replay_start_ms = now_ms;
139 }
140
141 test::RtpPacket packet;
142 if (!rtp_reader->NextPacket(&packet)) {
143 break;
144 }
145
146 int64_t deliver_in_ms = replay_start_ms + packet.time_ms - now_ms;
147 if (deliver_in_ms > 0) {
Benjamin Wright3295c012019-03-29 15:56:06 -0700148 // Set an upper limit on sleep to prevent timing out.
149 SleepMs(std::min(deliver_in_ms, static_cast<int64_t>(100)));
Benjamin Wright47dbcab2019-03-14 15:01:30 -0700150 }
151
152 ++num_packets;
153 switch (call->Receiver()->DeliverPacket(
154 webrtc::MediaType::VIDEO,
155 rtc::CopyOnWriteBuffer(packet.data, packet.length),
156 /* packet_time_us */ -1)) {
157 case PacketReceiver::DELIVERY_OK:
158 break;
159 case PacketReceiver::DELIVERY_UNKNOWN_SSRC: {
160 RTPHeader header;
161 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
162
163 parser->Parse(packet.data, packet.length, &header);
164 if (unknown_packets[header.ssrc] == 0) {
165 RTC_LOG(LS_ERROR) << "Unknown SSRC: " << header.ssrc;
166 }
167 ++unknown_packets[header.ssrc];
168 break;
169 }
170 case PacketReceiver::DELIVERY_PACKET_ERROR: {
171 RTC_LOG(LS_ERROR)
172 << "Packet error, corrupt packets or incorrect setup?";
173 RTPHeader header;
174 std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
175 parser->Parse(packet.data, packet.length, &header);
176 RTC_LOG(LS_ERROR) << "Packet packet_length=" << packet.length
177 << " payload_type=" << header.payloadType
178 << " sequence_number=" << header.sequenceNumber
179 << " time_stamp=" << header.timestamp
180 << " ssrc=" << header.ssrc;
181 break;
182 }
183 }
184 }
185 RTC_LOG(LS_INFO) << "num_packets: " << num_packets;
186
187 for (const auto& unknown_packet : unknown_packets) {
188 RTC_LOG(LS_ERROR) << "Packets for unknown ssrc " << unknown_packet.first
189 << ":" << unknown_packet.second;
190 }
191}
192
193} // namespace test
194} // namespace webrtc