15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_renderer_host.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind_helpers.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
11a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_main_loop.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/media/audio_stream_monitor.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/audio_mirroring_manager.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/media_internals.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_input_device_manager.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_sync_reader.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_manager.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/media/audio_messages.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/content_browser_client.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/media_observer.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/common/content_switches.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "media/audio/audio_manager_base.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_bus.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioBus;
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using media::AudioManager;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class AudioRendererHost::AudioEntry
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public media::AudioOutputController::EventHandler {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AudioEntry(AudioRendererHost* host,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             int stream_id,
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             int render_view_id,
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             int render_frame_id,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             const media::AudioParameters& params,
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             const std::string& output_device_id,
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             scoped_ptr<base::SharedMemory> shared_memory,
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             scoped_ptr<media::AudioOutputController::SyncReader> reader);
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~AudioEntry();
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int stream_id() const {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return stream_id_;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int render_view_id() const {
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return render_view_id_;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int render_frame_id() const { return render_frame_id_; }
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  media::AudioOutputController* controller() const { return controller_.get(); }
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::SharedMemory* shared_memory() {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return shared_memory_.get();
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  media::AudioOutputController::SyncReader* reader() const {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return reader_.get();
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool playing() const { return playing_; }
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void set_playing(bool playing) { playing_ = playing; }
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // media::AudioOutputController::EventHandler implementation.
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnCreated() OVERRIDE;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnPlaying() OVERRIDE;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnPaused() OVERRIDE;
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnError() OVERRIDE;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      OVERRIDE;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AudioRendererHost* const host_;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int stream_id_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The routing ID of the source render view/frame.
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int render_view_id_;
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const int render_frame_id_;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Shared memory for transmission of the audio data.  Used by |reader_|.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const scoped_ptr<base::SharedMemory> shared_memory_;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The synchronous reader to be used by |controller_|.
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The AudioOutputController that manages the audio stream.
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const scoped_refptr<media::AudioOutputController> controller_;
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool playing_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AudioRendererHost::AudioEntry::AudioEntry(
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    AudioRendererHost* host,
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int stream_id,
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int render_view_id,
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int render_frame_id,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const media::AudioParameters& params,
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const std::string& output_device_id,
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::SharedMemory> shared_memory,
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<media::AudioOutputController::SyncReader> reader)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : host_(host),
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_id_(stream_id),
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      render_view_id_(render_view_id),
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      render_frame_id_(render_frame_id),
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      shared_memory_(shared_memory.Pass()),
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      reader_(reader.Pass()),
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      controller_(media::AudioOutputController::Create(host->audio_manager_,
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                       this,
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                       params,
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                       output_device_id,
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                                       reader_.get())),
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      playing_(false) {
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(controller_.get());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioRendererHost::AudioEntry::~AudioEntry() {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioRendererHost implementations.
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioRendererHost::AudioRendererHost(
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int render_process_id,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    media::AudioManager* audio_manager,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AudioMirroringManager* mirroring_manager,
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaInternals* media_internals,
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaStreamManager* media_stream_manager)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : BrowserMessageFilter(AudioMsgStart),
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_process_id_(render_process_id),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      audio_manager_(audio_manager),
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mirroring_manager_(mirroring_manager),
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      audio_log_(media_internals->CreateAudioLog(
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      media_stream_manager_(media_stream_manager),
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      num_playing_streams_(0) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(audio_manager_);
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(media_stream_manager_);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioRendererHost::~AudioRendererHost() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_entries_.empty());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void AudioRendererHost::GetOutputControllers(
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int render_view_id,
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const RenderViewHost::GetAudioOutputControllersCallback& callback) const {
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BrowserThread::PostTaskAndReplyWithResult(
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      BrowserThread::IO,
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      FROM_HERE,
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      base::Bind(&AudioRendererHost::DoGetOutputControllers, this,
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                 render_view_id),
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      callback);
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererHost::OnChannelClosing() {
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Since the IPC sender is gone, close all requested audio streams.
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (!audio_entries_.empty()) {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Note: OnCloseStream() removes the entries from audio_entries_.
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OnCloseStream(audio_entries_.begin()->first);
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererHost::OnDestruct() const {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::DeleteOnIOThread::Destruct(this);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::AudioEntry::OnCreated() {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::AudioEntry::OnPlaying() {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 host_,
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 stream_id_,
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 true));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::AudioEntry::OnPaused() {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 host_,
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 stream_id_,
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 false));
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::AudioEntry::OnError() {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::IO,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size,
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                   int new_sample_rate) {
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BrowserThread::PostTask(
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      BrowserThread::IO,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(base::IgnoreResult(&AudioRendererHost::Send), host_,
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 new AudioMsg_NotifyDeviceChanged(
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     stream_id_, new_buffer_size, new_sample_rate)));
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid AudioRendererHost::DoCompleteCreation(int stream_id) {
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!PeerHandle()) {
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DLOG(WARNING) << "Renderer process handle is invalid.";
219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ReportErrorAndClose(stream_id);
220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  AudioEntry* const entry = LookupById(stream_id);
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!entry) {
225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ReportErrorAndClose(stream_id);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once the audio stream is created then complete the creation process by
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mapping shared memory and sharing with the renderer process.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryHandle foreign_memory_handle;
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              &foreign_memory_handle)) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we failed to map and share the shared memory then close the audio
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // stream and send an error message.
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ReportErrorAndClose(entry->stream_id());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::SyncSocket::TransitDescriptor socket_descriptor;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we failed to prepare the sync socket for the renderer then we fail
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the construction of audio stream.
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) {
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ReportErrorAndClose(entry->stream_id());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new AudioMsg_NotifyStreamCreated(
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      entry->stream_id(), foreign_memory_handle, socket_descriptor,
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      entry->shared_memory()->requested_size()));
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                   bool is_playing) {
258effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AudioEntry* const entry = LookupById(stream_id);
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!entry)
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Send(new AudioMsg_NotifyStreamStateChanged(
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stream_id,
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      is_playing ? media::AudioOutputIPCDelegate::kPlaying
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 : media::AudioOutputIPCDelegate::kPaused));
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (is_playing) {
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AudioStreamMonitor::StartMonitoringStream(
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        render_process_id_,
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        entry->render_frame_id(),
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        entry->stream_id(),
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   entry->controller()));
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(dalecurtis): See about using AudioStreamMonitor instead.
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!entry->playing()) {
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      entry->set_playing(true);
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::AtomicRefCountInc(&num_playing_streams_);
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AudioStreamMonitor::StopMonitoringStream(
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        render_process_id_, entry->render_frame_id(), entry->stream_id());
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(dalecurtis): See about using AudioStreamMonitor instead.
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (entry->playing()) {
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      entry->set_playing(false);
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::AtomicRefCountDec(&num_playing_streams_);
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)RenderViewHost::AudioOutputControllerList
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  RenderViewHost::AudioOutputControllerList controllers;
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AudioEntryMap::const_iterator it = audio_entries_.begin();
2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (; it != audio_entries_.end(); ++it) {
2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    AudioEntry* entry = it->second;
3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (entry->render_view_id() == render_view_id)
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      controllers.push_back(entry->controller());
3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return controllers;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IPC Messages handler
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererHost::OnCreateStream(
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int stream_id, int render_view_id, int render_frame_id, int session_id,
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const media::AudioParameters& params) {
326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DVLOG(1) << "AudioRendererHost@" << this
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           << "::OnCreateStream(stream_id=" << stream_id
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << ", render_view_id=" << render_view_id
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << ", session_id=" << session_id << ")";
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_GT(render_view_id, 0);
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_GT(render_frame_id, 0);
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // media::AudioParameters is validated in the deserializer.
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (LookupById(stream_id) != NULL) {
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendErrorMessage(stream_id);
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Initialize the |output_device_id| to an empty string which indicates that
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the default device should be used. If a StreamDeviceInfo instance was found
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // though, then we use the matched output device.
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string output_device_id;
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const StreamDeviceInfo* info = media_stream_manager_->
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (info)
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    output_device_id = info->device.matched_output_device_id;
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the shared memory and share with the renderer process.
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendErrorMessage(stream_id);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioSyncReader> reader(
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new AudioSyncReader(shared_memory.get(), params));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!reader->Init()) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendErrorMessage(stream_id);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  MediaObserver* const media_observer =
366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      GetContentClient()->browser()->GetMediaObserver();
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (media_observer)
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<AudioEntry> entry(new AudioEntry(
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this,
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      stream_id,
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      render_view_id,
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      render_frame_id,
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      params,
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      output_device_id,
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      shared_memory.Pass(),
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      reader.PassAs<media::AudioOutputController::SyncReader>()));
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (mirroring_manager_) {
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    mirroring_manager_->AddDiverter(
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        render_process_id_, entry->render_frame_id(), entry->controller());
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_entries_.insert(std::make_pair(stream_id, entry.release()));
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_log_->OnCreated(stream_id, params, output_device_id);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererHost::OnPlayStream(int stream_id) {
388effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupById(stream_id);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendErrorMessage(stream_id);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->controller()->Play();
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnStarted(stream_id);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererHost::OnPauseStream(int stream_id) {
401effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupById(stream_id);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendErrorMessage(stream_id);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->controller()->Pause();
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnStopped(stream_id);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioEntry* entry = LookupById(stream_id);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendErrorMessage(stream_id);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the volume is valid.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (volume < 0 || volume > 1.0)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->controller()->SetVolume(volume);
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnSetVolume(stream_id, volume);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::SendErrorMessage(int stream_id) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Send(new AudioMsg_NotifyStreamStateChanged(
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stream_id, media::AudioOutputIPCDelegate::kError));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::OnCloseStream(int stream_id) {
435effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Prevent oustanding callbacks from attempting to close/delete the same
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // AudioEntry twice.
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AudioEntryMap::iterator i = audio_entries_.find(stream_id);
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (i == audio_entries_.end())
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<AudioEntry> entry(i->second);
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  audio_entries_.erase(i);
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  media::AudioOutputController* const controller = entry->controller();
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (mirroring_manager_)
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    mirroring_manager_->RemoveDiverter(controller);
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  controller->Close(
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnClosed(stream_id);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
454effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AudioStreamMonitor::StopMonitoringStream(
4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      render_process_id_, entry->render_frame_id(), entry->stream_id());
4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (entry->playing())
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::AtomicRefCountDec(&num_playing_streams_);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioRendererHost::ReportErrorAndClose(int stream_id) {
462effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure this isn't a stray callback executing after the stream has been
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // closed, so error notifications aren't sent after clients believe the stream
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // is closed.
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!LookupById(stream_id))
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendErrorMessage(stream_id);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  audio_log_->OnError(stream_id);
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OnCloseStream(stream_id);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
477effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return i != audio_entries_.end() ? i->second : NULL;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool AudioRendererHost::HasActiveAudio() {
48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return !base::AtomicRefCountIsZero(&num_playing_streams_);
48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
488