| 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 |