blob: 6dd02c808ebb5421405c1512c45c4db96f49502d [file] [log] [blame]
Bjorn Terelius36411852015-07-30 12:45:18 +02001/*
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
Peter Boström5c389d32015-09-25 13:58:30 +020011#include "webrtc/call/rtc_event_log.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020012
terelius4311ba52016-04-22 12:40:37 -070013#include <limits>
terelius1adce142015-10-16 08:51:08 -070014#include <vector>
Bjorn Terelius36411852015-07-30 12:45:18 +020015
16#include "webrtc/base/checks.h"
terelius4311ba52016-04-22 12:40:37 -070017#include "webrtc/base/constructormagic.h"
18#include "webrtc/base/event.h"
19#include "webrtc/base/swap_queue.h"
20#include "webrtc/base/thread_checker.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020021#include "webrtc/call.h"
terelius4311ba52016-04-22 12:40:37 -070022#include "webrtc/call/rtc_event_log_helper_thread.h"
tereliusd66daa22015-11-06 09:00:18 -080023#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
terelius2f9fd5d2015-09-04 03:39:42 -070024#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
tereliusd66daa22015-11-06 09:00:18 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010026#include "webrtc/system_wrappers/include/clock.h"
27#include "webrtc/system_wrappers/include/file_wrapper.h"
terelius4311ba52016-04-22 12:40:37 -070028#include "webrtc/system_wrappers/include/logging.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020029
30#ifdef ENABLE_RTC_EVENT_LOG
31// Files generated at build-time by the protobuf compiler.
32#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
Peter Boström5c389d32015-09-25 13:58:30 +020033#include "external/webrtc/webrtc/call/rtc_event_log.pb.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020034#else
Peter Boström5c389d32015-09-25 13:58:30 +020035#include "webrtc/call/rtc_event_log.pb.h"
Bjorn Terelius36411852015-07-30 12:45:18 +020036#endif
37#endif
38
39namespace webrtc {
40
41#ifndef ENABLE_RTC_EVENT_LOG
42
43// No-op implementation if flag is not set.
terelius4311ba52016-04-22 12:40:37 -070044class RtcEventLogNullImpl final : public RtcEventLog {
Bjorn Terelius36411852015-07-30 12:45:18 +020045 public:
terelius4311ba52016-04-22 12:40:37 -070046 bool StartLogging(const std::string& file_name,
47 int64_t max_size_bytes) override {
48 return false;
49 }
50 bool StartLogging(rtc::PlatformFile platform_file,
51 int64_t max_size_bytes) override {
52 return false;
53 }
54 void StopLogging() override {}
Bjorn Terelius36411852015-07-30 12:45:18 +020055 void LogVideoReceiveStreamConfig(
56 const VideoReceiveStream::Config& config) override {}
57 void LogVideoSendStreamConfig(
58 const VideoSendStream::Config& config) override {}
terelius429c3452016-01-21 05:42:04 -080059 void LogRtpHeader(PacketDirection direction,
Bjorn Terelius36411852015-07-30 12:45:18 +020060 MediaType media_type,
61 const uint8_t* header,
terelius2f9fd5d2015-09-04 03:39:42 -070062 size_t packet_length) override {}
terelius429c3452016-01-21 05:42:04 -080063 void LogRtcpPacket(PacketDirection direction,
Bjorn Terelius36411852015-07-30 12:45:18 +020064 MediaType media_type,
65 const uint8_t* packet,
66 size_t length) override {}
Ivo Creusenae856f22015-09-17 16:30:16 +020067 void LogAudioPlayout(uint32_t ssrc) override {}
terelius006d93d2015-11-05 12:02:15 -080068 void LogBwePacketLossEvent(int32_t bitrate,
69 uint8_t fraction_loss,
70 int32_t total_packets) override {}
Bjorn Terelius36411852015-07-30 12:45:18 +020071};
72
73#else // ENABLE_RTC_EVENT_LOG is defined
74
75class RtcEventLogImpl final : public RtcEventLog {
76 public:
terelius4311ba52016-04-22 12:40:37 -070077 explicit RtcEventLogImpl(const Clock* clock);
78 ~RtcEventLogImpl() override;
terelius1adce142015-10-16 08:51:08 -070079
terelius4311ba52016-04-22 12:40:37 -070080 bool StartLogging(const std::string& file_name,
81 int64_t max_size_bytes) override;
82 bool StartLogging(rtc::PlatformFile platform_file,
83 int64_t max_size_bytes) override;
Bjorn Terelius36411852015-07-30 12:45:18 +020084 void StopLogging() override;
85 void LogVideoReceiveStreamConfig(
86 const VideoReceiveStream::Config& config) override;
87 void LogVideoSendStreamConfig(const VideoSendStream::Config& config) override;
terelius429c3452016-01-21 05:42:04 -080088 void LogRtpHeader(PacketDirection direction,
Bjorn Terelius36411852015-07-30 12:45:18 +020089 MediaType media_type,
90 const uint8_t* header,
terelius2f9fd5d2015-09-04 03:39:42 -070091 size_t packet_length) override;
terelius429c3452016-01-21 05:42:04 -080092 void LogRtcpPacket(PacketDirection direction,
Bjorn Terelius36411852015-07-30 12:45:18 +020093 MediaType media_type,
94 const uint8_t* packet,
95 size_t length) override;
Ivo Creusenae856f22015-09-17 16:30:16 +020096 void LogAudioPlayout(uint32_t ssrc) override;
terelius006d93d2015-11-05 12:02:15 -080097 void LogBwePacketLossEvent(int32_t bitrate,
98 uint8_t fraction_loss,
99 int32_t total_packets) override;
Bjorn Terelius36411852015-07-30 12:45:18 +0200100
101 private:
terelius4311ba52016-04-22 12:40:37 -0700102 // Message queue for passing control messages to the logging thread.
103 SwapQueue<RtcEventLogHelperThread::ControlMessage> message_queue_;
Bjorn Terelius36411852015-07-30 12:45:18 +0200104
terelius4311ba52016-04-22 12:40:37 -0700105 // Message queue for passing events to the logging thread.
106 SwapQueue<std::unique_ptr<rtclog::Event> > event_queue_;
terelius1adce142015-10-16 08:51:08 -0700107
terelius4311ba52016-04-22 12:40:37 -0700108 rtc::Event wake_up_;
109 rtc::Event stopped_;
110
terelius1adce142015-10-16 08:51:08 -0700111 const Clock* const clock_;
terelius4311ba52016-04-22 12:40:37 -0700112
113 RtcEventLogHelperThread helper_thread_;
114 rtc::ThreadChecker thread_checker_;
115
116 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcEventLogImpl);
Bjorn Terelius36411852015-07-30 12:45:18 +0200117};
118
119namespace {
120// The functions in this namespace convert enums from the runtime format
121// that the rest of the WebRtc project can use, to the corresponding
122// serialized enum which is defined by the protobuf.
123
pbosda903ea2015-10-02 02:36:56 -0700124rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) {
Bjorn Terelius36411852015-07-30 12:45:18 +0200125 switch (rtcp_mode) {
pbosda903ea2015-10-02 02:36:56 -0700126 case RtcpMode::kCompound:
Bjorn Terelius36411852015-07-30 12:45:18 +0200127 return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
pbosda903ea2015-10-02 02:36:56 -0700128 case RtcpMode::kReducedSize:
Bjorn Terelius36411852015-07-30 12:45:18 +0200129 return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE;
pbosda903ea2015-10-02 02:36:56 -0700130 case RtcpMode::kOff:
131 RTC_NOTREACHED();
132 return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
Bjorn Terelius36411852015-07-30 12:45:18 +0200133 }
134 RTC_NOTREACHED();
135 return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
136}
137
138rtclog::MediaType ConvertMediaType(MediaType media_type) {
139 switch (media_type) {
140 case MediaType::ANY:
141 return rtclog::MediaType::ANY;
142 case MediaType::AUDIO:
143 return rtclog::MediaType::AUDIO;
144 case MediaType::VIDEO:
145 return rtclog::MediaType::VIDEO;
146 case MediaType::DATA:
147 return rtclog::MediaType::DATA;
148 }
149 RTC_NOTREACHED();
150 return rtclog::ANY;
151}
152
terelius4311ba52016-04-22 12:40:37 -0700153// The RTP and RTCP buffers reserve space for twice the expected number of
154// sent packets because they also contain received packets.
155static const int kEventsPerSecond = 1000;
156static const int kControlMessagesPerSecond = 10;
terelius1adce142015-10-16 08:51:08 -0700157} // namespace
158
Bjorn Terelius36411852015-07-30 12:45:18 +0200159// RtcEventLogImpl member functions.
terelius4311ba52016-04-22 12:40:37 -0700160RtcEventLogImpl::RtcEventLogImpl(const Clock* clock)
161 // Allocate buffers for roughly one second of history.
162 : message_queue_(kControlMessagesPerSecond),
163 event_queue_(kEventsPerSecond),
164 wake_up_(false, false),
165 stopped_(false, false),
166 clock_(clock),
167 helper_thread_(&message_queue_,
168 &event_queue_,
169 &wake_up_,
170 &stopped_,
171 clock),
172 thread_checker_() {
173 thread_checker_.DetachFromThread();
terelius1adce142015-10-16 08:51:08 -0700174}
175
terelius4311ba52016-04-22 12:40:37 -0700176RtcEventLogImpl::~RtcEventLogImpl() {
177 // The RtcEventLogHelperThread destructor closes the file
178 // and waits for the thread to terminate.
terelius1adce142015-10-16 08:51:08 -0700179}
Bjorn Terelius36411852015-07-30 12:45:18 +0200180
terelius4311ba52016-04-22 12:40:37 -0700181bool RtcEventLogImpl::StartLogging(const std::string& file_name,
182 int64_t max_size_bytes) {
183 RTC_DCHECK(thread_checker_.CalledOnValidThread());
184 RtcEventLogHelperThread::ControlMessage message;
185 message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
ivocc1513ee2016-05-13 08:30:39 -0700186 message.max_size_bytes = max_size_bytes <= 0
187 ? std::numeric_limits<int64_t>::max()
188 : max_size_bytes;
terelius4311ba52016-04-22 12:40:37 -0700189 message.start_time = clock_->TimeInMicroseconds();
190 message.stop_time = std::numeric_limits<int64_t>::max();
191 message.file.reset(FileWrapper::Create());
192 if (message.file->OpenFile(file_name.c_str(), false) != 0) {
ivoc112a3d82015-10-16 02:22:18 -0700193 return false;
194 }
terelius4311ba52016-04-22 12:40:37 -0700195 if (!message_queue_.Insert(&message)) {
196 LOG(LS_WARNING) << "Message queue full. Can't start logging.";
ivoc112a3d82015-10-16 02:22:18 -0700197 return false;
198 }
ivoc112a3d82015-10-16 02:22:18 -0700199 return true;
200}
201
terelius4311ba52016-04-22 12:40:37 -0700202bool RtcEventLogImpl::StartLogging(rtc::PlatformFile platform_file,
203 int64_t max_size_bytes) {
204 RTC_DCHECK(thread_checker_.CalledOnValidThread());
205 RtcEventLogHelperThread::ControlMessage message;
206 message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
ivocc1513ee2016-05-13 08:30:39 -0700207 message.max_size_bytes = max_size_bytes <= 0
208 ? std::numeric_limits<int64_t>::max()
209 : max_size_bytes;
terelius4311ba52016-04-22 12:40:37 -0700210 message.start_time = clock_->TimeInMicroseconds();
211 message.stop_time = std::numeric_limits<int64_t>::max();
212 message.file.reset(FileWrapper::Create());
213 FILE* file_handle = rtc::FdopenPlatformFileForWriting(platform_file);
214 if (!file_handle) {
215 return false;
terelius1adce142015-10-16 08:51:08 -0700216 }
terelius4311ba52016-04-22 12:40:37 -0700217 if (message.file->OpenFromFileHandle(file_handle, true, false) != 0) {
218 return false;
Bjorn Terelius36411852015-07-30 12:45:18 +0200219 }
terelius4311ba52016-04-22 12:40:37 -0700220 if (!message_queue_.Insert(&message)) {
221 LOG(LS_WARNING) << "Message queue full. Can't start logging.";
222 return false;
223 }
224 return true;
Bjorn Terelius36411852015-07-30 12:45:18 +0200225}
226
227void RtcEventLogImpl::StopLogging() {
terelius4311ba52016-04-22 12:40:37 -0700228 RTC_DCHECK(thread_checker_.CalledOnValidThread());
229 RtcEventLogHelperThread::ControlMessage message;
230 message.message_type = RtcEventLogHelperThread::ControlMessage::STOP_FILE;
231 message.stop_time = clock_->TimeInMicroseconds();
232 while (!message_queue_.Insert(&message)) {
233 // TODO(terelius): We would like to have a blocking Insert function in the
234 // SwapQueue, but for the time being we will just clear any previous
235 // messages.
236 // Since StopLogging waits for the thread, it is essential that we don't
237 // clear any STOP_FILE messages. To ensure that there is only one call at a
238 // time, we require that all calls to StopLogging are made on the same
239 // thread.
240 LOG(LS_WARNING) << "Message queue full. Clearing queue to stop logging.";
241 message_queue_.Clear();
242 }
243 wake_up_.Set(); // Request the output thread to wake up.
244 stopped_.Wait(rtc::Event::kForever); // Wait for the log to stop.
Bjorn Terelius36411852015-07-30 12:45:18 +0200245}
246
247void RtcEventLogImpl::LogVideoReceiveStreamConfig(
248 const VideoReceiveStream::Config& config) {
terelius4311ba52016-04-22 12:40:37 -0700249 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
250 event->set_timestamp_us(clock_->TimeInMicroseconds());
251 event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
Bjorn Terelius36411852015-07-30 12:45:18 +0200252
253 rtclog::VideoReceiveConfig* receiver_config =
terelius4311ba52016-04-22 12:40:37 -0700254 event->mutable_video_receiver_config();
Bjorn Terelius36411852015-07-30 12:45:18 +0200255 receiver_config->set_remote_ssrc(config.rtp.remote_ssrc);
256 receiver_config->set_local_ssrc(config.rtp.local_ssrc);
257
258 receiver_config->set_rtcp_mode(ConvertRtcpMode(config.rtp.rtcp_mode));
Bjorn Terelius36411852015-07-30 12:45:18 +0200259 receiver_config->set_remb(config.rtp.remb);
260
261 for (const auto& kv : config.rtp.rtx) {
262 rtclog::RtxMap* rtx = receiver_config->add_rtx_map();
263 rtx->set_payload_type(kv.first);
264 rtx->mutable_config()->set_rtx_ssrc(kv.second.ssrc);
265 rtx->mutable_config()->set_rtx_payload_type(kv.second.payload_type);
266 }
267
268 for (const auto& e : config.rtp.extensions) {
269 rtclog::RtpHeaderExtension* extension =
270 receiver_config->add_header_extensions();
271 extension->set_name(e.name);
272 extension->set_id(e.id);
273 }
274
275 for (const auto& d : config.decoders) {
276 rtclog::DecoderConfig* decoder = receiver_config->add_decoders();
277 decoder->set_name(d.payload_name);
278 decoder->set_payload_type(d.payload_type);
279 }
terelius4311ba52016-04-22 12:40:37 -0700280 if (!event_queue_.Insert(&event)) {
281 LOG(LS_WARNING) << "Config queue full. Not logging config event.";
282 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200283}
284
285void RtcEventLogImpl::LogVideoSendStreamConfig(
286 const VideoSendStream::Config& config) {
terelius4311ba52016-04-22 12:40:37 -0700287 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
288 event->set_timestamp_us(clock_->TimeInMicroseconds());
289 event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
Bjorn Terelius36411852015-07-30 12:45:18 +0200290
terelius4311ba52016-04-22 12:40:37 -0700291 rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config();
Bjorn Terelius36411852015-07-30 12:45:18 +0200292
293 for (const auto& ssrc : config.rtp.ssrcs) {
294 sender_config->add_ssrcs(ssrc);
295 }
296
297 for (const auto& e : config.rtp.extensions) {
298 rtclog::RtpHeaderExtension* extension =
299 sender_config->add_header_extensions();
300 extension->set_name(e.name);
301 extension->set_id(e.id);
302 }
303
304 for (const auto& rtx_ssrc : config.rtp.rtx.ssrcs) {
305 sender_config->add_rtx_ssrcs(rtx_ssrc);
306 }
307 sender_config->set_rtx_payload_type(config.rtp.rtx.payload_type);
308
Bjorn Terelius36411852015-07-30 12:45:18 +0200309 rtclog::EncoderConfig* encoder = sender_config->mutable_encoder();
310 encoder->set_name(config.encoder_settings.payload_name);
311 encoder->set_payload_type(config.encoder_settings.payload_type);
terelius4311ba52016-04-22 12:40:37 -0700312 if (!event_queue_.Insert(&event)) {
313 LOG(LS_WARNING) << "Config queue full. Not logging config event.";
314 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200315}
316
terelius429c3452016-01-21 05:42:04 -0800317void RtcEventLogImpl::LogRtpHeader(PacketDirection direction,
Bjorn Terelius36411852015-07-30 12:45:18 +0200318 MediaType media_type,
319 const uint8_t* header,
terelius2f9fd5d2015-09-04 03:39:42 -0700320 size_t packet_length) {
321 // Read header length (in bytes) from packet data.
322 if (packet_length < 12u) {
323 return; // Don't read outside the packet.
324 }
325 const bool x = (header[0] & 0x10) != 0;
326 const uint8_t cc = header[0] & 0x0f;
327 size_t header_length = 12u + cc * 4u;
328
329 if (x) {
330 if (packet_length < 12u + cc * 4u + 4u) {
331 return; // Don't read outside the packet.
332 }
333 size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4);
334 header_length += (x_len + 1) * 4;
335 }
336
terelius4311ba52016-04-22 12:40:37 -0700337 std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event());
338 rtp_event->set_timestamp_us(clock_->TimeInMicroseconds());
339 rtp_event->set_type(rtclog::Event::RTP_EVENT);
340 rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket);
341 rtp_event->mutable_rtp_packet()->set_type(ConvertMediaType(media_type));
342 rtp_event->mutable_rtp_packet()->set_packet_length(packet_length);
343 rtp_event->mutable_rtp_packet()->set_header(header, header_length);
344 if (!event_queue_.Insert(&rtp_event)) {
345 LOG(LS_WARNING) << "RTP queue full. Not logging RTP packet.";
346 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200347}
348
terelius429c3452016-01-21 05:42:04 -0800349void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction,
Bjorn Terelius36411852015-07-30 12:45:18 +0200350 MediaType media_type,
351 const uint8_t* packet,
352 size_t length) {
terelius4311ba52016-04-22 12:40:37 -0700353 std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event());
354 rtcp_event->set_timestamp_us(clock_->TimeInMicroseconds());
355 rtcp_event->set_type(rtclog::Event::RTCP_EVENT);
356 rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket);
357 rtcp_event->mutable_rtcp_packet()->set_type(ConvertMediaType(media_type));
tereliusd66daa22015-11-06 09:00:18 -0800358
359 RTCPUtility::RtcpCommonHeader header;
360 const uint8_t* block_begin = packet;
361 const uint8_t* packet_end = packet + length;
362 RTC_DCHECK(length <= IP_PACKET_SIZE);
363 uint8_t buffer[IP_PACKET_SIZE];
364 uint32_t buffer_length = 0;
365 while (block_begin < packet_end) {
366 if (!RtcpParseCommonHeader(block_begin, packet_end - block_begin,
367 &header)) {
368 break; // Incorrect message header.
369 }
370 uint32_t block_size = header.BlockSize();
371 switch (header.packet_type) {
372 case RTCPUtility::PT_SR:
373 FALLTHROUGH();
374 case RTCPUtility::PT_RR:
375 FALLTHROUGH();
376 case RTCPUtility::PT_BYE:
377 FALLTHROUGH();
378 case RTCPUtility::PT_IJ:
379 FALLTHROUGH();
380 case RTCPUtility::PT_RTPFB:
381 FALLTHROUGH();
382 case RTCPUtility::PT_PSFB:
383 FALLTHROUGH();
384 case RTCPUtility::PT_XR:
385 // We log sender reports, receiver reports, bye messages
386 // inter-arrival jitter, third-party loss reports, payload-specific
387 // feedback and extended reports.
388 memcpy(buffer + buffer_length, block_begin, block_size);
389 buffer_length += block_size;
390 break;
391 case RTCPUtility::PT_SDES:
392 FALLTHROUGH();
393 case RTCPUtility::PT_APP:
394 FALLTHROUGH();
395 default:
396 // We don't log sender descriptions, application defined messages
397 // or message blocks of unknown type.
398 break;
399 }
400
401 block_begin += block_size;
402 }
terelius4311ba52016-04-22 12:40:37 -0700403 rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length);
404 if (!event_queue_.Insert(&rtcp_event)) {
405 LOG(LS_WARNING) << "RTCP queue full. Not logging RTCP packet.";
406 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200407}
408
Ivo Creusenae856f22015-09-17 16:30:16 +0200409void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) {
terelius4311ba52016-04-22 12:40:37 -0700410 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
411 event->set_timestamp_us(clock_->TimeInMicroseconds());
412 event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT);
413 auto playout_event = event->mutable_audio_playout_event();
Ivo Creusen301aaed2015-10-08 18:07:41 +0200414 playout_event->set_local_ssrc(ssrc);
terelius4311ba52016-04-22 12:40:37 -0700415 if (!event_queue_.Insert(&event)) {
416 LOG(LS_WARNING) << "Playout queue full. Not logging ACM playout.";
417 }
Bjorn Terelius36411852015-07-30 12:45:18 +0200418}
419
terelius006d93d2015-11-05 12:02:15 -0800420void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate,
421 uint8_t fraction_loss,
422 int32_t total_packets) {
terelius4311ba52016-04-22 12:40:37 -0700423 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
424 event->set_timestamp_us(clock_->TimeInMicroseconds());
425 event->set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT);
426 auto bwe_event = event->mutable_bwe_packet_loss_event();
terelius006d93d2015-11-05 12:02:15 -0800427 bwe_event->set_bitrate(bitrate);
428 bwe_event->set_fraction_loss(fraction_loss);
429 bwe_event->set_total_packets(total_packets);
terelius4311ba52016-04-22 12:40:37 -0700430 if (!event_queue_.Insert(&event)) {
431 LOG(LS_WARNING) << "BWE loss queue full. Not logging BWE update.";
Bjorn Terelius36411852015-07-30 12:45:18 +0200432 }
433}
434
435bool RtcEventLog::ParseRtcEventLog(const std::string& file_name,
436 rtclog::EventStream* result) {
437 char tmp_buffer[1024];
438 int bytes_read = 0;
kwibergb25345e2016-03-12 06:10:44 -0800439 std::unique_ptr<FileWrapper> dump_file(FileWrapper::Create());
Bjorn Terelius36411852015-07-30 12:45:18 +0200440 if (dump_file->OpenFile(file_name.c_str(), true) != 0) {
441 return false;
442 }
443 std::string dump_buffer;
444 while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) {
445 dump_buffer.append(tmp_buffer, bytes_read);
446 }
447 dump_file->CloseFile();
448 return result->ParseFromString(dump_buffer);
449}
450
451#endif // ENABLE_RTC_EVENT_LOG
452
453// RtcEventLog member functions.
terelius4311ba52016-04-22 12:40:37 -0700454std::unique_ptr<RtcEventLog> RtcEventLog::Create(const Clock* clock) {
455#ifdef ENABLE_RTC_EVENT_LOG
456 return std::unique_ptr<RtcEventLog>(new RtcEventLogImpl(clock));
457#else
458 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl());
459#endif // ENABLE_RTC_EVENT_LOG
Bjorn Terelius36411852015-07-30 12:45:18 +0200460}
terelius1adce142015-10-16 08:51:08 -0700461
Bjorn Terelius36411852015-07-30 12:45:18 +0200462} // namespace webrtc