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

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

Issue 2380683005: Moved RtcEventLog files from call/ to logging/ (new top level dir) (Closed)
Patch Set: Rebase to master Created 4 years, 2 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/call/rtc_event_log_parser.h ('k') | webrtc/call/rtc_event_log_unittest.cc » ('j') | 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) 2016 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 #include <istream>
17 #include <utility>
18
19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/logging.h"
21 #include "webrtc/call.h"
22 #include "webrtc/call/rtc_event_log.h"
23 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
24 #include "webrtc/system_wrappers/include/file_wrapper.h"
25
26 namespace webrtc {
27
28 namespace {
29 MediaType GetRuntimeMediaType(rtclog::MediaType media_type) {
30 switch (media_type) {
31 case rtclog::MediaType::ANY:
32 return MediaType::ANY;
33 case rtclog::MediaType::AUDIO:
34 return MediaType::AUDIO;
35 case rtclog::MediaType::VIDEO:
36 return MediaType::VIDEO;
37 case rtclog::MediaType::DATA:
38 return MediaType::DATA;
39 }
40 RTC_NOTREACHED();
41 return MediaType::ANY;
42 }
43
44 RtcpMode GetRuntimeRtcpMode(rtclog::VideoReceiveConfig::RtcpMode rtcp_mode) {
45 switch (rtcp_mode) {
46 case rtclog::VideoReceiveConfig::RTCP_COMPOUND:
47 return RtcpMode::kCompound;
48 case rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE:
49 return RtcpMode::kReducedSize;
50 }
51 RTC_NOTREACHED();
52 return RtcpMode::kOff;
53 }
54
55 ParsedRtcEventLog::EventType GetRuntimeEventType(
56 rtclog::Event::EventType event_type) {
57 switch (event_type) {
58 case rtclog::Event::UNKNOWN_EVENT:
59 return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
60 case rtclog::Event::LOG_START:
61 return ParsedRtcEventLog::EventType::LOG_START;
62 case rtclog::Event::LOG_END:
63 return ParsedRtcEventLog::EventType::LOG_END;
64 case rtclog::Event::RTP_EVENT:
65 return ParsedRtcEventLog::EventType::RTP_EVENT;
66 case rtclog::Event::RTCP_EVENT:
67 return ParsedRtcEventLog::EventType::RTCP_EVENT;
68 case rtclog::Event::AUDIO_PLAYOUT_EVENT:
69 return ParsedRtcEventLog::EventType::AUDIO_PLAYOUT_EVENT;
70 case rtclog::Event::BWE_PACKET_LOSS_EVENT:
71 return ParsedRtcEventLog::EventType::BWE_PACKET_LOSS_EVENT;
72 case rtclog::Event::BWE_PACKET_DELAY_EVENT:
73 return ParsedRtcEventLog::EventType::BWE_PACKET_DELAY_EVENT;
74 case rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT:
75 return ParsedRtcEventLog::EventType::VIDEO_RECEIVER_CONFIG_EVENT;
76 case rtclog::Event::VIDEO_SENDER_CONFIG_EVENT:
77 return ParsedRtcEventLog::EventType::VIDEO_SENDER_CONFIG_EVENT;
78 case rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT:
79 return ParsedRtcEventLog::EventType::AUDIO_RECEIVER_CONFIG_EVENT;
80 case rtclog::Event::AUDIO_SENDER_CONFIG_EVENT:
81 return ParsedRtcEventLog::EventType::AUDIO_SENDER_CONFIG_EVENT;
82 }
83 RTC_NOTREACHED();
84 return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
85 }
86
87 std::pair<uint64_t, bool> ParseVarInt(std::istream& stream) {
88 uint64_t varint = 0;
89 for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
90 // The most significant bit of each byte is 0 if it is the last byte in
91 // the varint and 1 otherwise. Thus, we take the 7 least significant bits
92 // of each byte and shift them 7 bits for each byte read previously to get
93 // the (unsigned) integer.
94 int byte = stream.get();
95 if (stream.eof()) {
96 return std::make_pair(varint, false);
97 }
98 RTC_DCHECK(0 <= byte && byte <= 255);
99 varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read);
100 if ((byte & 0x80) == 0) {
101 return std::make_pair(varint, true);
102 }
103 }
104 return std::make_pair(varint, false);
105 }
106
107 } // namespace
108
109 bool ParsedRtcEventLog::ParseFile(const std::string& filename) {
110 std::ifstream file(filename, std::ios_base::in | std::ios_base::binary);
111 if (!file.good() || !file.is_open()) {
112 LOG(LS_WARNING) << "Could not open file for reading.";
113 return false;
114 }
115
116 return ParseStream(file);
117 }
118
119 bool ParsedRtcEventLog::ParseString(const std::string& s) {
120 std::istringstream stream(s, std::ios_base::in | std::ios_base::binary);
121 return ParseStream(stream);
122 }
123
124 bool ParsedRtcEventLog::ParseStream(std::istream& stream) {
125 events_.clear();
126 const size_t kMaxEventSize = (1u << 16) - 1;
127 std::vector<char> tmp_buffer(kMaxEventSize);
128 uint64_t tag;
129 uint64_t message_length;
130 bool success;
131
132 RTC_DCHECK(stream.good());
133
134 while (1) {
135 // Check whether we have reached end of file.
136 stream.peek();
137 if (stream.eof()) {
138 return true;
139 }
140
141 // Read the next message tag. The tag number is defined as
142 // (fieldnumber << 3) | wire_type. In our case, the field number is
143 // supposed to be 1 and the wire type for an length-delimited field is 2.
144 const uint64_t kExpectedTag = (1 << 3) | 2;
145 std::tie(tag, success) = ParseVarInt(stream);
146 if (!success) {
147 LOG(LS_WARNING) << "Missing field tag from beginning of protobuf event.";
148 return false;
149 } else if (tag != kExpectedTag) {
150 LOG(LS_WARNING) << "Unexpected field tag at beginning of protobuf event.";
151 return false;
152 }
153
154 // Read the length field.
155 std::tie(message_length, success) = ParseVarInt(stream);
156 if (!success) {
157 LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
158 return false;
159 } else if (message_length > kMaxEventSize) {
160 LOG(LS_WARNING) << "Protobuf message length is too large.";
161 return false;
162 }
163
164 // Read the next protobuf event to a temporary char buffer.
165 stream.read(tmp_buffer.data(), message_length);
166 if (stream.gcount() != static_cast<int>(message_length)) {
167 LOG(LS_WARNING) << "Failed to read protobuf message from file.";
168 return false;
169 }
170
171 // Parse the protobuf event from the buffer.
172 rtclog::Event event;
173 if (!event.ParseFromArray(tmp_buffer.data(), message_length)) {
174 LOG(LS_WARNING) << "Failed to parse protobuf message.";
175 return false;
176 }
177 events_.push_back(event);
178 }
179 }
180
181 size_t ParsedRtcEventLog::GetNumberOfEvents() const {
182 return events_.size();
183 }
184
185 int64_t ParsedRtcEventLog::GetTimestamp(size_t index) const {
186 RTC_CHECK_LT(index, GetNumberOfEvents());
187 const rtclog::Event& event = events_[index];
188 RTC_CHECK(event.has_timestamp_us());
189 return event.timestamp_us();
190 }
191
192 ParsedRtcEventLog::EventType ParsedRtcEventLog::GetEventType(
193 size_t index) const {
194 RTC_CHECK_LT(index, GetNumberOfEvents());
195 const rtclog::Event& event = events_[index];
196 RTC_CHECK(event.has_type());
197 return GetRuntimeEventType(event.type());
198 }
199
200 // The header must have space for at least IP_PACKET_SIZE bytes.
201 void ParsedRtcEventLog::GetRtpHeader(size_t index,
202 PacketDirection* incoming,
203 MediaType* media_type,
204 uint8_t* header,
205 size_t* header_length,
206 size_t* total_length) const {
207 RTC_CHECK_LT(index, GetNumberOfEvents());
208 const rtclog::Event& event = events_[index];
209 RTC_CHECK(event.has_type());
210 RTC_CHECK_EQ(event.type(), rtclog::Event::RTP_EVENT);
211 RTC_CHECK(event.has_rtp_packet());
212 const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
213 // Get direction of packet.
214 RTC_CHECK(rtp_packet.has_incoming());
215 if (incoming != nullptr) {
216 *incoming = rtp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
217 }
218 // Get media type.
219 RTC_CHECK(rtp_packet.has_type());
220 if (media_type != nullptr) {
221 *media_type = GetRuntimeMediaType(rtp_packet.type());
222 }
223 // Get packet length.
224 RTC_CHECK(rtp_packet.has_packet_length());
225 if (total_length != nullptr) {
226 *total_length = rtp_packet.packet_length();
227 }
228 // Get header length.
229 RTC_CHECK(rtp_packet.has_header());
230 if (header_length != nullptr) {
231 *header_length = rtp_packet.header().size();
232 }
233 // Get header contents.
234 if (header != nullptr) {
235 const size_t kMinRtpHeaderSize = 12;
236 RTC_CHECK_GE(rtp_packet.header().size(), kMinRtpHeaderSize);
237 RTC_CHECK_LE(rtp_packet.header().size(),
238 static_cast<size_t>(IP_PACKET_SIZE));
239 memcpy(header, rtp_packet.header().data(), rtp_packet.header().size());
240 }
241 }
242
243 // The packet must have space for at least IP_PACKET_SIZE bytes.
244 void ParsedRtcEventLog::GetRtcpPacket(size_t index,
245 PacketDirection* incoming,
246 MediaType* media_type,
247 uint8_t* packet,
248 size_t* length) const {
249 RTC_CHECK_LT(index, GetNumberOfEvents());
250 const rtclog::Event& event = events_[index];
251 RTC_CHECK(event.has_type());
252 RTC_CHECK_EQ(event.type(), rtclog::Event::RTCP_EVENT);
253 RTC_CHECK(event.has_rtcp_packet());
254 const rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
255 // Get direction of packet.
256 RTC_CHECK(rtcp_packet.has_incoming());
257 if (incoming != nullptr) {
258 *incoming = rtcp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
259 }
260 // Get media type.
261 RTC_CHECK(rtcp_packet.has_type());
262 if (media_type != nullptr) {
263 *media_type = GetRuntimeMediaType(rtcp_packet.type());
264 }
265 // Get packet length.
266 RTC_CHECK(rtcp_packet.has_packet_data());
267 if (length != nullptr) {
268 *length = rtcp_packet.packet_data().size();
269 }
270 // Get packet contents.
271 if (packet != nullptr) {
272 RTC_CHECK_LE(rtcp_packet.packet_data().size(),
273 static_cast<unsigned>(IP_PACKET_SIZE));
274 memcpy(packet, rtcp_packet.packet_data().data(),
275 rtcp_packet.packet_data().size());
276 }
277 }
278
279 void ParsedRtcEventLog::GetVideoReceiveConfig(
280 size_t index,
281 VideoReceiveStream::Config* config) const {
282 RTC_CHECK_LT(index, GetNumberOfEvents());
283 const rtclog::Event& event = events_[index];
284 RTC_CHECK(config != nullptr);
285 RTC_CHECK(event.has_type());
286 RTC_CHECK_EQ(event.type(), rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
287 RTC_CHECK(event.has_video_receiver_config());
288 const rtclog::VideoReceiveConfig& receiver_config =
289 event.video_receiver_config();
290 // Get SSRCs.
291 RTC_CHECK(receiver_config.has_remote_ssrc());
292 config->rtp.remote_ssrc = receiver_config.remote_ssrc();
293 RTC_CHECK(receiver_config.has_local_ssrc());
294 config->rtp.local_ssrc = receiver_config.local_ssrc();
295 // Get RTCP settings.
296 RTC_CHECK(receiver_config.has_rtcp_mode());
297 config->rtp.rtcp_mode = GetRuntimeRtcpMode(receiver_config.rtcp_mode());
298 RTC_CHECK(receiver_config.has_remb());
299 config->rtp.remb = receiver_config.remb();
300 // Get RTX map.
301 config->rtp.rtx.clear();
302 for (int i = 0; i < receiver_config.rtx_map_size(); i++) {
303 const rtclog::RtxMap& map = receiver_config.rtx_map(i);
304 RTC_CHECK(map.has_payload_type());
305 RTC_CHECK(map.has_config());
306 RTC_CHECK(map.config().has_rtx_ssrc());
307 RTC_CHECK(map.config().has_rtx_payload_type());
308 webrtc::VideoReceiveStream::Config::Rtp::Rtx rtx_pair;
309 rtx_pair.ssrc = map.config().rtx_ssrc();
310 rtx_pair.payload_type = map.config().rtx_payload_type();
311 config->rtp.rtx.insert(std::make_pair(map.payload_type(), rtx_pair));
312 }
313 // Get header extensions.
314 config->rtp.extensions.clear();
315 for (int i = 0; i < receiver_config.header_extensions_size(); i++) {
316 RTC_CHECK(receiver_config.header_extensions(i).has_name());
317 RTC_CHECK(receiver_config.header_extensions(i).has_id());
318 const std::string& name = receiver_config.header_extensions(i).name();
319 int id = receiver_config.header_extensions(i).id();
320 config->rtp.extensions.push_back(RtpExtension(name, id));
321 }
322 // Get decoders.
323 config->decoders.clear();
324 for (int i = 0; i < receiver_config.decoders_size(); i++) {
325 RTC_CHECK(receiver_config.decoders(i).has_name());
326 RTC_CHECK(receiver_config.decoders(i).has_payload_type());
327 VideoReceiveStream::Decoder decoder;
328 decoder.payload_name = receiver_config.decoders(i).name();
329 decoder.payload_type = receiver_config.decoders(i).payload_type();
330 config->decoders.push_back(decoder);
331 }
332 }
333
334 void ParsedRtcEventLog::GetVideoSendConfig(
335 size_t index,
336 VideoSendStream::Config* config) const {
337 RTC_CHECK_LT(index, GetNumberOfEvents());
338 const rtclog::Event& event = events_[index];
339 RTC_CHECK(config != nullptr);
340 RTC_CHECK(event.has_type());
341 RTC_CHECK_EQ(event.type(), rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
342 RTC_CHECK(event.has_video_sender_config());
343 const rtclog::VideoSendConfig& sender_config = event.video_sender_config();
344 // Get SSRCs.
345 config->rtp.ssrcs.clear();
346 for (int i = 0; i < sender_config.ssrcs_size(); i++) {
347 config->rtp.ssrcs.push_back(sender_config.ssrcs(i));
348 }
349 // Get header extensions.
350 config->rtp.extensions.clear();
351 for (int i = 0; i < sender_config.header_extensions_size(); i++) {
352 RTC_CHECK(sender_config.header_extensions(i).has_name());
353 RTC_CHECK(sender_config.header_extensions(i).has_id());
354 const std::string& name = sender_config.header_extensions(i).name();
355 int id = sender_config.header_extensions(i).id();
356 config->rtp.extensions.push_back(RtpExtension(name, id));
357 }
358 // Get RTX settings.
359 config->rtp.rtx.ssrcs.clear();
360 for (int i = 0; i < sender_config.rtx_ssrcs_size(); i++) {
361 config->rtp.rtx.ssrcs.push_back(sender_config.rtx_ssrcs(i));
362 }
363 if (sender_config.rtx_ssrcs_size() > 0) {
364 RTC_CHECK(sender_config.has_rtx_payload_type());
365 config->rtp.rtx.payload_type = sender_config.rtx_payload_type();
366 } else {
367 // Reset RTX payload type default value if no RTX SSRCs are used.
368 config->rtp.rtx.payload_type = -1;
369 }
370 // Get encoder.
371 RTC_CHECK(sender_config.has_encoder());
372 RTC_CHECK(sender_config.encoder().has_name());
373 RTC_CHECK(sender_config.encoder().has_payload_type());
374 config->encoder_settings.payload_name = sender_config.encoder().name();
375 config->encoder_settings.payload_type =
376 sender_config.encoder().payload_type();
377 }
378
379 void ParsedRtcEventLog::GetAudioPlayout(size_t index, uint32_t* ssrc) const {
380 RTC_CHECK_LT(index, GetNumberOfEvents());
381 const rtclog::Event& event = events_[index];
382 RTC_CHECK(event.has_type());
383 RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_PLAYOUT_EVENT);
384 RTC_CHECK(event.has_audio_playout_event());
385 const rtclog::AudioPlayoutEvent& loss_event = event.audio_playout_event();
386 RTC_CHECK(loss_event.has_local_ssrc());
387 if (ssrc != nullptr) {
388 *ssrc = loss_event.local_ssrc();
389 }
390 }
391
392 void ParsedRtcEventLog::GetBwePacketLossEvent(size_t index,
393 int32_t* bitrate,
394 uint8_t* fraction_loss,
395 int32_t* total_packets) const {
396 RTC_CHECK_LT(index, GetNumberOfEvents());
397 const rtclog::Event& event = events_[index];
398 RTC_CHECK(event.has_type());
399 RTC_CHECK_EQ(event.type(), rtclog::Event::BWE_PACKET_LOSS_EVENT);
400 RTC_CHECK(event.has_bwe_packet_loss_event());
401 const rtclog::BwePacketLossEvent& loss_event = event.bwe_packet_loss_event();
402 RTC_CHECK(loss_event.has_bitrate());
403 if (bitrate != nullptr) {
404 *bitrate = loss_event.bitrate();
405 }
406 RTC_CHECK(loss_event.has_fraction_loss());
407 if (fraction_loss != nullptr) {
408 *fraction_loss = loss_event.fraction_loss();
409 }
410 RTC_CHECK(loss_event.has_total_packets());
411 if (total_packets != nullptr) {
412 *total_packets = loss_event.total_packets();
413 }
414 }
415
416 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/call/rtc_event_log_parser.h ('k') | webrtc/call/rtc_event_log_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698