Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1014)

Side by Side Diff: webrtc/logging/rtc_event_log/rtc_event_log2text.cc

Issue 2673403002: New tool for printing basic packet information from an RTC event log to stdout. (Closed)
Patch Set: Parse RTCP correctly Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/logging/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2017 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 <iostream>
12 #include <sstream>
13 #include <string>
14
15 #include "gflags/gflags.h"
16 #include "webrtc/base/checks.h"
17 #include "webrtc/call/call.h"
18 #include "webrtc/common_types.h"
19 #include "webrtc/logging/rtc_event_log/rtc_event_log_parser.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
21 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
22 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
23 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
24 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
25 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
26 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
27 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
28 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
29 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
30 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
31 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
32 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
33 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
34 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
35 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
36 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
37
38 namespace {
39
40 DEFINE_bool(noincoming, false, "Excludes incoming packets.");
41 DEFINE_bool(nooutgoing, false, "Excludes outgoing packets.");
42 // TODO(terelius): Note that the media type doesn't work with outgoing packets.
43 DEFINE_bool(noaudio, false, "Excludes audio packets.");
44 // TODO(terelius): Note that the media type doesn't work with outgoing packets.
45 DEFINE_bool(novideo, false, "Excludes video packets.");
46 // TODO(terelius): Note that the media type doesn't work with outgoing packets.
47 DEFINE_bool(nodata, false, "Excludes data packets.");
48 DEFINE_bool(nortp, false, "Excludes RTP packets.");
49 DEFINE_bool(nortcp, false, "Excludes RTCP packets.");
50 // TODO(terelius): Allow a list of SSRCs.
51 DEFINE_string(ssrc,
52 "",
53 "Print only packets with this SSRC (decimal or hex, the latter "
54 "starting with 0x).");
55
56 static uint32_t filtered_ssrc = 0;
57
58 // Parses the input string for a valid SSRC. If a valid SSRC is found, it is
59 // written to the static global variable |filtered_ssrc|, and true is returned.
60 // Otherwise, false is returned.
61 // The empty string must be validated as true, because it is the default value
62 // of the command-line flag. In this case, no value is written to the output
63 // variable.
64 bool ParseSsrc(std::string str) {
65 // If the input string starts with 0x or 0X it indicates a hexadecimal number.
66 auto read_mode = std::dec;
67 if (str.size() > 2 &&
68 (str.substr(0, 2) == "0x" || str.substr(0, 2) == "0X")) {
69 read_mode = std::hex;
70 str = str.substr(2);
71 }
72 std::stringstream ss(str);
73 ss >> read_mode >> filtered_ssrc;
74 return str.empty() || (!ss.fail() && ss.eof());
75 }
76
77 bool ExcludePacket(webrtc::PacketDirection direction,
78 webrtc::MediaType media_type,
79 uint32_t packet_ssrc) {
80 if (FLAGS_nooutgoing && direction == webrtc::kOutgoingPacket)
81 return true;
82 if (FLAGS_noincoming && direction == webrtc::kIncomingPacket)
83 return true;
84 if (FLAGS_noaudio && media_type == webrtc::MediaType::AUDIO)
85 return true;
86 if (FLAGS_novideo && media_type == webrtc::MediaType::VIDEO)
87 return true;
88 if (FLAGS_nodata && media_type == webrtc::MediaType::DATA)
89 return true;
90 if (!FLAGS_ssrc.empty() && packet_ssrc != filtered_ssrc)
91 return true;
92 return false;
93 }
94
95 const char* StreamInfo(webrtc::PacketDirection direction,
96 webrtc::MediaType media_type) {
97 if (direction == webrtc::kOutgoingPacket) {
98 if (media_type == webrtc::MediaType::AUDIO)
99 return "(out,audio)";
100 else if (media_type == webrtc::MediaType::VIDEO)
101 return "(out,video)";
102 else if (media_type == webrtc::MediaType::DATA)
103 return "(out,data)";
104 else
105 return "(out)";
106 }
107 if (direction == webrtc::kIncomingPacket) {
108 if (media_type == webrtc::MediaType::AUDIO)
109 return "(in,audio)";
110 else if (media_type == webrtc::MediaType::VIDEO)
111 return "(in,video)";
112 else if (media_type == webrtc::MediaType::DATA)
113 return "(in,data)";
114 else
115 return "(in)";
116 }
117 return "(unknown)";
118 }
119
120 void PrintSenderReport(const webrtc::rtcp::CommonHeader& rtcp_block,
121 uint64_t log_timestamp,
122 webrtc::PacketDirection direction,
123 webrtc::MediaType media_type) {
124 webrtc::rtcp::SenderReport sr;
125 if (!sr.Parse(rtcp_block))
126 return;
127 if (ExcludePacket(direction, media_type, sr.sender_ssrc()))
128 return;
129 std::cout << log_timestamp << "\t"
130 << "RTCP_SR" << StreamInfo(direction, media_type)
131 << "\tSSRC=" << sr.sender_ssrc()
132 << "\ttimestamp=" << sr.rtp_timestamp() << std::endl;
133 }
134
135 void PrintReceiverReport(const webrtc::rtcp::CommonHeader& rtcp_block,
136 uint64_t log_timestamp,
137 webrtc::PacketDirection direction,
138 webrtc::MediaType media_type) {
139 webrtc::rtcp::ReceiverReport rr;
140 if (!rr.Parse(rtcp_block))
141 return;
142 if (ExcludePacket(direction, media_type, rr.sender_ssrc()))
143 return;
144 std::cout << log_timestamp << "\t"
145 << "RTCP_RR" << StreamInfo(direction, media_type)
146 << "\tSSRC=" << rr.sender_ssrc() << std::endl;
147 }
148
149 void PrintXr(const webrtc::rtcp::CommonHeader& rtcp_block,
150 uint64_t log_timestamp,
151 webrtc::PacketDirection direction,
152 webrtc::MediaType media_type) {
153 webrtc::rtcp::ExtendedReports xr;
154 if (!xr.Parse(rtcp_block))
155 return;
156 if (ExcludePacket(direction, media_type, xr.sender_ssrc()))
157 return;
158 std::cout << log_timestamp << "\t"
159 << "RTCP_XR" << StreamInfo(direction, media_type)
160 << "\tSSRC=" << xr.sender_ssrc() << std::endl;
161 }
162
163 void PrintSdes(const webrtc::rtcp::CommonHeader& rtcp_block,
164 uint64_t log_timestamp,
165 webrtc::PacketDirection direction,
166 webrtc::MediaType media_type) {
167 std::cout << log_timestamp << "\t"
168 << "RTCP_SDES" << StreamInfo(direction, media_type) << std::endl;
169 RTC_NOTREACHED() << "SDES should have been redacted when writing the log";
170 }
171
172 void PrintBye(const webrtc::rtcp::CommonHeader& rtcp_block,
173 uint64_t log_timestamp,
174 webrtc::PacketDirection direction,
175 webrtc::MediaType media_type) {
176 webrtc::rtcp::Bye bye;
177 if (!bye.Parse(rtcp_block))
178 return;
179 if (ExcludePacket(direction, media_type, bye.sender_ssrc()))
180 return;
181 std::cout << log_timestamp << "\t"
182 << "RTCP_BYE" << StreamInfo(direction, media_type)
183 << "\tSSRC=" << bye.sender_ssrc() << std::endl;
184 }
185
186 void PrintRtpFeedback(const webrtc::rtcp::CommonHeader& rtcp_block,
187 uint64_t log_timestamp,
188 webrtc::PacketDirection direction,
189 webrtc::MediaType media_type) {
190 std::cout << "Rtp feedback found";
191 switch (rtcp_block.fmt()) {
192 case webrtc::rtcp::Nack::kFeedbackMessageType: {
193 webrtc::rtcp::Nack nack;
194 if (!nack.Parse(rtcp_block))
195 return;
196 if (ExcludePacket(direction, media_type, nack.sender_ssrc()))
197 return;
198 std::cout << log_timestamp << "\t"
199 << "RTCP_NACK" << StreamInfo(direction, media_type)
200 << "\tSSRC=" << nack.sender_ssrc() << std::endl;
201 break;
202 }
203 case webrtc::rtcp::Tmmbr::kFeedbackMessageType: {
204 webrtc::rtcp::Tmmbr tmmbr;
205 if (!tmmbr.Parse(rtcp_block))
206 return;
207 if (ExcludePacket(direction, media_type, tmmbr.sender_ssrc()))
208 return;
209 std::cout << log_timestamp << "\t"
210 << "RTCP_TMMBR" << StreamInfo(direction, media_type)
211 << "\tSSRC=" << tmmbr.sender_ssrc() << std::endl;
212 break;
213 }
214 case webrtc::rtcp::Tmmbn::kFeedbackMessageType: {
215 webrtc::rtcp::Tmmbn tmmbn;
216 if (!tmmbn.Parse(rtcp_block))
217 return;
218 if (ExcludePacket(direction, media_type, tmmbn.sender_ssrc()))
219 return;
220 std::cout << log_timestamp << "\t"
221 << "RTCP_TMMBN" << StreamInfo(direction, media_type)
222 << "\tSSRC=" << tmmbn.sender_ssrc() << std::endl;
223 break;
224 }
225 case webrtc::rtcp::RapidResyncRequest::kFeedbackMessageType: {
226 webrtc::rtcp::RapidResyncRequest sr_req;
227 if (!sr_req.Parse(rtcp_block))
228 return;
229 if (ExcludePacket(direction, media_type, sr_req.sender_ssrc()))
230 return;
231 std::cout << log_timestamp << "\t"
232 << "RTCP_SRREQ" << StreamInfo(direction, media_type)
233 << "\tSSRC=" << sr_req.sender_ssrc() << std::endl;
234 break;
235 }
236 case webrtc::rtcp::TransportFeedback::kFeedbackMessageType: {
237 webrtc::rtcp::TransportFeedback transport_feedback;
238 if (!transport_feedback.Parse(rtcp_block))
239 return;
240 if (ExcludePacket(direction, media_type,
241 transport_feedback.sender_ssrc()))
242 return;
243 std::cout << log_timestamp << "\t"
244 << "RTCP_NEWFB" << StreamInfo(direction, media_type)
245 << "\tSSRC=" << transport_feedback.sender_ssrc() << std::endl;
246 break;
247 }
248 default:
249 RTC_DCHECK(false);
250 break;
251 }
252 }
253
254 void PrintPsFeedback(const webrtc::rtcp::CommonHeader& rtcp_block,
255 uint64_t log_timestamp,
256 webrtc::PacketDirection direction,
257 webrtc::MediaType media_type) {
258 switch (rtcp_block.fmt()) {
259 case webrtc::rtcp::Pli::kFeedbackMessageType: {
260 webrtc::rtcp::Pli pli;
261 if (!pli.Parse(rtcp_block))
262 return;
263 if (ExcludePacket(direction, media_type, pli.sender_ssrc()))
264 return;
265 std::cout << log_timestamp << "\t"
266 << "RTCP_PLI" << StreamInfo(direction, media_type)
267 << "\tSSRC=" << pli.sender_ssrc() << std::endl;
268 break;
269 }
270 case webrtc::rtcp::Sli::kFeedbackMessageType: {
271 webrtc::rtcp::Sli sli;
272 if (!sli.Parse(rtcp_block))
273 return;
274 if (ExcludePacket(direction, media_type, sli.sender_ssrc()))
275 return;
276 std::cout << log_timestamp << "\t"
277 << "RTCP_SLI" << StreamInfo(direction, media_type)
278 << "\tSSRC=" << sli.sender_ssrc() << std::endl;
279 break;
280 }
281 case webrtc::rtcp::Rpsi::kFeedbackMessageType: {
282 webrtc::rtcp::Rpsi rpsi;
283 if (!rpsi.Parse(rtcp_block))
284 return;
285 if (ExcludePacket(direction, media_type, rpsi.sender_ssrc()))
286 return;
287 std::cout << log_timestamp << "\t"
288 << "RTCP_RPSI" << StreamInfo(direction, media_type)
289 << "\tSSRC=" << rpsi.sender_ssrc() << std::endl;
290 break;
291 }
292 case webrtc::rtcp::Fir::kFeedbackMessageType: {
293 webrtc::rtcp::Fir fir;
294 if (!fir.Parse(rtcp_block))
295 return;
296 if (ExcludePacket(direction, media_type, fir.sender_ssrc()))
297 return;
298 std::cout << log_timestamp << "\t"
299 << "RTCP_FIR" << StreamInfo(direction, media_type)
300 << "\tSSRC=" << fir.sender_ssrc() << std::endl;
301 break;
302 }
303 case webrtc::rtcp::Remb::kFeedbackMessageType: {
304 webrtc::rtcp::Remb remb;
305 if (!remb.Parse(rtcp_block))
306 return;
307 if (ExcludePacket(direction, media_type, remb.sender_ssrc()))
308 return;
309 std::cout << log_timestamp << "\t"
310 << "RTCP_REMB" << StreamInfo(direction, media_type)
311 << "\tSSRC=" << remb.sender_ssrc() << std::endl;
312 break;
313 }
314 default:
315 break;
316 }
317 }
318
319 } // namespace
320
321 // This utility will print basic information about each packet to stdout.
322 // Note that parser will assert if the protobuf event is missing some required
323 // fields and we attempt to access them. We don't handle this at the moment.
324 int main(int argc, char* argv[]) {
325 std::string program_name = argv[0];
326 std::string usage =
327 "Tool for printing packet information from an RtcEventLog as text.\n"
328 "Run " +
329 program_name +
330 " --helpshort for usage.\n"
331 "Example usage:\n" +
332 program_name + " input.rel\n";
333 google::SetUsageMessage(usage);
334 google::ParseCommandLineFlags(&argc, &argv, true);
335
336 if (argc != 2) {
337 std::cout << google::ProgramUsage();
338 return 0;
339 }
340 std::string input_file = argv[1];
341
342 if (!FLAGS_ssrc.empty())
343 RTC_CHECK(ParseSsrc(FLAGS_ssrc)) << "Flag verification has failed.";
344
345 webrtc::ParsedRtcEventLog parsed_stream;
346 if (!parsed_stream.ParseFile(input_file)) {
347 std::cerr << "Error while parsing input file: " << input_file << std::endl;
348 return -1;
349 }
350
351 for (size_t i = 0; i < parsed_stream.GetNumberOfEvents(); i++) {
352 if (!FLAGS_nortp &&
353 parsed_stream.GetEventType(i) == webrtc::ParsedRtcEventLog::RTP_EVENT) {
354 size_t header_length;
355 size_t total_length;
356 uint8_t header[IP_PACKET_SIZE];
357 webrtc::PacketDirection direction;
358 webrtc::MediaType media_type;
359 parsed_stream.GetRtpHeader(i, &direction, &media_type, header,
360 &header_length, &total_length);
361
362 // Parse header to get SSRC and RTP time.
363 webrtc::RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
364 webrtc::RTPHeader parsed_header;
365 rtp_parser.Parse(&parsed_header);
366
367 if (ExcludePacket(direction, media_type, parsed_header.ssrc))
368 continue;
369
370 std::cout << parsed_stream.GetTimestamp(i) << "\tRTP"
371 << StreamInfo(direction, media_type)
372 << "\tSSRC=" << parsed_header.ssrc
373 << "\ttimestamp=" << parsed_header.timestamp << std::endl;
374 }
375 if (!FLAGS_nortcp &&
376 parsed_stream.GetEventType(i) ==
377 webrtc::ParsedRtcEventLog::RTCP_EVENT) {
378 size_t length;
379 uint8_t packet[IP_PACKET_SIZE];
380 webrtc::PacketDirection direction;
381 webrtc::MediaType media_type;
382 parsed_stream.GetRtcpPacket(i, &direction, &media_type, packet, &length);
383
384 webrtc::rtcp::CommonHeader rtcp_block;
385 const uint8_t* packet_end = packet + length;
386 for (const uint8_t* next_block = packet; next_block != packet_end;
387 next_block = rtcp_block.NextPacket()) {
388 ptrdiff_t remaining_blocks_size = packet_end - next_block;
389 RTC_DCHECK_GT(remaining_blocks_size, 0);
390 if (!rtcp_block.Parse(next_block, remaining_blocks_size)) {
391 break;
392 }
393
394 uint64_t log_timestamp = parsed_stream.GetTimestamp(i);
395 switch (rtcp_block.type()) {
396 case webrtc::rtcp::SenderReport::kPacketType:
397 PrintSenderReport(rtcp_block, log_timestamp, direction, media_type);
398 break;
399 case webrtc::rtcp::ReceiverReport::kPacketType:
400 PrintReceiverReport(rtcp_block, log_timestamp, direction,
401 media_type);
402 break;
403 case webrtc::rtcp::Sdes::kPacketType:
404 PrintSdes(rtcp_block, log_timestamp, direction, media_type);
405 break;
406 case webrtc::rtcp::ExtendedReports::kPacketType:
407 PrintXr(rtcp_block, log_timestamp, direction, media_type);
408 break;
409 case webrtc::rtcp::Bye::kPacketType:
410 PrintBye(rtcp_block, log_timestamp, direction, media_type);
411 break;
412 case webrtc::rtcp::Rtpfb::kPacketType:
413 PrintRtpFeedback(rtcp_block, log_timestamp, direction, media_type);
414 break;
415 case webrtc::rtcp::Psfb::kPacketType:
416 PrintPsFeedback(rtcp_block, log_timestamp, direction, media_type);
417 break;
418 default:
419 break;
420 }
421 }
422 }
423 }
424 return 0;
425 }
OLDNEW
« no previous file with comments | « webrtc/logging/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698