1364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius/* 2364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * 4364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * Use of this source code is governed by a BSD-style license 5364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * that can be found in the LICENSE file in the root of the source 6364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * tree. An additional intellectual property rights grant can be found 7364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * in the file PATENTS. All contributing project authors may 8364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius * be found in the AUTHORS file in the root of the source tree. 9364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius */ 10364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 115c389d3e09646c0e2ed76d5ccb37a3419a09eb6aPeter Boström#include "webrtc/call/rtc_event_log.h" 12364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 13364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#include <deque> 141adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius#include <vector> 15364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 16364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#include "webrtc/base/checks.h" 17364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#include "webrtc/base/criticalsection.h" 18364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#include "webrtc/base/thread_annotations.h" 19364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#include "webrtc/call.h" 20d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 212f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 22d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 2398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/clock.h" 2498f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/file_wrapper.h" 25364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 26364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#ifdef ENABLE_RTC_EVENT_LOG 27364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// Files generated at build-time by the protobuf compiler. 28364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#ifdef WEBRTC_ANDROID_PLATFORM_BUILD 295c389d3e09646c0e2ed76d5ccb37a3419a09eb6aPeter Boström#include "external/webrtc/webrtc/call/rtc_event_log.pb.h" 30364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#else 315c389d3e09646c0e2ed76d5ccb37a3419a09eb6aPeter Boström#include "webrtc/call/rtc_event_log.pb.h" 32364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#endif 33364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#endif 34364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 35364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusnamespace webrtc { 36364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 37364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#ifndef ENABLE_RTC_EVENT_LOG 38364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 39364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// No-op implementation if flag is not set. 40364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusclass RtcEventLogImpl final : public RtcEventLog { 41364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius public: 421adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius void SetBufferDuration(int64_t buffer_duration_us) override {} 43364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void StartLogging(const std::string& file_name, int duration_ms) override {} 44112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc bool StartLogging(rtc::PlatformFile log_file) override { return false; } 45364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void StopLogging(void) override {} 46364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogVideoReceiveStreamConfig( 47364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const VideoReceiveStream::Config& config) override {} 48364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogVideoSendStreamConfig( 49364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const VideoSendStream::Config& config) override {} 50364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogRtpHeader(bool incoming, 51364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius MediaType media_type, 52364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const uint8_t* header, 532f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius size_t packet_length) override {} 54364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogRtcpPacket(bool incoming, 55364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius MediaType media_type, 56364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const uint8_t* packet, 57364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius size_t length) override {} 58ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen void LogAudioPlayout(uint32_t ssrc) override {} 59006d93d3c679ffd15223c327d649066a72400639terelius void LogBwePacketLossEvent(int32_t bitrate, 60006d93d3c679ffd15223c327d649066a72400639terelius uint8_t fraction_loss, 61006d93d3c679ffd15223c327d649066a72400639terelius int32_t total_packets) override {} 62364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius}; 63364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 64364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#else // ENABLE_RTC_EVENT_LOG is defined 65364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 66364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusclass RtcEventLogImpl final : public RtcEventLog { 67364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius public: 681adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius RtcEventLogImpl(); 691adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius 701adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius void SetBufferDuration(int64_t buffer_duration_us) override; 71364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void StartLogging(const std::string& file_name, int duration_ms) override; 72112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc bool StartLogging(rtc::PlatformFile log_file) override; 73364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void StopLogging() override; 74364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogVideoReceiveStreamConfig( 75364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const VideoReceiveStream::Config& config) override; 76364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogVideoSendStreamConfig(const VideoSendStream::Config& config) override; 77364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogRtpHeader(bool incoming, 78364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius MediaType media_type, 79364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const uint8_t* header, 802f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius size_t packet_length) override; 81364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void LogRtcpPacket(bool incoming, 82364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius MediaType media_type, 83364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const uint8_t* packet, 84364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius size_t length) override; 85ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen void LogAudioPlayout(uint32_t ssrc) override; 86006d93d3c679ffd15223c327d649066a72400639terelius void LogBwePacketLossEvent(int32_t bitrate, 87006d93d3c679ffd15223c327d649066a72400639terelius uint8_t fraction_loss, 88006d93d3c679ffd15223c327d649066a72400639terelius int32_t total_packets) override; 89364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 90364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius private: 91112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc // Starts logging. This function assumes the file_ has been opened succesfully 92112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc // and that the start_time_us_ and _duration_us_ have been set. 93112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc void StartLoggingLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_); 94364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Stops logging and clears the stored data and buffers. 95364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void StopLoggingLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_); 96364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Adds a new event to the logfile if logging is active, or adds it to the 97364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // list of recent log events otherwise. 98364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void HandleEvent(rtclog::Event* event) EXCLUSIVE_LOCKS_REQUIRED(crit_); 99364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Writes the event to the file. Note that this will destroy the state of the 100364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // input argument. 101364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void StoreToFile(rtclog::Event* event) EXCLUSIVE_LOCKS_REQUIRED(crit_); 102364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Adds the event to the list of recent events, and removes any events that 103364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // are too old and no longer fall in the time window. 104364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius void AddRecentEvent(const rtclog::Event& event) 105364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius EXCLUSIVE_LOCKS_REQUIRED(crit_); 106364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 107364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CriticalSection crit_; 108112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::scoped_ptr<FileWrapper> file_ GUARDED_BY(crit_) = 109112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::scoped_ptr<FileWrapper>(FileWrapper::Create()); 110112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::PlatformFile platform_file_ GUARDED_BY(crit_) = 111112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::kInvalidPlatformFileValue; 112364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::EventStream stream_ GUARDED_BY(crit_); 113364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius std::deque<rtclog::Event> recent_log_events_ GUARDED_BY(crit_); 1141adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius std::vector<rtclog::Event> config_events_ GUARDED_BY(crit_); 1151adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius 1161adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius // Microseconds to record log events, before starting the actual log. 1171adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius int64_t buffer_duration_us_ GUARDED_BY(crit_); 1181adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius bool currently_logging_ GUARDED_BY(crit_); 1191adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius int64_t start_time_us_ GUARDED_BY(crit_); 1201adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius int64_t duration_us_ GUARDED_BY(crit_); 1211adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius const Clock* const clock_; 122364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius}; 123364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 124364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusnamespace { 125364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// The functions in this namespace convert enums from the runtime format 126364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// that the rest of the WebRtc project can use, to the corresponding 127364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// serialized enum which is defined by the protobuf. 128364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 129364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// Do not add default return values to the conversion functions in this 130364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// unnamed namespace. The intention is to make the compiler warn if anyone 131364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// adds unhandled new events/modes/etc. 132364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 133da903eaabbb6c6830efcafc3c2ade1d36f511e43pbosrtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) { 134364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius switch (rtcp_mode) { 135da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos case RtcpMode::kCompound: 136364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::VideoReceiveConfig::RTCP_COMPOUND; 137da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos case RtcpMode::kReducedSize: 138364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE; 139da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos case RtcpMode::kOff: 140da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos RTC_NOTREACHED(); 141da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos return rtclog::VideoReceiveConfig::RTCP_COMPOUND; 142364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 143364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius RTC_NOTREACHED(); 144364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::VideoReceiveConfig::RTCP_COMPOUND; 145364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 146364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 147364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusrtclog::MediaType ConvertMediaType(MediaType media_type) { 148364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius switch (media_type) { 149364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius case MediaType::ANY: 150364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::MediaType::ANY; 151364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius case MediaType::AUDIO: 152364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::MediaType::AUDIO; 153364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius case MediaType::VIDEO: 154364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::MediaType::VIDEO; 155364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius case MediaType::DATA: 156364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::MediaType::DATA; 157364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 158364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius RTC_NOTREACHED(); 159364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtclog::ANY; 160364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 161364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 162364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} // namespace 163364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 1641adce14c87f8316b5c3f4ee16b8f573c8bf14761tereliusnamespace { 1651adce14c87f8316b5c3f4ee16b8f573c8bf14761tereliusbool IsConfigEvent(const rtclog::Event& event) { 1661adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius rtclog::Event_EventType event_type = event.type(); 1671adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius return event_type == rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT || 1681adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius event_type == rtclog::Event::VIDEO_SENDER_CONFIG_EVENT || 1691adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius event_type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT || 1701adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius event_type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT; 1711adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius} 1721adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius} // namespace 1731adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius 174364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// RtcEventLogImpl member functions. 1751adce14c87f8316b5c3f4ee16b8f573c8bf14761tereliusRtcEventLogImpl::RtcEventLogImpl() 1761adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius : file_(FileWrapper::Create()), 1771adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius stream_(), 1781adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius buffer_duration_us_(10000000), 1791adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius currently_logging_(false), 1801adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius start_time_us_(0), 1811adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius duration_us_(0), 1821adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius clock_(Clock::GetRealTimeClock()) { 1831adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius} 1841adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius 1851adce14c87f8316b5c3f4ee16b8f573c8bf14761tereliusvoid RtcEventLogImpl::SetBufferDuration(int64_t buffer_duration_us) { 1861adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius rtc::CritScope lock(&crit_); 1871adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius buffer_duration_us_ = buffer_duration_us; 1881adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius} 189364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 190364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::StartLogging(const std::string& file_name, 191364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius int duration_ms) { 192364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 193364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (currently_logging_) { 194364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StopLoggingLocked(); 195364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 196364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (file_->OpenFile(file_name.c_str(), false) != 0) { 197364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return; 198364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 199364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius start_time_us_ = clock_->TimeInMicroseconds(); 200364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius duration_us_ = static_cast<int64_t>(duration_ms) * 1000; 201112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc StartLoggingLocked(); 202112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc} 203112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc 204112a3d81db02d349af0ce6c0827da6d8fbc421a8ivocbool RtcEventLogImpl::StartLogging(rtc::PlatformFile log_file) { 205112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::CritScope lock(&crit_); 206112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc 207112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc if (currently_logging_) { 208112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc StopLoggingLocked(); 209112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc } 210112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc RTC_DCHECK(platform_file_ == rtc::kInvalidPlatformFileValue); 211112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc 212112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc FILE* file_stream = rtc::FdopenPlatformFileForWriting(log_file); 213112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc if (!file_stream) { 214112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::ClosePlatformFile(log_file); 215112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc return false; 216112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc } 217112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc 218112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc if (file_->OpenFromFileHandle(file_stream, true, false) != 0) { 219112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::ClosePlatformFile(log_file); 220112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc return false; 221112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc } 222112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc platform_file_ = log_file; 223112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc // Set the start time and duration to keep logging for 10 minutes. 224112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc start_time_us_ = clock_->TimeInMicroseconds(); 225112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc duration_us_ = 10 * 60 * 1000000; 226112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc StartLoggingLocked(); 227112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc return true; 228112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc} 229112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc 230112a3d81db02d349af0ce6c0827da6d8fbc421a8ivocvoid RtcEventLogImpl::StartLoggingLocked() { 231112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc currently_logging_ = true; 2321adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius 2331adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius // Write all old configuration events to the log file. 2341adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius for (auto& event : config_events_) { 2351adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius StoreToFile(&event); 2361adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius } 2371adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius // Write all recent configuration events to the log file, and 2381adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius // write all other recent events to the log file, ignoring any old events. 239364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (auto& event : recent_log_events_) { 2401adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius if (IsConfigEvent(event)) { 2411adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius StoreToFile(&event); 2421adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius config_events_.push_back(event); 2431adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius } else if (event.timestamp_us() >= start_time_us_ - buffer_duration_us_) { 244364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StoreToFile(&event); 245364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 246364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 247364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius recent_log_events_.clear(); 248364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Write a LOG_START event to the file. 249364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event start_event; 250364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius start_event.set_timestamp_us(start_time_us_); 251301aaed813b55e28c12e89bb58ae8f8d8136c47eIvo Creusen start_event.set_type(rtclog::Event::LOG_START); 252364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StoreToFile(&start_event); 253364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 254364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 255364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::StopLogging() { 256364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 257364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StopLoggingLocked(); 258364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 259364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 260364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::LogVideoReceiveStreamConfig( 261364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const VideoReceiveStream::Config& config) { 262364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 263364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 264364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event event; 265006d93d3c679ffd15223c327d649066a72400639terelius event.set_timestamp_us(clock_->TimeInMicroseconds()); 266364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius event.set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT); 267364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 268364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::VideoReceiveConfig* receiver_config = 269364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius event.mutable_video_receiver_config(); 270364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius receiver_config->set_remote_ssrc(config.rtp.remote_ssrc); 271364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius receiver_config->set_local_ssrc(config.rtp.local_ssrc); 272364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 273364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius receiver_config->set_rtcp_mode(ConvertRtcpMode(config.rtp.rtcp_mode)); 274364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius receiver_config->set_remb(config.rtp.remb); 275364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 276364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (const auto& kv : config.rtp.rtx) { 277364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::RtxMap* rtx = receiver_config->add_rtx_map(); 278364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtx->set_payload_type(kv.first); 279364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtx->mutable_config()->set_rtx_ssrc(kv.second.ssrc); 280364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtx->mutable_config()->set_rtx_payload_type(kv.second.payload_type); 281364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 282364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 283364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (const auto& e : config.rtp.extensions) { 284364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::RtpHeaderExtension* extension = 285364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius receiver_config->add_header_extensions(); 286364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius extension->set_name(e.name); 287364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius extension->set_id(e.id); 288364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 289364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 290364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (const auto& d : config.decoders) { 291364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::DecoderConfig* decoder = receiver_config->add_decoders(); 292364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius decoder->set_name(d.payload_name); 293364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius decoder->set_payload_type(d.payload_type); 294364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 295364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius HandleEvent(&event); 296364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 297364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 298364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::LogVideoSendStreamConfig( 299364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const VideoSendStream::Config& config) { 300364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 301364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 302364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event event; 303006d93d3c679ffd15223c327d649066a72400639terelius event.set_timestamp_us(clock_->TimeInMicroseconds()); 304364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius event.set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT); 305364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 306364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::VideoSendConfig* sender_config = event.mutable_video_sender_config(); 307364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 308364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (const auto& ssrc : config.rtp.ssrcs) { 309364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius sender_config->add_ssrcs(ssrc); 310364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 311364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 312364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (const auto& e : config.rtp.extensions) { 313364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::RtpHeaderExtension* extension = 314364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius sender_config->add_header_extensions(); 315364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius extension->set_name(e.name); 316364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius extension->set_id(e.id); 317364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 318364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 319364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius for (const auto& rtx_ssrc : config.rtp.rtx.ssrcs) { 320364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius sender_config->add_rtx_ssrcs(rtx_ssrc); 321364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 322364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius sender_config->set_rtx_payload_type(config.rtp.rtx.payload_type); 323364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 324364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::EncoderConfig* encoder = sender_config->mutable_encoder(); 325364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius encoder->set_name(config.encoder_settings.payload_name); 326364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius encoder->set_payload_type(config.encoder_settings.payload_type); 327364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius HandleEvent(&event); 328364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 329364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 330364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::LogRtpHeader(bool incoming, 331364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius MediaType media_type, 332364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const uint8_t* header, 3332f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius size_t packet_length) { 3342f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius // Read header length (in bytes) from packet data. 3352f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius if (packet_length < 12u) { 3362f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius return; // Don't read outside the packet. 3372f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius } 3382f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius const bool x = (header[0] & 0x10) != 0; 3392f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius const uint8_t cc = header[0] & 0x0f; 3402f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius size_t header_length = 12u + cc * 4u; 3412f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius 3422f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius if (x) { 3432f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius if (packet_length < 12u + cc * 4u + 4u) { 3442f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius return; // Don't read outside the packet. 3452f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius } 3462f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4); 3472f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius header_length += (x_len + 1) * 4; 3482f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius } 3492f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius 350364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 351364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event rtp_event; 352006d93d3c679ffd15223c327d649066a72400639terelius rtp_event.set_timestamp_us(clock_->TimeInMicroseconds()); 353364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtp_event.set_type(rtclog::Event::RTP_EVENT); 354364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtp_event.mutable_rtp_packet()->set_incoming(incoming); 355364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtp_event.mutable_rtp_packet()->set_type(ConvertMediaType(media_type)); 3562f9fd5ddb9097054b71fce20ba24bc34b2f084c0terelius rtp_event.mutable_rtp_packet()->set_packet_length(packet_length); 357364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtp_event.mutable_rtp_packet()->set_header(header, header_length); 358364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius HandleEvent(&rtp_event); 359364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 360364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 361364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::LogRtcpPacket(bool incoming, 362364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius MediaType media_type, 363364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius const uint8_t* packet, 364364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius size_t length) { 365364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 366364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event rtcp_event; 367006d93d3c679ffd15223c327d649066a72400639terelius rtcp_event.set_timestamp_us(clock_->TimeInMicroseconds()); 368364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtcp_event.set_type(rtclog::Event::RTCP_EVENT); 369364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtcp_event.mutable_rtcp_packet()->set_incoming(incoming); 370364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtcp_event.mutable_rtcp_packet()->set_type(ConvertMediaType(media_type)); 371d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius 372d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius RTCPUtility::RtcpCommonHeader header; 373d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius const uint8_t* block_begin = packet; 374d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius const uint8_t* packet_end = packet + length; 375d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius RTC_DCHECK(length <= IP_PACKET_SIZE); 376d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius uint8_t buffer[IP_PACKET_SIZE]; 377d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius uint32_t buffer_length = 0; 378d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius while (block_begin < packet_end) { 379d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius if (!RtcpParseCommonHeader(block_begin, packet_end - block_begin, 380d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius &header)) { 381d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius break; // Incorrect message header. 382d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius } 383d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius uint32_t block_size = header.BlockSize(); 384d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius switch (header.packet_type) { 385d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_SR: 386d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 387d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_RR: 388d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 389d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_BYE: 390d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 391d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_IJ: 392d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 393d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_RTPFB: 394d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 395d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_PSFB: 396d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 397d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_XR: 398d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius // We log sender reports, receiver reports, bye messages 399d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius // inter-arrival jitter, third-party loss reports, payload-specific 400d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius // feedback and extended reports. 401d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius memcpy(buffer + buffer_length, block_begin, block_size); 402d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius buffer_length += block_size; 403d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius break; 404d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_SDES: 405d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 406d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius case RTCPUtility::PT_APP: 407d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius FALLTHROUGH(); 408d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius default: 409d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius // We don't log sender descriptions, application defined messages 410d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius // or message blocks of unknown type. 411d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius break; 412d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius } 413d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius 414d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius block_begin += block_size; 415d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius } 416d66daa2d2f9fe8ea2bd0e912e2d8c6c4f388f14eterelius rtcp_event.mutable_rtcp_packet()->set_packet_data(buffer, buffer_length); 417364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius HandleEvent(&rtcp_event); 418364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 419364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 420ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusenvoid RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) { 421364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::CritScope lock(&crit_); 422364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event event; 423006d93d3c679ffd15223c327d649066a72400639terelius event.set_timestamp_us(clock_->TimeInMicroseconds()); 424301aaed813b55e28c12e89bb58ae8f8d8136c47eIvo Creusen event.set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT); 425301aaed813b55e28c12e89bb58ae8f8d8136c47eIvo Creusen auto playout_event = event.mutable_audio_playout_event(); 426301aaed813b55e28c12e89bb58ae8f8d8136c47eIvo Creusen playout_event->set_local_ssrc(ssrc); 427364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius HandleEvent(&event); 428364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 429364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 430006d93d3c679ffd15223c327d649066a72400639tereliusvoid RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate, 431006d93d3c679ffd15223c327d649066a72400639terelius uint8_t fraction_loss, 432006d93d3c679ffd15223c327d649066a72400639terelius int32_t total_packets) { 433006d93d3c679ffd15223c327d649066a72400639terelius rtc::CritScope lock(&crit_); 434006d93d3c679ffd15223c327d649066a72400639terelius rtclog::Event event; 435006d93d3c679ffd15223c327d649066a72400639terelius event.set_timestamp_us(clock_->TimeInMicroseconds()); 436006d93d3c679ffd15223c327d649066a72400639terelius event.set_type(rtclog::Event::BWE_PACKET_LOSS_EVENT); 437006d93d3c679ffd15223c327d649066a72400639terelius auto bwe_event = event.mutable_bwe_packet_loss_event(); 438006d93d3c679ffd15223c327d649066a72400639terelius bwe_event->set_bitrate(bitrate); 439006d93d3c679ffd15223c327d649066a72400639terelius bwe_event->set_fraction_loss(fraction_loss); 440006d93d3c679ffd15223c327d649066a72400639terelius bwe_event->set_total_packets(total_packets); 441006d93d3c679ffd15223c327d649066a72400639terelius HandleEvent(&event); 442006d93d3c679ffd15223c327d649066a72400639terelius} 443006d93d3c679ffd15223c327d649066a72400639terelius 444364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::StopLoggingLocked() { 445364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (currently_logging_) { 446364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius currently_logging_ = false; 447301aaed813b55e28c12e89bb58ae8f8d8136c47eIvo Creusen // Create a LogEnd event 448364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::Event event; 449006d93d3c679ffd15223c327d649066a72400639terelius event.set_timestamp_us(clock_->TimeInMicroseconds()); 450301aaed813b55e28c12e89bb58ae8f8d8136c47eIvo Creusen event.set_type(rtclog::Event::LOG_END); 451364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Store the event and close the file 45291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(file_->Open()); 453364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StoreToFile(&event); 454364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius file_->CloseFile(); 455112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc if (platform_file_ != rtc::kInvalidPlatformFileValue) { 456112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc rtc::ClosePlatformFile(platform_file_); 457112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc platform_file_ = rtc::kInvalidPlatformFileValue; 458112a3d81db02d349af0ce6c0827da6d8fbc421a8ivoc } 459364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 46091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!file_->Open()); 461364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius stream_.Clear(); 462364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 463364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 464364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::HandleEvent(rtclog::Event* event) { 465364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (currently_logging_) { 466364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (clock_->TimeInMicroseconds() < start_time_us_ + duration_us_) { 467364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StoreToFile(event); 468364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return; 469364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 470364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius StopLoggingLocked(); 471364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 472364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius AddRecentEvent(*event); 473364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 474364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 475364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::StoreToFile(rtclog::Event* event) { 476364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Reuse the same object at every log event. 477364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (stream_.stream_size() < 1) { 478364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius stream_.add_stream(); 479364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 48091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK_EQ(stream_.stream_size(), 1); 481364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius stream_.mutable_stream(0)->Swap(event); 482364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // TODO(terelius): Doesn't this create a new EventStream per event? 483364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius // Is this guaranteed to work e.g. in future versions of protobuf? 484364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius std::string dump_buffer; 485364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius stream_.SerializeToString(&dump_buffer); 486364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius file_->Write(dump_buffer.data(), dump_buffer.size()); 487364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 488364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 489364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusvoid RtcEventLogImpl::AddRecentEvent(const rtclog::Event& event) { 490364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius recent_log_events_.push_back(event); 491364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius while (recent_log_events_.front().timestamp_us() < 4921adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius event.timestamp_us() - buffer_duration_us_) { 4931adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius if (IsConfigEvent(recent_log_events_.front())) { 4941adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius config_events_.push_back(recent_log_events_.front()); 4951adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius } 496364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius recent_log_events_.pop_front(); 497364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 498364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 499364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 500364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusbool RtcEventLog::ParseRtcEventLog(const std::string& file_name, 501364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtclog::EventStream* result) { 502364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius char tmp_buffer[1024]; 503364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius int bytes_read = 0; 504364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius rtc::scoped_ptr<FileWrapper> dump_file(FileWrapper::Create()); 505364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius if (dump_file->OpenFile(file_name.c_str(), true) != 0) { 506364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return false; 507364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 508364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius std::string dump_buffer; 509364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) { 510364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius dump_buffer.append(tmp_buffer, bytes_read); 511364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius } 512364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius dump_file->CloseFile(); 513364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return result->ParseFromString(dump_buffer); 514364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 515364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 516364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius#endif // ENABLE_RTC_EVENT_LOG 517364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius 518364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius// RtcEventLog member functions. 519364118518fda145434e9405b619749e8f2ff70c7Bjorn Tereliusrtc::scoped_ptr<RtcEventLog> RtcEventLog::Create() { 520364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius return rtc::scoped_ptr<RtcEventLog>(new RtcEventLogImpl()); 521364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} 5221adce14c87f8316b5c3f4ee16b8f573c8bf14761terelius 523364118518fda145434e9405b619749e8f2ff70c7Bjorn Terelius} // namespace webrtc 524