OLD | NEW |
---|---|
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/histogram.h" | 5 #include "base/histogram.h" |
6 #include "base/lock.h" | 6 #include "base/lock.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/process.h" | 8 #include "base/process.h" |
9 #include "base/shared_memory.h" | 9 #include "base/shared_memory.h" |
10 #include "base/waitable_event.h" | 10 #include "base/waitable_event.h" |
11 #include "chrome/browser/renderer_host/audio_renderer_host.h" | 11 #include "chrome/browser/renderer_host/audio_renderer_host.h" |
12 #include "chrome/common/ipc_logging.h" | |
12 #include "chrome/common/render_messages.h" | 13 #include "chrome/common/render_messages.h" |
13 | 14 |
14 namespace { | 15 namespace { |
15 | 16 |
16 void RecordIPCAudioLatency(base::TimeDelta latency) { | 17 void RecordRoundTripLatency(base::TimeDelta latency) { |
17 // Create a histogram of minimum 1ms and maximum 1000ms with 100 buckets. | 18 static ThreadSafeHistogram histogram("Audio.IPC_RoundTripLatency", |
18 static ThreadSafeHistogram histogram("Audio.IPCTransportLatency", | |
19 1, 1000, 100); | 19 1, 1000, 100); |
20 histogram.AddTime(latency); | 20 histogram.AddTime(latency); |
21 } | 21 } |
22 | 22 |
23 void RecordReceiveLatency(base::TimeDelta latency) { | |
24 static ThreadSafeHistogram histogram("Audio.IPC_Browser_ReceiveLatency", | |
25 1, 500, 100); | |
26 histogram.AddTime(latency); | |
27 } | |
28 | |
29 void RecordProcessTime(base::TimeDelta latency) { | |
30 static ThreadSafeHistogram histogram("Audio.IPC_Browser_ProcessTime", | |
31 1, 100, 100); | |
32 histogram.AddTime(latency); | |
33 } | |
34 | |
23 } // namespace | 35 } // namespace |
24 | 36 |
25 //----------------------------------------------------------------------------- | 37 //----------------------------------------------------------------------------- |
26 // AudioRendererHost::IPCAudioSource implementations. | 38 // AudioRendererHost::IPCAudioSource implementations. |
27 | 39 |
28 AudioRendererHost::IPCAudioSource::IPCAudioSource( | 40 AudioRendererHost::IPCAudioSource::IPCAudioSource( |
29 AudioRendererHost* host, | 41 AudioRendererHost* host, |
30 int process_id, | 42 int process_id, |
31 int route_id, | 43 int route_id, |
32 int stream_id, | 44 int stream_id, |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 return; | 157 return; |
146 double left_channel, right_channel; | 158 double left_channel, right_channel; |
147 stream_->GetVolume(&left_channel, &right_channel); | 159 stream_->GetVolume(&left_channel, &right_channel); |
148 host_->Send(new ViewMsg_NotifyAudioStreamVolume(route_id_, stream_id_, | 160 host_->Send(new ViewMsg_NotifyAudioStreamVolume(route_id_, stream_id_, |
149 left_channel, right_channel)); | 161 left_channel, right_channel)); |
150 } | 162 } |
151 | 163 |
152 size_t AudioRendererHost::IPCAudioSource::OnMoreData(AudioOutputStream* stream, | 164 size_t AudioRendererHost::IPCAudioSource::OnMoreData(AudioOutputStream* stream, |
153 void* dest, | 165 void* dest, |
154 size_t max_size) { | 166 size_t max_size) { |
155 base::TimeTicks tick_start = base::TimeTicks::HighResNow(); | 167 #ifdef IPC_MESSAGE_LOG_ENABLED |
scherkus (not reviewing)
2009/04/30 02:15:10
do you know how we get this defined?
| |
168 base::Time tick_start = base::Time::Now(); | |
scherkus (not reviewing)
2009/04/30 02:15:10
curious... why not HighResNow?
| |
169 #endif | |
156 { | 170 { |
157 AutoLock auto_lock(lock_); | 171 AutoLock auto_lock(lock_); |
158 // If we are ever stopped, don't ask for more audio packet from the | 172 // If we are ever stopped, don't ask for more audio packet from the |
159 // renderer. | 173 // renderer. |
160 if (stop_providing_packets_) | 174 if (stop_providing_packets_) |
161 return 0; | 175 return 0; |
162 } | 176 } |
163 | 177 |
164 // If we have an initial packet, use it immediately only in IO thread. | 178 // If we have an initial packet, use it immediately only in IO thread. |
165 // There's a case when IO thread is blocked and audio hardware thread can | 179 // There's a case when IO thread is blocked and audio hardware thread can |
(...skipping 22 matching lines...) Expand all Loading... | |
188 packet_read_event_.Wait(); | 202 packet_read_event_.Wait(); |
189 | 203 |
190 size_t last_packet_size = 0; | 204 size_t last_packet_size = 0; |
191 { | 205 { |
192 AutoLock auto_lock(lock_); | 206 AutoLock auto_lock(lock_); |
193 last_packet_size = last_packet_size_; | 207 last_packet_size = last_packet_size_; |
194 } | 208 } |
195 | 209 |
196 size_t copied = SafeCopyBuffer(dest, max_size, | 210 size_t copied = SafeCopyBuffer(dest, max_size, |
197 shared_memory_.memory(), last_packet_size); | 211 shared_memory_.memory(), last_packet_size); |
198 RecordIPCAudioLatency(base::TimeTicks::HighResNow() - tick_start); | 212 #ifdef IPC_MESSAGE_LOG_ENABLED |
213 // The logging to round trip latency doesn't have dependency on IPC logging. | |
214 // But it's good we use IPC logging to trigger logging of total latency. | |
215 if (IPC::Logging::current()->Enabled()) | |
216 RecordRoundTripLatency(base::Time::Now() - tick_start); | |
217 #endif | |
199 return copied; | 218 return copied; |
200 } | 219 } |
201 | 220 |
202 void AudioRendererHost::IPCAudioSource::OnClose(AudioOutputStream* stream) { | 221 void AudioRendererHost::IPCAudioSource::OnClose(AudioOutputStream* stream) { |
203 StopWaitingForPacket(); | 222 StopWaitingForPacket(); |
204 } | 223 } |
205 | 224 |
206 void AudioRendererHost::IPCAudioSource::OnError(AudioOutputStream* stream, | 225 void AudioRendererHost::IPCAudioSource::OnError(AudioOutputStream* stream, |
207 int code) { | 226 int code) { |
208 host_->SendErrorMessage(route_id_, stream_id_, code); | 227 host_->SendErrorMessage(route_id_, stream_id_, code); |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
406 | 425 |
407 void AudioRendererHost::OnNotifyPacketReady(const IPC::Message& msg, | 426 void AudioRendererHost::OnNotifyPacketReady(const IPC::Message& msg, |
408 int stream_id, size_t packet_size) { | 427 int stream_id, size_t packet_size) { |
409 DCHECK(MessageLoop::current() == io_loop_); | 428 DCHECK(MessageLoop::current() == io_loop_); |
410 IPCAudioSource* source = Lookup(msg.routing_id(), stream_id); | 429 IPCAudioSource* source = Lookup(msg.routing_id(), stream_id); |
411 if (source) { | 430 if (source) { |
412 source->NotifyPacketReady(packet_size); | 431 source->NotifyPacketReady(packet_size); |
413 } else { | 432 } else { |
414 SendErrorMessage(msg.routing_id(), stream_id, 0); | 433 SendErrorMessage(msg.routing_id(), stream_id, 0); |
415 } | 434 } |
435 #ifdef IPC_MESSAGE_LOG_ENABLED | |
436 if (IPC::Logging::current()->Enabled()) { | |
437 RecordReceiveLatency(base::Time::FromInternalValue(msg.received_time()) - | |
438 base::Time::FromInternalValue(msg.sent_time())); | |
439 RecordProcessTime(base::Time::Now() - | |
440 base::Time::FromInternalValue(msg.received_time())); | |
441 } | |
442 #endif | |
416 } | 443 } |
417 | 444 |
418 void AudioRendererHost::OnInitialized() { | 445 void AudioRendererHost::OnInitialized() { |
419 DCHECK(MessageLoop::current() == io_loop_); | 446 DCHECK(MessageLoop::current() == io_loop_); |
420 // Increase the ref count of this object so it is active until we do | 447 // Increase the ref count of this object so it is active until we do |
421 // Release(). | 448 // Release(). |
422 AddRef(); | 449 AddRef(); |
423 } | 450 } |
424 | 451 |
425 void AudioRendererHost::OnDestroyed() { | 452 void AudioRendererHost::OnDestroyed() { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 if (MessageLoop::current() == io_loop_) { | 518 if (MessageLoop::current() == io_loop_) { |
492 OnDestroySource(source); | 519 OnDestroySource(source); |
493 } else { | 520 } else { |
494 // TODO(hclam): make sure it's always safe to post a task to IO loop. | 521 // TODO(hclam): make sure it's always safe to post a task to IO loop. |
495 // It is possible that IO message loop is destroyed but there's still some | 522 // It is possible that IO message loop is destroyed but there's still some |
496 // dangling audio hardware threads that try to call this method. | 523 // dangling audio hardware threads that try to call this method. |
497 io_loop_->PostTask(FROM_HERE, | 524 io_loop_->PostTask(FROM_HERE, |
498 NewRunnableMethod(this, &AudioRendererHost::OnDestroySource, source)); | 525 NewRunnableMethod(this, &AudioRendererHost::OnDestroySource, source)); |
499 } | 526 } |
500 } | 527 } |
OLD | NEW |