| 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/media/audio_renderer_host.h" | 5 #include "content/browser/renderer_host/media/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 "content/browser/renderer_host/media/audio_common.h" | 10 #include "content/browser/renderer_host/media/audio_common.h" |
| 11 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 11 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
| 12 #include "content/common/media/audio_messages.h" | 12 #include "content/common/media/audio_messages.h" |
| 13 #include "ipc/ipc_logging.h" | 13 #include "ipc/ipc_logging.h" |
| 14 | 14 |
| 15 | 15 |
| 16 AudioRendererHost::AudioEntry::AudioEntry() | 16 AudioRendererHost::AudioEntry::AudioEntry() |
| 17 : render_view_id(0), | 17 : stream_id(0), |
| 18 stream_id(0), | |
| 19 pending_buffer_request(false), | 18 pending_buffer_request(false), |
| 20 pending_close(false) { | 19 pending_close(false) { |
| 21 } | 20 } |
| 22 | 21 |
| 23 AudioRendererHost::AudioEntry::~AudioEntry() {} | 22 AudioRendererHost::AudioEntry::~AudioEntry() {} |
| 24 | 23 |
| 25 /////////////////////////////////////////////////////////////////////////////// | |
| 26 // AudioRendererHost implementations. | |
| 27 AudioRendererHost::AudioRendererHost() { | 24 AudioRendererHost::AudioRendererHost() { |
| 28 } | 25 } |
| 29 | 26 |
| 30 AudioRendererHost::~AudioRendererHost() { | 27 AudioRendererHost::~AudioRendererHost() { |
| 31 DCHECK(audio_entries_.empty()); | 28 DCHECK(audio_entries_.empty()); |
| 32 } | 29 } |
| 33 | 30 |
| 34 void AudioRendererHost::OnChannelClosing() { | 31 void AudioRendererHost::OnChannelClosing() { |
| 35 BrowserMessageFilter::OnChannelClosing(); | 32 BrowserMessageFilter::OnChannelClosing(); |
| 36 | 33 |
| 37 // Since the IPC channel is gone, close all requested audio streams. | 34 // Since the IPC channel is gone, close all requested audio streams. |
| 38 DeleteEntries(); | 35 DeleteEntries(); |
| 39 } | 36 } |
| 40 | 37 |
| 41 void AudioRendererHost::OnDestruct() const { | 38 void AudioRendererHost::OnDestruct() const { |
| 42 BrowserThread::DeleteOnIOThread::Destruct(this); | 39 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 43 } | 40 } |
| 44 | 41 |
| 45 /////////////////////////////////////////////////////////////////////////////// | |
| 46 // media::AudioOutputController::EventHandler implementations. | |
| 47 void AudioRendererHost::OnCreated(media::AudioOutputController* controller) { | 42 void AudioRendererHost::OnCreated(media::AudioOutputController* controller) { |
| 48 BrowserThread::PostTask( | 43 BrowserThread::PostTask( |
| 49 BrowserThread::IO, | 44 BrowserThread::IO, |
| 50 FROM_HERE, | 45 FROM_HERE, |
| 51 NewRunnableMethod( | 46 NewRunnableMethod( |
| 52 this, | 47 this, |
| 53 &AudioRendererHost::DoCompleteCreation, | 48 &AudioRendererHost::DoCompleteCreation, |
| 54 make_scoped_refptr(controller))); | 49 make_scoped_refptr(controller))); |
| 55 } | 50 } |
| 56 | 51 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 128 |
| 134 // If we failed to prepare the sync socket for the renderer then we fail | 129 // If we failed to prepare the sync socket for the renderer then we fail |
| 135 // the construction of audio stream. | 130 // the construction of audio stream. |
| 136 if (!reader->PrepareForeignSocketHandle(peer_handle(), | 131 if (!reader->PrepareForeignSocketHandle(peer_handle(), |
| 137 &foreign_socket_handle)) { | 132 &foreign_socket_handle)) { |
| 138 DeleteEntryOnError(entry); | 133 DeleteEntryOnError(entry); |
| 139 return; | 134 return; |
| 140 } | 135 } |
| 141 | 136 |
| 142 Send(new AudioMsg_NotifyLowLatencyStreamCreated( | 137 Send(new AudioMsg_NotifyLowLatencyStreamCreated( |
| 143 entry->render_view_id, entry->stream_id, foreign_memory_handle, | 138 entry->stream_id, foreign_memory_handle, |
| 144 foreign_socket_handle, entry->shared_memory.created_size())); | 139 foreign_socket_handle, entry->shared_memory.created_size())); |
| 145 return; | 140 return; |
| 146 } | 141 } |
| 147 | 142 |
| 148 // The normal audio stream has created, send a message to the renderer | 143 // The normal audio stream has created, send a message to the renderer |
| 149 // process. | 144 // process. |
| 150 Send(new AudioMsg_NotifyStreamCreated( | 145 Send(new AudioMsg_NotifyStreamCreated( |
| 151 entry->render_view_id, entry->stream_id, foreign_memory_handle, | 146 entry->stream_id, foreign_memory_handle, |
| 152 entry->shared_memory.created_size())); | 147 entry->shared_memory.created_size())); |
| 153 } | 148 } |
| 154 | 149 |
| 155 void AudioRendererHost::DoSendPlayingMessage( | 150 void AudioRendererHost::DoSendPlayingMessage( |
| 156 media::AudioOutputController* controller) { | 151 media::AudioOutputController* controller) { |
| 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 158 | 153 |
| 159 AudioEntry* entry = LookupByController(controller); | 154 AudioEntry* entry = LookupByController(controller); |
| 160 if (!entry) | 155 if (!entry) |
| 161 return; | 156 return; |
| 162 | 157 |
| 163 Send(new AudioMsg_NotifyStreamStateChanged( | 158 Send(new AudioMsg_NotifyStreamStateChanged( |
| 164 entry->render_view_id, entry->stream_id, kAudioStreamPlaying)); | 159 entry->stream_id, kAudioStreamPlaying)); |
| 165 } | 160 } |
| 166 | 161 |
| 167 void AudioRendererHost::DoSendPausedMessage( | 162 void AudioRendererHost::DoSendPausedMessage( |
| 168 media::AudioOutputController* controller) { | 163 media::AudioOutputController* controller) { |
| 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 170 | 165 |
| 171 AudioEntry* entry = LookupByController(controller); | 166 AudioEntry* entry = LookupByController(controller); |
| 172 if (!entry) | 167 if (!entry) |
| 173 return; | 168 return; |
| 174 | 169 |
| 175 Send(new AudioMsg_NotifyStreamStateChanged( | 170 Send(new AudioMsg_NotifyStreamStateChanged( |
| 176 entry->render_view_id, entry->stream_id, kAudioStreamPaused)); | 171 entry->stream_id, kAudioStreamPaused)); |
| 177 } | 172 } |
| 178 | 173 |
| 179 void AudioRendererHost::DoRequestMoreData( | 174 void AudioRendererHost::DoRequestMoreData( |
| 180 media::AudioOutputController* controller, | 175 media::AudioOutputController* controller, |
| 181 AudioBuffersState buffers_state) { | 176 AudioBuffersState buffers_state) { |
| 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 183 | 178 |
| 184 // If we already have a pending request then return. | 179 // If we already have a pending request then return. |
| 185 AudioEntry* entry = LookupByController(controller); | 180 AudioEntry* entry = LookupByController(controller); |
| 186 if (!entry || entry->pending_buffer_request) | 181 if (!entry || entry->pending_buffer_request) |
| 187 return; | 182 return; |
| 188 | 183 |
| 189 DCHECK(!entry->controller->LowLatencyMode()); | 184 DCHECK(!entry->controller->LowLatencyMode()); |
| 190 entry->pending_buffer_request = true; | 185 entry->pending_buffer_request = true; |
| 191 Send(new AudioMsg_RequestPacket( | 186 Send(new AudioMsg_RequestPacket(entry->stream_id, buffers_state)); |
| 192 entry->render_view_id, entry->stream_id, buffers_state)); | |
| 193 } | 187 } |
| 194 | 188 |
| 195 void AudioRendererHost::DoHandleError(media::AudioOutputController* controller, | 189 void AudioRendererHost::DoHandleError(media::AudioOutputController* controller, |
| 196 int error_code) { | 190 int error_code) { |
| 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 198 | 192 |
| 199 AudioEntry* entry = LookupByController(controller); | 193 AudioEntry* entry = LookupByController(controller); |
| 200 if (!entry) | 194 if (!entry) |
| 201 return; | 195 return; |
| 202 | 196 |
| 203 DeleteEntryOnError(entry); | 197 DeleteEntryOnError(entry); |
| 204 } | 198 } |
| 205 | 199 |
| 206 /////////////////////////////////////////////////////////////////////////////// | |
| 207 // IPC Messages handler | |
| 208 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message, | 200 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message, |
| 209 bool* message_was_ok) { | 201 bool* message_was_ok) { |
| 210 bool handled = true; | 202 bool handled = true; |
| 211 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok) | 203 IPC_BEGIN_MESSAGE_MAP_EX(AudioRendererHost, message, *message_was_ok) |
| 212 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) | 204 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) |
| 213 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) | 205 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) |
| 214 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) | 206 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) |
| 215 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) | 207 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) |
| 216 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | 208 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) |
| 217 IPC_MESSAGE_HANDLER(AudioHostMsg_NotifyPacketReady, OnNotifyPacketReady) | 209 IPC_MESSAGE_HANDLER(AudioHostMsg_NotifyPacketReady, OnNotifyPacketReady) |
| 218 IPC_MESSAGE_HANDLER(AudioHostMsg_GetVolume, OnGetVolume) | 210 IPC_MESSAGE_HANDLER(AudioHostMsg_GetVolume, OnGetVolume) |
| 219 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | 211 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
| 220 IPC_MESSAGE_UNHANDLED(handled = false) | 212 IPC_MESSAGE_UNHANDLED(handled = false) |
| 221 IPC_END_MESSAGE_MAP_EX() | 213 IPC_END_MESSAGE_MAP_EX() |
| 222 | 214 |
| 223 return handled; | 215 return handled; |
| 224 } | 216 } |
| 225 | 217 |
| 226 void AudioRendererHost::OnCreateStream( | 218 void AudioRendererHost::OnCreateStream( |
| 227 const IPC::Message& msg, int stream_id, | 219 int stream_id, const AudioParameters& params, bool low_latency) { |
| 228 const AudioParameters& params, bool low_latency) { | |
| 229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 230 DCHECK(LookupById(msg.routing_id(), stream_id) == NULL); | 221 DCHECK(LookupById(stream_id) == NULL); |
| 231 | 222 |
| 232 AudioParameters audio_params(params); | 223 AudioParameters audio_params(params); |
| 233 | 224 |
| 234 // Select the hardware packet size if not specified. | 225 // Select the hardware packet size if not specified. |
| 235 if (!audio_params.samples_per_packet) { | 226 if (!audio_params.samples_per_packet) { |
| 236 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); | 227 audio_params.samples_per_packet = SelectSamplesPerPacket(audio_params); |
| 237 } | 228 } |
| 238 uint32 packet_size = audio_params.GetPacketSize(); | 229 uint32 packet_size = audio_params.GetPacketSize(); |
| 239 | 230 |
| 240 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 231 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
| 241 // Create the shared memory and share with the renderer process. | 232 // Create the shared memory and share with the renderer process. |
| 242 if (!entry->shared_memory.CreateAndMapAnonymous(packet_size)) { | 233 if (!entry->shared_memory.CreateAndMapAnonymous(packet_size)) { |
| 243 // If creation of shared memory failed then send an error message. | 234 // If creation of shared memory failed then send an error message. |
| 244 SendErrorMessage(msg.routing_id(), stream_id); | 235 SendErrorMessage(stream_id); |
| 245 return; | 236 return; |
| 246 } | 237 } |
| 247 | 238 |
| 248 if (low_latency) { | 239 if (low_latency) { |
| 249 // If this is the low latency mode, we need to construct a SyncReader first. | 240 // If this is the low latency mode, we need to construct a SyncReader first. |
| 250 scoped_ptr<AudioSyncReader> reader( | 241 scoped_ptr<AudioSyncReader> reader( |
| 251 new AudioSyncReader(&entry->shared_memory)); | 242 new AudioSyncReader(&entry->shared_memory)); |
| 252 | 243 |
| 253 // Then try to initialize the sync reader. | 244 // Then try to initialize the sync reader. |
| 254 if (!reader->Init()) { | 245 if (!reader->Init()) { |
| 255 SendErrorMessage(msg.routing_id(), stream_id); | 246 SendErrorMessage(stream_id); |
| 256 return; | 247 return; |
| 257 } | 248 } |
| 258 | 249 |
| 259 // If we have successfully created the SyncReader then assign it to the | 250 // If we have successfully created the SyncReader then assign it to the |
| 260 // entry and construct an AudioOutputController. | 251 // entry and construct an AudioOutputController. |
| 261 entry->reader.reset(reader.release()); | 252 entry->reader.reset(reader.release()); |
| 262 entry->controller = | 253 entry->controller = |
| 263 media::AudioOutputController::CreateLowLatency(this, audio_params, | 254 media::AudioOutputController::CreateLowLatency(this, audio_params, |
| 264 entry->reader.get()); | 255 entry->reader.get()); |
| 265 } else { | 256 } else { |
| 266 // The choice of buffer capacity is based on experiment. | 257 // The choice of buffer capacity is based on experiment. |
| 267 entry->controller = | 258 entry->controller = |
| 268 media::AudioOutputController::Create(this, audio_params, | 259 media::AudioOutputController::Create(this, audio_params, |
| 269 3 * packet_size); | 260 3 * packet_size); |
| 270 } | 261 } |
| 271 | 262 |
| 272 if (!entry->controller) { | 263 if (!entry->controller) { |
| 273 SendErrorMessage(msg.routing_id(), stream_id); | 264 SendErrorMessage(stream_id); |
| 274 return; | 265 return; |
| 275 } | 266 } |
| 276 | 267 |
| 277 // If we have created the controller successfully create a entry and add it | 268 // If we have created the controller successfully create a entry and add it |
| 278 // to the map. | 269 // to the map. |
| 279 entry->render_view_id = msg.routing_id(); | |
| 280 entry->stream_id = stream_id; | 270 entry->stream_id = stream_id; |
| 281 | 271 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
| 282 audio_entries_.insert(std::make_pair( | |
| 283 AudioEntryId(msg.routing_id(), stream_id), | |
| 284 entry.release())); | |
| 285 } | 272 } |
| 286 | 273 |
| 287 void AudioRendererHost::OnPlayStream(const IPC::Message& msg, int stream_id) { | 274 void AudioRendererHost::OnPlayStream(int stream_id) { |
| 288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 289 | 276 |
| 290 AudioEntry* entry = LookupById(msg.routing_id(), stream_id); | 277 AudioEntry* entry = LookupById(stream_id); |
| 291 if (!entry) { | 278 if (!entry) { |
| 292 SendErrorMessage(msg.routing_id(), stream_id); | 279 SendErrorMessage(stream_id); |
| 293 return; | 280 return; |
| 294 } | 281 } |
| 295 | 282 |
| 296 entry->controller->Play(); | 283 entry->controller->Play(); |
| 297 } | 284 } |
| 298 | 285 |
| 299 void AudioRendererHost::OnPauseStream(const IPC::Message& msg, int stream_id) { | 286 void AudioRendererHost::OnPauseStream(int stream_id) { |
| 300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 301 | 288 |
| 302 AudioEntry* entry = LookupById(msg.routing_id(), stream_id); | 289 AudioEntry* entry = LookupById(stream_id); |
| 303 if (!entry) { | 290 if (!entry) { |
| 304 SendErrorMessage(msg.routing_id(), stream_id); | 291 SendErrorMessage(stream_id); |
| 305 return; | 292 return; |
| 306 } | 293 } |
| 307 | 294 |
| 308 entry->controller->Pause(); | 295 entry->controller->Pause(); |
| 309 } | 296 } |
| 310 | 297 |
| 311 void AudioRendererHost::OnFlushStream(const IPC::Message& msg, int stream_id) { | 298 void AudioRendererHost::OnFlushStream(int stream_id) { |
| 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 313 | 300 |
| 314 AudioEntry* entry = LookupById(msg.routing_id(), stream_id); | 301 AudioEntry* entry = LookupById(stream_id); |
| 315 if (!entry) { | 302 if (!entry) { |
| 316 SendErrorMessage(msg.routing_id(), stream_id); | 303 SendErrorMessage(stream_id); |
| 317 return; | 304 return; |
| 318 } | 305 } |
| 319 | 306 |
| 320 entry->controller->Flush(); | 307 entry->controller->Flush(); |
| 321 } | 308 } |
| 322 | 309 |
| 323 void AudioRendererHost::OnCloseStream(const IPC::Message& msg, int stream_id) { | 310 void AudioRendererHost::OnCloseStream(int stream_id) { |
| 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 325 | 312 |
| 326 AudioEntry* entry = LookupById(msg.routing_id(), stream_id); | 313 AudioEntry* entry = LookupById(stream_id); |
| 327 | 314 |
| 328 if (entry) | 315 if (entry) |
| 329 CloseAndDeleteStream(entry); | 316 CloseAndDeleteStream(entry); |
| 330 } | 317 } |
| 331 | 318 |
| 332 void AudioRendererHost::OnSetVolume(const IPC::Message& msg, int stream_id, | 319 void AudioRendererHost::OnSetVolume(int stream_id, |
| 333 double volume) { | 320 double volume) { |
| 334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 335 | 322 |
| 336 AudioEntry* entry = LookupById(msg.routing_id(), stream_id); | 323 AudioEntry* entry = LookupById(stream_id); |
| 337 if (!entry) { | 324 if (!entry) { |
| 338 SendErrorMessage(msg.routing_id(), stream_id); | 325 SendErrorMessage(stream_id); |
| 339 return; | 326 return; |
| 340 } | 327 } |
| 341 | 328 |
| 342 // Make sure the volume is valid. | 329 // Make sure the volume is valid. |
| 343 if (volume < 0 || volume > 1.0) | 330 if (volume < 0 || volume > 1.0) |
| 344 return; | 331 return; |
| 345 entry->controller->SetVolume(volume); | 332 entry->controller->SetVolume(volume); |
| 346 } | 333 } |
| 347 | 334 |
| 348 void AudioRendererHost::OnGetVolume(const IPC::Message& msg, int stream_id) { | 335 void AudioRendererHost::OnGetVolume(int stream_id) { |
| 349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 350 NOTREACHED() << "This message shouldn't be received"; | 337 NOTREACHED() << "This message shouldn't be received"; |
| 351 } | 338 } |
| 352 | 339 |
| 353 void AudioRendererHost::OnNotifyPacketReady( | 340 void AudioRendererHost::OnNotifyPacketReady(int stream_id, uint32 packet_size) { |
| 354 const IPC::Message& msg, int stream_id, uint32 packet_size) { | |
| 355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 356 | 342 |
| 357 AudioEntry* entry = LookupById(msg.routing_id(), stream_id); | 343 AudioEntry* entry = LookupById(stream_id); |
| 358 if (!entry) { | 344 if (!entry) { |
| 359 SendErrorMessage(msg.routing_id(), stream_id); | 345 SendErrorMessage(stream_id); |
| 360 return; | 346 return; |
| 361 } | 347 } |
| 362 | 348 |
| 363 DCHECK(!entry->controller->LowLatencyMode()); | 349 DCHECK(!entry->controller->LowLatencyMode()); |
| 364 CHECK(packet_size <= entry->shared_memory.created_size()); | 350 CHECK(packet_size <= entry->shared_memory.created_size()); |
| 365 | 351 |
| 366 if (!entry->pending_buffer_request) { | 352 if (!entry->pending_buffer_request) { |
| 367 NOTREACHED() << "Buffer received but no such pending request"; | 353 NOTREACHED() << "Buffer received but no such pending request"; |
| 368 } | 354 } |
| 369 entry->pending_buffer_request = false; | 355 entry->pending_buffer_request = false; |
| 370 | 356 |
| 371 // Enqueue the data to media::AudioOutputController. | 357 // Enqueue the data to media::AudioOutputController. |
| 372 entry->controller->EnqueueData( | 358 entry->controller->EnqueueData( |
| 373 reinterpret_cast<uint8*>(entry->shared_memory.memory()), | 359 reinterpret_cast<uint8*>(entry->shared_memory.memory()), |
| 374 packet_size); | 360 packet_size); |
| 375 } | 361 } |
| 376 | 362 |
| 377 void AudioRendererHost::SendErrorMessage(int32 render_view_id, | 363 void AudioRendererHost::SendErrorMessage(int stream_id) { |
| 378 int32 stream_id) { | |
| 379 Send(new AudioMsg_NotifyStreamStateChanged( | 364 Send(new AudioMsg_NotifyStreamStateChanged( |
| 380 render_view_id, stream_id, kAudioStreamError)); | 365 stream_id, kAudioStreamError)); |
| 381 } | 366 } |
| 382 | 367 |
| 383 void AudioRendererHost::DeleteEntries() { | 368 void AudioRendererHost::DeleteEntries() { |
| 384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 385 | 370 |
| 386 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 371 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
| 387 i != audio_entries_.end(); ++i) { | 372 i != audio_entries_.end(); ++i) { |
| 388 CloseAndDeleteStream(i->second); | 373 CloseAndDeleteStream(i->second); |
| 389 } | 374 } |
| 390 } | 375 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 403 BrowserThread::IO, FROM_HERE, | 388 BrowserThread::IO, FROM_HERE, |
| 404 NewRunnableMethod(this, &AudioRendererHost::DeleteEntry, entry)); | 389 NewRunnableMethod(this, &AudioRendererHost::DeleteEntry, entry)); |
| 405 } | 390 } |
| 406 | 391 |
| 407 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { | 392 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { |
| 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 409 | 394 |
| 410 // Delete the entry when this method goes out of scope. | 395 // Delete the entry when this method goes out of scope. |
| 411 scoped_ptr<AudioEntry> entry_deleter(entry); | 396 scoped_ptr<AudioEntry> entry_deleter(entry); |
| 412 | 397 |
| 413 // Erase the entry from the map. | 398 // Erase the entry identified by |stream_id| from the map. |
| 414 audio_entries_.erase( | 399 audio_entries_.erase(entry->stream_id); |
| 415 AudioEntryId(entry->render_view_id, entry->stream_id)); | |
| 416 } | 400 } |
| 417 | 401 |
| 418 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { | 402 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { |
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 420 | 404 |
| 421 // Sends the error message first before we close the stream because | 405 // Sends the error message first before we close the stream because |
| 422 // |entry| is destroyed in DeleteEntry(). | 406 // |entry| is destroyed in DeleteEntry(). |
| 423 SendErrorMessage(entry->render_view_id, entry->stream_id); | 407 SendErrorMessage(entry->stream_id); |
| 424 CloseAndDeleteStream(entry); | 408 CloseAndDeleteStream(entry); |
| 425 } | 409 } |
| 426 | 410 |
| 427 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById( | 411 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
| 428 int route_id, int stream_id) { | |
| 429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 430 | 413 |
| 431 AudioEntryMap::iterator i = audio_entries_.find( | 414 AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
| 432 AudioEntryId(route_id, stream_id)); | |
| 433 if (i != audio_entries_.end() && !i->second->pending_close) | 415 if (i != audio_entries_.end() && !i->second->pending_close) |
| 434 return i->second; | 416 return i->second; |
| 435 return NULL; | 417 return NULL; |
| 436 } | 418 } |
| 437 | 419 |
| 438 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( | 420 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( |
| 439 media::AudioOutputController* controller) { | 421 media::AudioOutputController* controller) { |
| 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 422 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 441 | 423 |
| 442 // Iterate the map of entries. | 424 // Iterate the map of entries. |
| 443 // TODO(hclam): Implement a faster look up method. | |
| 444 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 425 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
| 445 i != audio_entries_.end(); ++i) { | 426 i != audio_entries_.end(); ++i) { |
| 446 if (!i->second->pending_close && controller == i->second->controller.get()) | 427 if (!i->second->pending_close && controller == i->second->controller.get()) |
| 447 return i->second; | 428 return i->second; |
| 448 } | 429 } |
| 449 return NULL; | 430 return NULL; |
| 450 } | 431 } |
| OLD | NEW |