8c06395eca68ecf94496c47946a26066060004d0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / media / audio_renderer_host.cc
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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/media/audio_renderer_host.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/shared_memory.h"
10 #include "base/metrics/histogram.h"
11 #include "base/process/process.h"
12 #include "content/browser/browser_main_loop.h"
13 #include "content/browser/media/audio_stream_monitor.h"
14 #include "content/browser/media/capture/audio_mirroring_manager.h"
15 #include "content/browser/media/media_internals.h"
16 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
17 #include "content/browser/renderer_host/media/audio_sync_reader.h"
18 #include "content/browser/renderer_host/media/media_stream_manager.h"
19 #include "content/common/media/audio_messages.h"
20 #include "content/public/browser/content_browser_client.h"
21 #include "content/public/browser/media_observer.h"
22 #include "content/public/common/content_switches.h"
23 #include "media/audio/audio_manager_base.h"
24 #include "media/base/audio_bus.h"
25 #include "media/base/limits.h"
26
27 using media::AudioBus;
28 using media::AudioManager;
29
30 namespace content {
31
32 class AudioRendererHost::AudioEntry
33     : public media::AudioOutputController::EventHandler {
34  public:
35   AudioEntry(AudioRendererHost* host,
36              int stream_id,
37              int render_view_id,
38              int render_frame_id,
39              const media::AudioParameters& params,
40              const std::string& output_device_id,
41              scoped_ptr<base::SharedMemory> shared_memory,
42              scoped_ptr<media::AudioOutputController::SyncReader> reader);
43   virtual ~AudioEntry();
44
45   int stream_id() const {
46     return stream_id_;
47   }
48
49   int render_view_id() const {
50     return render_view_id_;
51   }
52
53   int render_frame_id() const { return render_frame_id_; }
54
55   media::AudioOutputController* controller() const { return controller_.get(); }
56
57   base::SharedMemory* shared_memory() {
58     return shared_memory_.get();
59   }
60
61   media::AudioOutputController::SyncReader* reader() const {
62     return reader_.get();
63   }
64
65   bool playing() const { return playing_; }
66   void set_playing(bool playing) { playing_ = playing; }
67
68  private:
69   // media::AudioOutputController::EventHandler implementation.
70   virtual void OnCreated() OVERRIDE;
71   virtual void OnPlaying() OVERRIDE;
72   virtual void OnPaused() OVERRIDE;
73   virtual void OnError() OVERRIDE;
74   virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
75       OVERRIDE;
76
77   AudioRendererHost* const host_;
78   const int stream_id_;
79
80   // The routing ID of the source render view/frame.
81   const int render_view_id_;
82   const int render_frame_id_;
83
84   // Shared memory for transmission of the audio data.  Used by |reader_|.
85   const scoped_ptr<base::SharedMemory> shared_memory_;
86
87   // The synchronous reader to be used by |controller_|.
88   const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
89
90   // The AudioOutputController that manages the audio stream.
91   const scoped_refptr<media::AudioOutputController> controller_;
92
93   bool playing_;
94 };
95
96 AudioRendererHost::AudioEntry::AudioEntry(
97     AudioRendererHost* host,
98     int stream_id,
99     int render_view_id,
100     int render_frame_id,
101     const media::AudioParameters& params,
102     const std::string& output_device_id,
103     scoped_ptr<base::SharedMemory> shared_memory,
104     scoped_ptr<media::AudioOutputController::SyncReader> reader)
105     : host_(host),
106       stream_id_(stream_id),
107       render_view_id_(render_view_id),
108       render_frame_id_(render_frame_id),
109       shared_memory_(shared_memory.Pass()),
110       reader_(reader.Pass()),
111       controller_(media::AudioOutputController::Create(host->audio_manager_,
112                                                        this,
113                                                        params,
114                                                        output_device_id,
115                                                        reader_.get())),
116       playing_(false) {
117   DCHECK(controller_.get());
118 }
119
120 AudioRendererHost::AudioEntry::~AudioEntry() {}
121
122 ///////////////////////////////////////////////////////////////////////////////
123 // AudioRendererHost implementations.
124
125 AudioRendererHost::AudioRendererHost(
126     int render_process_id,
127     media::AudioManager* audio_manager,
128     AudioMirroringManager* mirroring_manager,
129     MediaInternals* media_internals,
130     MediaStreamManager* media_stream_manager)
131     : BrowserMessageFilter(AudioMsgStart),
132       render_process_id_(render_process_id),
133       audio_manager_(audio_manager),
134       mirroring_manager_(mirroring_manager),
135       audio_log_(media_internals->CreateAudioLog(
136           media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
137       media_stream_manager_(media_stream_manager),
138       num_playing_streams_(0) {
139   DCHECK(audio_manager_);
140   DCHECK(media_stream_manager_);
141 }
142
143 AudioRendererHost::~AudioRendererHost() {
144   DCHECK(audio_entries_.empty());
145 }
146
147 void AudioRendererHost::GetOutputControllers(
148     int render_view_id,
149     const RenderViewHost::GetAudioOutputControllersCallback& callback) const {
150   BrowserThread::PostTaskAndReplyWithResult(
151       BrowserThread::IO,
152       FROM_HERE,
153       base::Bind(&AudioRendererHost::DoGetOutputControllers, this,
154                  render_view_id),
155       callback);
156 }
157
158 void AudioRendererHost::OnChannelClosing() {
159   // Since the IPC sender is gone, close all requested audio streams.
160   while (!audio_entries_.empty()) {
161     // Note: OnCloseStream() removes the entries from audio_entries_.
162     OnCloseStream(audio_entries_.begin()->first);
163   }
164 }
165
166 void AudioRendererHost::OnDestruct() const {
167   BrowserThread::DeleteOnIOThread::Destruct(this);
168 }
169
170 void AudioRendererHost::AudioEntry::OnCreated() {
171   BrowserThread::PostTask(
172       BrowserThread::IO,
173       FROM_HERE,
174       base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
175 }
176
177 void AudioRendererHost::AudioEntry::OnPlaying() {
178   BrowserThread::PostTask(
179       BrowserThread::IO,
180       FROM_HERE,
181       base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
182                  host_,
183                  stream_id_,
184                  true));
185 }
186
187 void AudioRendererHost::AudioEntry::OnPaused() {
188   BrowserThread::PostTask(
189       BrowserThread::IO,
190       FROM_HERE,
191       base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
192                  host_,
193                  stream_id_,
194                  false));
195 }
196
197 void AudioRendererHost::AudioEntry::OnError() {
198   BrowserThread::PostTask(
199       BrowserThread::IO,
200       FROM_HERE,
201       base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
202 }
203
204 void AudioRendererHost::AudioEntry::OnDeviceChange(int new_buffer_size,
205                                                    int new_sample_rate) {
206   BrowserThread::PostTask(
207       BrowserThread::IO,
208       FROM_HERE,
209       base::Bind(base::IgnoreResult(&AudioRendererHost::Send), host_,
210                  new AudioMsg_NotifyDeviceChanged(
211                      stream_id_, new_buffer_size, new_sample_rate)));
212 }
213
214 void AudioRendererHost::DoCompleteCreation(int stream_id) {
215   DCHECK_CURRENTLY_ON(BrowserThread::IO);
216
217   if (!PeerHandle()) {
218     DLOG(WARNING) << "Renderer process handle is invalid.";
219     ReportErrorAndClose(stream_id);
220     return;
221   }
222
223   AudioEntry* const entry = LookupById(stream_id);
224   if (!entry) {
225     ReportErrorAndClose(stream_id);
226     return;
227   }
228
229   // Once the audio stream is created then complete the creation process by
230   // mapping shared memory and sharing with the renderer process.
231   base::SharedMemoryHandle foreign_memory_handle;
232   if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
233                                               &foreign_memory_handle)) {
234     // If we failed to map and share the shared memory then close the audio
235     // stream and send an error message.
236     ReportErrorAndClose(entry->stream_id());
237     return;
238   }
239
240   AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
241
242   base::SyncSocket::TransitDescriptor socket_descriptor;
243
244   // If we failed to prepare the sync socket for the renderer then we fail
245   // the construction of audio stream.
246   if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) {
247     ReportErrorAndClose(entry->stream_id());
248     return;
249   }
250
251   Send(new AudioMsg_NotifyStreamCreated(
252       entry->stream_id(), foreign_memory_handle, socket_descriptor,
253       entry->shared_memory()->requested_size()));
254 }
255
256 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
257                                                    bool is_playing) {
258   DCHECK_CURRENTLY_ON(BrowserThread::IO);
259
260   AudioEntry* const entry = LookupById(stream_id);
261   if (!entry)
262     return;
263
264   Send(new AudioMsg_NotifyStreamStateChanged(
265       stream_id,
266       is_playing ? media::AudioOutputIPCDelegate::kPlaying
267                  : media::AudioOutputIPCDelegate::kPaused));
268
269   if (is_playing) {
270     AudioStreamMonitor::StartMonitoringStream(
271         render_process_id_,
272         entry->render_frame_id(),
273         entry->stream_id(),
274         base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
275                    entry->controller()));
276     // TODO(dalecurtis): See about using AudioStreamMonitor instead.
277     if (!entry->playing()) {
278       entry->set_playing(true);
279       base::AtomicRefCountInc(&num_playing_streams_);
280     }
281   } else {
282     AudioStreamMonitor::StopMonitoringStream(
283         render_process_id_, entry->render_frame_id(), entry->stream_id());
284     // TODO(dalecurtis): See about using AudioStreamMonitor instead.
285     if (entry->playing()) {
286       entry->set_playing(false);
287       base::AtomicRefCountDec(&num_playing_streams_);
288     }
289   }
290 }
291
292 RenderViewHost::AudioOutputControllerList
293 AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
294   DCHECK_CURRENTLY_ON(BrowserThread::IO);
295
296   RenderViewHost::AudioOutputControllerList controllers;
297   AudioEntryMap::const_iterator it = audio_entries_.begin();
298   for (; it != audio_entries_.end(); ++it) {
299     AudioEntry* entry = it->second;
300     if (entry->render_view_id() == render_view_id)
301       controllers.push_back(entry->controller());
302   }
303
304   return controllers;
305 }
306
307 ///////////////////////////////////////////////////////////////////////////////
308 // IPC Messages handler
309 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
310   bool handled = true;
311   IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
312     IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
313     IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
314     IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
315     IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
316     IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
317     IPC_MESSAGE_UNHANDLED(handled = false)
318   IPC_END_MESSAGE_MAP()
319
320   return handled;
321 }
322
323 void AudioRendererHost::OnCreateStream(
324     int stream_id, int render_view_id, int render_frame_id, int session_id,
325     const media::AudioParameters& params) {
326   DCHECK_CURRENTLY_ON(BrowserThread::IO);
327
328   DVLOG(1) << "AudioRendererHost@" << this
329            << "::OnCreateStream(stream_id=" << stream_id
330            << ", render_view_id=" << render_view_id
331            << ", session_id=" << session_id << ")";
332   DCHECK_GT(render_view_id, 0);
333   DCHECK_GT(render_frame_id, 0);
334
335   // media::AudioParameters is validated in the deserializer.
336   if (LookupById(stream_id) != NULL) {
337     SendErrorMessage(stream_id);
338     return;
339   }
340
341   // Initialize the |output_device_id| to an empty string which indicates that
342   // the default device should be used. If a StreamDeviceInfo instance was found
343   // though, then we use the matched output device.
344   std::string output_device_id;
345   const StreamDeviceInfo* info = media_stream_manager_->
346       audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
347   if (info)
348     output_device_id = info->device.matched_output_device_id;
349
350   // Create the shared memory and share with the renderer process.
351   uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);
352   scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
353   if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
354     SendErrorMessage(stream_id);
355     return;
356   }
357
358   scoped_ptr<AudioSyncReader> reader(
359       new AudioSyncReader(shared_memory.get(), params));
360   if (!reader->Init()) {
361     SendErrorMessage(stream_id);
362     return;
363   }
364
365   MediaObserver* const media_observer =
366       GetContentClient()->browser()->GetMediaObserver();
367   if (media_observer)
368     media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
369
370   scoped_ptr<AudioEntry> entry(new AudioEntry(
371       this,
372       stream_id,
373       render_view_id,
374       render_frame_id,
375       params,
376       output_device_id,
377       shared_memory.Pass(),
378       reader.PassAs<media::AudioOutputController::SyncReader>()));
379   if (mirroring_manager_) {
380     mirroring_manager_->AddDiverter(
381         render_process_id_, entry->render_frame_id(), entry->controller());
382   }
383   audio_entries_.insert(std::make_pair(stream_id, entry.release()));
384   audio_log_->OnCreated(stream_id, params, output_device_id);
385 }
386
387 void AudioRendererHost::OnPlayStream(int stream_id) {
388   DCHECK_CURRENTLY_ON(BrowserThread::IO);
389
390   AudioEntry* entry = LookupById(stream_id);
391   if (!entry) {
392     SendErrorMessage(stream_id);
393     return;
394   }
395
396   entry->controller()->Play();
397   audio_log_->OnStarted(stream_id);
398 }
399
400 void AudioRendererHost::OnPauseStream(int stream_id) {
401   DCHECK_CURRENTLY_ON(BrowserThread::IO);
402
403   AudioEntry* entry = LookupById(stream_id);
404   if (!entry) {
405     SendErrorMessage(stream_id);
406     return;
407   }
408
409   entry->controller()->Pause();
410   audio_log_->OnStopped(stream_id);
411 }
412
413 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
414   DCHECK_CURRENTLY_ON(BrowserThread::IO);
415
416   AudioEntry* entry = LookupById(stream_id);
417   if (!entry) {
418     SendErrorMessage(stream_id);
419     return;
420   }
421
422   // Make sure the volume is valid.
423   if (volume < 0 || volume > 1.0)
424     return;
425   entry->controller()->SetVolume(volume);
426   audio_log_->OnSetVolume(stream_id, volume);
427 }
428
429 void AudioRendererHost::SendErrorMessage(int stream_id) {
430   Send(new AudioMsg_NotifyStreamStateChanged(
431       stream_id, media::AudioOutputIPCDelegate::kError));
432 }
433
434 void AudioRendererHost::OnCloseStream(int stream_id) {
435   DCHECK_CURRENTLY_ON(BrowserThread::IO);
436
437   // Prevent oustanding callbacks from attempting to close/delete the same
438   // AudioEntry twice.
439   AudioEntryMap::iterator i = audio_entries_.find(stream_id);
440   if (i == audio_entries_.end())
441     return;
442   scoped_ptr<AudioEntry> entry(i->second);
443   audio_entries_.erase(i);
444
445   media::AudioOutputController* const controller = entry->controller();
446   if (mirroring_manager_)
447     mirroring_manager_->RemoveDiverter(controller);
448   controller->Close(
449       base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
450   audio_log_->OnClosed(stream_id);
451 }
452
453 void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
454   DCHECK_CURRENTLY_ON(BrowserThread::IO);
455   AudioStreamMonitor::StopMonitoringStream(
456       render_process_id_, entry->render_frame_id(), entry->stream_id());
457   if (entry->playing())
458     base::AtomicRefCountDec(&num_playing_streams_);
459 }
460
461 void AudioRendererHost::ReportErrorAndClose(int stream_id) {
462   DCHECK_CURRENTLY_ON(BrowserThread::IO);
463
464   // Make sure this isn't a stray callback executing after the stream has been
465   // closed, so error notifications aren't sent after clients believe the stream
466   // is closed.
467   if (!LookupById(stream_id))
468     return;
469
470   SendErrorMessage(stream_id);
471
472   audio_log_->OnError(stream_id);
473   OnCloseStream(stream_id);
474 }
475
476 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
477   DCHECK_CURRENTLY_ON(BrowserThread::IO);
478
479   AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
480   return i != audio_entries_.end() ? i->second : NULL;
481 }
482
483 bool AudioRendererHost::HasActiveAudio() {
484   return !base::AtomicRefCountIsZero(&num_playing_streams_);
485 }
486
487 }  // namespace content