OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/bind.h" | 7 #include "base/bind.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/process.h" | 9 #include "base/process.h" |
10 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
11 #include "content/browser/browser_main_loop.h" | 11 #include "content/browser/browser_main_loop.h" |
12 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 12 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
13 #include "content/common/media/audio_messages.h" | 13 #include "content/common/media/audio_messages.h" |
14 #include "content/public/browser/media_observer.h" | 14 #include "content/public/browser/media_observer.h" |
15 #include "media/audio/audio_util.h" | 15 #include "media/audio/audio_util.h" |
16 | 16 |
17 using content::BrowserMessageFilter; | 17 using content::BrowserMessageFilter; |
18 using content::BrowserThread; | 18 using content::BrowserThread; |
19 | 19 |
20 AudioRendererHost::AudioEntry::AudioEntry() | 20 AudioRendererHost::AudioEntry::AudioEntry() |
21 : stream_id(0), | 21 : stream_id(0), |
22 pending_close(false) { | 22 pending_close(false) { |
23 } | 23 } |
24 | 24 |
25 AudioRendererHost::AudioEntry::~AudioEntry() {} | 25 AudioRendererHost::AudioEntry::~AudioEntry() {} |
26 | 26 |
27 /////////////////////////////////////////////////////////////////////////////// | 27 /////////////////////////////////////////////////////////////////////////////// |
28 // AudioRendererHost implementations. | 28 // AudioRendererHost implementations. |
29 AudioRendererHost::AudioRendererHost( | 29 AudioRendererHost::AudioRendererHost( |
| 30 int render_process_id, |
30 media::AudioManager* audio_manager, | 31 media::AudioManager* audio_manager, |
31 content::MediaObserver* media_observer) | 32 content::MediaObserver* media_observer) |
32 : audio_manager_(audio_manager), | 33 : render_process_id_(render_process_id), |
| 34 audio_manager_(audio_manager), |
33 media_observer_(media_observer) { | 35 media_observer_(media_observer) { |
34 } | 36 } |
35 | 37 |
36 AudioRendererHost::~AudioRendererHost() { | 38 AudioRendererHost::~AudioRendererHost() { |
37 DCHECK(audio_entries_.empty()); | 39 DCHECK(audio_entries_.empty()); |
38 } | 40 } |
39 | 41 |
40 void AudioRendererHost::OnChannelClosing() { | 42 void AudioRendererHost::OnChannelClosing() { |
41 BrowserMessageFilter::OnChannelClosing(); | 43 BrowserMessageFilter::OnChannelClosing(); |
42 | 44 |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 audio_manager_, this, audio_params, entry->reader.get()); | 232 audio_manager_, this, audio_params, entry->reader.get()); |
231 | 233 |
232 if (!entry->controller) { | 234 if (!entry->controller) { |
233 SendErrorMessage(stream_id); | 235 SendErrorMessage(stream_id); |
234 return; | 236 return; |
235 } | 237 } |
236 | 238 |
237 // If we have created the controller successfully, create an entry and add it | 239 // If we have created the controller successfully, create an entry and add it |
238 // to the map. | 240 // to the map. |
239 entry->stream_id = stream_id; | 241 entry->stream_id = stream_id; |
| 242 entry->render_view_id = render_view_id; |
240 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 243 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
241 if (media_observer_) | 244 if (media_observer_) { |
242 media_observer_->OnSetAudioStreamStatus(this, stream_id, "created"); | 245 media_observer_->OnSetAudioStreamStatus( |
| 246 render_process_id_, render_view_id, stream_id, "created"); |
| 247 } |
243 } | 248 } |
244 | 249 |
245 void AudioRendererHost::OnPlayStream(int stream_id) { | 250 void AudioRendererHost::OnPlayStream(int stream_id) { |
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
247 | 252 |
248 AudioEntry* entry = LookupById(stream_id); | 253 AudioEntry* entry = LookupById(stream_id); |
249 if (!entry) { | 254 if (!entry) { |
250 SendErrorMessage(stream_id); | 255 SendErrorMessage(stream_id); |
251 return; | 256 return; |
252 } | 257 } |
253 | 258 |
254 entry->controller->Play(); | 259 entry->controller->Play(); |
255 if (media_observer_) | 260 if (media_observer_) { |
256 media_observer_->OnSetAudioStreamPlaying(this, stream_id, true); | 261 media_observer_->OnSetAudioStreamPlaying( |
| 262 render_process_id_, entry->render_view_id, stream_id, true); |
| 263 } |
257 } | 264 } |
258 | 265 |
259 void AudioRendererHost::OnPauseStream(int stream_id) { | 266 void AudioRendererHost::OnPauseStream(int stream_id) { |
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
261 | 268 |
262 AudioEntry* entry = LookupById(stream_id); | 269 AudioEntry* entry = LookupById(stream_id); |
263 if (!entry) { | 270 if (!entry) { |
264 SendErrorMessage(stream_id); | 271 SendErrorMessage(stream_id); |
265 return; | 272 return; |
266 } | 273 } |
267 | 274 |
268 entry->controller->Pause(); | 275 entry->controller->Pause(); |
269 if (media_observer_) | 276 if (media_observer_) { |
270 media_observer_->OnSetAudioStreamPlaying(this, stream_id, false); | 277 media_observer_->OnSetAudioStreamPlaying( |
| 278 render_process_id_, entry->render_view_id, stream_id, false); |
| 279 } |
271 } | 280 } |
272 | 281 |
273 void AudioRendererHost::OnFlushStream(int stream_id) { | 282 void AudioRendererHost::OnFlushStream(int stream_id) { |
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
275 | 284 |
276 AudioEntry* entry = LookupById(stream_id); | 285 AudioEntry* entry = LookupById(stream_id); |
277 if (!entry) { | 286 if (!entry) { |
278 SendErrorMessage(stream_id); | 287 SendErrorMessage(stream_id); |
279 return; | 288 return; |
280 } | 289 } |
281 | 290 |
282 entry->controller->Flush(); | 291 entry->controller->Flush(); |
283 if (media_observer_) | 292 if (media_observer_) { |
284 media_observer_->OnSetAudioStreamStatus(this, stream_id, "flushed"); | 293 media_observer_->OnSetAudioStreamStatus( |
| 294 render_process_id_, entry->render_view_id, stream_id, "flushed"); |
| 295 } |
285 } | 296 } |
286 | 297 |
287 void AudioRendererHost::OnCloseStream(int stream_id) { | 298 void AudioRendererHost::OnCloseStream(int stream_id) { |
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
289 | 300 |
290 if (media_observer_) | 301 AudioEntry* entry = LookupById(stream_id); |
291 media_observer_->OnSetAudioStreamStatus(this, stream_id, "closed"); | 302 if (!entry) |
| 303 return; |
292 | 304 |
293 AudioEntry* entry = LookupById(stream_id); | 305 if (media_observer_) { |
| 306 media_observer_->OnSetAudioStreamStatus( |
| 307 render_process_id_, entry->render_view_id, stream_id, "closed"); |
| 308 } |
294 | 309 |
295 if (entry) | 310 CloseAndDeleteStream(entry); |
296 CloseAndDeleteStream(entry); | |
297 } | 311 } |
298 | 312 |
299 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { | 313 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { |
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
301 | 315 |
302 AudioEntry* entry = LookupById(stream_id); | 316 AudioEntry* entry = LookupById(stream_id); |
303 if (!entry) { | 317 if (!entry) { |
304 SendErrorMessage(stream_id); | 318 SendErrorMessage(stream_id); |
305 return; | 319 return; |
306 } | 320 } |
307 | 321 |
308 // Make sure the volume is valid. | 322 // Make sure the volume is valid. |
309 if (volume < 0 || volume > 1.0) | 323 if (volume < 0 || volume > 1.0) |
310 return; | 324 return; |
311 entry->controller->SetVolume(volume); | 325 entry->controller->SetVolume(volume); |
312 if (media_observer_) | 326 if (media_observer_) { |
313 media_observer_->OnSetAudioStreamVolume(this, stream_id, volume); | 327 media_observer_->OnSetAudioStreamVolume( |
| 328 render_process_id_, entry->render_view_id, stream_id, volume); |
| 329 } |
314 } | 330 } |
315 | 331 |
316 void AudioRendererHost::SendErrorMessage(int32 stream_id) { | 332 void AudioRendererHost::SendErrorMessage(int32 stream_id) { |
317 Send(new AudioMsg_NotifyStreamStateChanged( | 333 Send(new AudioMsg_NotifyStreamStateChanged( |
318 stream_id, media::AudioOutputIPCDelegate::kError)); | 334 stream_id, media::AudioOutputIPCDelegate::kError)); |
319 } | 335 } |
320 | 336 |
321 void AudioRendererHost::DeleteEntries() { | 337 void AudioRendererHost::DeleteEntries() { |
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
323 | 339 |
(...skipping 16 matching lines...) Expand all Loading... |
340 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { | 356 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { |
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
342 | 358 |
343 // Delete the entry when this method goes out of scope. | 359 // Delete the entry when this method goes out of scope. |
344 scoped_ptr<AudioEntry> entry_deleter(entry); | 360 scoped_ptr<AudioEntry> entry_deleter(entry); |
345 | 361 |
346 // Erase the entry identified by |stream_id| from the map. | 362 // Erase the entry identified by |stream_id| from the map. |
347 audio_entries_.erase(entry->stream_id); | 363 audio_entries_.erase(entry->stream_id); |
348 | 364 |
349 // Notify the media observer. | 365 // Notify the media observer. |
350 if (media_observer_) | 366 if (media_observer_) { |
351 media_observer_->OnDeleteAudioStream(this, entry->stream_id); | 367 media_observer_->OnDeleteAudioStream( |
| 368 render_process_id_, entry->render_view_id, entry->stream_id); |
| 369 } |
352 } | 370 } |
353 | 371 |
354 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { | 372 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { |
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
356 | 374 |
357 // Sends the error message first before we close the stream because | 375 // Sends the error message first before we close the stream because |
358 // |entry| is destroyed in DeleteEntry(). | 376 // |entry| is destroyed in DeleteEntry(). |
359 SendErrorMessage(entry->stream_id); | 377 SendErrorMessage(entry->stream_id); |
360 | 378 |
361 if (media_observer_) | 379 if (media_observer_) { |
362 media_observer_->OnSetAudioStreamStatus(this, entry->stream_id, "error"); | 380 media_observer_->OnSetAudioStreamStatus( |
| 381 render_process_id_, entry->render_view_id, entry->stream_id, "error"); |
| 382 } |
363 CloseAndDeleteStream(entry); | 383 CloseAndDeleteStream(entry); |
364 } | 384 } |
365 | 385 |
366 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 386 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
368 | 388 |
369 AudioEntryMap::iterator i = audio_entries_.find(stream_id); | 389 AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
370 if (i != audio_entries_.end() && !i->second->pending_close) | 390 if (i != audio_entries_.end() && !i->second->pending_close) |
371 return i->second; | 391 return i->second; |
372 return NULL; | 392 return NULL; |
373 } | 393 } |
374 | 394 |
375 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( | 395 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( |
376 media::AudioOutputController* controller) { | 396 media::AudioOutputController* controller) { |
377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
378 | 398 |
379 // Iterate the map of entries. | 399 // Iterate the map of entries. |
380 // TODO(hclam): Implement a faster look up method. | 400 // TODO(hclam): Implement a faster look up method. |
381 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 401 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
382 i != audio_entries_.end(); ++i) { | 402 i != audio_entries_.end(); ++i) { |
383 if (!i->second->pending_close && controller == i->second->controller.get()) | 403 if (!i->second->pending_close && controller == i->second->controller.get()) |
384 return i->second; | 404 return i->second; |
385 } | 405 } |
386 return NULL; | 406 return NULL; |
387 } | 407 } |
OLD | NEW |