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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) | 187 IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) |
186 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | 188 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) |
187 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | 189 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
188 IPC_MESSAGE_UNHANDLED(handled = false) | 190 IPC_MESSAGE_UNHANDLED(handled = false) |
189 IPC_END_MESSAGE_MAP_EX() | 191 IPC_END_MESSAGE_MAP_EX() |
190 | 192 |
191 return handled; | 193 return handled; |
192 } | 194 } |
193 | 195 |
194 void AudioRendererHost::OnCreateStream( | 196 void AudioRendererHost::OnCreateStream( |
195 int stream_id, const media::AudioParameters& params) { | 197 int render_view_id, int stream_id, const media::AudioParameters& params) { |
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
197 DCHECK(LookupById(stream_id) == NULL); | 199 DCHECK(LookupById(stream_id) == NULL); |
198 | 200 |
199 media::AudioParameters audio_params(params); | 201 media::AudioParameters audio_params(params); |
200 DCHECK_GT(audio_params.frames_per_buffer(), 0); | 202 DCHECK_GT(audio_params.frames_per_buffer(), 0); |
201 | 203 |
202 uint32 buffer_size = audio_params.GetBytesPerBuffer(); | 204 uint32 buffer_size = audio_params.GetBytesPerBuffer(); |
203 | 205 |
204 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 206 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
205 | 207 |
(...skipping 23 matching lines...) Expand all Loading... |
229 | 231 |
230 if (!entry->controller) { | 232 if (!entry->controller) { |
231 SendErrorMessage(stream_id); | 233 SendErrorMessage(stream_id); |
232 return; | 234 return; |
233 } | 235 } |
234 | 236 |
235 // If we have created the controller successfully, create an entry and add it | 237 // If we have created the controller successfully, create an entry and add it |
236 // to the map. | 238 // to the map. |
237 entry->stream_id = stream_id; | 239 entry->stream_id = stream_id; |
238 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 240 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
239 if (media_observer_) | 241 if (media_observer_) { |
240 media_observer_->OnSetAudioStreamStatus(this, stream_id, "created"); | 242 media_observer_->OnSetAudioStreamStatus( |
| 243 this, stream_id, render_process_id_, render_view_id, "created"); |
| 244 } |
241 } | 245 } |
242 | 246 |
243 void AudioRendererHost::OnPlayStream(int stream_id) { | 247 void AudioRendererHost::OnPlayStream(int stream_id) { |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
245 | 249 |
246 AudioEntry* entry = LookupById(stream_id); | 250 AudioEntry* entry = LookupById(stream_id); |
247 if (!entry) { | 251 if (!entry) { |
248 SendErrorMessage(stream_id); | 252 SendErrorMessage(stream_id); |
249 return; | 253 return; |
250 } | 254 } |
(...skipping 20 matching lines...) Expand all Loading... |
271 void AudioRendererHost::OnFlushStream(int stream_id) { | 275 void AudioRendererHost::OnFlushStream(int stream_id) { |
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
273 | 277 |
274 AudioEntry* entry = LookupById(stream_id); | 278 AudioEntry* entry = LookupById(stream_id); |
275 if (!entry) { | 279 if (!entry) { |
276 SendErrorMessage(stream_id); | 280 SendErrorMessage(stream_id); |
277 return; | 281 return; |
278 } | 282 } |
279 | 283 |
280 entry->controller->Flush(); | 284 entry->controller->Flush(); |
281 if (media_observer_) | 285 if (media_observer_) { |
282 media_observer_->OnSetAudioStreamStatus(this, stream_id, "flushed"); | 286 media_observer_->OnSetAudioStreamStatus( |
| 287 this, stream_id, render_process_id_, 0, "flushed"); |
| 288 } |
283 } | 289 } |
284 | 290 |
285 void AudioRendererHost::OnCloseStream(int stream_id) { | 291 void AudioRendererHost::OnCloseStream(int stream_id) { |
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
287 | 293 |
288 if (media_observer_) | 294 if (media_observer_) { |
289 media_observer_->OnSetAudioStreamStatus(this, stream_id, "closed"); | 295 media_observer_->OnSetAudioStreamStatus( |
| 296 this, stream_id, render_process_id_, 0, "closed"); |
| 297 } |
290 | 298 |
291 AudioEntry* entry = LookupById(stream_id); | 299 AudioEntry* entry = LookupById(stream_id); |
292 | 300 |
293 if (entry) | 301 if (entry) |
294 CloseAndDeleteStream(entry); | 302 CloseAndDeleteStream(entry); |
295 } | 303 } |
296 | 304 |
297 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { | 305 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { |
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
299 | 307 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 media_observer_->OnDeleteAudioStream(this, entry->stream_id); | 356 media_observer_->OnDeleteAudioStream(this, entry->stream_id); |
349 } | 357 } |
350 | 358 |
351 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { | 359 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { |
352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
353 | 361 |
354 // Sends the error message first before we close the stream because | 362 // Sends the error message first before we close the stream because |
355 // |entry| is destroyed in DeleteEntry(). | 363 // |entry| is destroyed in DeleteEntry(). |
356 SendErrorMessage(entry->stream_id); | 364 SendErrorMessage(entry->stream_id); |
357 | 365 |
358 if (media_observer_) | 366 if (media_observer_) { |
359 media_observer_->OnSetAudioStreamStatus(this, entry->stream_id, "error"); | 367 media_observer_->OnSetAudioStreamStatus( |
| 368 this, entry->stream_id, render_process_id_, 0, "error"); |
| 369 } |
360 CloseAndDeleteStream(entry); | 370 CloseAndDeleteStream(entry); |
361 } | 371 } |
362 | 372 |
363 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 373 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
365 | 375 |
366 AudioEntryMap::iterator i = audio_entries_.find(stream_id); | 376 AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
367 if (i != audio_entries_.end() && !i->second->pending_close) | 377 if (i != audio_entries_.end() && !i->second->pending_close) |
368 return i->second; | 378 return i->second; |
369 return NULL; | 379 return NULL; |
370 } | 380 } |
371 | 381 |
372 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( | 382 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( |
373 media::AudioOutputController* controller) { | 383 media::AudioOutputController* controller) { |
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
375 | 385 |
376 // Iterate the map of entries. | 386 // Iterate the map of entries. |
377 // TODO(hclam): Implement a faster look up method. | 387 // TODO(hclam): Implement a faster look up method. |
378 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 388 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
379 i != audio_entries_.end(); ++i) { | 389 i != audio_entries_.end(); ++i) { |
380 if (!i->second->pending_close && controller == i->second->controller.get()) | 390 if (!i->second->pending_close && controller == i->second->controller.get()) |
381 return i->second; | 391 return i->second; |
382 } | 392 } |
383 return NULL; | 393 return NULL; |
384 } | 394 } |
OLD | NEW |