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

Side by Side Diff: webrtc/call/rtc_event_log.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.h ('k') | webrtc/call/rtc_event_log.proto » ('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) 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.h"
12
13 #include <limits>
14 #include <vector>
15
16 #include "webrtc/base/checks.h"
17 #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"
21 #include "webrtc/call.h"
22 #include "webrtc/call/rtc_event_log_helper_thread.h"
23 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
24 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
25 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
26 #include "webrtc/system_wrappers/include/clock.h"
27 #include "webrtc/system_wrappers/include/file_wrapper.h"
28 #include "webrtc/system_wrappers/include/logging.h"
29
30 #ifdef ENABLE_RTC_EVENT_LOG
31 // Files generated at build-time by the protobuf compiler.
32 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
33 #include "external/webrtc/webrtc/call/rtc_event_log.pb.h"
34 #else
35 #include "webrtc/call/rtc_event_log.pb.h"
36 #endif
37 #endif
38
39 namespace webrtc {
40
41 #ifdef ENABLE_RTC_EVENT_LOG
42
43 class RtcEventLogImpl final : public RtcEventLog {
44 public:
45 explicit RtcEventLogImpl(const Clock* clock);
46 ~RtcEventLogImpl() override;
47
48 bool StartLogging(const std::string& file_name,
49 int64_t max_size_bytes) override;
50 bool StartLogging(rtc::PlatformFile platform_file,
51 int64_t max_size_bytes) override;
52 void StopLogging() override;
53 void LogVideoReceiveStreamConfig(
54 const VideoReceiveStream::Config& config) override;
55 void LogVideoSendStreamConfig(const VideoSendStream::Config& config) override;
56 void LogRtpHeader(PacketDirection direction,
57 MediaType media_type,
58 const uint8_t* header,
59 size_t packet_length) override;
60 void LogRtcpPacket(PacketDirection direction,
61 MediaType media_type,
62 const uint8_t* packet,
63 size_t length) override;
64 void LogAudioPlayout(uint32_t ssrc) override;
65 void LogBwePacketLossEvent(int32_t bitrate,
66 uint8_t fraction_loss,
67 int32_t total_packets) override;
68
69 private:
70 void StoreEvent(std::unique_ptr<rtclog::Event>* event);
71
72 // Message queue for passing control messages to the logging thread.
73 SwapQueue<RtcEventLogHelperThread::ControlMessage> message_queue_;
74
75 // Message queue for passing events to the logging thread.
76 SwapQueue<std::unique_ptr<rtclog::Event> > event_queue_;
77
78 const Clock* const clock_;
79
80 RtcEventLogHelperThread helper_thread_;
81 rtc::ThreadChecker thread_checker_;
82
83 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcEventLogImpl);
84 };
85
86 namespace {
87 // The functions in this namespace convert enums from the runtime format
88 // that the rest of the WebRtc project can use, to the corresponding
89 // serialized enum which is defined by the protobuf.
90
91 rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) {
92 switch (rtcp_mode) {
93 case RtcpMode::kCompound:
94 return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
95 case RtcpMode::kReducedSize:
96 return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE;
97 case RtcpMode::kOff:
98 RTC_NOTREACHED();
99 return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
100 }
101 RTC_NOTREACHED();
102 return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
103 }
104
105 rtclog::MediaType ConvertMediaType(MediaType media_type) {
106 switch (media_type) {
107 case MediaType::ANY:
108 return rtclog::MediaType::ANY;
109 case MediaType::AUDIO:
110 return rtclog::MediaType::AUDIO;
111 case MediaType::VIDEO:
112 return rtclog::MediaType::VIDEO;
113 case MediaType::DATA:
114 return rtclog::MediaType::DATA;
115 }
116 RTC_NOTREACHED();
117 return rtclog::ANY;
118 }
119
120 // The RTP and RTCP buffers reserve space for twice the expected number of
121 // sent packets because they also contain received packets.
122 static const int kEventsPerSecond = 1000;
123 static const int kControlMessagesPerSecond = 10;
124 } // namespace
125
126 // RtcEventLogImpl member functions.
127 RtcEventLogImpl::RtcEventLogImpl(const Clock* clock)
128 // Allocate buffers for roughly one second of history.
129 : message_queue_(kControlMessagesPerSecond),
130 event_queue_(kEventsPerSecond),
131 clock_(clock),
132 helper_thread_(&message_queue_,
133 &event_queue_,
134 clock),
135 thread_checker_() {
136 thread_checker_.DetachFromThread();
137 }
138
139 RtcEventLogImpl::~RtcEventLogImpl() {
140 // The RtcEventLogHelperThread destructor closes the file
141 // and waits for the thread to terminate.
142 }
143
144 bool RtcEventLogImpl::StartLogging(const std::string& file_name,
145 int64_t max_size_bytes) {
146 RTC_DCHECK(thread_checker_.CalledOnValidThread());
147 RtcEventLogHelperThread::ControlMessage message;
148 message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
149 message.max_size_bytes = max_size_bytes <= 0
150 ? std::numeric_limits<int64_t>::max()
151 : max_size_bytes;
152 message.start_time = clock_->TimeInMicroseconds();
153 message.stop_time = std::numeric_limits<int64_t>::max();
154 message.file.reset(FileWrapper::Create());
155 if (!message.file->OpenFile(file_name.c_str(), false)) {
156 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
157 return false;
158 }
159 if (!message_queue_.Insert(&message)) {
160 LOG(LS_ERROR) << "Message queue full. Can't start logging.";
161 return false;
162 }
163 helper_thread_.SignalNewEvent();
164 LOG(LS_INFO) << "Starting WebRTC event log.";
165 return true;
166 }
167
168 bool RtcEventLogImpl::StartLogging(rtc::PlatformFile platform_file,
169 int64_t max_size_bytes) {
170 RTC_DCHECK(thread_checker_.CalledOnValidThread());
171 RtcEventLogHelperThread::ControlMessage message;
172 message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
173 message.max_size_bytes = max_size_bytes <= 0
174 ? std::numeric_limits<int64_t>::max()
175 : max_size_bytes;
176 message.start_time = clock_->TimeInMicroseconds();
177 message.stop_time = std::numeric_limits<int64_t>::max();
178 message.file.reset(FileWrapper::Create());
179 FILE* file_handle = rtc::FdopenPlatformFileForWriting(platform_file);
180 if (!file_handle) {
181 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
182 // Even though we failed to open a FILE*, the platform_file is still open
183 // and needs to be closed.
184 if (!rtc::ClosePlatformFile(platform_file)) {
185 LOG(LS_ERROR) << "Can't close file.";
186 }
187 return false;
188 }
189 if (!message.file->OpenFromFileHandle(file_handle)) {
190 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
191 return false;
192 }
193 if (!message_queue_.Insert(&message)) {
194 LOG(LS_ERROR) << "Message queue full. Can't start logging.";
195 return false;
196 }
197 helper_thread_.SignalNewEvent();
198 LOG(LS_INFO) << "Starting WebRTC event log.";
199 return true;
200 }
201
202 void RtcEventLogImpl::StopLogging() {
203 RTC_DCHECK(thread_checker_.CalledOnValidThread());
204 RtcEventLogHelperThread::ControlMessage message;
205 message.message_type = RtcEventLogHelperThread::ControlMessage::STOP_FILE;
206 message.stop_time = clock_->TimeInMicroseconds();
207 while (!message_queue_.Insert(&message)) {
208 // TODO(terelius): We would like to have a blocking Insert function in the
209 // SwapQueue, but for the time being we will just clear any previous
210 // messages.
211 // Since StopLogging waits for the thread, it is essential that we don't
212 // clear any STOP_FILE messages. To ensure that there is only one call at a
213 // time, we require that all calls to StopLogging are made on the same
214 // thread.
215 LOG(LS_ERROR) << "Message queue full. Clearing queue to stop logging.";
216 message_queue_.Clear();
217 }
218 LOG(LS_INFO) << "Stopping WebRTC event log.";
219 helper_thread_.WaitForFileFinished();
220 }
221
222 void RtcEventLogImpl::LogVideoReceiveStreamConfig(
223 const VideoReceiveStream::Config& config) {
224 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
225 event->set_timestamp_us(clock_->TimeInMicroseconds());
226 event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
227
228 rtclog::VideoReceiveConfig* receiver_config =
229 event->mutable_video_receiver_config();
230 receiver_config->set_remote_ssrc(config.rtp.remote_ssrc);
231 receiver_config->set_local_ssrc(config.rtp.local_ssrc);
232
233 receiver_config->set_rtcp_mode(ConvertRtcpMode(config.rtp.rtcp_mode));
234 receiver_config->set_remb(config.rtp.remb);
235
236 for (const auto& kv : config.rtp.rtx) {
237 rtclog::RtxMap* rtx = receiver_config->add_rtx_map();
238 rtx->set_payload_type(kv.first);
239 rtx->mutable_config()->set_rtx_ssrc(kv.second.ssrc);
240 rtx->mutable_config()->set_rtx_payload_type(kv.second.payload_type);
241 }
242
243 for (const auto& e : config.rtp.extensions) {
244 rtclog::RtpHeaderExtension* extension =
245 receiver_config->add_header_extensions();
246 extension->set_name(e.uri);
247 extension->set_id(e.id);
248 }
249
250 for (const auto& d : config.decoders) {
251 rtclog::DecoderConfig* decoder = receiver_config->add_decoders();
252 decoder->set_name(d.payload_name);
253 decoder->set_payload_type(d.payload_type);
254 }
255 StoreEvent(&event);
256 }
257
258 void RtcEventLogImpl::LogVideoSendStreamConfig(
259 const VideoSendStream::Config& config) {
260 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
261 event->set_timestamp_us(clock_->TimeInMicroseconds());
262 event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
263
264 rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config();
265
266 for (const auto& ssrc : config.rtp.ssrcs) {
267 sender_config->add_ssrcs(ssrc);
268 }
269
270 for (const auto& e : config.rtp.extensions) {
271 rtclog::RtpHeaderExtension* extension =
272 sender_config->add_header_extensions();
273 extension->set_name(e.uri);
274 extension->set_id(e.id);
275 }
276
277 for (const auto& rtx_ssrc : config.rtp.rtx.ssrcs) {
278 sender_config->add_rtx_ssrcs(rtx_ssrc);
279 }
280 sender_config->set_rtx_payload_type(config.rtp.rtx.payload_type);
281
282 rtclog::EncoderConfig* encoder = sender_config->mutable_encoder();
283 encoder->set_name(config.encoder_settings.payload_name);
284 encoder->set_payload_type(config.encoder_settings.payload_type);
285 StoreEvent(&event);
286 }
287
288 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction,
289 MediaType media_type,
290 const uint8_t* header,
291 size_t packet_length) {
292 // Read header length (in bytes) from packet data.
293 if (packet_length < 12u) {
294 return; // Don't read outside the packet.
295 }
296 const bool x = (header[0] & 0x10) != 0;
297 const uint8_t cc = header[0] & 0x0f;
298 size_t header_length = 12u + cc * 4u;
299
300 if (x) {
301 if (packet_length < 12u + cc * 4u + 4u) {
302 return; // Don't read outside the packet.
303 }
304 size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4);
305 header_length += (x_len + 1) * 4;
306 }
307
308 std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event());
309 rtp_event->set_timestamp_us(clock_->TimeInMicroseconds());
310 rtp_event->set_type(rtclog::Event::RTP_EVENT);
311 rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket);
312 rtp_event->mutable_rtp_packet()->set_type(ConvertMediaType(media_type));
313 rtp_event->mutable_rtp_packet()->set_packet_length(packet_length);
314 rtp_event->mutable_rtp_packet()->set_header(header, header_length);
315 StoreEvent(&rtp_event);
316 }
317
318 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction,
319 MediaType media_type,
320 const uint8_t* packet,
321 size_t length) {
322 std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event());
323 rtcp_event->set_timestamp_us(clock_->TimeInMicroseconds());
324 rtcp_event->set_type(rtclog::Event::RTCP_EVENT);
325 rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket);
326 rtcp_event->mutable_rtcp_packet()->set_type(ConvertMediaType(media_type));
327
328 RTCPUtility::RtcpCommonHeader header;
329 const uint8_t* block_begin = packet;
330 const uint8_t* packet_end = packet + length;
331 RTC_DCHECK(length <= IP_PACKET_SIZE);
332 uint8_t buffer[IP_PACKET_SIZE];
333 uint32_t buffer_length = 0;
334 while (block_begin < packet_end) {
335 if (!RtcpParseCommonHeader(block_begin, packet_end - block_begin,
336 &header)) {
337 break; // Incorrect message header.
338 }
339 uint32_t block_size = header.BlockSize();
340 switch (header.packet_type) {
341 case RTCPUtility::PT_SR:
342 FALLTHROUGH();
343 case RTCPUtility::PT_RR:
344 FALLTHROUGH();
345 case RTCPUtility::PT_BYE:
346 FALLTHROUGH();
347 case RTCPUtility::PT_IJ:
348 FALLTHROUGH();
349 case RTCPUtility::PT_RTPFB:
350 FALLTHROUGH();
351 case RTCPUtility::PT_PSFB:
352 FALLTHROUGH();
353 case RTCPUtility::PT_XR:
354 // We log sender reports, receiver reports, bye messages
355 // inter-arrival jitter, third-party loss reports, payload-specific
356 // feedback and extended reports.
357 memcpy(buffer + buffer_length, block_begin, block_size);
358 buffer_length += block_size;
359 break;
360 case RTCPUtility::PT_SDES:
361 FALLTHROUGH();
362 case RTCPUtility::PT_APP:
363 FALLTHROUGH();
364 default:
365 // We don't log sender descriptions, application defined messages
366 // or message blocks of unknown type.
367 break;
368 }
369
370 block_begin += block_size;
371 }
372 rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length);
373 StoreEvent(&rtcp_event);
374 }
375
376 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) {
377 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
378 event->set_timestamp_us(clock_->TimeInMicroseconds());
379 event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT);
380 auto playout_event = event->mutable_audio_playout_event();
381 playout_event->set_local_ssrc(ssrc);
382 StoreEvent(&event);
383 }
384
385 void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate,
386 uint8_t fraction_loss,
387 int32_t total_packets) {
388 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
389 event->set_timestamp_us(clock_->TimeInMicroseconds());
390 event->set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT);
391 auto bwe_event = event->mutable_bwe_packet_loss_event();
392 bwe_event->set_bitrate(bitrate);
393 bwe_event->set_fraction_loss(fraction_loss);
394 bwe_event->set_total_packets(total_packets);
395 StoreEvent(&event);
396 }
397
398 void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event>* event) {
399 if (!event_queue_.Insert(event)) {
400 LOG(LS_ERROR) << "WebRTC event log queue full. Dropping event.";
401 }
402 helper_thread_.SignalNewEvent();
403 }
404
405 bool RtcEventLog::ParseRtcEventLog(const std::string& file_name,
406 rtclog::EventStream* result) {
407 char tmp_buffer[1024];
408 int bytes_read = 0;
409 std::unique_ptr<FileWrapper> dump_file(FileWrapper::Create());
410 if (!dump_file->OpenFile(file_name.c_str(), true)) {
411 return false;
412 }
413 std::string dump_buffer;
414 while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) {
415 dump_buffer.append(tmp_buffer, bytes_read);
416 }
417 dump_file->CloseFile();
418 return result->ParseFromString(dump_buffer);
419 }
420
421 #endif // ENABLE_RTC_EVENT_LOG
422
423 bool RtcEventLogNullImpl::StartLogging(rtc::PlatformFile platform_file,
424 int64_t max_size_bytes) {
425 // The platform_file is open and needs to be closed.
426 if (!rtc::ClosePlatformFile(platform_file)) {
427 LOG(LS_ERROR) << "Can't close file.";
428 }
429 return false;
430 }
431
432 // RtcEventLog member functions.
433 std::unique_ptr<RtcEventLog> RtcEventLog::Create(const Clock* clock) {
434 #ifdef ENABLE_RTC_EVENT_LOG
435 return std::unique_ptr<RtcEventLog>(new RtcEventLogImpl(clock));
436 #else
437 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl());
438 #endif // ENABLE_RTC_EVENT_LOG
439 }
440
441 std::unique_ptr<RtcEventLog> RtcEventLog::CreateNull() {
442 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl());
443 }
444
445 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/call/rtc_event_log.h ('k') | webrtc/call/rtc_event_log.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698