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

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

Issue 2035483003: Hibernate the thread if there are no events in the queue. Wake it up when an event is added to the … (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Nit Created 4 years, 6 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
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
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 void LogRtcpPacket(PacketDirection direction, 96 void LogRtcpPacket(PacketDirection direction,
97 MediaType media_type, 97 MediaType media_type,
98 const uint8_t* packet, 98 const uint8_t* packet,
99 size_t length) override; 99 size_t length) override;
100 void LogAudioPlayout(uint32_t ssrc) override; 100 void LogAudioPlayout(uint32_t ssrc) override;
101 void LogBwePacketLossEvent(int32_t bitrate, 101 void LogBwePacketLossEvent(int32_t bitrate,
102 uint8_t fraction_loss, 102 uint8_t fraction_loss,
103 int32_t total_packets) override; 103 int32_t total_packets) override;
104 104
105 private: 105 private:
106 void StoreEvent(std::unique_ptr<rtclog::Event>* event);
107
106 // Message queue for passing control messages to the logging thread. 108 // Message queue for passing control messages to the logging thread.
107 SwapQueue<RtcEventLogHelperThread::ControlMessage> message_queue_; 109 SwapQueue<RtcEventLogHelperThread::ControlMessage> message_queue_;
108 110
109 // Message queue for passing events to the logging thread. 111 // Message queue for passing events to the logging thread.
110 SwapQueue<std::unique_ptr<rtclog::Event> > event_queue_; 112 SwapQueue<std::unique_ptr<rtclog::Event> > event_queue_;
111 113
112 rtc::Event wake_up_; 114 rtc::Event wake_up_;
115 rtc::Event end_hibernation_;
113 rtc::Event stopped_; 116 rtc::Event stopped_;
114 117
115 const Clock* const clock_; 118 const Clock* const clock_;
116 119
117 RtcEventLogHelperThread helper_thread_; 120 RtcEventLogHelperThread helper_thread_;
118 rtc::ThreadChecker thread_checker_; 121 rtc::ThreadChecker thread_checker_;
119 122
120 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcEventLogImpl); 123 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcEventLogImpl);
121 }; 124 };
122 125
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 static const int kEventsPerSecond = 1000; 162 static const int kEventsPerSecond = 1000;
160 static const int kControlMessagesPerSecond = 10; 163 static const int kControlMessagesPerSecond = 10;
161 } // namespace 164 } // namespace
162 165
163 // RtcEventLogImpl member functions. 166 // RtcEventLogImpl member functions.
164 RtcEventLogImpl::RtcEventLogImpl(const Clock* clock) 167 RtcEventLogImpl::RtcEventLogImpl(const Clock* clock)
165 // Allocate buffers for roughly one second of history. 168 // Allocate buffers for roughly one second of history.
166 : message_queue_(kControlMessagesPerSecond), 169 : message_queue_(kControlMessagesPerSecond),
167 event_queue_(kEventsPerSecond), 170 event_queue_(kEventsPerSecond),
168 wake_up_(false, false), 171 wake_up_(false, false),
172 end_hibernation_(false, false),
169 stopped_(false, false), 173 stopped_(false, false),
170 clock_(clock), 174 clock_(clock),
171 helper_thread_(&message_queue_, 175 helper_thread_(&message_queue_,
172 &event_queue_, 176 &event_queue_,
173 &wake_up_, 177 &wake_up_,
178 &end_hibernation_,
174 &stopped_, 179 &stopped_,
175 clock), 180 clock),
176 thread_checker_() { 181 thread_checker_() {
177 thread_checker_.DetachFromThread(); 182 thread_checker_.DetachFromThread();
178 } 183 }
179 184
180 RtcEventLogImpl::~RtcEventLogImpl() { 185 RtcEventLogImpl::~RtcEventLogImpl() {
181 // The RtcEventLogHelperThread destructor closes the file 186 // The RtcEventLogHelperThread destructor closes the file
182 // and waits for the thread to terminate. 187 // and waits for the thread to terminate.
183 } 188 }
(...skipping 10 matching lines...) Expand all
194 message.stop_time = std::numeric_limits<int64_t>::max(); 199 message.stop_time = std::numeric_limits<int64_t>::max();
195 message.file.reset(FileWrapper::Create()); 200 message.file.reset(FileWrapper::Create());
196 if (message.file->OpenFile(file_name.c_str(), false) != 0) { 201 if (message.file->OpenFile(file_name.c_str(), false) != 0) {
197 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started."; 202 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
198 return false; 203 return false;
199 } 204 }
200 if (!message_queue_.Insert(&message)) { 205 if (!message_queue_.Insert(&message)) {
201 LOG(LS_ERROR) << "Message queue full. Can't start logging."; 206 LOG(LS_ERROR) << "Message queue full. Can't start logging.";
202 return false; 207 return false;
203 } 208 }
209 end_hibernation_.Set();
204 LOG(LS_INFO) << "Starting WebRTC event log."; 210 LOG(LS_INFO) << "Starting WebRTC event log.";
205 return true; 211 return true;
206 } 212 }
207 213
208 bool RtcEventLogImpl::StartLogging(rtc::PlatformFile platform_file, 214 bool RtcEventLogImpl::StartLogging(rtc::PlatformFile platform_file,
209 int64_t max_size_bytes) { 215 int64_t max_size_bytes) {
210 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 216 RTC_DCHECK(thread_checker_.CalledOnValidThread());
211 RtcEventLogHelperThread::ControlMessage message; 217 RtcEventLogHelperThread::ControlMessage message;
212 message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE; 218 message.message_type = RtcEventLogHelperThread::ControlMessage::START_FILE;
213 message.max_size_bytes = max_size_bytes <= 0 219 message.max_size_bytes = max_size_bytes <= 0
(...skipping 13 matching lines...) Expand all
227 return false; 233 return false;
228 } 234 }
229 if (message.file->OpenFromFileHandle(file_handle, true, false) != 0) { 235 if (message.file->OpenFromFileHandle(file_handle, true, false) != 0) {
230 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started."; 236 LOG(LS_ERROR) << "Can't open file. WebRTC event log not started.";
231 return false; 237 return false;
232 } 238 }
233 if (!message_queue_.Insert(&message)) { 239 if (!message_queue_.Insert(&message)) {
234 LOG(LS_ERROR) << "Message queue full. Can't start logging."; 240 LOG(LS_ERROR) << "Message queue full. Can't start logging.";
235 return false; 241 return false;
236 } 242 }
243 end_hibernation_.Set();
237 LOG(LS_INFO) << "Starting WebRTC event log."; 244 LOG(LS_INFO) << "Starting WebRTC event log.";
238 return true; 245 return true;
239 } 246 }
240 247
241 void RtcEventLogImpl::StopLogging() { 248 void RtcEventLogImpl::StopLogging() {
242 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 249 RTC_DCHECK(thread_checker_.CalledOnValidThread());
243 RtcEventLogHelperThread::ControlMessage message; 250 RtcEventLogHelperThread::ControlMessage message;
244 message.message_type = RtcEventLogHelperThread::ControlMessage::STOP_FILE; 251 message.message_type = RtcEventLogHelperThread::ControlMessage::STOP_FILE;
245 message.stop_time = clock_->TimeInMicroseconds(); 252 message.stop_time = clock_->TimeInMicroseconds();
246 while (!message_queue_.Insert(&message)) { 253 while (!message_queue_.Insert(&message)) {
247 // TODO(terelius): We would like to have a blocking Insert function in the 254 // TODO(terelius): We would like to have a blocking Insert function in the
248 // SwapQueue, but for the time being we will just clear any previous 255 // SwapQueue, but for the time being we will just clear any previous
249 // messages. 256 // messages.
250 // Since StopLogging waits for the thread, it is essential that we don't 257 // Since StopLogging waits for the thread, it is essential that we don't
251 // clear any STOP_FILE messages. To ensure that there is only one call at a 258 // clear any STOP_FILE messages. To ensure that there is only one call at a
252 // time, we require that all calls to StopLogging are made on the same 259 // time, we require that all calls to StopLogging are made on the same
253 // thread. 260 // thread.
254 LOG(LS_ERROR) << "Message queue full. Clearing queue to stop logging."; 261 LOG(LS_ERROR) << "Message queue full. Clearing queue to stop logging.";
255 message_queue_.Clear(); 262 message_queue_.Clear();
256 } 263 }
257 LOG(LS_INFO) << "Stopping WebRTC event log."; 264 LOG(LS_INFO) << "Stopping WebRTC event log.";
265 end_hibernation_.Set();
pbos-webrtc 2016/06/03 08:54:25 Should the last three lines here be replaced with
terelius 2016/06/08 11:47:29 Done. Note that this only reduces the number of sh
258 wake_up_.Set(); // Request the output thread to wake up. 266 wake_up_.Set(); // Request the output thread to wake up.
259 stopped_.Wait(rtc::Event::kForever); // Wait for the log to stop. 267 stopped_.Wait(rtc::Event::kForever); // Wait for the log to stop.
260 } 268 }
261 269
262 void RtcEventLogImpl::LogVideoReceiveStreamConfig( 270 void RtcEventLogImpl::LogVideoReceiveStreamConfig(
263 const VideoReceiveStream::Config& config) { 271 const VideoReceiveStream::Config& config) {
264 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); 272 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
265 event->set_timestamp_us(clock_->TimeInMicroseconds()); 273 event->set_timestamp_us(clock_->TimeInMicroseconds());
266 event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT); 274 event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT);
267 275
(...skipping 17 matching lines...) Expand all
285 receiver_config->add_header_extensions(); 293 receiver_config->add_header_extensions();
286 extension->set_name(e.uri); 294 extension->set_name(e.uri);
287 extension->set_id(e.id); 295 extension->set_id(e.id);
288 } 296 }
289 297
290 for (const auto& d : config.decoders) { 298 for (const auto& d : config.decoders) {
291 rtclog::DecoderConfig* decoder = receiver_config->add_decoders(); 299 rtclog::DecoderConfig* decoder = receiver_config->add_decoders();
292 decoder->set_name(d.payload_name); 300 decoder->set_name(d.payload_name);
293 decoder->set_payload_type(d.payload_type); 301 decoder->set_payload_type(d.payload_type);
294 } 302 }
295 if (!event_queue_.Insert(&event)) { 303 StoreEvent(&event);
296 LOG(LS_ERROR) << "Config queue full. Not logging config event.";
297 }
298 } 304 }
299 305
300 void RtcEventLogImpl::LogVideoSendStreamConfig( 306 void RtcEventLogImpl::LogVideoSendStreamConfig(
301 const VideoSendStream::Config& config) { 307 const VideoSendStream::Config& config) {
302 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); 308 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
303 event->set_timestamp_us(clock_->TimeInMicroseconds()); 309 event->set_timestamp_us(clock_->TimeInMicroseconds());
304 event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT); 310 event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT);
305 311
306 rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config(); 312 rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config();
307 313
308 for (const auto& ssrc : config.rtp.ssrcs) { 314 for (const auto& ssrc : config.rtp.ssrcs) {
309 sender_config->add_ssrcs(ssrc); 315 sender_config->add_ssrcs(ssrc);
310 } 316 }
311 317
312 for (const auto& e : config.rtp.extensions) { 318 for (const auto& e : config.rtp.extensions) {
313 rtclog::RtpHeaderExtension* extension = 319 rtclog::RtpHeaderExtension* extension =
314 sender_config->add_header_extensions(); 320 sender_config->add_header_extensions();
315 extension->set_name(e.uri); 321 extension->set_name(e.uri);
316 extension->set_id(e.id); 322 extension->set_id(e.id);
317 } 323 }
318 324
319 for (const auto& rtx_ssrc : config.rtp.rtx.ssrcs) { 325 for (const auto& rtx_ssrc : config.rtp.rtx.ssrcs) {
320 sender_config->add_rtx_ssrcs(rtx_ssrc); 326 sender_config->add_rtx_ssrcs(rtx_ssrc);
321 } 327 }
322 sender_config->set_rtx_payload_type(config.rtp.rtx.payload_type); 328 sender_config->set_rtx_payload_type(config.rtp.rtx.payload_type);
323 329
324 rtclog::EncoderConfig* encoder = sender_config->mutable_encoder(); 330 rtclog::EncoderConfig* encoder = sender_config->mutable_encoder();
325 encoder->set_name(config.encoder_settings.payload_name); 331 encoder->set_name(config.encoder_settings.payload_name);
326 encoder->set_payload_type(config.encoder_settings.payload_type); 332 encoder->set_payload_type(config.encoder_settings.payload_type);
327 if (!event_queue_.Insert(&event)) { 333 StoreEvent(&event);
328 LOG(LS_ERROR) << "Config queue full. Not logging config event.";
329 }
330 } 334 }
331 335
332 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, 336 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction,
333 MediaType media_type, 337 MediaType media_type,
334 const uint8_t* header, 338 const uint8_t* header,
335 size_t packet_length) { 339 size_t packet_length) {
336 // Read header length (in bytes) from packet data. 340 // Read header length (in bytes) from packet data.
337 if (packet_length < 12u) { 341 if (packet_length < 12u) {
338 return; // Don't read outside the packet. 342 return; // Don't read outside the packet.
339 } 343 }
340 const bool x = (header[0] & 0x10) != 0; 344 const bool x = (header[0] & 0x10) != 0;
341 const uint8_t cc = header[0] & 0x0f; 345 const uint8_t cc = header[0] & 0x0f;
342 size_t header_length = 12u + cc * 4u; 346 size_t header_length = 12u + cc * 4u;
343 347
344 if (x) { 348 if (x) {
345 if (packet_length < 12u + cc * 4u + 4u) { 349 if (packet_length < 12u + cc * 4u + 4u) {
346 return; // Don't read outside the packet. 350 return; // Don't read outside the packet.
347 } 351 }
348 size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4); 352 size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4);
349 header_length += (x_len + 1) * 4; 353 header_length += (x_len + 1) * 4;
350 } 354 }
351 355
352 std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event()); 356 std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event());
353 rtp_event->set_timestamp_us(clock_->TimeInMicroseconds()); 357 rtp_event->set_timestamp_us(clock_->TimeInMicroseconds());
354 rtp_event->set_type(rtclog::Event::RTP_EVENT); 358 rtp_event->set_type(rtclog::Event::RTP_EVENT);
355 rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket); 359 rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket);
356 rtp_event->mutable_rtp_packet()->set_type(ConvertMediaType(media_type)); 360 rtp_event->mutable_rtp_packet()->set_type(ConvertMediaType(media_type));
357 rtp_event->mutable_rtp_packet()->set_packet_length(packet_length); 361 rtp_event->mutable_rtp_packet()->set_packet_length(packet_length);
358 rtp_event->mutable_rtp_packet()->set_header(header, header_length); 362 rtp_event->mutable_rtp_packet()->set_header(header, header_length);
359 if (!event_queue_.Insert(&rtp_event)) { 363 StoreEvent(&rtp_event);
360 LOG(LS_ERROR) << "RTP queue full. Not logging RTP packet.";
361 }
362 } 364 }
363 365
364 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction, 366 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction,
365 MediaType media_type, 367 MediaType media_type,
366 const uint8_t* packet, 368 const uint8_t* packet,
367 size_t length) { 369 size_t length) {
368 std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event()); 370 std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event());
369 rtcp_event->set_timestamp_us(clock_->TimeInMicroseconds()); 371 rtcp_event->set_timestamp_us(clock_->TimeInMicroseconds());
370 rtcp_event->set_type(rtclog::Event::RTCP_EVENT); 372 rtcp_event->set_type(rtclog::Event::RTCP_EVENT);
371 rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket); 373 rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 FALLTHROUGH(); 411 FALLTHROUGH();
410 default: 412 default:
411 // We don't log sender descriptions, application defined messages 413 // We don't log sender descriptions, application defined messages
412 // or message blocks of unknown type. 414 // or message blocks of unknown type.
413 break; 415 break;
414 } 416 }
415 417
416 block_begin += block_size; 418 block_begin += block_size;
417 } 419 }
418 rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length); 420 rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length);
419 if (!event_queue_.Insert(&rtcp_event)) { 421 StoreEvent(&rtcp_event);
420 LOG(LS_ERROR) << "RTCP queue full. Not logging RTCP packet.";
421 }
422 } 422 }
423 423
424 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) { 424 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) {
425 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); 425 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
426 event->set_timestamp_us(clock_->TimeInMicroseconds()); 426 event->set_timestamp_us(clock_->TimeInMicroseconds());
427 event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT); 427 event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT);
428 auto playout_event = event->mutable_audio_playout_event(); 428 auto playout_event = event->mutable_audio_playout_event();
429 playout_event->set_local_ssrc(ssrc); 429 playout_event->set_local_ssrc(ssrc);
430 if (!event_queue_.Insert(&event)) { 430 StoreEvent(&event);
431 LOG(LS_ERROR) << "Playout queue full. Not logging ACM playout.";
432 }
433 } 431 }
434 432
435 void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate, 433 void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate,
436 uint8_t fraction_loss, 434 uint8_t fraction_loss,
437 int32_t total_packets) { 435 int32_t total_packets) {
438 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); 436 std::unique_ptr<rtclog::Event> event(new rtclog::Event());
439 event->set_timestamp_us(clock_->TimeInMicroseconds()); 437 event->set_timestamp_us(clock_->TimeInMicroseconds());
440 event->set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT); 438 event->set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT);
441 auto bwe_event = event->mutable_bwe_packet_loss_event(); 439 auto bwe_event = event->mutable_bwe_packet_loss_event();
442 bwe_event->set_bitrate(bitrate); 440 bwe_event->set_bitrate(bitrate);
443 bwe_event->set_fraction_loss(fraction_loss); 441 bwe_event->set_fraction_loss(fraction_loss);
444 bwe_event->set_total_packets(total_packets); 442 bwe_event->set_total_packets(total_packets);
445 if (!event_queue_.Insert(&event)) { 443 StoreEvent(&event);
446 LOG(LS_ERROR) << "BWE loss queue full. Not logging BWE update."; 444 }
445
446 void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event>* event) {
447 if (!event_queue_.Insert(event)) {
448 LOG(LS_ERROR) << "WebRTC event log queue full. Dropping event.";
447 } 449 }
450 end_hibernation_.Set();
448 } 451 }
449 452
450 bool RtcEventLog::ParseRtcEventLog(const std::string& file_name, 453 bool RtcEventLog::ParseRtcEventLog(const std::string& file_name,
451 rtclog::EventStream* result) { 454 rtclog::EventStream* result) {
452 char tmp_buffer[1024]; 455 char tmp_buffer[1024];
453 int bytes_read = 0; 456 int bytes_read = 0;
454 std::unique_ptr<FileWrapper> dump_file(FileWrapper::Create()); 457 std::unique_ptr<FileWrapper> dump_file(FileWrapper::Create());
455 if (dump_file->OpenFile(file_name.c_str(), true) != 0) { 458 if (dump_file->OpenFile(file_name.c_str(), true) != 0) {
456 return false; 459 return false;
457 } 460 }
(...skipping 10 matching lines...) Expand all
468 // RtcEventLog member functions. 471 // RtcEventLog member functions.
469 std::unique_ptr<RtcEventLog> RtcEventLog::Create(const Clock* clock) { 472 std::unique_ptr<RtcEventLog> RtcEventLog::Create(const Clock* clock) {
470 #ifdef ENABLE_RTC_EVENT_LOG 473 #ifdef ENABLE_RTC_EVENT_LOG
471 return std::unique_ptr<RtcEventLog>(new RtcEventLogImpl(clock)); 474 return std::unique_ptr<RtcEventLog>(new RtcEventLogImpl(clock));
472 #else 475 #else
473 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl()); 476 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl());
474 #endif // ENABLE_RTC_EVENT_LOG 477 #endif // ENABLE_RTC_EVENT_LOG
475 } 478 }
476 479
477 } // namespace webrtc 480 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/call/rtc_event_log_helper_thread.h » ('j') | webrtc/call/rtc_event_log_helper_thread.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698