| OLD | NEW |
| 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 |
| 11 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | 11 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" |
| 12 | 12 |
| 13 #include <atomic> | 13 #include <atomic> |
| 14 #include <deque> | 14 #include <deque> |
| 15 #include <functional> | 15 #include <functional> |
| 16 #include <limits> | 16 #include <limits> |
| 17 #include <memory> | 17 #include <memory> |
| 18 #include <utility> | 18 #include <utility> |
| 19 #include <vector> | 19 #include <vector> |
| 20 | 20 |
| 21 #include "webrtc/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h" |
| 22 // TODO(eladalon): Remove events/* when the deprecated functions are removed. |
| 23 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_network_adaptation
.h" |
| 24 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_playout.h" |
| 25 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_receive_stream_con
fig.h" |
| 26 #include "webrtc/logging/rtc_event_log/events/rtc_event_audio_send_stream_config
.h" |
| 27 #include "webrtc/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h
" |
| 28 #include "webrtc/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h" |
| 29 #include "webrtc/logging/rtc_event_log/events/rtc_event_logging_started.h" |
| 30 #include "webrtc/logging/rtc_event_log/events/rtc_event_logging_stopped.h" |
| 31 #include "webrtc/logging/rtc_event_log/events/rtc_event_probe_cluster_created.h" |
| 32 #include "webrtc/logging/rtc_event_log/events/rtc_event_probe_result_failure.h" |
| 33 #include "webrtc/logging/rtc_event_log/events/rtc_event_probe_result_success.h" |
| 34 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h" |
| 35 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h" |
| 36 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h" |
| 37 #include "webrtc/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h" |
| 38 #include "webrtc/logging/rtc_event_log/events/rtc_event_video_receive_stream_con
fig.h" |
| 39 #include "webrtc/logging/rtc_event_log/events/rtc_event_video_send_stream_config
.h" |
| 21 #include "webrtc/logging/rtc_event_log/rtc_stream_config.h" | 40 #include "webrtc/logging/rtc_event_log/rtc_stream_config.h" |
| 41 // TODO(eladalon): Remove these when deprecated functions are removed. |
| 22 #include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_networ
k_adaptor.h" | 42 #include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_networ
k_adaptor.h" |
| 23 #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" | 43 #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" |
| 24 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 44 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| 25 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 45 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| 26 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" | 46 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" |
| 27 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" | 47 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" |
| 28 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h" | 48 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h" |
| 29 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" | 49 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" |
| 30 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h" | 50 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h" |
| 31 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" | 51 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" |
| 32 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" | 52 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" |
| 33 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" | 53 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" |
| 34 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" | 54 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" |
| 35 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" | 55 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h" |
| 36 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" | 56 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
| 37 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | 57 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| 38 #include "webrtc/rtc_base/checks.h" | 58 #include "webrtc/rtc_base/checks.h" |
| 39 #include "webrtc/rtc_base/constructormagic.h" | 59 #include "webrtc/rtc_base/constructormagic.h" |
| 40 #include "webrtc/rtc_base/event.h" | 60 #include "webrtc/rtc_base/event.h" |
| 41 #include "webrtc/rtc_base/ignore_wundef.h" | |
| 42 #include "webrtc/rtc_base/logging.h" | 61 #include "webrtc/rtc_base/logging.h" |
| 43 #include "webrtc/rtc_base/protobuf_utils.h" | 62 #include "webrtc/rtc_base/protobuf_utils.h" |
| 44 #include "webrtc/rtc_base/ptr_util.h" | 63 #include "webrtc/rtc_base/ptr_util.h" |
| 45 #include "webrtc/rtc_base/sequenced_task_checker.h" | 64 #include "webrtc/rtc_base/sequenced_task_checker.h" |
| 46 #include "webrtc/rtc_base/task_queue.h" | 65 #include "webrtc/rtc_base/task_queue.h" |
| 47 #include "webrtc/rtc_base/thread_annotations.h" | 66 #include "webrtc/rtc_base/thread_annotations.h" |
| 48 #include "webrtc/rtc_base/timeutils.h" | 67 #include "webrtc/rtc_base/timeutils.h" |
| 68 // TODO(eladalon): Remove this when output is modularized away. |
| 49 #include "webrtc/system_wrappers/include/file_wrapper.h" | 69 #include "webrtc/system_wrappers/include/file_wrapper.h" |
| 50 #include "webrtc/typedefs.h" | 70 #include "webrtc/typedefs.h" |
| 51 | 71 |
| 52 #ifdef ENABLE_RTC_EVENT_LOG | |
| 53 // *.pb.h files are generated at build-time by the protobuf compiler. | |
| 54 RTC_PUSH_IGNORING_WUNDEF() | |
| 55 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD | |
| 56 #include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h" | |
| 57 #else | |
| 58 #include "webrtc/logging/rtc_event_log/rtc_event_log.pb.h" | |
| 59 #endif | |
| 60 RTC_POP_IGNORING_WUNDEF() | |
| 61 #endif | |
| 62 | |
| 63 namespace webrtc { | 72 namespace webrtc { |
| 64 | 73 |
| 65 #ifdef ENABLE_RTC_EVENT_LOG | 74 #ifdef ENABLE_RTC_EVENT_LOG |
| 66 | 75 |
| 67 namespace { | 76 namespace { |
| 68 const int kEventsInHistory = 10000; | 77 const int kEventsInHistory = 10000; |
| 69 | 78 |
| 70 bool IsConfigEvent(const rtclog::Event& event) { | |
| 71 rtclog::Event_EventType event_type = event.type(); | |
| 72 return event_type == rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT || | |
| 73 event_type == rtclog::Event::VIDEO_SENDER_CONFIG_EVENT || | |
| 74 event_type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT || | |
| 75 event_type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT; | |
| 76 } | |
| 77 | |
| 78 // Observe a limit on the number of concurrent logs, so as not to run into | 79 // Observe a limit on the number of concurrent logs, so as not to run into |
| 79 // OS-imposed limits on open files and/or threads/task-queues. | 80 // OS-imposed limits on open files and/or threads/task-queues. |
| 80 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. | 81 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. |
| 81 std::atomic<int> rtc_event_log_count(0); | 82 std::atomic<int> rtc_event_log_count(0); |
| 82 | 83 |
| 83 // TODO(eladalon): This class exists because C++11 doesn't allow transferring a | 84 // TODO(eladalon): This class exists because C++11 doesn't allow transferring a |
| 84 // unique_ptr to a lambda (a copy constructor is required). We should get | 85 // unique_ptr to a lambda (a copy constructor is required). We should get |
| 85 // rid of this when we move to C++14. | 86 // rid of this when we move to C++14. |
| 86 template <typename T> | 87 template <typename T> |
| 87 class ResourceOwningTask final : public rtc::QueuedTask { | 88 class ResourceOwningTask final : public rtc::QueuedTask { |
| 88 public: | 89 public: |
| 89 ResourceOwningTask(std::unique_ptr<T> resource, | 90 ResourceOwningTask(std::unique_ptr<T> resource, |
| 90 std::function<void(std::unique_ptr<T>)> handler) | 91 std::function<void(std::unique_ptr<T>)> handler) |
| 91 : resource_(std::move(resource)), handler_(handler) {} | 92 : resource_(std::move(resource)), handler_(handler) {} |
| 92 | 93 |
| 93 bool Run() override { | 94 bool Run() override { |
| 94 handler_(std::move(resource_)); | 95 handler_(std::move(resource_)); |
| 95 return true; | 96 return true; |
| 96 } | 97 } |
| 97 | 98 |
| 98 private: | 99 private: |
| 99 std::unique_ptr<T> resource_; | 100 std::unique_ptr<T> resource_; |
| 100 std::function<void(std::unique_ptr<T>)> handler_; | 101 std::function<void(std::unique_ptr<T>)> handler_; |
| 101 }; | 102 }; |
| 103 |
| 104 std::unique_ptr<RtcEventLogEncoder> CreateEncoder(EncodingType type) { |
| 105 switch (type) { |
| 106 case EncodingType::Legacy: |
| 107 return rtc::MakeUnique<RtcEventLogEncoderLegacy>(); |
| 108 default: |
| 109 LOG(LS_ERROR) << "Unknown RtcEventLog encoder type (" << int(type) << ")"; |
| 110 RTC_NOTREACHED(); |
| 111 } |
| 112 } |
| 102 } // namespace | 113 } // namespace |
| 103 | 114 |
| 104 class RtcEventLogImpl final : public RtcEventLog { | 115 class RtcEventLogImpl final : public RtcEventLog { |
| 105 public: | 116 public: |
| 106 RtcEventLogImpl(); | 117 explicit RtcEventLogImpl(std::unique_ptr<RtcEventLogEncoder> event_encoder); |
| 107 ~RtcEventLogImpl() override; | 118 ~RtcEventLogImpl() override; |
| 108 | 119 |
| 109 bool StartLogging(const std::string& file_name, | 120 bool StartLogging(const std::string& file_name, |
| 110 int64_t max_size_bytes) override; | 121 int64_t max_size_bytes) override; |
| 111 bool StartLogging(rtc::PlatformFile platform_file, | 122 bool StartLogging(rtc::PlatformFile platform_file, |
| 112 int64_t max_size_bytes) override; | 123 int64_t max_size_bytes) override; |
| 113 void StopLogging() override; | 124 void StopLogging() override; |
| 125 void Log(std::unique_ptr<RtcEvent> event) override; |
| 114 void LogVideoReceiveStreamConfig(const rtclog::StreamConfig& config) override; | 126 void LogVideoReceiveStreamConfig(const rtclog::StreamConfig& config) override; |
| 115 void LogVideoSendStreamConfig(const rtclog::StreamConfig& config) override; | 127 void LogVideoSendStreamConfig(const rtclog::StreamConfig& config) override; |
| 116 void LogAudioReceiveStreamConfig(const rtclog::StreamConfig& config) override; | 128 void LogAudioReceiveStreamConfig(const rtclog::StreamConfig& config) override; |
| 117 void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) override; | 129 void LogAudioSendStreamConfig(const rtclog::StreamConfig& config) override; |
| 118 // TODO(terelius): This can be removed as soon as the interface has been | 130 // TODO(terelius): This can be removed as soon as the interface has been |
| 119 // updated. | 131 // updated. |
| 120 void LogRtpHeader(PacketDirection direction, | 132 void LogRtpHeader(PacketDirection direction, |
| 121 const uint8_t* header, | 133 const uint8_t* header, |
| 122 size_t packet_length) override; | 134 size_t packet_length) override; |
| 123 // TODO(terelius): This can be made private, non-virtual as soon as the | 135 // TODO(terelius): This can be made private, non-virtual as soon as the |
| (...skipping 25 matching lines...) Expand all Loading... |
| 149 int min_probes, | 161 int min_probes, |
| 150 int min_bytes) override; | 162 int min_bytes) override; |
| 151 void LogProbeResultSuccess(int id, int bitrate_bps) override; | 163 void LogProbeResultSuccess(int id, int bitrate_bps) override; |
| 152 void LogProbeResultFailure(int id, | 164 void LogProbeResultFailure(int id, |
| 153 ProbeFailureReason failure_reason) override; | 165 ProbeFailureReason failure_reason) override; |
| 154 | 166 |
| 155 private: | 167 private: |
| 156 void StartLoggingInternal(std::unique_ptr<FileWrapper> file, | 168 void StartLoggingInternal(std::unique_ptr<FileWrapper> file, |
| 157 int64_t max_size_bytes); | 169 int64_t max_size_bytes); |
| 158 | 170 |
| 159 void StoreEvent(std::unique_ptr<rtclog::Event> event); | |
| 160 void LogProbeResult(int id, | |
| 161 rtclog::BweProbeResult::ResultType result, | |
| 162 int bitrate_bps); | |
| 163 | |
| 164 // Appends an event to the output protobuf string, returning true on success. | 171 // Appends an event to the output protobuf string, returning true on success. |
| 165 // Fails and returns false in case the limit on output size prevents the | 172 // Fails and returns false in case the limit on output size prevents the |
| 166 // event from being added; in this case, the output string is left unchanged. | 173 // event from being added; in this case, the output string is left unchanged. |
| 167 bool AppendEventToString(rtclog::Event* event, | 174 // The event is encoded before being appended. |
| 175 bool AppendEventToString(const RtcEvent& event, |
| 168 ProtoString* output_string) RTC_WARN_UNUSED_RESULT; | 176 ProtoString* output_string) RTC_WARN_UNUSED_RESULT; |
| 169 | 177 |
| 170 void LogToMemory(std::unique_ptr<rtclog::Event> event); | 178 void LogToMemory(std::unique_ptr<RtcEvent> event); |
| 171 | 179 |
| 172 void StartLogFile(); | 180 void StartLogFile(); |
| 173 void LogToFile(std::unique_ptr<rtclog::Event> event); | 181 void LogToFile(std::unique_ptr<RtcEvent> event); |
| 174 void StopLogFile(int64_t stop_time); | 182 void StopLogFile(int64_t stop_time); |
| 175 | 183 |
| 176 // Make sure that the event log is "managed" - created/destroyed, as well | 184 // Make sure that the event log is "managed" - created/destroyed, as well |
| 177 // as started/stopped - from the same thread/task-queue. | 185 // as started/stopped - from the same thread/task-queue. |
| 178 rtc::SequencedTaskChecker owner_sequence_checker_; | 186 rtc::SequencedTaskChecker owner_sequence_checker_; |
| 179 | 187 |
| 180 // History containing all past configuration events. | 188 // History containing all past configuration events. |
| 181 std::vector<std::unique_ptr<rtclog::Event>> config_history_ | 189 std::vector<std::unique_ptr<RtcEvent>> config_history_ |
| 182 RTC_ACCESS_ON(task_queue_); | 190 RTC_ACCESS_ON(task_queue_); |
| 183 | 191 |
| 184 // History containing the most recent (non-configuration) events (~10s). | 192 // History containing the most recent (non-configuration) events (~10s). |
| 185 std::deque<std::unique_ptr<rtclog::Event>> history_ | 193 std::deque<std::unique_ptr<RtcEvent>> history_ RTC_ACCESS_ON(task_queue_); |
| 186 RTC_ACCESS_ON(task_queue_); | |
| 187 | 194 |
| 188 std::unique_ptr<FileWrapper> file_ RTC_ACCESS_ON(task_queue_); | 195 std::unique_ptr<FileWrapper> file_ RTC_ACCESS_ON(task_queue_); |
| 189 | 196 |
| 190 size_t max_size_bytes_ RTC_ACCESS_ON(task_queue_); | 197 size_t max_size_bytes_ RTC_ACCESS_ON(task_queue_); |
| 191 size_t written_bytes_ RTC_ACCESS_ON(task_queue_); | 198 size_t written_bytes_ RTC_ACCESS_ON(task_queue_); |
| 192 | 199 |
| 200 std::unique_ptr<RtcEventLogEncoder> event_encoder_ RTC_ACCESS_ON(task_queue_); |
| 201 |
| 193 // Keep this last to ensure it destructs first, or else tasks living on the | 202 // Keep this last to ensure it destructs first, or else tasks living on the |
| 194 // queue might access other members after they've been torn down. | 203 // queue might access other members after they've been torn down. |
| 195 rtc::TaskQueue task_queue_; | 204 rtc::TaskQueue task_queue_; |
| 196 | 205 |
| 197 RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogImpl); | 206 RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogImpl); |
| 198 }; | 207 }; |
| 199 | 208 |
| 200 namespace { | 209 RtcEventLogImpl::RtcEventLogImpl( |
| 201 // The functions in this namespace convert enums from the runtime format | 210 std::unique_ptr<RtcEventLogEncoder> event_encoder) |
| 202 // that the rest of the WebRtc project can use, to the corresponding | |
| 203 // serialized enum which is defined by the protobuf. | |
| 204 | |
| 205 rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) { | |
| 206 switch (rtcp_mode) { | |
| 207 case RtcpMode::kCompound: | |
| 208 return rtclog::VideoReceiveConfig::RTCP_COMPOUND; | |
| 209 case RtcpMode::kReducedSize: | |
| 210 return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE; | |
| 211 case RtcpMode::kOff: | |
| 212 RTC_NOTREACHED(); | |
| 213 return rtclog::VideoReceiveConfig::RTCP_COMPOUND; | |
| 214 } | |
| 215 RTC_NOTREACHED(); | |
| 216 return rtclog::VideoReceiveConfig::RTCP_COMPOUND; | |
| 217 } | |
| 218 | |
| 219 rtclog::DelayBasedBweUpdate::DetectorState ConvertDetectorState( | |
| 220 BandwidthUsage state) { | |
| 221 switch (state) { | |
| 222 case BandwidthUsage::kBwNormal: | |
| 223 return rtclog::DelayBasedBweUpdate::BWE_NORMAL; | |
| 224 case BandwidthUsage::kBwUnderusing: | |
| 225 return rtclog::DelayBasedBweUpdate::BWE_UNDERUSING; | |
| 226 case BandwidthUsage::kBwOverusing: | |
| 227 return rtclog::DelayBasedBweUpdate::BWE_OVERUSING; | |
| 228 } | |
| 229 RTC_NOTREACHED(); | |
| 230 return rtclog::DelayBasedBweUpdate::BWE_NORMAL; | |
| 231 } | |
| 232 | |
| 233 rtclog::BweProbeResult::ResultType ConvertProbeResultType( | |
| 234 ProbeFailureReason failure_reason) { | |
| 235 switch (failure_reason) { | |
| 236 case kInvalidSendReceiveInterval: | |
| 237 return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL; | |
| 238 case kInvalidSendReceiveRatio: | |
| 239 return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO; | |
| 240 case kTimeout: | |
| 241 return rtclog::BweProbeResult::TIMEOUT; | |
| 242 } | |
| 243 RTC_NOTREACHED(); | |
| 244 return rtclog::BweProbeResult::SUCCESS; | |
| 245 } | |
| 246 | |
| 247 } // namespace | |
| 248 | |
| 249 RtcEventLogImpl::RtcEventLogImpl() | |
| 250 : file_(FileWrapper::Create()), | 211 : file_(FileWrapper::Create()), |
| 251 max_size_bytes_(std::numeric_limits<decltype(max_size_bytes_)>::max()), | 212 max_size_bytes_(std::numeric_limits<decltype(max_size_bytes_)>::max()), |
| 252 written_bytes_(0), | 213 written_bytes_(0), |
| 214 event_encoder_(std::move(event_encoder)), |
| 253 task_queue_("rtc_event_log") {} | 215 task_queue_("rtc_event_log") {} |
| 254 | 216 |
| 255 RtcEventLogImpl::~RtcEventLogImpl() { | 217 RtcEventLogImpl::~RtcEventLogImpl() { |
| 256 RTC_DCHECK_CALLED_SEQUENTIALLY(&owner_sequence_checker_); | 218 RTC_DCHECK_CALLED_SEQUENTIALLY(&owner_sequence_checker_); |
| 257 | 219 |
| 258 // If we're logging to the file, this will stop that. Blocking function. | 220 // If we're logging to the file, this will stop that. Blocking function. |
| 259 StopLogging(); | 221 StopLogging(); |
| 260 | 222 |
| 261 int count = std::atomic_fetch_sub(&rtc_event_log_count, 1) - 1; | 223 int count = std::atomic_fetch_sub(&rtc_event_log_count, 1) - 1; |
| 262 RTC_DCHECK_GE(count, 0); | 224 RTC_DCHECK_GE(count, 0); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 StopLogFile(stop_time); | 279 StopLogFile(stop_time); |
| 318 } | 280 } |
| 319 file_finished.Set(); | 281 file_finished.Set(); |
| 320 }); | 282 }); |
| 321 | 283 |
| 322 file_finished.Wait(rtc::Event::kForever); | 284 file_finished.Wait(rtc::Event::kForever); |
| 323 | 285 |
| 324 LOG(LS_INFO) << "WebRTC event log successfully stopped."; | 286 LOG(LS_INFO) << "WebRTC event log successfully stopped."; |
| 325 } | 287 } |
| 326 | 288 |
| 289 void RtcEventLogImpl::Log(std::unique_ptr<RtcEvent> event) { |
| 290 RTC_DCHECK(event); |
| 291 |
| 292 auto event_handler = [this](std::unique_ptr<RtcEvent> unencoded_event) { |
| 293 RTC_DCHECK_RUN_ON(&task_queue_); |
| 294 if (file_->is_open()) { |
| 295 LogToFile(std::move(unencoded_event)); |
| 296 } else { |
| 297 LogToMemory(std::move(unencoded_event)); |
| 298 } |
| 299 }; |
| 300 |
| 301 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<RtcEvent>>( |
| 302 std::move(event), event_handler)); |
| 303 } |
| 304 |
| 327 void RtcEventLogImpl::LogVideoReceiveStreamConfig( | 305 void RtcEventLogImpl::LogVideoReceiveStreamConfig( |
| 328 const rtclog::StreamConfig& config) { | 306 const rtclog::StreamConfig& config) { |
| 329 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 307 Log(rtc::MakeUnique<RtcEventVideoReceiveStreamConfig>( |
| 330 event->set_timestamp_us(rtc::TimeMicros()); | 308 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
| 331 event->set_type(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT); | |
| 332 | |
| 333 rtclog::VideoReceiveConfig* receiver_config = | |
| 334 event->mutable_video_receiver_config(); | |
| 335 receiver_config->set_remote_ssrc(config.remote_ssrc); | |
| 336 receiver_config->set_local_ssrc(config.local_ssrc); | |
| 337 | |
| 338 // TODO(perkj): Add field for rsid. | |
| 339 receiver_config->set_rtcp_mode(ConvertRtcpMode(config.rtcp_mode)); | |
| 340 receiver_config->set_remb(config.remb); | |
| 341 | |
| 342 for (const auto& e : config.rtp_extensions) { | |
| 343 rtclog::RtpHeaderExtension* extension = | |
| 344 receiver_config->add_header_extensions(); | |
| 345 extension->set_name(e.uri); | |
| 346 extension->set_id(e.id); | |
| 347 } | |
| 348 | |
| 349 for (const auto& d : config.codecs) { | |
| 350 rtclog::DecoderConfig* decoder = receiver_config->add_decoders(); | |
| 351 decoder->set_name(d.payload_name); | |
| 352 decoder->set_payload_type(d.payload_type); | |
| 353 if (d.rtx_payload_type != 0) { | |
| 354 rtclog::RtxMap* rtx = receiver_config->add_rtx_map(); | |
| 355 rtx->set_payload_type(d.payload_type); | |
| 356 rtx->mutable_config()->set_rtx_ssrc(config.rtx_ssrc); | |
| 357 rtx->mutable_config()->set_rtx_payload_type(d.rtx_payload_type); | |
| 358 } | |
| 359 } | |
| 360 StoreEvent(std::move(event)); | |
| 361 } | 309 } |
| 362 | 310 |
| 363 void RtcEventLogImpl::LogVideoSendStreamConfig( | 311 void RtcEventLogImpl::LogVideoSendStreamConfig( |
| 364 const rtclog::StreamConfig& config) { | 312 const rtclog::StreamConfig& config) { |
| 365 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 313 Log(rtc::MakeUnique<RtcEventVideoSendStreamConfig>( |
| 366 event->set_timestamp_us(rtc::TimeMicros()); | 314 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
| 367 event->set_type(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT); | |
| 368 | |
| 369 rtclog::VideoSendConfig* sender_config = event->mutable_video_sender_config(); | |
| 370 | |
| 371 // TODO(perkj): rtclog::VideoSendConfig should only contain one SSRC. | |
| 372 sender_config->add_ssrcs(config.local_ssrc); | |
| 373 if (config.rtx_ssrc != 0) { | |
| 374 sender_config->add_rtx_ssrcs(config.rtx_ssrc); | |
| 375 } | |
| 376 | |
| 377 for (const auto& e : config.rtp_extensions) { | |
| 378 rtclog::RtpHeaderExtension* extension = | |
| 379 sender_config->add_header_extensions(); | |
| 380 extension->set_name(e.uri); | |
| 381 extension->set_id(e.id); | |
| 382 } | |
| 383 | |
| 384 // TODO(perkj): rtclog::VideoSendConfig should contain many possible codec | |
| 385 // configurations. | |
| 386 for (const auto& codec : config.codecs) { | |
| 387 sender_config->set_rtx_payload_type(codec.rtx_payload_type); | |
| 388 rtclog::EncoderConfig* encoder = sender_config->mutable_encoder(); | |
| 389 encoder->set_name(codec.payload_name); | |
| 390 encoder->set_payload_type(codec.payload_type); | |
| 391 | |
| 392 if (config.codecs.size() > 1) { | |
| 393 LOG(WARNING) << "LogVideoSendStreamConfig currently only supports one " | |
| 394 << "codec. Logging codec :" << codec.payload_name; | |
| 395 break; | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 StoreEvent(std::move(event)); | |
| 400 } | 315 } |
| 401 | 316 |
| 402 void RtcEventLogImpl::LogAudioReceiveStreamConfig( | 317 void RtcEventLogImpl::LogAudioReceiveStreamConfig( |
| 403 const rtclog::StreamConfig& config) { | 318 const rtclog::StreamConfig& config) { |
| 404 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 319 Log(rtc::MakeUnique<RtcEventAudioReceiveStreamConfig>( |
| 405 event->set_timestamp_us(rtc::TimeMicros()); | 320 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
| 406 event->set_type(rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT); | |
| 407 | |
| 408 rtclog::AudioReceiveConfig* receiver_config = | |
| 409 event->mutable_audio_receiver_config(); | |
| 410 receiver_config->set_remote_ssrc(config.remote_ssrc); | |
| 411 receiver_config->set_local_ssrc(config.local_ssrc); | |
| 412 | |
| 413 for (const auto& e : config.rtp_extensions) { | |
| 414 rtclog::RtpHeaderExtension* extension = | |
| 415 receiver_config->add_header_extensions(); | |
| 416 extension->set_name(e.uri); | |
| 417 extension->set_id(e.id); | |
| 418 } | |
| 419 StoreEvent(std::move(event)); | |
| 420 } | 321 } |
| 421 | 322 |
| 422 void RtcEventLogImpl::LogAudioSendStreamConfig( | 323 void RtcEventLogImpl::LogAudioSendStreamConfig( |
| 423 const rtclog::StreamConfig& config) { | 324 const rtclog::StreamConfig& config) { |
| 424 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 325 Log(rtc::MakeUnique<RtcEventAudioSendStreamConfig>( |
| 425 event->set_timestamp_us(rtc::TimeMicros()); | 326 rtc::MakeUnique<rtclog::StreamConfig>(config))); |
| 426 event->set_type(rtclog::Event::AUDIO_SENDER_CONFIG_EVENT); | |
| 427 | |
| 428 rtclog::AudioSendConfig* sender_config = event->mutable_audio_sender_config(); | |
| 429 | |
| 430 sender_config->set_ssrc(config.local_ssrc); | |
| 431 | |
| 432 for (const auto& e : config.rtp_extensions) { | |
| 433 rtclog::RtpHeaderExtension* extension = | |
| 434 sender_config->add_header_extensions(); | |
| 435 extension->set_name(e.uri); | |
| 436 extension->set_id(e.id); | |
| 437 } | |
| 438 | |
| 439 StoreEvent(std::move(event)); | |
| 440 } | 327 } |
| 441 | 328 |
| 442 void RtcEventLogImpl::LogIncomingRtpHeader(const RtpPacketReceived& packet) { | 329 void RtcEventLogImpl::LogIncomingRtpHeader(const RtpPacketReceived& packet) { |
| 443 LogRtpHeader(kIncomingPacket, packet.data(), packet.size(), | 330 Log(rtc::MakeUnique<RtcEventRtpPacketIncoming>(packet)); |
| 444 PacedPacketInfo::kNotAProbe); | |
| 445 } | 331 } |
| 446 | 332 |
| 447 void RtcEventLogImpl::LogOutgoingRtpHeader(const RtpPacketToSend& packet, | 333 void RtcEventLogImpl::LogOutgoingRtpHeader(const RtpPacketToSend& packet, |
| 448 int probe_cluster_id) { | 334 int probe_cluster_id) { |
| 449 LogRtpHeader(kOutgoingPacket, packet.data(), packet.size(), probe_cluster_id); | 335 Log(rtc::MakeUnique<RtcEventRtpPacketOutgoing>(packet, probe_cluster_id)); |
| 450 } | 336 } |
| 451 | 337 |
| 452 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, | 338 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, |
| 453 const uint8_t* header, | 339 const uint8_t* header, |
| 454 size_t packet_length) { | 340 size_t packet_length) { |
| 455 LogRtpHeader(direction, header, packet_length, PacedPacketInfo::kNotAProbe); | 341 LogRtpHeader(direction, header, packet_length, PacedPacketInfo::kNotAProbe); |
| 456 } | 342 } |
| 457 | 343 |
| 458 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, | 344 void RtcEventLogImpl::LogRtpHeader(PacketDirection direction, |
| 459 const uint8_t* header, | 345 const uint8_t* header, |
| 460 size_t packet_length, | 346 size_t packet_length, |
| 461 int probe_cluster_id) { | 347 int probe_cluster_id) { |
| 462 // Read header length (in bytes) from packet data. | 348 // TODO(eladalon): This is highly inefficient. We're only doing this for |
| 463 if (packet_length < 12u) { | 349 // the deprecated interface. We should remove this soon. |
| 464 return; // Don't read outside the packet. | 350 if (direction == PacketDirection::kIncomingPacket) { |
| 351 RtpPacketReceived packet; |
| 352 packet.Parse(header, packet_length); |
| 353 Log(rtc::MakeUnique<RtcEventRtpPacketIncoming>(packet)); |
| 354 } else { |
| 355 RTC_CHECK_EQ(direction, PacketDirection::kOutgoingPacket); |
| 356 RtpPacketToSend packet(nullptr); |
| 357 packet.Parse(header, packet_length); |
| 358 Log(rtc::MakeUnique<RtcEventRtpPacketOutgoing>(packet, probe_cluster_id)); |
| 465 } | 359 } |
| 466 const bool x = (header[0] & 0x10) != 0; | |
| 467 const uint8_t cc = header[0] & 0x0f; | |
| 468 size_t header_length = 12u + cc * 4u; | |
| 469 | |
| 470 if (x) { | |
| 471 if (packet_length < 12u + cc * 4u + 4u) { | |
| 472 return; // Don't read outside the packet. | |
| 473 } | |
| 474 size_t x_len = ByteReader<uint16_t>::ReadBigEndian(header + 14 + cc * 4); | |
| 475 header_length += (x_len + 1) * 4; | |
| 476 } | |
| 477 | |
| 478 std::unique_ptr<rtclog::Event> rtp_event(new rtclog::Event()); | |
| 479 rtp_event->set_timestamp_us(rtc::TimeMicros()); | |
| 480 rtp_event->set_type(rtclog::Event::RTP_EVENT); | |
| 481 rtp_event->mutable_rtp_packet()->set_incoming(direction == kIncomingPacket); | |
| 482 rtp_event->mutable_rtp_packet()->set_packet_length(packet_length); | |
| 483 rtp_event->mutable_rtp_packet()->set_header(header, header_length); | |
| 484 if (probe_cluster_id != PacedPacketInfo::kNotAProbe) | |
| 485 rtp_event->mutable_rtp_packet()->set_probe_cluster_id(probe_cluster_id); | |
| 486 StoreEvent(std::move(rtp_event)); | |
| 487 } | 360 } |
| 488 | 361 |
| 489 void RtcEventLogImpl::LogIncomingRtcpPacket( | 362 void RtcEventLogImpl::LogIncomingRtcpPacket( |
| 490 rtc::ArrayView<const uint8_t> packet) { | 363 rtc::ArrayView<const uint8_t> packet) { |
| 491 LogRtcpPacket(kIncomingPacket, packet.data(), packet.size()); | 364 Log(rtc::MakeUnique<RtcEventRtcpPacketIncoming>(packet)); |
| 492 } | 365 } |
| 493 | 366 |
| 494 void RtcEventLogImpl::LogOutgoingRtcpPacket( | 367 void RtcEventLogImpl::LogOutgoingRtcpPacket( |
| 495 rtc::ArrayView<const uint8_t> packet) { | 368 rtc::ArrayView<const uint8_t> packet) { |
| 496 LogRtcpPacket(kOutgoingPacket, packet.data(), packet.size()); | 369 Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(packet)); |
| 497 } | 370 } |
| 498 | 371 |
| 499 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction, | 372 void RtcEventLogImpl::LogRtcpPacket(PacketDirection direction, |
| 500 const uint8_t* packet, | 373 const uint8_t* packet, |
| 501 size_t length) { | 374 size_t length) { |
| 502 std::unique_ptr<rtclog::Event> rtcp_event(new rtclog::Event()); | 375 if (direction == PacketDirection::kIncomingPacket) { |
| 503 rtcp_event->set_timestamp_us(rtc::TimeMicros()); | 376 LogIncomingRtcpPacket(rtc::ArrayView<const uint8_t>(packet, length)); |
| 504 rtcp_event->set_type(rtclog::Event::RTCP_EVENT); | 377 } else { |
| 505 rtcp_event->mutable_rtcp_packet()->set_incoming(direction == kIncomingPacket); | 378 RTC_CHECK_EQ(direction, PacketDirection::kOutgoingPacket); |
| 506 | 379 LogOutgoingRtcpPacket(rtc::ArrayView<const uint8_t>(packet, length)); |
| 507 rtcp::CommonHeader header; | |
| 508 const uint8_t* block_begin = packet; | |
| 509 const uint8_t* packet_end = packet + length; | |
| 510 RTC_DCHECK(length <= IP_PACKET_SIZE); | |
| 511 uint8_t buffer[IP_PACKET_SIZE]; | |
| 512 uint32_t buffer_length = 0; | |
| 513 while (block_begin < packet_end) { | |
| 514 if (!header.Parse(block_begin, packet_end - block_begin)) { | |
| 515 break; // Incorrect message header. | |
| 516 } | |
| 517 const uint8_t* next_block = header.NextPacket(); | |
| 518 uint32_t block_size = next_block - block_begin; | |
| 519 switch (header.type()) { | |
| 520 case rtcp::SenderReport::kPacketType: | |
| 521 case rtcp::ReceiverReport::kPacketType: | |
| 522 case rtcp::Bye::kPacketType: | |
| 523 case rtcp::ExtendedJitterReport::kPacketType: | |
| 524 case rtcp::Rtpfb::kPacketType: | |
| 525 case rtcp::Psfb::kPacketType: | |
| 526 case rtcp::ExtendedReports::kPacketType: | |
| 527 // We log sender reports, receiver reports, bye messages | |
| 528 // inter-arrival jitter, third-party loss reports, payload-specific | |
| 529 // feedback and extended reports. | |
| 530 memcpy(buffer + buffer_length, block_begin, block_size); | |
| 531 buffer_length += block_size; | |
| 532 break; | |
| 533 case rtcp::Sdes::kPacketType: | |
| 534 case rtcp::App::kPacketType: | |
| 535 default: | |
| 536 // We don't log sender descriptions, application defined messages | |
| 537 // or message blocks of unknown type. | |
| 538 break; | |
| 539 } | |
| 540 | |
| 541 block_begin += block_size; | |
| 542 } | 380 } |
| 543 rtcp_event->mutable_rtcp_packet()->set_packet_data(buffer, buffer_length); | |
| 544 StoreEvent(std::move(rtcp_event)); | |
| 545 } | 381 } |
| 546 | 382 |
| 547 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) { | 383 void RtcEventLogImpl::LogAudioPlayout(uint32_t ssrc) { |
| 548 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 384 Log(rtc::MakeUnique<RtcEventAudioPlayout>(ssrc)); |
| 549 event->set_timestamp_us(rtc::TimeMicros()); | |
| 550 event->set_type(rtclog::Event::AUDIO_PLAYOUT_EVENT); | |
| 551 auto playout_event = event->mutable_audio_playout_event(); | |
| 552 playout_event->set_local_ssrc(ssrc); | |
| 553 StoreEvent(std::move(event)); | |
| 554 } | 385 } |
| 555 | 386 |
| 556 void RtcEventLogImpl::LogLossBasedBweUpdate(int32_t bitrate_bps, | 387 void RtcEventLogImpl::LogLossBasedBweUpdate(int32_t bitrate_bps, |
| 557 uint8_t fraction_loss, | 388 uint8_t fraction_loss, |
| 558 int32_t total_packets) { | 389 int32_t total_packets) { |
| 559 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 390 Log(rtc::MakeUnique<RtcEventBweUpdateLossBased>(bitrate_bps, fraction_loss, |
| 560 event->set_timestamp_us(rtc::TimeMicros()); | 391 total_packets)); |
| 561 event->set_type(rtclog::Event::LOSS_BASED_BWE_UPDATE); | |
| 562 auto bwe_event = event->mutable_loss_based_bwe_update(); | |
| 563 bwe_event->set_bitrate_bps(bitrate_bps); | |
| 564 bwe_event->set_fraction_loss(fraction_loss); | |
| 565 bwe_event->set_total_packets(total_packets); | |
| 566 StoreEvent(std::move(event)); | |
| 567 } | 392 } |
| 568 | 393 |
| 569 void RtcEventLogImpl::LogDelayBasedBweUpdate(int32_t bitrate_bps, | 394 void RtcEventLogImpl::LogDelayBasedBweUpdate(int32_t bitrate_bps, |
| 570 BandwidthUsage detector_state) { | 395 BandwidthUsage detector_state) { |
| 571 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 396 Log(rtc::MakeUnique<RtcEventBweUpdateDelayBased>(bitrate_bps, |
| 572 event->set_timestamp_us(rtc::TimeMicros()); | 397 detector_state)); |
| 573 event->set_type(rtclog::Event::DELAY_BASED_BWE_UPDATE); | |
| 574 auto bwe_event = event->mutable_delay_based_bwe_update(); | |
| 575 bwe_event->set_bitrate_bps(bitrate_bps); | |
| 576 bwe_event->set_detector_state(ConvertDetectorState(detector_state)); | |
| 577 StoreEvent(std::move(event)); | |
| 578 } | 398 } |
| 579 | 399 |
| 580 void RtcEventLogImpl::LogAudioNetworkAdaptation( | 400 void RtcEventLogImpl::LogAudioNetworkAdaptation( |
| 581 const AudioEncoderRuntimeConfig& config) { | 401 const AudioEncoderRuntimeConfig& config) { |
| 582 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 402 Log(rtc::MakeUnique<RtcEventAudioNetworkAdaptation>( |
| 583 event->set_timestamp_us(rtc::TimeMicros()); | 403 rtc::MakeUnique<AudioEncoderRuntimeConfig>(config))); |
| 584 event->set_type(rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT); | |
| 585 auto audio_network_adaptation = event->mutable_audio_network_adaptation(); | |
| 586 if (config.bitrate_bps) | |
| 587 audio_network_adaptation->set_bitrate_bps(*config.bitrate_bps); | |
| 588 if (config.frame_length_ms) | |
| 589 audio_network_adaptation->set_frame_length_ms(*config.frame_length_ms); | |
| 590 if (config.uplink_packet_loss_fraction) { | |
| 591 audio_network_adaptation->set_uplink_packet_loss_fraction( | |
| 592 *config.uplink_packet_loss_fraction); | |
| 593 } | |
| 594 if (config.enable_fec) | |
| 595 audio_network_adaptation->set_enable_fec(*config.enable_fec); | |
| 596 if (config.enable_dtx) | |
| 597 audio_network_adaptation->set_enable_dtx(*config.enable_dtx); | |
| 598 if (config.num_channels) | |
| 599 audio_network_adaptation->set_num_channels(*config.num_channels); | |
| 600 StoreEvent(std::move(event)); | |
| 601 } | 404 } |
| 602 | 405 |
| 603 void RtcEventLogImpl::LogProbeClusterCreated(int id, | 406 void RtcEventLogImpl::LogProbeClusterCreated(int id, |
| 604 int bitrate_bps, | 407 int bitrate_bps, |
| 605 int min_probes, | 408 int min_probes, |
| 606 int min_bytes) { | 409 int min_bytes) { |
| 607 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | 410 Log(rtc::MakeUnique<RtcEventProbeClusterCreated>(id, bitrate_bps, min_probes, |
| 608 event->set_timestamp_us(rtc::TimeMicros()); | 411 min_bytes)); |
| 609 event->set_type(rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT); | |
| 610 | |
| 611 auto probe_cluster = event->mutable_probe_cluster(); | |
| 612 probe_cluster->set_id(id); | |
| 613 probe_cluster->set_bitrate_bps(bitrate_bps); | |
| 614 probe_cluster->set_min_packets(min_probes); | |
| 615 probe_cluster->set_min_bytes(min_bytes); | |
| 616 StoreEvent(std::move(event)); | |
| 617 } | 412 } |
| 618 | 413 |
| 619 void RtcEventLogImpl::LogProbeResultSuccess(int id, int bitrate_bps) { | 414 void RtcEventLogImpl::LogProbeResultSuccess(int id, int bitrate_bps) { |
| 620 LogProbeResult(id, rtclog::BweProbeResult::SUCCESS, bitrate_bps); | 415 Log(rtc::MakeUnique<RtcEventProbeResultSuccess>(id, bitrate_bps)); |
| 621 } | 416 } |
| 622 | 417 |
| 623 void RtcEventLogImpl::LogProbeResultFailure(int id, | 418 void RtcEventLogImpl::LogProbeResultFailure(int id, |
| 624 ProbeFailureReason failure_reason) { | 419 ProbeFailureReason failure_reason) { |
| 625 rtclog::BweProbeResult::ResultType result = | 420 Log(rtc::MakeUnique<RtcEventProbeResultFailure>(id, failure_reason)); |
| 626 ConvertProbeResultType(failure_reason); | |
| 627 LogProbeResult(id, result, -1); | |
| 628 } | |
| 629 | |
| 630 void RtcEventLogImpl::LogProbeResult(int id, | |
| 631 rtclog::BweProbeResult::ResultType result, | |
| 632 int bitrate_bps) { | |
| 633 std::unique_ptr<rtclog::Event> event(new rtclog::Event()); | |
| 634 event->set_timestamp_us(rtc::TimeMicros()); | |
| 635 event->set_type(rtclog::Event::BWE_PROBE_RESULT_EVENT); | |
| 636 | |
| 637 auto probe_result = event->mutable_probe_result(); | |
| 638 probe_result->set_id(id); | |
| 639 probe_result->set_result(result); | |
| 640 if (result == rtclog::BweProbeResult::SUCCESS) | |
| 641 probe_result->set_bitrate_bps(bitrate_bps); | |
| 642 StoreEvent(std::move(event)); | |
| 643 } | 421 } |
| 644 | 422 |
| 645 void RtcEventLogImpl::StartLoggingInternal(std::unique_ptr<FileWrapper> file, | 423 void RtcEventLogImpl::StartLoggingInternal(std::unique_ptr<FileWrapper> file, |
| 646 int64_t max_size_bytes) { | 424 int64_t max_size_bytes) { |
| 647 LOG(LS_INFO) << "Starting WebRTC event log."; | 425 LOG(LS_INFO) << "Starting WebRTC event log."; |
| 648 | 426 |
| 649 max_size_bytes = (max_size_bytes <= 0) | 427 max_size_bytes = (max_size_bytes <= 0) |
| 650 ? std::numeric_limits<decltype(max_size_bytes)>::max() | 428 ? std::numeric_limits<decltype(max_size_bytes)>::max() |
| 651 : max_size_bytes; | 429 : max_size_bytes; |
| 652 auto file_handler = [this, | 430 auto file_handler = [this, |
| 653 max_size_bytes](std::unique_ptr<FileWrapper> file) { | 431 max_size_bytes](std::unique_ptr<FileWrapper> file) { |
| 654 RTC_DCHECK_RUN_ON(&task_queue_); | 432 RTC_DCHECK_RUN_ON(&task_queue_); |
| 655 if (!file_->is_open()) { | 433 if (!file_->is_open()) { |
| 656 max_size_bytes_ = max_size_bytes; | 434 max_size_bytes_ = max_size_bytes; |
| 657 file_ = std::move(file); | 435 file_ = std::move(file); |
| 658 StartLogFile(); | 436 StartLogFile(); |
| 659 } else { | 437 } else { |
| 660 // Already started. Ignore message and close file handle. | 438 // Already started. Ignore message and close file handle. |
| 661 file->CloseFile(); | 439 file->CloseFile(); |
| 662 } | 440 } |
| 663 }; | 441 }; |
| 664 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<FileWrapper>>( | 442 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<FileWrapper>>( |
| 665 std::move(file), file_handler)); | 443 std::move(file), file_handler)); |
| 666 } | 444 } |
| 667 | 445 |
| 668 void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event> event) { | 446 bool RtcEventLogImpl::AppendEventToString(const RtcEvent& event, |
| 669 RTC_DCHECK(event); | |
| 670 | |
| 671 auto event_handler = [this](std::unique_ptr<rtclog::Event> rtclog_event) { | |
| 672 RTC_DCHECK_RUN_ON(&task_queue_); | |
| 673 if (file_->is_open()) { | |
| 674 LogToFile(std::move(rtclog_event)); | |
| 675 } else { | |
| 676 LogToMemory(std::move(rtclog_event)); | |
| 677 } | |
| 678 }; | |
| 679 | |
| 680 task_queue_.PostTask(rtc::MakeUnique<ResourceOwningTask<rtclog::Event>>( | |
| 681 std::move(event), event_handler)); | |
| 682 } | |
| 683 | |
| 684 bool RtcEventLogImpl::AppendEventToString(rtclog::Event* event, | |
| 685 ProtoString* output_string) { | 447 ProtoString* output_string) { |
| 686 RTC_DCHECK_RUN_ON(&task_queue_); | 448 RTC_DCHECK_RUN_ON(&task_queue_); |
| 687 | 449 |
| 688 // Even though we're only serializing a single event during this call, what | 450 std::string encoded_event = event_encoder_->Encode(event); |
| 689 // we intend to get is a list of events, with a tag and length preceding | |
| 690 // each actual event. To produce that, we serialize a list of a single event. | |
| 691 // If we later serialize additional events, the resulting ProtoString will | |
| 692 // be a proper concatenation of all those events. | |
| 693 | |
| 694 rtclog::EventStream event_stream; | |
| 695 event_stream.add_stream(); | |
| 696 | |
| 697 // As a tweak, we swap the new event into the event-stream, write that to | |
| 698 // file, then swap back. This saves on some copying. | |
| 699 rtclog::Event* output_event = event_stream.mutable_stream(0); | |
| 700 output_event->Swap(event); | |
| 701 | 451 |
| 702 bool appended; | 452 bool appended; |
| 703 size_t potential_new_size = | 453 size_t potential_new_size = |
| 704 written_bytes_ + output_string->size() + event_stream.ByteSize(); | 454 written_bytes_ + output_string->size() + encoded_event.length(); |
| 705 if (potential_new_size <= max_size_bytes_) { | 455 if (potential_new_size <= max_size_bytes_) { |
| 706 event_stream.AppendToString(output_string); | 456 *output_string += encoded_event; |
| 707 appended = true; | 457 appended = true; |
| 708 } else { | 458 } else { |
| 709 appended = false; | 459 appended = false; |
| 710 } | 460 } |
| 711 | 461 |
| 712 // When the function returns, the original Event will be unchanged. | |
| 713 output_event->Swap(event); | |
| 714 | |
| 715 return appended; | 462 return appended; |
| 716 } | 463 } |
| 717 | 464 |
| 718 void RtcEventLogImpl::LogToMemory(std::unique_ptr<rtclog::Event> event) { | 465 void RtcEventLogImpl::LogToMemory(std::unique_ptr<RtcEvent> event) { |
| 719 RTC_DCHECK_RUN_ON(&task_queue_); | 466 RTC_DCHECK_RUN_ON(&task_queue_); |
| 720 RTC_DCHECK(!file_->is_open()); | 467 RTC_DCHECK(!file_->is_open()); |
| 721 | 468 |
| 722 if (IsConfigEvent(*event.get())) { | 469 if (event->IsConfigEvent()) { |
| 723 config_history_.push_back(std::move(event)); | 470 config_history_.push_back(std::move(event)); |
| 724 } else { | 471 } else { |
| 725 history_.push_back(std::move(event)); | 472 history_.push_back(std::move(event)); |
| 726 if (history_.size() > kEventsInHistory) { | 473 if (history_.size() > kEventsInHistory) { |
| 727 history_.pop_front(); | 474 history_.pop_front(); |
| 728 } | 475 } |
| 729 } | 476 } |
| 730 } | 477 } |
| 731 | 478 |
| 732 void RtcEventLogImpl::StartLogFile() { | 479 void RtcEventLogImpl::StartLogFile() { |
| 733 RTC_DCHECK_RUN_ON(&task_queue_); | 480 RTC_DCHECK_RUN_ON(&task_queue_); |
| 734 RTC_DCHECK(file_->is_open()); | 481 RTC_DCHECK(file_->is_open()); |
| 735 | 482 |
| 736 ProtoString output_string; | 483 ProtoString output_string; |
| 737 | 484 |
| 738 // Create and serialize the LOG_START event. | 485 // Create and serialize the LOG_START event. |
| 739 // The timestamp used will correspond to when logging has started. The log | 486 // The timestamp used will correspond to when logging has started. The log |
| 740 // may contain events earlier than the LOG_START event. (In general, the | 487 // may contain events earlier than the LOG_START event. (In general, the |
| 741 // timestamps in the log are not monotonic.) | 488 // timestamps in the log are not monotonic.) |
| 742 rtclog::Event start_event; | 489 bool appended = AppendEventToString(RtcEventLoggingStarted(), &output_string); |
| 743 start_event.set_timestamp_us(rtc::TimeMicros()); | |
| 744 start_event.set_type(rtclog::Event::LOG_START); | |
| 745 bool appended = AppendEventToString(&start_event, &output_string); | |
| 746 | 490 |
| 747 // Serialize the config information for all old streams, including streams | 491 // Serialize the config information for all old streams, including streams |
| 748 // which were already logged to previous files. | 492 // which were already logged to previous files. |
| 749 for (auto& event : config_history_) { | 493 for (auto& event : config_history_) { |
| 750 if (!appended) { | 494 if (!appended) { |
| 751 break; | 495 break; |
| 752 } | 496 } |
| 753 appended = AppendEventToString(event.get(), &output_string); | 497 appended = AppendEventToString(*event, &output_string); |
| 754 } | 498 } |
| 755 | 499 |
| 756 // Serialize the events in the event queue. | 500 // Serialize the events in the event queue. |
| 757 while (appended && !history_.empty()) { | 501 while (appended && !history_.empty()) { |
| 758 appended = AppendEventToString(history_.front().get(), &output_string); | 502 appended = AppendEventToString(*history_.front(), &output_string); |
| 759 if (appended) { | 503 if (appended) { |
| 760 // Known issue - if writing to the file fails, these events will have | 504 // Known issue - if writing to the file fails, these events will have |
| 761 // been lost. If we try to open a new file, these events will be missing | 505 // been lost. If we try to open a new file, these events will be missing |
| 762 // from it. | 506 // from it. |
| 763 history_.pop_front(); | 507 history_.pop_front(); |
| 764 } | 508 } |
| 765 } | 509 } |
| 766 | 510 |
| 767 // Write to file. | 511 // Write to file. |
| 768 if (!file_->Write(output_string.data(), output_string.size())) { | 512 if (!file_->Write(output_string.data(), output_string.size())) { |
| 769 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; | 513 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; |
| 770 // The current FileWrapper implementation closes the file on error. | 514 // The current FileWrapper implementation closes the file on error. |
| 771 RTC_DCHECK(!file_->is_open()); | 515 RTC_DCHECK(!file_->is_open()); |
| 772 return; | 516 return; |
| 773 } | 517 } |
| 774 written_bytes_ += output_string.size(); | 518 written_bytes_ += output_string.size(); |
| 775 | 519 |
| 776 if (!appended) { | 520 if (!appended) { |
| 777 RTC_DCHECK(file_->is_open()); | 521 RTC_DCHECK(file_->is_open()); |
| 778 StopLogFile(rtc::TimeMicros()); | 522 StopLogFile(rtc::TimeMicros()); |
| 779 } | 523 } |
| 780 } | 524 } |
| 781 | 525 |
| 782 void RtcEventLogImpl::LogToFile(std::unique_ptr<rtclog::Event> event) { | 526 void RtcEventLogImpl::LogToFile(std::unique_ptr<RtcEvent> event) { |
| 783 RTC_DCHECK_RUN_ON(&task_queue_); | 527 RTC_DCHECK_RUN_ON(&task_queue_); |
| 784 RTC_DCHECK(file_->is_open()); | 528 RTC_DCHECK(file_->is_open()); |
| 785 | 529 |
| 786 ProtoString output_string; | 530 ProtoString output_string; |
| 787 | 531 |
| 788 bool appended = AppendEventToString(event.get(), &output_string); | 532 bool appended = AppendEventToString(*event, &output_string); |
| 789 | 533 |
| 790 if (IsConfigEvent(*event.get())) { | 534 if (event->IsConfigEvent()) { |
| 791 config_history_.push_back(std::move(event)); | 535 config_history_.push_back(std::move(event)); |
| 792 } | 536 } |
| 793 | 537 |
| 794 if (!appended) { | 538 if (!appended) { |
| 795 RTC_DCHECK(file_->is_open()); | 539 RTC_DCHECK(file_->is_open()); |
| 796 history_.push_back(std::move(event)); | 540 history_.push_back(std::move(event)); |
| 797 StopLogFile(rtc::TimeMicros()); | 541 StopLogFile(rtc::TimeMicros()); |
| 798 return; | 542 return; |
| 799 } | 543 } |
| 800 | 544 |
| 801 // Write string to file. | 545 // Write string to file. |
| 802 if (file_->Write(output_string.data(), output_string.size())) { | 546 if (file_->Write(output_string.data(), output_string.size())) { |
| 803 written_bytes_ += output_string.size(); | 547 written_bytes_ += output_string.size(); |
| 804 } else { | 548 } else { |
| 805 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; | 549 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; |
| 806 // The current FileWrapper implementation closes the file on error. | 550 // The current FileWrapper implementation closes the file on error. |
| 807 RTC_DCHECK(!file_->is_open()); | 551 RTC_DCHECK(!file_->is_open()); |
| 808 } | 552 } |
| 809 } | 553 } |
| 810 | 554 |
| 811 void RtcEventLogImpl::StopLogFile(int64_t stop_time) { | 555 void RtcEventLogImpl::StopLogFile(int64_t stop_time) { |
| 812 RTC_DCHECK_RUN_ON(&task_queue_); | 556 RTC_DCHECK_RUN_ON(&task_queue_); |
| 813 RTC_DCHECK(file_->is_open()); | 557 RTC_DCHECK(file_->is_open()); |
| 814 | 558 |
| 815 ProtoString output_string; | 559 ProtoString output_string; |
| 816 | 560 |
| 817 rtclog::Event end_event; | 561 bool appended = AppendEventToString(RtcEventLoggingStopped(), &output_string); |
| 818 end_event.set_timestamp_us(stop_time); | |
| 819 end_event.set_type(rtclog::Event::LOG_END); | |
| 820 bool appended = AppendEventToString(&end_event, &output_string); | |
| 821 | 562 |
| 822 if (appended) { | 563 if (appended) { |
| 823 if (!file_->Write(output_string.data(), output_string.size())) { | 564 if (!file_->Write(output_string.data(), output_string.size())) { |
| 824 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; | 565 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; |
| 825 // The current FileWrapper implementation closes the file on error. | 566 // The current FileWrapper implementation closes the file on error. |
| 826 RTC_DCHECK(!file_->is_open()); | 567 RTC_DCHECK(!file_->is_open()); |
| 827 } | 568 } |
| 828 written_bytes_ += output_string.size(); | 569 written_bytes_ += output_string.size(); |
| 829 } | 570 } |
| 830 | 571 |
| 831 max_size_bytes_ = std::numeric_limits<decltype(max_size_bytes_)>::max(); | 572 max_size_bytes_ = std::numeric_limits<decltype(max_size_bytes_)>::max(); |
| 832 written_bytes_ = 0; | 573 written_bytes_ = 0; |
| 833 | 574 |
| 834 file_->CloseFile(); | 575 file_->CloseFile(); |
| 835 RTC_DCHECK(!file_->is_open()); | 576 RTC_DCHECK(!file_->is_open()); |
| 836 } | 577 } |
| 837 | 578 |
| 838 #endif // ENABLE_RTC_EVENT_LOG | 579 #endif // ENABLE_RTC_EVENT_LOG |
| 839 | 580 |
| 840 // RtcEventLog member functions. | 581 // RtcEventLog member functions. |
| 841 std::unique_ptr<RtcEventLog> RtcEventLog::Create() { | 582 std::unique_ptr<RtcEventLog> RtcEventLog::Create(EncodingType encoding_type) { |
| 842 #ifdef ENABLE_RTC_EVENT_LOG | 583 #ifdef ENABLE_RTC_EVENT_LOG |
| 843 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. | 584 // TODO(eladalon): Known issue - there's a race over |rtc_event_log_count|. |
| 844 constexpr int kMaxLogCount = 5; | 585 constexpr int kMaxLogCount = 5; |
| 845 int count = 1 + std::atomic_fetch_add(&rtc_event_log_count, 1); | 586 int count = 1 + std::atomic_fetch_add(&rtc_event_log_count, 1); |
| 846 if (count > kMaxLogCount) { | 587 if (count > kMaxLogCount) { |
| 847 LOG(LS_WARNING) << "Denied creation of additional WebRTC event logs. " | 588 LOG(LS_WARNING) << "Denied creation of additional WebRTC event logs. " |
| 848 << count - 1 << " logs open already."; | 589 << count - 1 << " logs open already."; |
| 849 std::atomic_fetch_sub(&rtc_event_log_count, 1); | 590 std::atomic_fetch_sub(&rtc_event_log_count, 1); |
| 850 return CreateNull(); | 591 return CreateNull(); |
| 851 } | 592 } |
| 852 return rtc::MakeUnique<RtcEventLogImpl>(); | 593 auto encoder = CreateEncoder(encoding_type); |
| 594 return rtc::MakeUnique<RtcEventLogImpl>(std::move(encoder)); |
| 853 #else | 595 #else |
| 854 return CreateNull(); | 596 return CreateNull(); |
| 855 #endif // ENABLE_RTC_EVENT_LOG | 597 #endif // ENABLE_RTC_EVENT_LOG |
| 856 } | 598 } |
| 857 | 599 |
| 858 std::unique_ptr<RtcEventLog> RtcEventLog::CreateNull() { | 600 std::unique_ptr<RtcEventLog> RtcEventLog::CreateNull() { |
| 859 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl()); | 601 return std::unique_ptr<RtcEventLog>(new RtcEventLogNullImpl()); |
| 860 } | 602 } |
| 861 | 603 |
| 862 } // namespace webrtc | 604 } // namespace webrtc |
| OLD | NEW |