OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/renderer_host/audio_renderer_host.h" | 5 #include "content/browser/renderer_host/audio_renderer_host.h" |
6 | 6 |
7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.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 "chrome/common/render_messages.h" | |
11 #include "chrome/common/render_messages_params.h" | |
12 #include "content/browser/renderer_host/audio_sync_reader.h" | 10 #include "content/browser/renderer_host/audio_sync_reader.h" |
| 11 #include "content/common/audio_messages.h" |
13 #include "ipc/ipc_logging.h" | 12 #include "ipc/ipc_logging.h" |
14 | 13 |
15 namespace { | 14 namespace { |
16 | 15 |
17 // The minimum number of samples in a hardware packet. | 16 // The minimum number of samples in a hardware packet. |
18 // This value is selected so that we can handle down to 5khz sample rate. | 17 // This value is selected so that we can handle down to 5khz sample rate. |
19 const int kMinSamplesPerHardwarePacket = 1024; | 18 const int kMinSamplesPerHardwarePacket = 1024; |
20 | 19 |
21 // The maximum number of samples in a hardware packet. | 20 // The maximum number of samples in a hardware packet. |
22 // This value is selected so that we can handle up to 192khz sample rate. | 21 // This value is selected so that we can handle up to 192khz sample rate. |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 #endif | 159 #endif |
161 | 160 |
162 // If we failed to prepare the sync socket for the renderer then we fail | 161 // If we failed to prepare the sync socket for the renderer then we fail |
163 // the construction of audio stream. | 162 // the construction of audio stream. |
164 if (!reader->PrepareForeignSocketHandle(peer_handle(), | 163 if (!reader->PrepareForeignSocketHandle(peer_handle(), |
165 &foreign_socket_handle)) { | 164 &foreign_socket_handle)) { |
166 DeleteEntryOnError(entry); | 165 DeleteEntryOnError(entry); |
167 return; | 166 return; |
168 } | 167 } |
169 | 168 |
170 Send(new ViewMsg_NotifyLowLatencyAudioStreamCreated( | 169 Send(new AudioMsg_NotifyLowLatencyStreamCreated( |
171 entry->render_view_id, entry->stream_id, foreign_memory_handle, | 170 entry->render_view_id, entry->stream_id, foreign_memory_handle, |
172 foreign_socket_handle, entry->shared_memory.created_size())); | 171 foreign_socket_handle, entry->shared_memory.created_size())); |
173 return; | 172 return; |
174 } | 173 } |
175 | 174 |
176 // The normal audio stream has created, send a message to the renderer | 175 // The normal audio stream has created, send a message to the renderer |
177 // process. | 176 // process. |
178 Send(new ViewMsg_NotifyAudioStreamCreated( | 177 Send(new AudioMsg_NotifyStreamCreated( |
179 entry->render_view_id, entry->stream_id, foreign_memory_handle, | 178 entry->render_view_id, entry->stream_id, foreign_memory_handle, |
180 entry->shared_memory.created_size())); | 179 entry->shared_memory.created_size())); |
181 } | 180 } |
182 | 181 |
183 void AudioRendererHost::DoSendPlayingMessage( | 182 void AudioRendererHost::DoSendPlayingMessage( |
184 media::AudioOutputController* controller) { | 183 media::AudioOutputController* controller) { |
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
186 | 185 |
187 AudioEntry* entry = LookupByController(controller); | 186 AudioEntry* entry = LookupByController(controller); |
188 if (!entry) | 187 if (!entry) |
189 return; | 188 return; |
190 | 189 |
191 ViewMsg_AudioStreamState_Params params; | 190 Send(new AudioMsg_NotifyStreamStateChanged( |
192 params.state = ViewMsg_AudioStreamState_Params::kPlaying; | 191 entry->render_view_id, entry->stream_id, kAudioStreamPlaying)); |
193 Send(new ViewMsg_NotifyAudioStreamStateChanged( | |
194 entry->render_view_id, entry->stream_id, params)); | |
195 } | 192 } |
196 | 193 |
197 void AudioRendererHost::DoSendPausedMessage( | 194 void AudioRendererHost::DoSendPausedMessage( |
198 media::AudioOutputController* controller) { | 195 media::AudioOutputController* controller) { |
199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
200 | 197 |
201 AudioEntry* entry = LookupByController(controller); | 198 AudioEntry* entry = LookupByController(controller); |
202 if (!entry) | 199 if (!entry) |
203 return; | 200 return; |
204 | 201 |
205 ViewMsg_AudioStreamState_Params params; | 202 Send(new AudioMsg_NotifyStreamStateChanged( |
206 params.state = ViewMsg_AudioStreamState_Params::kPaused; | 203 entry->render_view_id, entry->stream_id, kAudioStreamPaused)); |
207 Send(new ViewMsg_NotifyAudioStreamStateChanged( | |
208 entry->render_view_id, entry->stream_id, params)); | |
209 } | 204 } |
210 | 205 |
211 void AudioRendererHost::DoRequestMoreData( | 206 void AudioRendererHost::DoRequestMoreData( |
212 media::AudioOutputController* controller, | 207 media::AudioOutputController* controller, |
213 AudioBuffersState buffers_state) { | 208 AudioBuffersState buffers_state) { |
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
215 | 210 |
216 // If we already have a pending request then return. | 211 // If we already have a pending request then return. |
217 AudioEntry* entry = LookupByController(controller); | 212 AudioEntry* entry = LookupByController(controller); |
218 if (!entry || entry->pending_buffer_request) | 213 if (!entry || entry->pending_buffer_request) |
219 return; | 214 return; |
220 | 215 |
221 DCHECK(!entry->controller->LowLatencyMode()); | 216 DCHECK(!entry->controller->LowLatencyMode()); |
222 entry->pending_buffer_request = true; | 217 entry->pending_buffer_request = true; |
223 Send(new ViewMsg_RequestAudioPacket( | 218 Send(new AudioMsg_RequestPacket( |
224 entry->render_view_id, entry->stream_id, buffers_state)); | 219 entry->render_view_id, entry->stream_id, buffers_state)); |
225 } | 220 } |
226 | 221 |
227 void AudioRendererHost::DoHandleError(media::AudioOutputController* controller, | 222 void AudioRendererHost::DoHandleError(media::AudioOutputController* controller, |
228 int error_code) { | 223 int error_code) { |
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
230 | 225 |
231 AudioEntry* entry = LookupByController(controller); | 226 AudioEntry* entry = LookupByController(controller); |
232 if (!entry) | 227 if (!entry) |
233 return; | 228 return; |
234 | 229 |
235 DeleteEntryOnError(entry); | 230 DeleteEntryOnError(entry); |
236 } | 231 } |
237 | 232 |
238 /////////////////////////////////////////////////////////////////////////////// | 233 /////////////////////////////////////////////////////////////////////////////// |
239 // IPC Messages handler | 234 // IPC Messages handler |
240 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message, | 235 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message, |
241 bool* message_was_ok) { | 236 bool* message_was_ok) { |
242 bool handled = true; | 237 bool handled = true; |
243 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok) | 238 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok) |
244 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateAudioStream, OnCreateStream) | 239 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) |
245 IPC_MESSAGE_HANDLER(ViewHostMsg_PlayAudioStream, OnPlayStream) | 240 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) |
246 IPC_MESSAGE_HANDLER(ViewHostMsg_PauseAudioStream, OnPauseStream) | 241 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) |
247 IPC_MESSAGE_HANDLER(ViewHostMsg_FlushAudioStream, OnFlushStream) | 242 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) |
248 IPC_MESSAGE_HANDLER(ViewHostMsg_CloseAudioStream, OnCloseStream) | 243 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) |
249 IPC_MESSAGE_HANDLER(ViewHostMsg_NotifyAudioPacketReady, OnNotifyPacketReady) | 244 IPC_MESSAGE_HANDLER(AudioHostMsg_NotifyPacketReady, OnNotifyPacketReady) |
250 IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioVolume, OnGetVolume) | 245 IPC_MESSAGE_HANDLER(AudioHostMsg_GetVolume, OnGetVolume) |
251 IPC_MESSAGE_HANDLER(ViewHostMsg_SetAudioVolume, OnSetVolume) | 246 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
252 IPC_MESSAGE_UNHANDLED(handled = false) | 247 IPC_MESSAGE_UNHANDLED(handled = false) |
253 IPC_END_MESSAGE_MAP_EX() | 248 IPC_END_MESSAGE_MAP_EX() |
254 | 249 |
255 return handled; | 250 return handled; |
256 } | 251 } |
257 | 252 |
258 void AudioRendererHost::OnCreateStream( | 253 void AudioRendererHost::OnCreateStream( |
259 const IPC::Message& msg, int stream_id, | 254 const IPC::Message& msg, int stream_id, |
260 const ViewHostMsg_Audio_CreateStream_Params& params, bool low_latency) { | 255 const AudioParameters& params, bool low_latency) { |
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
262 DCHECK(LookupById(msg.routing_id(), stream_id) == NULL); | 257 DCHECK(LookupById(msg.routing_id(), stream_id) == NULL); |
263 | 258 |
264 AudioParameters audio_params(params.params); | 259 AudioParameters audio_params(params); |
265 | 260 |
266 // Select the hardware packet size if not specified. | 261 // Select the hardware packet size if not specified. |
267 if (!audio_params.samples_per_packet) { | 262 if (!audio_params.samples_per_packet) { |
268 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); | 263 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); |
269 } | 264 } |
270 uint32 packet_size = audio_params.GetPacketSize(); | 265 uint32 packet_size = audio_params.GetPacketSize(); |
271 | 266 |
272 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 267 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
273 // Create the shared memory and share with the renderer process. | 268 // Create the shared memory and share with the renderer process. |
274 if (!entry->shared_memory.CreateAndMapAnonymous(packet_size)) { | 269 if (!entry->shared_memory.CreateAndMapAnonymous(packet_size)) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 entry->pending_buffer_request = false; | 396 entry->pending_buffer_request = false; |
402 | 397 |
403 // Enqueue the data to media::AudioOutputController. | 398 // Enqueue the data to media::AudioOutputController. |
404 entry->controller->EnqueueData( | 399 entry->controller->EnqueueData( |
405 reinterpret_cast<uint8*>(entry->shared_memory.memory()), | 400 reinterpret_cast<uint8*>(entry->shared_memory.memory()), |
406 packet_size); | 401 packet_size); |
407 } | 402 } |
408 | 403 |
409 void AudioRendererHost::SendErrorMessage(int32 render_view_id, | 404 void AudioRendererHost::SendErrorMessage(int32 render_view_id, |
410 int32 stream_id) { | 405 int32 stream_id) { |
411 ViewMsg_AudioStreamState_Params state; | 406 Send(new AudioMsg_NotifyStreamStateChanged( |
412 state.state = ViewMsg_AudioStreamState_Params::kError; | 407 render_view_id, stream_id, kAudioStreamError)); |
413 Send(new ViewMsg_NotifyAudioStreamStateChanged( | |
414 render_view_id, stream_id, state)); | |
415 } | 408 } |
416 | 409 |
417 void AudioRendererHost::DeleteEntries() { | 410 void AudioRendererHost::DeleteEntries() { |
418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
419 | 412 |
420 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 413 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
421 i != audio_entries_.end(); ++i) { | 414 i != audio_entries_.end(); ++i) { |
422 CloseAndDeleteStream(i->second); | 415 CloseAndDeleteStream(i->second); |
423 } | 416 } |
424 } | 417 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 | 468 |
476 // Iterate the map of entries. | 469 // Iterate the map of entries. |
477 // TODO(hclam): Implement a faster look up method. | 470 // TODO(hclam): Implement a faster look up method. |
478 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 471 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
479 i != audio_entries_.end(); ++i) { | 472 i != audio_entries_.end(); ++i) { |
480 if (!i->second->pending_close && controller == i->second->controller.get()) | 473 if (!i->second->pending_close && controller == i->second->controller.get()) |
481 return i->second; | 474 return i->second; |
482 } | 475 } |
483 return NULL; | 476 return NULL; |
484 } | 477 } |
OLD | NEW |