| 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 |