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_mirroring_manager.h" | |
12 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 13 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
13 #include "content/common/media/audio_messages.h" | 14 #include "content/common/media/audio_messages.h" |
14 #include "content/public/browser/media_observer.h" | 15 #include "content/public/browser/media_observer.h" |
15 #include "media/audio/shared_memory_util.h" | 16 #include "media/audio/shared_memory_util.h" |
16 #include "media/base/audio_bus.h" | 17 #include "media/base/audio_bus.h" |
17 #include "media/base/limits.h" | 18 #include "media/base/limits.h" |
18 | 19 |
19 using media::AudioBus; | 20 using media::AudioBus; |
20 | 21 |
21 namespace content { | 22 namespace content { |
22 | 23 |
24 namespace { | |
25 | |
26 // Simple wrapper around a media::AudioOutputController to implement the | |
27 // AudioMirroringManager::Diverter interface. | |
28 class ControllerDiverter : public AudioMirroringManager::Diverter { | |
DaleCurtis
2013/01/02 21:56:44
ISTM that you could just have AudioOutputControlle
miu
2013/01/03 22:30:42
Done.
I had thought about this, but I quickly dis
| |
29 public: | |
30 void SetController(media::AudioOutputController* controller); | |
31 | |
32 // AudioMirroringManager::Diverter implementation. | |
33 virtual const media::AudioParameters& GetAudioParameters() OVERRIDE; | |
34 virtual void StartDiverting(media::AudioOutputStream* stream) OVERRIDE; | |
35 virtual void StopDiverting() OVERRIDE; | |
36 | |
37 private: | |
38 media::AudioOutputController* controller_; // Not owned. | |
39 }; | |
DaleCurtis
2013/01/02 21:56:44
Disallow copy and assign? Why not make provide con
miu
2013/01/03 22:30:42
No longer applicable.
| |
40 | |
41 void ControllerDiverter::SetController(media::AudioOutputController* ctlr) { | |
42 controller_ = ctlr; | |
DaleCurtis
2013/01/02 21:56:44
DCHECK(ctlr) for haystack hunts.
miu
2013/01/03 22:30:42
No longer applicable.
| |
43 } | |
44 | |
45 const media::AudioParameters& ControllerDiverter::GetAudioParameters() { | |
46 return controller_->params(); | |
47 } | |
48 | |
49 void ControllerDiverter::StartDiverting(media::AudioOutputStream* stream) { | |
50 controller_->StartDiverting(stream); | |
51 } | |
52 | |
53 void ControllerDiverter::StopDiverting() { | |
54 controller_->StopDiverting(); | |
55 } | |
56 | |
57 } // namespace | |
58 | |
23 struct AudioRendererHost::AudioEntry { | 59 struct AudioRendererHost::AudioEntry { |
24 AudioEntry(); | 60 AudioEntry(); |
25 ~AudioEntry(); | 61 ~AudioEntry(); |
26 | 62 |
27 // The AudioOutputController that manages the audio stream. | 63 // The AudioOutputController that manages the audio stream. |
28 scoped_refptr<media::AudioOutputController> controller; | 64 scoped_refptr<media::AudioOutputController> controller; |
65 ControllerDiverter diverter; | |
29 | 66 |
30 // The audio stream ID. | 67 // The audio stream ID. |
31 int stream_id; | 68 int stream_id; |
32 | 69 |
70 // The routing ID of the source render view. | |
71 int render_view_id; | |
72 | |
33 // Shared memory for transmission of the audio data. | 73 // Shared memory for transmission of the audio data. |
34 base::SharedMemory shared_memory; | 74 base::SharedMemory shared_memory; |
35 | 75 |
36 // The synchronous reader to be used by the controller. We have the | 76 // The synchronous reader to be used by the controller. We have the |
37 // ownership of the reader. | 77 // ownership of the reader. |
38 scoped_ptr<media::AudioOutputController::SyncReader> reader; | 78 scoped_ptr<media::AudioOutputController::SyncReader> reader; |
39 | 79 |
40 // Set to true after we called Close() for the controller. | 80 // Set to true after we called Close() for the controller. |
41 bool pending_close; | 81 bool pending_close; |
42 }; | 82 }; |
43 | 83 |
44 AudioRendererHost::AudioEntry::AudioEntry() | 84 AudioRendererHost::AudioEntry::AudioEntry() |
45 : stream_id(0), | 85 : stream_id(0), |
86 render_view_id(MSG_ROUTING_NONE), | |
46 pending_close(false) { | 87 pending_close(false) { |
47 } | 88 } |
48 | 89 |
49 AudioRendererHost::AudioEntry::~AudioEntry() {} | 90 AudioRendererHost::AudioEntry::~AudioEntry() {} |
50 | 91 |
51 /////////////////////////////////////////////////////////////////////////////// | 92 /////////////////////////////////////////////////////////////////////////////// |
52 // AudioRendererHost implementations. | 93 // AudioRendererHost implementations. |
53 AudioRendererHost::AudioRendererHost( | 94 AudioRendererHost::AudioRendererHost( |
54 media::AudioManager* audio_manager, MediaObserver* media_observer) | 95 int render_process_id, |
55 : audio_manager_(audio_manager), | 96 media::AudioManager* audio_manager, |
97 AudioMirroringManager* mirroring_manager, | |
98 MediaObserver* media_observer) | |
99 : render_process_id_(render_process_id), | |
100 audio_manager_(audio_manager), | |
101 mirroring_manager_(mirroring_manager), | |
56 media_observer_(media_observer) { | 102 media_observer_(media_observer) { |
57 } | 103 } |
58 | 104 |
59 AudioRendererHost::~AudioRendererHost() { | 105 AudioRendererHost::~AudioRendererHost() { |
60 DCHECK(audio_entries_.empty()); | 106 DCHECK(audio_entries_.empty()); |
61 } | 107 } |
62 | 108 |
63 void AudioRendererHost::OnChannelClosing() { | 109 void AudioRendererHost::OnChannelClosing() { |
64 BrowserMessageFilter::OnChannelClosing(); | 110 BrowserMessageFilter::OnChannelClosing(); |
65 | 111 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 if (!reader->Init()) { | 308 if (!reader->Init()) { |
263 SendErrorMessage(stream_id); | 309 SendErrorMessage(stream_id); |
264 return; | 310 return; |
265 } | 311 } |
266 | 312 |
267 // If we have successfully created the SyncReader then assign it to the | 313 // If we have successfully created the SyncReader then assign it to the |
268 // entry and construct an AudioOutputController. | 314 // entry and construct an AudioOutputController. |
269 entry->reader.reset(reader.release()); | 315 entry->reader.reset(reader.release()); |
270 entry->controller = media::AudioOutputController::Create( | 316 entry->controller = media::AudioOutputController::Create( |
271 audio_manager_, this, audio_params, entry->reader.get()); | 317 audio_manager_, this, audio_params, entry->reader.get()); |
272 | |
273 if (!entry->controller) { | 318 if (!entry->controller) { |
274 SendErrorMessage(stream_id); | 319 SendErrorMessage(stream_id); |
275 return; | 320 return; |
276 } | 321 } |
277 | 322 |
323 entry->diverter.SetController(entry->controller); | |
324 | |
278 // If we have created the controller successfully, create an entry and add it | 325 // If we have created the controller successfully, create an entry and add it |
279 // to the map. | 326 // to the map. |
280 entry->stream_id = stream_id; | 327 entry->stream_id = stream_id; |
281 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 328 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
282 if (media_observer_) | 329 if (media_observer_) |
283 media_observer_->OnSetAudioStreamStatus(this, stream_id, "created"); | 330 media_observer_->OnSetAudioStreamStatus(this, stream_id, "created"); |
284 } | 331 } |
285 | 332 |
286 void AudioRendererHost::OnAssociateStreamWithProducer(int stream_id, | 333 void AudioRendererHost::OnAssociateStreamWithProducer(int stream_id, |
287 int render_view_id) { | 334 int render_view_id) { |
288 // TODO(miu): Will use render_view_id in upcoming change. | 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
336 | |
289 DVLOG(1) << "AudioRendererHost@" << this | 337 DVLOG(1) << "AudioRendererHost@" << this |
290 << "::OnAssociateStreamWithProducer(stream_id=" << stream_id | 338 << "::OnAssociateStreamWithProducer(stream_id=" << stream_id |
291 << ", render_view_id=" << render_view_id << ")"; | 339 << ", render_view_id=" << render_view_id << ")"; |
340 | |
341 AudioEntry* const entry = LookupById(stream_id); | |
342 if (!entry) { | |
343 SendErrorMessage(stream_id); | |
344 return; | |
345 } | |
346 | |
347 if (entry->render_view_id == render_view_id) | |
348 return; // No change. | |
349 | |
350 if (mirroring_manager_) { | |
DaleCurtis
2013/01/02 21:56:44
Mirroring manager should always be present since
miu
2013/01/03 22:30:42
Done. And fixed things so MediaObserver must neve
| |
351 mirroring_manager_->RemoveDiverter( | |
352 render_process_id_, entry->render_view_id, &entry->diverter); | |
353 } | |
354 entry->render_view_id = render_view_id; | |
355 if (mirroring_manager_) { | |
356 mirroring_manager_->AddDiverter( | |
357 render_process_id_, entry->render_view_id, &entry->diverter); | |
358 } | |
292 } | 359 } |
293 | 360 |
294 void AudioRendererHost::OnPlayStream(int stream_id) { | 361 void AudioRendererHost::OnPlayStream(int stream_id) { |
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
296 | 363 |
297 AudioEntry* entry = LookupById(stream_id); | 364 AudioEntry* entry = LookupById(stream_id); |
298 if (!entry) { | 365 if (!entry) { |
299 SendErrorMessage(stream_id); | 366 SendErrorMessage(stream_id); |
300 return; | 367 return; |
301 } | 368 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 440 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
374 i != audio_entries_.end(); ++i) { | 441 i != audio_entries_.end(); ++i) { |
375 CloseAndDeleteStream(i->second); | 442 CloseAndDeleteStream(i->second); |
376 } | 443 } |
377 } | 444 } |
378 | 445 |
379 void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) { | 446 void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) { |
380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 447 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
381 | 448 |
382 if (!entry->pending_close) { | 449 if (!entry->pending_close) { |
450 if (mirroring_manager_) { | |
DaleCurtis
2013/01/02 21:56:44
Ditto.
miu
2013/01/03 22:30:42
Done.
| |
451 mirroring_manager_->RemoveDiverter( | |
452 render_process_id_, entry->render_view_id, &entry->diverter); | |
453 } | |
383 entry->controller->Close( | 454 entry->controller->Close( |
384 base::Bind(&AudioRendererHost::DeleteEntry, this, entry)); | 455 base::Bind(&AudioRendererHost::DeleteEntry, this, entry)); |
385 entry->pending_close = true; | 456 entry->pending_close = true; |
386 } | 457 } |
387 } | 458 } |
388 | 459 |
389 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { | 460 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { |
390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 461 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
391 | 462 |
392 // Delete the entry when this method goes out of scope. | 463 // Delete the entry when this method goes out of scope. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 return NULL; | 506 return NULL; |
436 } | 507 } |
437 | 508 |
438 media::AudioOutputController* AudioRendererHost::LookupControllerByIdForTesting( | 509 media::AudioOutputController* AudioRendererHost::LookupControllerByIdForTesting( |
439 int stream_id) { | 510 int stream_id) { |
440 AudioEntry* const entry = LookupById(stream_id); | 511 AudioEntry* const entry = LookupById(stream_id); |
441 return entry ? entry->controller : NULL; | 512 return entry ? entry->controller : NULL; |
442 } | 513 } |
443 | 514 |
444 } // namespace content | 515 } // namespace content |
OLD | NEW |