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

Side by Side Diff: webrtc/modules/audio_coding/main/acm2/acm_dump.cc

Issue 1209563002: Added support for keeping a buffer of the previous X seconds, to add to (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addressed Henrik's review comments. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/modules/audio_coding/main/acm2/acm_dump_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
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
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 microseconds to record log events, before starting the
79 // actual log.
80 const int recent_log_duration_us = 10000000;
70 81
71 rtc::scoped_ptr<webrtc::CriticalSectionWrapper> crit_; 82 rtc::scoped_ptr<webrtc::CriticalSectionWrapper> crit_;
72 rtc::scoped_ptr<webrtc::FileWrapper> file_ GUARDED_BY(crit_); 83 rtc::scoped_ptr<webrtc::FileWrapper> file_ GUARDED_BY(crit_);
73 rtc::scoped_ptr<ACMDumpEventStream> stream_ GUARDED_BY(crit_); 84 rtc::scoped_ptr<ACMDumpEventStream> stream_ GUARDED_BY(crit_);
85 std::deque<ACMDumpEvent> recent_log_events_ GUARDED_BY(crit_);
74 bool active_ GUARDED_BY(crit_); 86 bool active_ GUARDED_BY(crit_);
75 int64_t start_time_us_ GUARDED_BY(crit_); 87 int64_t start_time_us_ GUARDED_BY(crit_);
76 int64_t duration_us_ GUARDED_BY(crit_); 88 int64_t duration_us_ GUARDED_BY(crit_);
77 const webrtc::Clock* clock_ GUARDED_BY(crit_); 89 const webrtc::Clock* clock_ GUARDED_BY(crit_);
stefan-webrtc 2015/06/25 14:55:44 No need to guard this since it's const, right?
kwiberg-webrtc 2015/06/25 14:58:59 Sounds reasonable. But then the actual pointer pro
ivoc 2015/06/25 15:14:48 Okay, that makes sense, I made the pointer const a
78 }; 90 };
79 91
80 namespace { 92 namespace {
81 93
82 // Convert from AcmDump's debug event enum (runtime format) to the corresponding 94 // Convert from AcmDump's debug event enum (runtime format) to the corresponding
83 // protobuf enum (serialized format). 95 // protobuf enum (serialized format).
84 ACMDumpDebugEvent_EventType convertDebugEvent(AcmDump::DebugEvent event_type) { 96 ACMDumpDebugEvent_EventType convertDebugEvent(AcmDump::DebugEvent event_type) {
85 switch (event_type) { 97 switch (event_type) {
86 case AcmDump::DebugEvent::kLogStart: 98 case AcmDump::DebugEvent::kLogStart:
87 return ACMDumpDebugEvent::LOG_START; 99 return ACMDumpDebugEvent::LOG_START;
(...skipping 17 matching lines...) Expand all
105 duration_us_(0), 117 duration_us_(0),
106 clock_(webrtc::Clock::GetRealTimeClock()) { 118 clock_(webrtc::Clock::GetRealTimeClock()) {
107 } 119 }
108 120
109 void AcmDumpImpl::StartLogging(const std::string& file_name, int duration_ms) { 121 void AcmDumpImpl::StartLogging(const std::string& file_name, int duration_ms) {
110 CriticalSectionScoped lock(crit_.get()); 122 CriticalSectionScoped lock(crit_.get());
111 Clear(); 123 Clear();
112 if (file_->OpenFile(file_name.c_str(), false) != 0) { 124 if (file_->OpenFile(file_name.c_str(), false) != 0) {
113 return; 125 return;
114 } 126 }
115 // Add a single object to the stream that is reused at every log event. 127 // Add LOG_START event to the recent event list. This call will also remove
116 stream_->add_stream(); 128 // any events that are too old from the recent event list.
129 LogDebugEventLocked(DebugEvent::kLogStart, "");
117 active_ = true; 130 active_ = true;
118 start_time_us_ = clock_->TimeInMicroseconds(); 131 start_time_us_ = clock_->TimeInMicroseconds();
119 duration_us_ = static_cast<int64_t>(duration_ms) * 1000; 132 duration_us_ = static_cast<int64_t>(duration_ms) * 1000;
120 // Log the start event. 133 // Write all the recent events to the log file.
121 std::stringstream log_msg; 134 for (auto&& event : recent_log_events_) {
122 log_msg << "Initial timestamp: " << start_time_us_; 135 StoreToFile(&event);
123 LogDebugEventLocked(DebugEvent::kLogStart, log_msg.str()); 136 }
137 recent_log_events_.clear();
124 } 138 }
125 139
126 void AcmDumpImpl::LogRtpPacket(bool incoming, 140 void AcmDumpImpl::LogRtpPacket(bool incoming,
127 const uint8_t* packet, 141 const uint8_t* packet,
128 size_t length) { 142 size_t length) {
129 CriticalSectionScoped lock(crit_.get()); 143 CriticalSectionScoped lock(crit_.get());
130 if (!CurrentlyLogging()) { 144 ACMDumpEvent rtp_event;
145 rtp_event.clear_debug_event();
stefan-webrtc 2015/06/25 14:55:44 Isn't the event clear when it is created?
ivoc 2015/06/25 15:14:48 You're right, this is an artifact from when we reu
146 const int64_t timestamp = clock_->TimeInMicroseconds();
147 rtp_event.set_timestamp_us(timestamp);
148 rtp_event.set_type(webrtc::ACMDumpEvent::RTP_EVENT);
stefan-webrtc 2015/06/25 14:55:44 Would it make sense to have these in the construct
ivoc 2015/06/25 15:14:48 That would make sense, but this class is automatic
stefan-webrtc 2015/06/25 15:18:22 Ah, that makes sense.
149 rtp_event.mutable_packet()->set_direction(
150 incoming ? ACMDumpRTPPacket::INCOMING : ACMDumpRTPPacket::OUTGOING);
151 rtp_event.mutable_packet()->set_rtp_data(packet, length);
152 if (CurrentlyLogging()) {
153 StoreToFile(&rtp_event);
154 } else {
131 StopIfNecessary(); 155 StopIfNecessary();
132 return; 156 AddRecentEvent(rtp_event);
133 } 157 }
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 } 158 }
148 159
149 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type, 160 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type,
150 const std::string& event_message) { 161 const std::string& event_message) {
151 CriticalSectionScoped lock(crit_.get()); 162 CriticalSectionScoped lock(crit_.get());
152 LogDebugEventLocked(event_type, event_message); 163 LogDebugEventLocked(event_type, event_message);
153 } 164 }
154 165
155 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type) { 166 void AcmDumpImpl::LogDebugEvent(DebugEvent event_type) {
156 CriticalSectionScoped lock(crit_.get()); 167 CriticalSectionScoped lock(crit_.get());
(...skipping 11 matching lines...) Expand all
168 void AcmDumpImpl::Clear() { 179 void AcmDumpImpl::Clear() {
169 if (active_ || file_->Open()) { 180 if (active_ || file_->Open()) {
170 file_->CloseFile(); 181 file_->CloseFile();
171 } 182 }
172 active_ = false; 183 active_ = false;
173 stream_->Clear(); 184 stream_->Clear();
174 } 185 }
175 186
176 void AcmDumpImpl::LogDebugEventLocked(DebugEvent event_type, 187 void AcmDumpImpl::LogDebugEventLocked(DebugEvent event_type,
177 const std::string& event_message) { 188 const std::string& event_message) {
178 if (!CurrentlyLogging()) { 189 ACMDumpEvent event;
179 StopIfNecessary(); 190 int64_t timestamp = clock_->TimeInMicroseconds();
180 return; 191 event.set_timestamp_us(timestamp);
181 } 192 event.set_type(webrtc::ACMDumpEvent::DEBUG_EVENT);
182 193 event.clear_packet();
183 // Reuse the same object at every log event. 194 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)); 195 debug_event->set_type(convertDebugEvent(event_type));
191 debug_event->set_message(event_message); 196 debug_event->set_message(event_message);
197 if (CurrentlyLogging()) {
198 StoreToFile(&event);
199 } else {
200 StopIfNecessary();
201 AddRecentEvent(event);
202 }
203 }
204
205 void AcmDumpImpl::StoreToFile(ACMDumpEvent* event) {
206 // Reuse the same object at every log event.
207 if (stream_->stream_size() < 1) {
208 stream_->add_stream();
209 }
210 stream_->mutable_stream(0)->Swap(event);
terelius 2015/06/25 16:21:03 The stream must not contain more than one event, o
ivoc 2015/06/26 08:08:56 Done.
211
192 std::string dump_buffer; 212 std::string dump_buffer;
193 stream_->SerializeToString(&dump_buffer); 213 stream_->SerializeToString(&dump_buffer);
194 file_->Write(dump_buffer.data(), dump_buffer.size()); 214 file_->Write(dump_buffer.data(), dump_buffer.size());
195 } 215 }
196 216
217 void AcmDumpImpl::AddRecentEvent(const ACMDumpEvent& event) {
218 recent_log_events_.push_back(event);
219 while (recent_log_events_.front().timestamp_us() <
220 event.timestamp_us() - recent_log_duration_us) {
221 recent_log_events_.pop_front();
222 }
223 }
224
197 #endif // RTC_AUDIOCODING_DEBUG_DUMP 225 #endif // RTC_AUDIOCODING_DEBUG_DUMP
198 226
199 // AcmDump member functions. 227 // AcmDump member functions.
200 rtc::scoped_ptr<AcmDump> AcmDump::Create() { 228 rtc::scoped_ptr<AcmDump> AcmDump::Create() {
201 return rtc::scoped_ptr<AcmDump>(new AcmDumpImpl()); 229 return rtc::scoped_ptr<AcmDump>(new AcmDumpImpl());
202 } 230 }
203 231
204 bool AcmDump::ParseAcmDump(const std::string& file_name, 232 bool AcmDump::ParseAcmDump(const std::string& file_name,
205 ACMDumpEventStream* result) { 233 ACMDumpEventStream* result) {
206 char tmp_buffer[1024]; 234 char tmp_buffer[1024];
207 int bytes_read = 0; 235 int bytes_read = 0;
208 rtc::scoped_ptr<FileWrapper> dump_file(FileWrapper::Create()); 236 rtc::scoped_ptr<FileWrapper> dump_file(FileWrapper::Create());
209 if (dump_file->OpenFile(file_name.c_str(), true) != 0) { 237 if (dump_file->OpenFile(file_name.c_str(), true) != 0) {
210 return false; 238 return false;
211 } 239 }
212 std::string dump_buffer; 240 std::string dump_buffer;
213 while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) { 241 while ((bytes_read = dump_file->Read(tmp_buffer, sizeof(tmp_buffer))) > 0) {
214 dump_buffer.append(tmp_buffer, bytes_read); 242 dump_buffer.append(tmp_buffer, bytes_read);
215 } 243 }
216 dump_file->CloseFile(); 244 dump_file->CloseFile();
217 return result->ParseFromString(dump_buffer); 245 return result->ParseFromString(dump_buffer);
218 } 246 }
219 247
220 } // namespace webrtc 248 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/modules/audio_coding/main/acm2/acm_dump_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698