OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <iostream> | 11 #include <iostream> |
12 #include <memory> | 12 #include <memory> |
13 #include <sstream> | 13 #include <sstream> |
14 #include <string> | 14 #include <string> |
15 | 15 |
16 #include "gflags/gflags.h" | 16 #include "gflags/gflags.h" |
17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 18 #include "webrtc/call.h" |
18 #include "webrtc/call/rtc_event_log.h" | 19 #include "webrtc/call/rtc_event_log.h" |
| 20 #include "webrtc/call/rtc_event_log_parser.h" |
19 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
20 #include "webrtc/test/rtp_file_writer.h" | 22 #include "webrtc/test/rtp_file_writer.h" |
21 | 23 |
22 // Files generated at build-time by the protobuf compiler. | |
23 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD | |
24 #include "external/webrtc/webrtc/call/rtc_event_log.pb.h" | |
25 #else | |
26 #include "webrtc/call/rtc_event_log.pb.h" | |
27 #endif | |
28 | |
29 namespace { | 24 namespace { |
30 | 25 |
31 DEFINE_bool(noaudio, | 26 DEFINE_bool(noaudio, |
32 false, | 27 false, |
33 "Excludes audio packets from the converted RTPdump file."); | 28 "Excludes audio packets from the converted RTPdump file."); |
34 DEFINE_bool(novideo, | 29 DEFINE_bool(novideo, |
35 false, | 30 false, |
36 "Excludes video packets from the converted RTPdump file."); | 31 "Excludes video packets from the converted RTPdump file."); |
37 DEFINE_bool(nodata, | 32 DEFINE_bool(nodata, |
38 false, | 33 false, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 return 0; | 82 return 0; |
88 } | 83 } |
89 std::string input_file = argv[1]; | 84 std::string input_file = argv[1]; |
90 std::string output_file = argv[2]; | 85 std::string output_file = argv[2]; |
91 | 86 |
92 uint32_t ssrc_filter = 0; | 87 uint32_t ssrc_filter = 0; |
93 if (!FLAGS_ssrc.empty()) | 88 if (!FLAGS_ssrc.empty()) |
94 RTC_CHECK(ParseSsrc(FLAGS_ssrc, &ssrc_filter)) | 89 RTC_CHECK(ParseSsrc(FLAGS_ssrc, &ssrc_filter)) |
95 << "Flag verification has failed."; | 90 << "Flag verification has failed."; |
96 | 91 |
97 webrtc::rtclog::EventStream event_stream; | 92 webrtc::ParsedRtcEventLog parsed_stream; |
98 if (!webrtc::RtcEventLog::ParseRtcEventLog(input_file, &event_stream)) { | 93 if (!parsed_stream.ParseFile(input_file)) { |
99 std::cerr << "Error while parsing input file: " << input_file << std::endl; | 94 std::cerr << "Error while parsing input file: " << input_file << std::endl; |
100 return -1; | 95 return -1; |
101 } | 96 } |
102 | 97 |
103 std::unique_ptr<webrtc::test::RtpFileWriter> rtp_writer( | 98 std::unique_ptr<webrtc::test::RtpFileWriter> rtp_writer( |
104 webrtc::test::RtpFileWriter::Create( | 99 webrtc::test::RtpFileWriter::Create( |
105 webrtc::test::RtpFileWriter::FileFormat::kRtpDump, output_file)); | 100 webrtc::test::RtpFileWriter::FileFormat::kRtpDump, output_file)); |
106 | 101 |
107 if (!rtp_writer.get()) { | 102 if (!rtp_writer.get()) { |
108 std::cerr << "Error while opening output file: " << output_file | 103 std::cerr << "Error while opening output file: " << output_file |
109 << std::endl; | 104 << std::endl; |
110 return -1; | 105 return -1; |
111 } | 106 } |
112 | 107 |
113 std::cout << "Found " << event_stream.stream_size() | 108 std::cout << "Found " << parsed_stream.GetNumberOfEvents() |
114 << " events in the input file." << std::endl; | 109 << " events in the input file." << std::endl; |
115 int rtp_counter = 0, rtcp_counter = 0; | 110 int rtp_counter = 0, rtcp_counter = 0; |
116 bool header_only = false; | 111 bool header_only = false; |
117 // TODO(ivoc): This can be refactored once the packet interpretation | 112 for (size_t i = 0; i < parsed_stream.GetNumberOfEvents(); i++) { |
118 // functions are finished. | 113 // The parsed_stream will assert if the protobuf event is missing |
119 for (int i = 0; i < event_stream.stream_size(); i++) { | 114 // some required fields and we attempt to access them. We could consider |
120 const webrtc::rtclog::Event& event = event_stream.stream(i); | 115 // a softer failure option, but it does not seem useful to generate |
121 if (!FLAGS_nortp && event.has_type() && event.type() == event.RTP_EVENT) { | 116 // RTP dumps based on broken event logs. |
122 if (event.has_timestamp_us() && event.has_rtp_packet() && | 117 if (!FLAGS_nortp && |
123 event.rtp_packet().has_header() && | 118 parsed_stream.GetEventType(i) == webrtc::ParsedRtcEventLog::RTP_EVENT) { |
124 event.rtp_packet().header().size() >= 12 && | 119 webrtc::test::RtpPacket packet; |
125 event.rtp_packet().has_packet_length() && | 120 webrtc::PacketDirection direction; |
126 event.rtp_packet().has_type()) { | 121 webrtc::MediaType media_type; |
127 const webrtc::rtclog::RtpPacket& rtp_packet = event.rtp_packet(); | 122 parsed_stream.GetRtpHeader(i, &direction, &media_type, packet.data, |
128 if (FLAGS_noaudio && rtp_packet.type() == webrtc::rtclog::AUDIO) | 123 &packet.length, &packet.original_length); |
| 124 if (packet.original_length > packet.length) |
| 125 header_only = true; |
| 126 packet.time_ms = parsed_stream.GetTimestamp(i) / 1000; |
| 127 |
| 128 // TODO(terelius): Maybe add a flag to dump outgoing traffic instead? |
| 129 if (direction == webrtc::kOutgoingPacket) |
| 130 continue; |
| 131 if (FLAGS_noaudio && media_type == webrtc::MediaType::AUDIO) |
| 132 continue; |
| 133 if (FLAGS_novideo && media_type == webrtc::MediaType::VIDEO) |
| 134 continue; |
| 135 if (FLAGS_nodata && media_type == webrtc::MediaType::DATA) |
| 136 continue; |
| 137 if (!FLAGS_ssrc.empty()) { |
| 138 const uint32_t packet_ssrc = |
| 139 webrtc::ByteReader<uint32_t>::ReadBigEndian( |
| 140 reinterpret_cast<const uint8_t*>(packet.data + 8)); |
| 141 if (packet_ssrc != ssrc_filter) |
129 continue; | 142 continue; |
130 if (FLAGS_novideo && rtp_packet.type() == webrtc::rtclog::VIDEO) | 143 } |
| 144 |
| 145 rtp_writer->WritePacket(&packet); |
| 146 rtp_counter++; |
| 147 } |
| 148 if (!FLAGS_nortcp && |
| 149 parsed_stream.GetEventType(i) == |
| 150 webrtc::ParsedRtcEventLog::RTCP_EVENT) { |
| 151 webrtc::test::RtpPacket packet; |
| 152 webrtc::PacketDirection direction; |
| 153 webrtc::MediaType media_type; |
| 154 parsed_stream.GetRtcpPacket(i, &direction, &media_type, packet.data, |
| 155 &packet.length); |
| 156 // For RTCP packets the original_length should be set to 0 in the |
| 157 // RTPdump format. |
| 158 packet.original_length = 0; |
| 159 packet.time_ms = parsed_stream.GetTimestamp(i) / 1000; |
| 160 |
| 161 // TODO(terelius): Maybe add a flag to dump outgoing traffic instead? |
| 162 if (direction == webrtc::kOutgoingPacket) |
| 163 continue; |
| 164 if (FLAGS_noaudio && media_type == webrtc::MediaType::AUDIO) |
| 165 continue; |
| 166 if (FLAGS_novideo && media_type == webrtc::MediaType::VIDEO) |
| 167 continue; |
| 168 if (FLAGS_nodata && media_type == webrtc::MediaType::DATA) |
| 169 continue; |
| 170 if (!FLAGS_ssrc.empty()) { |
| 171 const uint32_t packet_ssrc = |
| 172 webrtc::ByteReader<uint32_t>::ReadBigEndian( |
| 173 reinterpret_cast<const uint8_t*>(packet.data + 4)); |
| 174 if (packet_ssrc != ssrc_filter) |
131 continue; | 175 continue; |
132 if (FLAGS_nodata && rtp_packet.type() == webrtc::rtclog::DATA) | 176 } |
133 continue; | |
134 if (!FLAGS_ssrc.empty()) { | |
135 const uint32_t packet_ssrc = | |
136 webrtc::ByteReader<uint32_t>::ReadBigEndian( | |
137 reinterpret_cast<const uint8_t*>(rtp_packet.header().data() + | |
138 8)); | |
139 if (packet_ssrc != ssrc_filter) | |
140 continue; | |
141 } | |
142 | 177 |
143 webrtc::test::RtpPacket packet; | 178 rtp_writer->WritePacket(&packet); |
144 packet.length = rtp_packet.header().size(); | 179 rtcp_counter++; |
145 if (packet.length > packet.kMaxPacketBufferSize) { | |
146 std::cout << "Skipping packet with size " << packet.length | |
147 << ", the maximum supported size is " | |
148 << packet.kMaxPacketBufferSize << std::endl; | |
149 continue; | |
150 } | |
151 packet.original_length = rtp_packet.packet_length(); | |
152 if (packet.original_length > packet.length) | |
153 header_only = true; | |
154 packet.time_ms = event.timestamp_us() / 1000; | |
155 memcpy(packet.data, rtp_packet.header().data(), packet.length); | |
156 rtp_writer->WritePacket(&packet); | |
157 rtp_counter++; | |
158 } else { | |
159 std::cout << "Skipping malformed event." << std::endl; | |
160 } | |
161 } | |
162 if (!FLAGS_nortcp && event.has_type() && event.type() == event.RTCP_EVENT) { | |
163 if (event.has_timestamp_us() && event.has_rtcp_packet() && | |
164 event.rtcp_packet().has_type() && | |
165 event.rtcp_packet().has_packet_data() && | |
166 event.rtcp_packet().packet_data().size() > 0) { | |
167 const webrtc::rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet(); | |
168 if (FLAGS_noaudio && rtcp_packet.type() == webrtc::rtclog::AUDIO) | |
169 continue; | |
170 if (FLAGS_novideo && rtcp_packet.type() == webrtc::rtclog::VIDEO) | |
171 continue; | |
172 if (FLAGS_nodata && rtcp_packet.type() == webrtc::rtclog::DATA) | |
173 continue; | |
174 if (!FLAGS_ssrc.empty()) { | |
175 const uint32_t packet_ssrc = | |
176 webrtc::ByteReader<uint32_t>::ReadBigEndian( | |
177 reinterpret_cast<const uint8_t*>( | |
178 rtcp_packet.packet_data().data() + 4)); | |
179 if (packet_ssrc != ssrc_filter) | |
180 continue; | |
181 } | |
182 | |
183 webrtc::test::RtpPacket packet; | |
184 packet.length = rtcp_packet.packet_data().size(); | |
185 if (packet.length > packet.kMaxPacketBufferSize) { | |
186 std::cout << "Skipping packet with size " << packet.length | |
187 << ", the maximum supported size is " | |
188 << packet.kMaxPacketBufferSize << std::endl; | |
189 continue; | |
190 } | |
191 // For RTCP packets the original_length should be set to 0 in the | |
192 // RTPdump format. | |
193 packet.original_length = 0; | |
194 packet.time_ms = event.timestamp_us() / 1000; | |
195 memcpy(packet.data, rtcp_packet.packet_data().data(), packet.length); | |
196 rtp_writer->WritePacket(&packet); | |
197 rtcp_counter++; | |
198 } else { | |
199 std::cout << "Skipping malformed event." << std::endl; | |
200 } | |
201 } | 180 } |
202 } | 181 } |
203 std::cout << "Wrote " << rtp_counter << (header_only ? " header-only" : "") | 182 std::cout << "Wrote " << rtp_counter << (header_only ? " header-only" : "") |
204 << " RTP packets and " << rtcp_counter << " RTCP packets to the " | 183 << " RTP packets and " << rtcp_counter << " RTCP packets to the " |
205 << "output file." << std::endl; | 184 << "output file." << std::endl; |
206 return 0; | 185 return 0; |
207 } | 186 } |
OLD | NEW |