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/modules/audio_coding/main/acm2/acm_dump.h" | 11 #include "webrtc/modules/audio_coding/main/acm2/acm_dump.h" |
12 | 12 |
13 #include <sstream> | 13 #include <deque> |
14 | 14 |
15 #include "webrtc/base/checks.h" | 15 #include "webrtc/base/checks.h" |
16 #include "webrtc/base/thread_annotations.h" | 16 #include "webrtc/base/thread_annotations.h" |
17 #include "webrtc/system_wrappers/interface/clock.h" | 17 #include "webrtc/system_wrappers/interface/clock.h" |
18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | 18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
19 #include "webrtc/system_wrappers/interface/file_wrapper.h" | 19 #include "webrtc/system_wrappers/interface/file_wrapper.h" |
20 | 20 |
21 // Files generated at build-time by the protobuf compiler. | 21 // Files generated at build-time by the protobuf compiler. |
22 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD | 22 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD |
23 #include "external/webrtc/webrtc/modules/audio_coding/dump.pb.h" | 23 #include "external/webrtc/webrtc/modules/audio_coding/dump.pb.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 void Clear() EXCLUSIVE_LOCKS_REQUIRED(crit_); | 60 void Clear() EXCLUSIVE_LOCKS_REQUIRED(crit_); |
61 // Returns true if the logging is currently active. | 61 // Returns true if the logging is currently active. |
62 bool CurrentlyLogging() const EXCLUSIVE_LOCKS_REQUIRED(crit_) { | 62 bool CurrentlyLogging() const EXCLUSIVE_LOCKS_REQUIRED(crit_) { |
63 return active_ && | 63 return active_ && |
64 (clock_->TimeInMicroseconds() <= start_time_us_ + duration_us_); | 64 (clock_->TimeInMicroseconds() <= start_time_us_ + duration_us_); |
65 } | 65 } |
66 // This function is identical to LogDebugEvent, but requires holding the lock. | 66 // This function is identical to LogDebugEvent, but requires holding the lock. |
67 void LogDebugEventLocked(DebugEvent event_type, | 67 void LogDebugEventLocked(DebugEvent event_type, |
68 const std::string& event_message) | 68 const std::string& event_message) |
69 EXCLUSIVE_LOCKS_REQUIRED(crit_); | 69 EXCLUSIVE_LOCKS_REQUIRED(crit_); |
70 // Writes the event to the file. Note that this will destroy the state of the | |
71 // input argument. | |
72 void StoreToFile(ACMDumpEvent* event) EXCLUSIVE_LOCKS_REQUIRED(crit_); | |
73 // Adds the event to the list of recent events, and removes any events that | |
74 // are too old and no longer fall in the time window. | |
75 void AddRecentEvent(const ACMDumpEvent& event) | |
76 EXCLUSIVE_LOCKS_REQUIRED(crit_); | |
77 | |
78 // Amount of time in us to record log events, before starting the actual log. | |
hlundin-webrtc
2015/06/25 13:20:56
Write microseconds instead of us in comments. Alth
ivoc
2015/06/25 13:55:22
Good point.
| |
79 const int recent_log_duration_us = 10000000; | |
70 | 80 |
71 rtc::scoped_ptr<webrtc::CriticalSectionWrapper> crit_; | 81 rtc::scoped_ptr<webrtc::CriticalSectionWrapper> crit_; |
72 rtc::scoped_ptr<webrtc::FileWrapper> file_ GUARDED_BY(crit_); | 82 rtc::scoped_ptr<webrtc::FileWrapper> file_ GUARDED_BY(crit_); |
73 rtc::scoped_ptr<ACMDumpEventStream> stream_ GUARDED_BY(crit_); | 83 rtc::scoped_ptr<ACMDumpEventStream> stream_ GUARDED_BY(crit_); |
84 std::deque<ACMDumpEvent> recent_log_events_ GUARDED_BY(crit_); | |
74 bool active_ GUARDED_BY(crit_); | 85 bool active_ GUARDED_BY(crit_); |
75 int64_t start_time_us_ GUARDED_BY(crit_); | 86 int64_t start_time_us_ GUARDED_BY(crit_); |
76 int64_t duration_us_ GUARDED_BY(crit_); | 87 int64_t duration_us_ GUARDED_BY(crit_); |
77 const webrtc::Clock* clock_ GUARDED_BY(crit_); | 88 const webrtc::Clock* clock_ GUARDED_BY(crit_); |
78 }; | 89 }; |
79 | 90 |
80 namespace { | 91 namespace { |
81 | 92 |
82 // Convert from AcmDump's debug event enum (runtime format) to the corresponding | 93 // Convert from AcmDump's debug event enum (runtime format) to the corresponding |
83 // protobuf enum (serialized format). | 94 // protobuf enum (serialized format). |
(...skipping 21 matching lines...) Expand all Loading... | |
105 duration_us_(0), | 116 duration_us_(0), |
106 clock_(webrtc::Clock::GetRealTimeClock()) { | 117 clock_(webrtc::Clock::GetRealTimeClock()) { |
107 } | 118 } |
108 | 119 |
109 void AcmDumpImpl::StartLogging(const std::string& file_name, int duration_ms) { | 120 void AcmDumpImpl::StartLogging(const std::string& file_name, int duration_ms) { |
110 CriticalSectionScoped lock(crit_.get()); | 121 CriticalSectionScoped lock(crit_.get()); |
111 Clear(); | 122 Clear(); |
112 if (file_->OpenFile(file_name.c_str(), false) != 0) { | 123 if (file_->OpenFile(file_name.c_str(), false) != 0) { |
113 return; | 124 return; |
114 } | 125 } |
115 // Add a single object to the stream that is reused at every log event. | 126 // Add start event to the recent event list, and remove any old events from |
hlundin-webrtc
2015/06/25 13:20:56
The comment is slightly confusing. I first thought
ivoc
2015/06/25 13:55:23
What I meant to say is that this call to LogDebugE
| |
116 stream_->add_stream(); | 127 // the list. |
128 LogDebugEventLocked(DebugEvent::kLogStart, ""); | |
117 active_ = true; | 129 active_ = true; |
118 start_time_us_ = clock_->TimeInMicroseconds(); | 130 start_time_us_ = clock_->TimeInMicroseconds(); |
119 duration_us_ = static_cast<int64_t>(duration_ms) * 1000; | 131 duration_us_ = static_cast<int64_t>(duration_ms) * 1000; |
120 // Log the start event. | 132 // Write all the recent events to the log file. |
121 std::stringstream log_msg; | 133 for (auto&& event : recent_log_events_) { |
122 log_msg << "Initial timestamp: " << start_time_us_; | 134 StoreToFile(&event); |
123 LogDebugEventLocked(DebugEvent::kLogStart, log_msg.str()); | 135 } |
136 recent_log_events_.clear(); | |
124 } | 137 } |
125 | 138 |
126 void AcmDumpImpl::LogRtpPacket(bool incoming, | 139 void AcmDumpImpl::LogRtpPacket(bool incoming, |
127 const uint8_t* packet, | 140 const uint8_t* packet, |
128 size_t length) { | 141 size_t length) { |
129 CriticalSectionScoped lock(crit_.get()); | 142 CriticalSectionScoped lock(crit_.get()); |
130 if (!CurrentlyLogging()) { | 143 ACMDumpEvent rtp_event; |
144 rtp_event.clear_debug_event(); | |
145 const int64_t timestamp = clock_->TimeInMicroseconds(); | |
146 rtp_event.set_timestamp_us(timestamp); | |
147 rtp_event.set_type(webrtc::ACMDumpEvent::RTP_EVENT); | |
148 rtp_event.mutable_packet()->set_direction( | |
149 incoming ? ACMDumpRTPPacket::INCOMING : ACMDumpRTPPacket::OUTGOING); | |
150 rtp_event.mutable_packet()->set_rtp_data(packet, length); | |
151 if (CurrentlyLogging()) { | |
152 StoreToFile(&rtp_event); | |
153 } else { | |
131 StopIfNecessary(); | 154 StopIfNecessary(); |
132 return; | 155 AddRecentEvent(rtp_event); |
133 } | 156 } |
134 // Reuse the same object at every log event. | |
135 auto rtp_event = stream_->mutable_stream(0); | |
136 rtp_event->clear_debug_event(); | |
137 const int64_t timestamp = clock_->TimeInMicroseconds() - start_time_us_; | |
138 rtp_event->set_timestamp_us(timestamp); | |
139 rtp_event->set_type(webrtc::ACMDumpEvent::RTP_EVENT); | |
140 rtp_event->mutable_packet()->set_direction( | |
141 incoming ? ACMDumpRTPPacket::INCOMING : ACMDumpRTPPacket::OUTGOING); | |
142 rtp_event->mutable_packet()->set_rtp_data(packet, length); | |
143 std::string dump_buffer; | |
144 stream_->SerializeToString(&dump_buffer); | |
145 file_->Write(dump_buffer.data(), dump_buffer.size()); | |
146 file_->Flush(); | |
147 } | 157 } |
148 | 158 |
149 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type, | 159 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type, |
150 const std::string& event_message) { | 160 const std::string& event_message) { |
151 CriticalSectionScoped lock(crit_.get()); | 161 CriticalSectionScoped lock(crit_.get()); |
152 LogDebugEventLocked(event_type, event_message); | 162 LogDebugEventLocked(event_type, event_message); |
153 } | 163 } |
154 | 164 |
155 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type) { | 165 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type) { |
156 CriticalSectionScoped lock(crit_.get()); | 166 CriticalSectionScoped lock(crit_.get()); |
(...skipping 11 matching lines...) Expand all Loading... | |
168 void AcmDumpImpl::Clear() { | 178 void AcmDumpImpl::Clear() { |
169 if (active_ || file_->Open()) { | 179 if (active_ || file_->Open()) { |
170 file_->CloseFile(); | 180 file_->CloseFile(); |
171 } | 181 } |
172 active_ = false; | 182 active_ = false; |
173 stream_->Clear(); | 183 stream_->Clear(); |
174 } | 184 } |
175 | 185 |
176 void AcmDumpImpl::LogDebugEventLocked(DebugEvent event_type, | 186 void AcmDumpImpl::LogDebugEventLocked(DebugEvent event_type, |
177 const std::string& event_message) { | 187 const std::string& event_message) { |
178 if (!CurrentlyLogging()) { | 188 ACMDumpEvent event; |
179 StopIfNecessary(); | 189 int64_t timestamp = clock_->TimeInMicroseconds(); |
180 return; | 190 event.set_timestamp_us(timestamp); |
181 } | 191 event.set_type(webrtc::ACMDumpEvent::DEBUG_EVENT); |
182 | 192 event.clear_packet(); |
183 // Reuse the same object at every log event. | 193 auto debug_event = event.mutable_debug_event(); |
184 auto event = stream_->mutable_stream(0); | |
185 int64_t timestamp = clock_->TimeInMicroseconds() - start_time_us_; | |
186 event->set_timestamp_us(timestamp); | |
187 event->set_type(webrtc::ACMDumpEvent::DEBUG_EVENT); | |
188 event->clear_packet(); | |
189 auto debug_event = event->mutable_debug_event(); | |
190 debug_event->set_type(convertDebugEvent(event_type)); | 194 debug_event->set_type(convertDebugEvent(event_type)); |
191 debug_event->set_message(event_message); | 195 debug_event->set_message(event_message); |
196 if (CurrentlyLogging()) { | |
197 StoreToFile(&event); | |
198 } else { | |
199 StopIfNecessary(); | |
200 AddRecentEvent(event); | |
201 } | |
202 } | |
203 | |
204 void AcmDumpImpl::StoreToFile(ACMDumpEvent* event) { | |
205 // Reuse the same object at every log event. | |
206 if (stream_->stream_size() < 1) { | |
207 stream_->add_stream(); | |
208 } | |
209 stream_->mutable_stream(0)->Swap(event); | |
210 | |
192 std::string dump_buffer; | 211 std::string dump_buffer; |
193 stream_->SerializeToString(&dump_buffer); | 212 stream_->SerializeToString(&dump_buffer); |
194 file_->Write(dump_buffer.data(), dump_buffer.size()); | 213 file_->Write(dump_buffer.data(), dump_buffer.size()); |
195 } | 214 } |
196 | 215 |
216 void AcmDumpImpl::AddRecentEvent(const ACMDumpEvent& event) { | |
217 recent_log_events_.push_back(event); | |
218 while (recent_log_events_.front().timestamp_us() < | |
219 event.timestamp_us() - recent_log_duration_us) { | |
220 recent_log_events_.pop_front(); | |
221 } | |
222 } | |
223 | |
197 #endif // RTC_AUDIOCODING_DEBUG_DUMP | 224 #endif // RTC_AUDIOCODING_DEBUG_DUMP |
198 | 225 |
199 // AcmDump member functions. | 226 // AcmDump member functions. |
200 rtc::scoped_ptr<AcmDump> AcmDump::Create() { | 227 rtc::scoped_ptr<AcmDump> AcmDump::Create() { |
201 return rtc::scoped_ptr<AcmDump>(new AcmDumpImpl()); | 228 return rtc::scoped_ptr<AcmDump>(new AcmDumpImpl()); |
202 } | 229 } |
203 | 230 |
204 bool AcmDump::ParseAcmDump(const std::string& file_name, | 231 bool AcmDump::ParseAcmDump(const std::string& file_name, |
205 ACMDumpEventStream* result) { | 232 ACMDumpEventStream* result) { |
206 char tmp_buffer[1024]; | 233 char tmp_buffer[1024]; |
207 int bytes_read = 0; | 234 int bytes_read = 0; |
208 rtc::scoped_ptr<FileWrapper> dump_file(FileWrapper::Create()); | 235 rtc::scoped_ptr<FileWrapper> dump_file(FileWrapper::Create()); |
209 if (dump_file->OpenFile(file_name.c_str(), true) != 0) { | 236 if (dump_file->OpenFile(file_name.c_str(), true) != 0) { |
210 return false; | 237 return false; |
211 } | 238 } |
212 std::string dump_buffer; | 239 std::string dump_buffer; |
213 while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) { | 240 while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) { |
214 dump_buffer.append(tmp_buffer, bytes_read); | 241 dump_buffer.append(tmp_buffer, bytes_read); |
215 } | 242 } |
216 dump_file->CloseFile(); | 243 dump_file->CloseFile(); |
217 return result->ParseFromString(dump_buffer); | 244 return result->ParseFromString(dump_buffer); |
218 } | 245 } |
219 | 246 |
220 } // namespace webrtc | 247 } // namespace webrtc |
OLD | NEW |