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

Side by Side Diff: webrtc/call/rtc_event_log_parser.cc

Issue 1768773002: New parser for event log. Manually parse the outermost EventStream (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Move parser to its own build target. Fix comments from Henrik. Created 4 years, 8 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
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 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 "webrtc/call/rtc_event_log_parser.h"
12
13 #include <string.h>
14
15 #include <fstream>
16
17 #include "webrtc/base/checks.h"
18 #include "webrtc/base/logging.h"
19 #include "webrtc/base/scoped_ptr.h"
20 #include "webrtc/call.h"
21 #include "webrtc/call/rtc_event_log.h"
22 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
23 #include "webrtc/system_wrappers/include/file_wrapper.h"
24
25 namespace webrtc {
26
27 namespace {
28 MediaType GetRuntimeMediaType(rtclog::MediaType media_type) {
29 switch (media_type) {
30 case rtclog::MediaType::ANY:
31 return MediaType::ANY;
32 case rtclog::MediaType::AUDIO:
33 return MediaType::AUDIO;
34 case rtclog::MediaType::VIDEO:
35 return MediaType::VIDEO;
36 case rtclog::MediaType::DATA:
37 return MediaType::DATA;
38 }
39 RTC_NOTREACHED();
40 return MediaType::ANY;
41 }
42
43 RtcpMode GetRuntimeRtcpMode(rtclog::VideoReceiveConfig::RtcpMode rtcp_mode) {
44 switch (rtcp_mode) {
45 case rtclog::VideoReceiveConfig::RTCP_COMPOUND:
46 return RtcpMode::kCompound;
47 case rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE:
48 return RtcpMode::kReducedSize;
49 }
50 RTC_NOTREACHED();
51 return RtcpMode::kOff;
52 }
53
54 ParsedRtcEventLog::EventType GetRuntimeEventType(
55 rtclog::Event::EventType event_type) {
56 switch (event_type) {
57 case rtclog::Event::UNKNOWN_EVENT:
58 return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
59 case rtclog::Event::LOG_START:
60 return ParsedRtcEventLog::EventType::LOG_START;
61 case rtclog::Event::LOG_END:
62 return ParsedRtcEventLog::EventType::LOG_END;
63 case rtclog::Event::RTP_EVENT:
64 return ParsedRtcEventLog::EventType::RTP_EVENT;
65 case rtclog::Event::RTCP_EVENT:
66 return ParsedRtcEventLog::EventType::RTCP_EVENT;
67 case rtclog::Event::AUDIO_PLAYOUT_EVENT:
68 return ParsedRtcEventLog::EventType::AUDIO_PLAYOUT_EVENT;
69 case rtclog::Event::BWE_PACKET_LOSS_EVENT:
70 return ParsedRtcEventLog::EventType::BWE_PACKET_LOSS_EVENT;
71 case rtclog::Event::BWE_PACKET_DELAY_EVENT:
72 return ParsedRtcEventLog::EventType::BWE_PACKET_DELAY_EVENT;
73 case rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT:
74 return ParsedRtcEventLog::EventType::VIDEO_RECEIVER_CONFIG_EVENT;
75 case rtclog::Event::VIDEO_SENDER_CONFIG_EVENT:
76 return ParsedRtcEventLog::EventType::VIDEO_SENDER_CONFIG_EVENT;
77 case rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT:
78 return ParsedRtcEventLog::EventType::AUDIO_RECEIVER_CONFIG_EVENT;
79 case rtclog::Event::AUDIO_SENDER_CONFIG_EVENT:
80 return ParsedRtcEventLog::EventType::AUDIO_SENDER_CONFIG_EVENT;
81 }
82 RTC_NOTREACHED();
83 return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
84 }
85
86 bool ParseVarInt(std::FILE* file, uint64_t* varint, size_t* bytes_read) {
87 uint8_t byte;
88 *varint = 0;
89 for (*bytes_read = 0; *bytes_read < 10 && fread(&byte, 1, 1, file) == 1;
90 (*bytes_read)++) {
91 *varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * *bytes_read);
ivoc 2016/04/01 08:27:59 Would be a good idea to add some comments here to
terelius 2016/04/19 17:01:45 Done.
92 if ((byte & 0x80) == 0) {
93 return true;
94 }
95 }
96 return false;
ivoc 2016/04/01 08:27:59 How about returning bytes_read from this function,
terelius 2016/04/19 17:01:45 It is slightly more complicated because we also ne
97 }
98
99 } // namespace
100
101 bool ParsedRtcEventLog::ParseFile(const std::string& filename) {
102 stream_.clear();
103 const size_t kMaxEventSize = 1u << 16;
104 char tmp_buffer[kMaxEventSize];
105
106 std::FILE* file = fopen(filename.c_str(), "rb");
107 if (!file) {
108 LOG(LS_WARNING) << "Could not open file for reading.";
109 return false;
110 }
111
112 while (1) {
113 // Peek at the next message tag.
114 uint64_t tag,
115 expected_tag = (1 << 3) | 2; // (fieldnumber << 3) | wire_type
ivoc 2016/04/01 08:27:59 Some explanation for the bit juggling would be nic
terelius 2016/04/19 17:01:45 I've added a little, but it is hard to give any ju
116 size_t bytes_read;
117 if (!ParseVarInt(file, &tag, &bytes_read) || tag != expected_tag) {
118 fclose(file);
119 if (bytes_read == 0) {
120 return true; // Reached end of file.
121 }
122 LOG(LS_WARNING)
123 << "Missing expected tag from beginning of protobuf event.";
124 return false;
125 }
126
127 // Peek at the length field.
128 uint64_t message_length;
129 if (!ParseVarInt(file, &message_length, &bytes_read) ||
130 message_length >= kMaxEventSize) {
131 LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
132 fclose(file);
133 return false;
134 }
135
136 if (fread(tmp_buffer, 1, message_length, file) != message_length) {
137 LOG(LS_WARNING) << "Failed to read protobuf message from file.";
138 fclose(file);
139 return false;
140 }
141
142 rtclog::Event event;
143 if (!event.ParseFromArray(tmp_buffer, message_length)) {
144 LOG(LS_WARNING) << "Failed to parse protobuf message.";
145 fclose(file);
146 return false;
147 }
148 stream_.push_back(event);
149 }
150 }
151
152 size_t ParsedRtcEventLog::GetNumberOfEvents() const {
153 return stream_.size();
154 }
155
156 int64_t ParsedRtcEventLog::GetTimestamp(size_t i) const {
157 RTC_CHECK_LT(i, GetNumberOfEvents());
158 const rtclog::Event& event = stream_[i];
159 RTC_CHECK(event.has_timestamp_us());
160 return event.timestamp_us();
161 }
162
163 ParsedRtcEventLog::EventType ParsedRtcEventLog::GetEventType(size_t i) const {
164 RTC_CHECK_LT(i, GetNumberOfEvents());
165 const rtclog::Event& event = stream_[i];
166 RTC_CHECK(event.has_type());
167 return GetRuntimeEventType(event.type());
168 }
169
170 // The header must have space for at least IP_PACKET_SIZE bytes.
171 void ParsedRtcEventLog::GetRtpHeader(size_t i,
172 PacketDirection* incoming,
173 MediaType* media_type,
174 uint8_t* header,
175 size_t* header_length,
176 size_t* total_length) const {
177 RTC_CHECK_LT(i, GetNumberOfEvents());
178 const rtclog::Event& event = stream_[i];
179 RTC_CHECK(event.has_type());
180 RTC_CHECK_EQ(event.type(), rtclog::Event::RTP_EVENT);
181 RTC_CHECK(event.has_rtp_packet());
182 const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
183 // Get direction of packet.
184 RTC_CHECK(rtp_packet.has_incoming());
ivoc 2016/04/01 08:27:59 I guess these CHECKs can be inside of the ifs, rig
terelius 2016/04/19 17:01:45 They could, but since these fields are specified a
ivoc 2016/04/25 08:08:11 Acknowledged.
185 if (incoming != nullptr)
186 *incoming = rtp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
187 // Get media type.
188 RTC_CHECK(rtp_packet.has_type());
189 if (media_type != nullptr) {
190 *media_type = GetRuntimeMediaType(rtp_packet.type());
191 }
192 // Get packet length.
193 RTC_CHECK(rtp_packet.has_packet_length());
194 if (total_length != nullptr)
195 *total_length = rtp_packet.packet_length();
196 // Get header length.
197 RTC_CHECK(rtp_packet.has_header());
198 if (header_length != nullptr)
199 *header_length = rtp_packet.header().size();
200 // Get header contents.
201 if (header != nullptr) {
202 RTC_CHECK_GE(rtp_packet.header().size(), 12u);
203 RTC_CHECK_LE(rtp_packet.header().size(),
204 static_cast<unsigned>(IP_PACKET_SIZE));
205 memcpy(header, rtp_packet.header().data(), rtp_packet.header().size());
206 }
207 }
208
209 // The packet must have space for at least IP_PACKET_SIZE bytes.
210 void ParsedRtcEventLog::GetRtcpPacket(size_t i,
211 PacketDirection* incoming,
212 MediaType* media_type,
213 uint8_t* packet,
214 size_t* length) const {
215 RTC_CHECK_LT(i, GetNumberOfEvents());
216 const rtclog::Event& event = stream_[i];
217 RTC_CHECK(event.has_type());
218 RTC_CHECK_EQ(event.type(), rtclog::Event::RTCP_EVENT);
219 RTC_CHECK(event.has_rtcp_packet());
220 const rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
221 // Get direction of packet.
222 RTC_CHECK(rtcp_packet.has_incoming());
223 if (incoming != nullptr)
224 *incoming = rtcp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
225 // Get media type.
226 RTC_CHECK(rtcp_packet.has_type());
227 if (media_type != nullptr) {
228 *media_type = GetRuntimeMediaType(rtcp_packet.type());
229 }
230 // Get packet length.
231 RTC_CHECK(rtcp_packet.has_packet_data());
232 if (length != nullptr)
233 *length = rtcp_packet.packet_data().size();
234 // Get packet contents.
235 if (packet != nullptr) {
236 RTC_CHECK_LE(rtcp_packet.packet_data().size(),
237 static_cast<unsigned>(IP_PACKET_SIZE));
238 memcpy(packet, rtcp_packet.packet_data().data(),
239 rtcp_packet.packet_data().size());
240 }
241 }
242
243 void ParsedRtcEventLog::GetVideoReceiveConfig(
244 size_t i,
245 VideoReceiveStream::Config* config) const {
246 RTC_CHECK_LT(i, GetNumberOfEvents());
247 const rtclog::Event& event = stream_[i];
248 RTC_CHECK(config != nullptr);
249 RTC_CHECK(event.has_type());
250 RTC_CHECK_EQ(event.type(), rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
251 RTC_CHECK(event.has_video_receiver_config());
252 const rtclog::VideoReceiveConfig& receiver_config =
253 event.video_receiver_config();
254 // Get SSRCs.
255 RTC_CHECK(receiver_config.has_remote_ssrc());
256 config->rtp.remote_ssrc = receiver_config.remote_ssrc();
257 RTC_CHECK(receiver_config.has_local_ssrc());
258 config->rtp.local_ssrc = receiver_config.local_ssrc();
259 // Get RTCP settings.
260 RTC_CHECK(receiver_config.has_rtcp_mode());
261 config->rtp.rtcp_mode = GetRuntimeRtcpMode(receiver_config.rtcp_mode());
262 RTC_CHECK(receiver_config.has_remb());
263 config->rtp.remb = receiver_config.remb();
264 // Get RTX map.
265 config->rtp.rtx.clear();
266 for (int i = 0; i < receiver_config.rtx_map_size(); i++) {
267 const rtclog::RtxMap& map = receiver_config.rtx_map(i);
268 RTC_CHECK(map.has_payload_type());
269 RTC_CHECK(map.has_config());
270 RTC_CHECK(map.config().has_rtx_ssrc());
271 RTC_CHECK(map.config().has_rtx_payload_type());
272 webrtc::VideoReceiveStream::Config::Rtp::Rtx rtx_pair;
273 rtx_pair.ssrc = map.config().rtx_ssrc();
274 rtx_pair.payload_type = map.config().rtx_payload_type();
275 config->rtp.rtx.insert(std::make_pair(map.payload_type(), rtx_pair));
276 }
277 // Get header extensions.
278 config->rtp.extensions.clear();
279 for (int i = 0; i < receiver_config.header_extensions_size(); i++) {
280 RTC_CHECK(receiver_config.header_extensions(i).has_name());
281 RTC_CHECK(receiver_config.header_extensions(i).has_id());
282 const std::string& name = receiver_config.header_extensions(i).name();
283 int id = receiver_config.header_extensions(i).id();
284 config->rtp.extensions.push_back(RtpExtension(name, id));
285 }
286 // Get decoders.
287 config->decoders.clear();
288 for (int i = 0; i < receiver_config.decoders_size(); i++) {
289 RTC_CHECK(receiver_config.decoders(i).has_name());
290 RTC_CHECK(receiver_config.decoders(i).has_payload_type());
291 VideoReceiveStream::Decoder decoder;
292 decoder.payload_name = receiver_config.decoders(i).name();
293 decoder.payload_type = receiver_config.decoders(i).payload_type();
294 config->decoders.push_back(decoder);
295 }
296 }
297
298 void ParsedRtcEventLog::GetVideoSendConfig(
299 size_t i,
300 VideoSendStream::Config* config) const {
301 RTC_CHECK_LT(i, GetNumberOfEvents());
302 const rtclog::Event& event = stream_[i];
303 RTC_CHECK(config != nullptr);
304 RTC_CHECK(event.has_type());
305 RTC_CHECK_EQ(event.type(), rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
306 RTC_CHECK(event.has_video_sender_config());
307 const rtclog::VideoSendConfig& sender_config = event.video_sender_config();
308 // Get SSRCs.
309 config->rtp.ssrcs.clear();
310 for (int i = 0; i < sender_config.ssrcs_size(); i++) {
311 config->rtp.ssrcs.push_back(sender_config.ssrcs(i));
312 }
313 // Get header extensions.
314 config->rtp.extensions.clear();
315 for (int i = 0; i < sender_config.header_extensions_size(); i++) {
316 RTC_CHECK(sender_config.header_extensions(i).has_name());
317 RTC_CHECK(sender_config.header_extensions(i).has_id());
318 const std::string& name = sender_config.header_extensions(i).name();
319 int id = sender_config.header_extensions(i).id();
320 config->rtp.extensions.push_back(RtpExtension(name, id));
321 }
322 // Get RTX settings.
323 config->rtp.rtx.ssrcs.clear();
324 for (int i = 0; i < sender_config.rtx_ssrcs_size(); i++) {
325 config->rtp.rtx.ssrcs.push_back(sender_config.rtx_ssrcs(i));
326 }
327 if (sender_config.rtx_ssrcs_size() > 0) {
328 RTC_CHECK(sender_config.has_rtx_payload_type());
329 config->rtp.rtx.payload_type = sender_config.rtx_payload_type();
330 } else {
331 // Reset RTX payload type default value if no RTX SSRCs are used.
332 config->rtp.rtx.payload_type = -1;
333 }
334 // Get encoder.
335 RTC_CHECK(sender_config.has_encoder());
336 RTC_CHECK(sender_config.encoder().has_name());
337 RTC_CHECK(sender_config.encoder().has_payload_type());
338 config->encoder_settings.payload_name = sender_config.encoder().name();
339 config->encoder_settings.payload_type =
340 sender_config.encoder().payload_type();
341 }
342
343 void ParsedRtcEventLog::GetAudioPlayout(size_t i, uint32_t* ssrc) const {
344 RTC_CHECK_LT(i, GetNumberOfEvents());
345 const rtclog::Event& event = stream_[i];
346 RTC_CHECK(event.has_type());
347 RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_PLAYOUT_EVENT);
348 RTC_CHECK(event.has_audio_playout_event());
349 const rtclog::AudioPlayoutEvent& loss_event = event.audio_playout_event();
350 RTC_CHECK(loss_event.has_local_ssrc());
351 if (ssrc != nullptr)
352 *ssrc = loss_event.local_ssrc();
353 }
354
355 void ParsedRtcEventLog::GetBwePacketLossEvent(size_t i,
356 int32_t* bitrate,
357 uint8_t* fraction_loss,
358 int32_t* total_packets) const {
359 RTC_CHECK_LT(i, GetNumberOfEvents());
360 const rtclog::Event& event = stream_[i];
361 RTC_CHECK(event.has_type());
362 RTC_CHECK_EQ(event.type(), rtclog::Event::BWE_PACKET_LOSS_EVENT);
363 RTC_CHECK(event.has_bwe_packet_loss_event());
364 const rtclog::BwePacketLossEvent& loss_event = event.bwe_packet_loss_event();
365 RTC_CHECK(loss_event.has_bitrate());
366 if (bitrate != nullptr)
367 *bitrate = loss_event.bitrate();
368 RTC_CHECK(loss_event.has_fraction_loss());
369 if (fraction_loss != nullptr)
370 *fraction_loss = loss_event.fraction_loss();
371 RTC_CHECK(loss_event.has_total_packets());
372 if (total_packets != nullptr)
373 *total_packets = loss_event.total_packets();
374 }
375
376 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698