1 /*
2 * Copyright (c) 2022 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 "rtc_tools/rtc_event_log_to_text/converter.h"
12
13 #include <inttypes.h>
14
15 #include <map>
16 #include <vector>
17
18 #include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
19 #include "logging/rtc_event_log/events/rtc_event_alr_state.h"
20 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
21 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
22 #include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
23 #include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
24 #include "logging/rtc_event_log/events/rtc_event_begin_log.h"
25 #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
26 #include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
27 #include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
28 #include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
29 #include "logging/rtc_event_log/events/rtc_event_end_log.h"
30 #include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
31 #include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
32 #include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
33 #include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
34 #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
35 #include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
36 #include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
37 #include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
38 #include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
39 #include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
40 #include "logging/rtc_event_log/events/rtc_event_route_change.h"
41 #include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
42 #include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
43 #include "logging/rtc_event_log/rtc_event_log_parser.h"
44 #include "logging/rtc_event_log/rtc_event_processor.h"
45 #include "logging/rtc_event_log/rtc_stream_config.h"
46 #include "rtc_base/logging.h"
47
48 namespace webrtc {
49 namespace {
50
PrintHeaderExtensionConfig(FILE * output,const std::vector<RtpExtension> & rtp_extensions)51 void PrintHeaderExtensionConfig(
52 FILE* output,
53 const std::vector<RtpExtension>& rtp_extensions) {
54 if (rtp_extensions.empty())
55 return;
56 fprintf(output, " extension_map=");
57 for (const RtpExtension& extension : rtp_extensions) {
58 fprintf(output, "{uri:%s,id:%d}", extension.uri.c_str(), extension.id);
59 }
60 }
61
62 } // namespace
63
Convert(std::string inputfile,FILE * output,ParsedRtcEventLog::UnconfiguredHeaderExtensions handle_unconfigured_extensions)64 bool Convert(std::string inputfile,
65 FILE* output,
66 ParsedRtcEventLog::UnconfiguredHeaderExtensions
67 handle_unconfigured_extensions) {
68 ParsedRtcEventLog parsed_log(handle_unconfigured_extensions,
69 /*allow_incomplete_logs=*/true);
70
71 auto status = parsed_log.ParseFile(inputfile);
72 if (!status.ok()) {
73 RTC_LOG(LS_ERROR) << "Failed to parse " << inputfile << ": "
74 << status.message();
75 return false;
76 }
77
78 auto audio_recv_stream_handler = [&](const LoggedAudioRecvConfig& event) {
79 fprintf(output, "AUDIO_RECV_STREAM_CONFIG %" PRId64, event.log_time_ms());
80 fprintf(output, " remote_ssrc=%u", event.config.remote_ssrc);
81 fprintf(output, " local_ssrc=%u", event.config.local_ssrc);
82 PrintHeaderExtensionConfig(output, event.config.rtp_extensions);
83 fprintf(output, "\n");
84 };
85
86 auto audio_send_stream_handler = [&](const LoggedAudioSendConfig& event) {
87 fprintf(output, "AUDIO_SEND_STREAM_CONFIG %" PRId64, event.log_time_ms());
88 fprintf(output, " ssrc=%u", event.config.local_ssrc);
89 PrintHeaderExtensionConfig(output, event.config.rtp_extensions);
90 fprintf(output, "\n");
91 };
92
93 auto video_recv_stream_handler = [&](const LoggedVideoRecvConfig& event) {
94 fprintf(output, "VIDEO_RECV_STREAM_CONFIG %" PRId64, event.log_time_ms());
95 fprintf(output, " remote_ssrc=%u", event.config.remote_ssrc);
96 fprintf(output, " local_ssrc=%u", event.config.local_ssrc);
97 fprintf(output, " rtx_ssrc=%u", event.config.rtx_ssrc);
98 PrintHeaderExtensionConfig(output, event.config.rtp_extensions);
99 fprintf(output, "\n");
100 };
101
102 auto video_send_stream_handler = [&](const LoggedVideoSendConfig& event) {
103 fprintf(output, "VIDEO_SEND_STREAM_CONFIG %" PRId64, event.log_time_ms());
104 fprintf(output, " ssrc=%u", event.config.local_ssrc);
105 fprintf(output, " rtx_ssrc=%u", event.config.rtx_ssrc);
106 PrintHeaderExtensionConfig(output, event.config.rtp_extensions);
107 fprintf(output, "\n");
108 };
109
110 auto start_logging_handler = [&](const LoggedStartEvent& event) {
111 fprintf(output, "START_LOG %" PRId64 "\n", event.log_time_ms());
112 };
113
114 auto stop_logging_handler = [&](const LoggedStopEvent& event) {
115 fprintf(output, "STOP_LOG %" PRId64 "\n", event.log_time_ms());
116 };
117
118 auto alr_state_handler = [&](const LoggedAlrStateEvent& event) {
119 fprintf(output, "ALR_STATE %" PRId64 " in_alr=%u\n", event.log_time_ms(),
120 event.in_alr);
121 };
122
123 auto audio_playout_handler = [&](const LoggedAudioPlayoutEvent& event) {
124 fprintf(output, "AUDIO_PLAYOUT %" PRId64 " ssrc=%u\n", event.log_time_ms(),
125 event.ssrc);
126 };
127
128 auto audio_network_adaptation_handler =
129 [&](const LoggedAudioNetworkAdaptationEvent& event) {
130 fprintf(output, "AUDIO_NETWORK_ADAPTATION %" PRId64,
131 event.log_time_ms());
132
133 if (event.config.enable_dtx.has_value())
134 fprintf(output, " enable_dtx=%u", event.config.enable_dtx.value());
135 if (event.config.enable_fec.has_value())
136 fprintf(output, " enable_fec=%u", event.config.enable_fec.value());
137 if (event.config.bitrate_bps.has_value())
138 fprintf(output, " bitrate_bps=%d", event.config.bitrate_bps.value());
139 if (event.config.num_channels.has_value()) {
140 fprintf(output, " num_channels=%zu",
141 event.config.num_channels.value());
142 }
143 if (event.config.frame_length_ms.has_value()) {
144 fprintf(output, " frame_length_ms=%d",
145 event.config.frame_length_ms.value());
146 }
147 fprintf(output, " last_fl_change_increase=%u",
148 event.config.last_fl_change_increase);
149 if (event.config.uplink_packet_loss_fraction.has_value()) {
150 fprintf(output, " uplink_packet_loss_fraction=%f",
151 event.config.uplink_packet_loss_fraction.value());
152 }
153 fprintf(output, "\n");
154 };
155
156 auto bwe_probe_cluster_created_handler =
157 [&](const LoggedBweProbeClusterCreatedEvent& event) {
158 fprintf(output,
159 "BWE_PROBE_CREATED %" PRId64
160 " id=%d bitrate_bps=%d min_packets=%u "
161 "min_bytes=%u\n",
162 event.log_time_ms(), event.id, event.bitrate_bps,
163 event.min_packets, event.min_bytes);
164 };
165
166 auto bwe_probe_failure_handler =
167 [&](const LoggedBweProbeFailureEvent& event) {
168 fprintf(output, "BWE_PROBE_FAILURE %" PRId64 " id=%d reason=%d\n",
169 event.log_time_ms(), event.id, event.failure_reason);
170 };
171
172 auto bwe_probe_success_handler =
173 [&](const LoggedBweProbeSuccessEvent& event) {
174 fprintf(output, "BWE_PROBE_SUCCESS %" PRId64 " id=%d bitrate_bps=%d\n",
175 event.log_time_ms(), event.id, event.bitrate_bps);
176 };
177
178 auto bwe_delay_update_handler = [&](const LoggedBweDelayBasedUpdate& event) {
179 static const std::map<BandwidthUsage, std::string> text{
180 {BandwidthUsage::kBwNormal, "NORMAL"},
181 {BandwidthUsage::kBwUnderusing, "UNDERUSING"},
182 {BandwidthUsage::kBwOverusing, "OVERUSING"},
183 {BandwidthUsage::kLast, "LAST"}};
184
185 fprintf(output,
186 "BWE_DELAY_BASED %" PRId64 " bitrate_bps=%d detector_state=%s\n",
187 event.log_time_ms(), event.bitrate_bps,
188 text.at(event.detector_state).c_str());
189 };
190
191 auto bwe_loss_update_handler = [&](const LoggedBweLossBasedUpdate& event) {
192 fprintf(output,
193 "BWE_LOSS_BASED %" PRId64
194 " bitrate_bps=%d fraction_lost=%d "
195 "expected_packets=%d\n",
196 event.log_time_ms(), event.bitrate_bps, event.fraction_lost,
197 event.expected_packets);
198 };
199
200 auto dtls_transport_state_handler =
201 [&](const LoggedDtlsTransportState& event) {
202 fprintf(output, "DTLS_TRANSPORT_STATE %" PRId64 " state=%d\n",
203 event.log_time_ms(), event.dtls_transport_state);
204 };
205
206 auto dtls_transport_writable_handler =
207 [&](const LoggedDtlsWritableState& event) {
208 fprintf(output, "DTLS_WRITABLE %" PRId64 " writable=%u\n",
209 event.log_time_ms(), event.writable);
210 };
211
212 auto ice_candidate_pair_config_handler =
213 [&](const LoggedIceCandidatePairConfig& event) {
214 static const std::map<IceCandidatePairConfigType, std::string>
215 update_type_name{
216 {IceCandidatePairConfigType::kAdded, "ADDED"},
217 {IceCandidatePairConfigType::kUpdated, "UPDATED"},
218 {IceCandidatePairConfigType::kDestroyed, "DESTROYED"},
219 {IceCandidatePairConfigType::kSelected, "SELECTED"},
220 {IceCandidatePairConfigType::kNumValues, "NUM_VALUES"}};
221
222 static const std::map<IceCandidateType, std::string>
223 candidate_type_name{{IceCandidateType::kUnknown, "UNKNOWN"},
224 {IceCandidateType::kLocal, "LOCAL"},
225 {IceCandidateType::kStun, "STUN"},
226 {IceCandidateType::kPrflx, "PRFLX"},
227 {IceCandidateType::kRelay, "RELAY"},
228 {IceCandidateType::kNumValues, "NUM_VALUES"}};
229
230 static const std::map<IceCandidatePairProtocol, std::string>
231 protocol_name{{IceCandidatePairProtocol::kUnknown, "UNKNOWN"},
232 {IceCandidatePairProtocol::kUdp, "UDP"},
233 {IceCandidatePairProtocol::kTcp, "TCP"},
234 {IceCandidatePairProtocol::kSsltcp, "SSLTCP"},
235 {IceCandidatePairProtocol::kTls, "TLS"},
236 {IceCandidatePairProtocol::kNumValues, "NUM_VALUES"}};
237
238 static const std::map<IceCandidatePairAddressFamily, std::string>
239 address_family_name{
240 {IceCandidatePairAddressFamily::kUnknown, "UNKNOWN"},
241 {IceCandidatePairAddressFamily::kIpv4, "IPv4"},
242 {IceCandidatePairAddressFamily::kIpv6, "IPv6"},
243 {IceCandidatePairAddressFamily::kNumValues, "NUM_VALUES"}};
244
245 static const std::map<IceCandidateNetworkType, std::string>
246 network_type_name{
247 {IceCandidateNetworkType::kUnknown, "UNKNOWN"},
248 {IceCandidateNetworkType::kEthernet, "ETHERNET"},
249 {IceCandidateNetworkType::kLoopback, "LOOPBACK"},
250 {IceCandidateNetworkType::kWifi, "WIFI"},
251 {IceCandidateNetworkType::kVpn, "VPN"},
252 {IceCandidateNetworkType::kCellular, "CELLULAR"},
253 {IceCandidateNetworkType::kNumValues, "NUM_VALUES"}};
254
255 fprintf(output, "ICE_CANDIDATE_CONFIG %" PRId64, event.log_time_ms());
256 fprintf(output, " id=%u", event.candidate_pair_id);
257 fprintf(output, " type=%s", update_type_name.at(event.type).c_str());
258 fprintf(output, " local_network=%s",
259 network_type_name.at(event.local_network_type).c_str());
260 fprintf(output, " local_address_family=%s",
261 address_family_name.at(event.local_address_family).c_str());
262 fprintf(output, " local_candidate_type=%s",
263 candidate_type_name.at(event.local_candidate_type).c_str());
264 fprintf(output, " local_relay_protocol=%s",
265 protocol_name.at(event.local_relay_protocol).c_str());
266 fprintf(output, " remote_address=%s",
267 address_family_name.at(event.remote_address_family).c_str());
268 fprintf(output, " remote_candidate_type=%s",
269 candidate_type_name.at(event.remote_candidate_type).c_str());
270 fprintf(output, " candidate_pair_protocol=%s",
271 protocol_name.at(event.candidate_pair_protocol).c_str());
272 fprintf(output, "\n");
273 };
274
275 auto ice_candidate_pair_event_handler =
276 [&](const LoggedIceCandidatePairEvent& event) {
277 static const std::map<IceCandidatePairEventType, std::string>
278 check_type_name{
279 {IceCandidatePairEventType::kCheckSent, "CHECK_SENT"},
280 {IceCandidatePairEventType::kCheckReceived, "CHECK_RECEIVED"},
281 {IceCandidatePairEventType::kCheckResponseSent,
282 "CHECK_RESPONSE_SENT"},
283 {IceCandidatePairEventType::kCheckResponseReceived,
284 "CHECK_RESPONSE_RECEIVED"},
285 {IceCandidatePairEventType::kNumValues, "NUM_VALUES"}};
286
287 fprintf(output, "ICE_CANDIDATE_UPDATE %" PRId64, event.log_time_ms());
288 fprintf(output, " id=%u", event.candidate_pair_id);
289 fprintf(output, " type=%s", check_type_name.at(event.type).c_str());
290 fprintf(output, " transaction_id=%u", event.transaction_id);
291 fprintf(output, "\n");
292 };
293
294 auto route_change_handler = [&](const LoggedRouteChangeEvent& event) {
295 fprintf(output, "ROUTE_CHANGE %" PRId64 " connected=%u overhead=%u\n",
296 event.log_time_ms(), event.connected, event.overhead);
297 };
298
299 auto remote_estimate_handler = [&](const LoggedRemoteEstimateEvent& event) {
300 fprintf(output, "REMOTE_ESTIMATE %" PRId64, event.log_time_ms());
301 if (event.link_capacity_lower.has_value()) {
302 fprintf(output, " link_capacity_lower_kbps=%" PRId64,
303 event.link_capacity_lower.value().kbps());
304 }
305 if (event.link_capacity_upper.has_value()) {
306 fprintf(output, " link_capacity_upper_kbps=%" PRId64,
307 event.link_capacity_upper.value().kbps());
308 }
309 fprintf(output, "\n");
310 };
311
312 auto incoming_rtp_packet_handler = [&](const LoggedRtpPacketIncoming& event) {
313 fprintf(output, "RTP_IN %" PRId64, event.log_time_ms());
314 fprintf(output, " ssrc=%u", event.rtp.header.ssrc);
315 fprintf(output, " seq_no=%u", event.rtp.header.sequenceNumber);
316 fprintf(output, " marker=%u", event.rtp.header.markerBit);
317 fprintf(output, " pt=%u", event.rtp.header.payloadType);
318 fprintf(output, " timestamp=%u", event.rtp.header.timestamp);
319 if (event.rtp.header.extension.hasAbsoluteSendTime) {
320 fprintf(output, " abs_send_time=%u",
321 event.rtp.header.extension.absoluteSendTime);
322 }
323 if (event.rtp.header.extension.hasTransmissionTimeOffset) {
324 fprintf(output, " transmission_offset=%d",
325 event.rtp.header.extension.transmissionTimeOffset);
326 }
327 if (event.rtp.header.extension.hasAudioLevel) {
328 fprintf(output, " voice_activity=%d",
329 event.rtp.header.extension.voiceActivity);
330 fprintf(output, " audio_level=%u", event.rtp.header.extension.audioLevel);
331 }
332 if (event.rtp.header.extension.hasVideoRotation) {
333 fprintf(output, " video_rotation=%d",
334 event.rtp.header.extension.videoRotation);
335 }
336 if (event.rtp.header.extension.hasTransportSequenceNumber) {
337 fprintf(output, " transport_seq_no=%u",
338 event.rtp.header.extension.transportSequenceNumber);
339 }
340 fprintf(output, " header_length=%zu", event.rtp.header_length);
341 fprintf(output, " padding_length=%zu", event.rtp.header.paddingLength);
342 fprintf(output, " total_length=%zu", event.rtp.total_length);
343 fprintf(output, "\n");
344 };
345
346 auto outgoing_rtp_packet_handler = [&](const LoggedRtpPacketOutgoing& event) {
347 fprintf(output, "RTP_OUT %" PRId64, event.log_time_ms());
348 fprintf(output, " ssrc=%u", event.rtp.header.ssrc);
349 fprintf(output, " seq_no=%u", event.rtp.header.sequenceNumber);
350 fprintf(output, " marker=%u", event.rtp.header.markerBit);
351 fprintf(output, " pt=%u", event.rtp.header.payloadType);
352 fprintf(output, " timestamp=%u", event.rtp.header.timestamp);
353 if (event.rtp.header.extension.hasAbsoluteSendTime) {
354 fprintf(output, " abs_send_time=%u",
355 event.rtp.header.extension.absoluteSendTime);
356 }
357 if (event.rtp.header.extension.hasTransmissionTimeOffset) {
358 fprintf(output, " transmission_offset=%d",
359 event.rtp.header.extension.transmissionTimeOffset);
360 }
361 if (event.rtp.header.extension.hasAudioLevel) {
362 fprintf(output, " voice_activity=%d",
363 event.rtp.header.extension.voiceActivity);
364 fprintf(output, " audio_level=%u", event.rtp.header.extension.audioLevel);
365 }
366 if (event.rtp.header.extension.hasVideoRotation) {
367 fprintf(output, " video_rotation=%d",
368 event.rtp.header.extension.videoRotation);
369 }
370 if (event.rtp.header.extension.hasTransportSequenceNumber) {
371 fprintf(output, " transport_seq_no=%u",
372 event.rtp.header.extension.transportSequenceNumber);
373 }
374 fprintf(output, " header_length=%zu", event.rtp.header_length);
375 fprintf(output, " padding_length=%zu", event.rtp.header.paddingLength);
376 fprintf(output, " total_length=%zu", event.rtp.total_length);
377 fprintf(output, "\n");
378 };
379
380 auto incoming_rtcp_packet_handler =
381 [&](const LoggedRtcpPacketIncoming& event) {
382 fprintf(output, "RTCP_IN %" PRId64 " <contents omitted>\n",
383 event.log_time_ms());
384 };
385
386 auto outgoing_rtcp_packet_handler =
387 [&](const LoggedRtcpPacketOutgoing& event) {
388 fprintf(output, "RTCP_OUT %" PRId64 " <contents omitted>\n",
389 event.log_time_ms());
390 };
391
392 auto generic_packet_received_handler =
393 [&](const LoggedGenericPacketReceived& event) {
394 fprintf(output,
395 "GENERIC_PACKET_RECV %" PRId64 " packet_no=%" PRId64
396 " length=%d\n",
397 event.log_time_ms(), event.packet_number, event.packet_length);
398 };
399
400 auto generic_packet_sent_handler = [&](const LoggedGenericPacketSent& event) {
401 fprintf(output,
402 "GENERIC_PACKET_SENT %" PRId64 " packet_no=%" PRId64
403 " overhead_length=%zu "
404 "payload_length=%zu padding_length=%zu\n",
405 event.log_time_ms(), event.packet_number, event.overhead_length,
406 event.payload_length, event.padding_length);
407 };
408
409 auto generic_ack_received_handler =
410 [&](const LoggedGenericAckReceived& event) {
411 fprintf(output, "GENERIC_ACK_RECV %" PRId64 " <contents omitted>\n",
412 event.log_time_ms());
413 };
414
415 auto decoded_frame_handler = [&](const LoggedFrameDecoded& event) {
416 static const std::map<VideoCodecType, std::string> codec_name{
417 {VideoCodecType::kVideoCodecGeneric, "GENERIC"},
418 {VideoCodecType::kVideoCodecVP8, "VP8"},
419 {VideoCodecType::kVideoCodecVP9, "VP9"},
420 {VideoCodecType::kVideoCodecAV1, "AV1"},
421 {VideoCodecType::kVideoCodecH264, "H264"},
422 {VideoCodecType::kVideoCodecMultiplex, "MULTIPLEX"}};
423
424 fprintf(output,
425 "FRAME_DECODED %" PRId64 " render_time=%" PRId64
426 " ssrc=%u width=%d height=%d "
427 "codec=%s qp=%u\n",
428 event.log_time_ms(), event.render_time_ms, event.ssrc, event.width,
429 event.height, codec_name.at(event.codec).c_str(), event.qp);
430 };
431
432 RtcEventProcessor processor;
433
434 // Stream configs
435 processor.AddEvents(parsed_log.audio_recv_configs(),
436 audio_recv_stream_handler);
437 processor.AddEvents(parsed_log.audio_send_configs(),
438 audio_send_stream_handler);
439 processor.AddEvents(parsed_log.video_recv_configs(),
440 video_recv_stream_handler);
441 processor.AddEvents(parsed_log.video_send_configs(),
442 video_send_stream_handler);
443
444 // Start and stop
445 processor.AddEvents(parsed_log.start_log_events(), start_logging_handler);
446 processor.AddEvents(parsed_log.stop_log_events(), stop_logging_handler);
447
448 // Audio
449 for (const auto& kv : parsed_log.audio_playout_events()) {
450 processor.AddEvents(kv.second, audio_playout_handler);
451 }
452 processor.AddEvents(parsed_log.audio_network_adaptation_events(),
453 audio_network_adaptation_handler);
454
455 // Bandwidth estimation and pacing
456 processor.AddEvents(parsed_log.alr_state_events(), alr_state_handler);
457 processor.AddEvents(parsed_log.bwe_probe_cluster_created_events(),
458 bwe_probe_cluster_created_handler);
459 processor.AddEvents(parsed_log.bwe_probe_failure_events(),
460 bwe_probe_failure_handler);
461 processor.AddEvents(parsed_log.bwe_probe_success_events(),
462 bwe_probe_success_handler);
463 processor.AddEvents(parsed_log.bwe_delay_updates(), bwe_delay_update_handler);
464 processor.AddEvents(parsed_log.bwe_loss_updates(), bwe_loss_update_handler);
465 processor.AddEvents(parsed_log.remote_estimate_events(),
466 remote_estimate_handler);
467
468 // Connectivity
469 processor.AddEvents(parsed_log.dtls_transport_states(),
470 dtls_transport_state_handler);
471 processor.AddEvents(parsed_log.dtls_writable_states(),
472 dtls_transport_writable_handler);
473 processor.AddEvents(parsed_log.ice_candidate_pair_configs(),
474 ice_candidate_pair_config_handler);
475 processor.AddEvents(parsed_log.ice_candidate_pair_events(),
476 ice_candidate_pair_event_handler);
477 processor.AddEvents(parsed_log.route_change_events(), route_change_handler);
478
479 // RTP
480 for (const auto& stream : parsed_log.incoming_rtp_packets_by_ssrc()) {
481 processor.AddEvents(stream.incoming_packets, incoming_rtp_packet_handler);
482 }
483 for (const auto& stream : parsed_log.outgoing_rtp_packets_by_ssrc()) {
484 processor.AddEvents(stream.outgoing_packets, outgoing_rtp_packet_handler);
485 }
486
487 // RTCP
488 processor.AddEvents(parsed_log.incoming_rtcp_packets(),
489 incoming_rtcp_packet_handler);
490 processor.AddEvents(parsed_log.outgoing_rtcp_packets(),
491 outgoing_rtcp_packet_handler);
492
493 // Generic packets
494 processor.AddEvents(parsed_log.generic_packets_received(),
495 generic_packet_received_handler);
496 processor.AddEvents(parsed_log.generic_packets_sent(),
497 generic_packet_sent_handler);
498 processor.AddEvents(parsed_log.generic_acks_received(),
499 generic_ack_received_handler);
500
501 // Video frames
502 for (const auto& kv : parsed_log.decoded_frames()) {
503 processor.AddEvents(kv.second, decoded_frame_handler);
504 }
505
506 processor.ProcessEventsInOrder();
507
508 return true;
509 }
510
511 } // namespace webrtc
512