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" |
(...skipping 13 matching lines...) Expand all Loading... |
24 } | 24 } |
25 | 25 |
26 AudioRendererHost::AudioEntry::~AudioEntry() {} | 26 AudioRendererHost::AudioEntry::~AudioEntry() {} |
27 | 27 |
28 /////////////////////////////////////////////////////////////////////////////// | 28 /////////////////////////////////////////////////////////////////////////////// |
29 // AudioRendererHost implementations. | 29 // AudioRendererHost implementations. |
30 AudioRendererHost::AudioRendererHost( | 30 AudioRendererHost::AudioRendererHost( |
31 content::ResourceContext* resource_context, | 31 content::ResourceContext* resource_context, |
32 AudioManager* audio_manager) | 32 AudioManager* audio_manager) |
33 : resource_context_(resource_context), | 33 : resource_context_(resource_context), |
34 audio_manager_(audio_manager), | 34 audio_manager_(audio_manager) { |
35 media_observer_(NULL) { | |
36 } | 35 } |
37 | 36 |
38 AudioRendererHost::~AudioRendererHost() { | 37 AudioRendererHost::~AudioRendererHost() { |
39 DCHECK(audio_entries_.empty()); | 38 DCHECK(audio_entries_.empty()); |
40 } | 39 } |
41 | 40 |
42 void AudioRendererHost::OnChannelClosing() { | 41 void AudioRendererHost::OnChannelClosing() { |
43 BrowserMessageFilter::OnChannelClosing(); | 42 BrowserMessageFilter::OnChannelClosing(); |
44 | 43 |
| 44 // Channel is closing, so |resource_context_| is about to become invalid. |
| 45 resource_context_ = NULL; |
| 46 |
45 // Since the IPC channel is gone, close all requested audio streams. | 47 // Since the IPC channel is gone, close all requested audio streams. |
46 DeleteEntries(); | 48 DeleteEntries(); |
47 } | 49 } |
48 | 50 |
49 void AudioRendererHost::OnDestruct() const { | 51 void AudioRendererHost::OnDestruct() const { |
50 BrowserThread::DeleteOnIOThread::Destruct(this); | 52 BrowserThread::DeleteOnIOThread::Destruct(this); |
51 } | 53 } |
52 | 54 |
53 /////////////////////////////////////////////////////////////////////////////// | 55 /////////////////////////////////////////////////////////////////////////////// |
54 // media::AudioOutputController::EventHandler implementations. | 56 // media::AudioOutputController::EventHandler implementations. |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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; |
240 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 242 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
241 GetMediaObserver()->OnSetAudioStreamStatus(this, stream_id, "created"); | 243 if (GetMediaObserver()) |
| 244 GetMediaObserver()->OnSetAudioStreamStatus(this, stream_id, "created"); |
242 } | 245 } |
243 | 246 |
244 void AudioRendererHost::OnPlayStream(int stream_id) { | 247 void AudioRendererHost::OnPlayStream(int stream_id) { |
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
246 | 249 |
247 AudioEntry* entry = LookupById(stream_id); | 250 AudioEntry* entry = LookupById(stream_id); |
248 if (!entry) { | 251 if (!entry) { |
249 SendErrorMessage(stream_id); | 252 SendErrorMessage(stream_id); |
250 return; | 253 return; |
251 } | 254 } |
252 | 255 |
253 entry->controller->Play(); | 256 entry->controller->Play(); |
254 GetMediaObserver()->OnSetAudioStreamPlaying(this, stream_id, true); | 257 if (GetMediaObserver()) |
| 258 GetMediaObserver()->OnSetAudioStreamPlaying(this, stream_id, true); |
255 } | 259 } |
256 | 260 |
257 void AudioRendererHost::OnPauseStream(int stream_id) { | 261 void AudioRendererHost::OnPauseStream(int stream_id) { |
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
259 | 263 |
260 AudioEntry* entry = LookupById(stream_id); | 264 AudioEntry* entry = LookupById(stream_id); |
261 if (!entry) { | 265 if (!entry) { |
262 SendErrorMessage(stream_id); | 266 SendErrorMessage(stream_id); |
263 return; | 267 return; |
264 } | 268 } |
265 | 269 |
266 entry->controller->Pause(); | 270 entry->controller->Pause(); |
267 GetMediaObserver()->OnSetAudioStreamPlaying(this, stream_id, false); | 271 if (GetMediaObserver()) |
| 272 GetMediaObserver()->OnSetAudioStreamPlaying(this, stream_id, false); |
268 } | 273 } |
269 | 274 |
270 void AudioRendererHost::OnFlushStream(int stream_id) { | 275 void AudioRendererHost::OnFlushStream(int stream_id) { |
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
272 | 277 |
273 AudioEntry* entry = LookupById(stream_id); | 278 AudioEntry* entry = LookupById(stream_id); |
274 if (!entry) { | 279 if (!entry) { |
275 SendErrorMessage(stream_id); | 280 SendErrorMessage(stream_id); |
276 return; | 281 return; |
277 } | 282 } |
278 | 283 |
279 entry->controller->Flush(); | 284 entry->controller->Flush(); |
280 GetMediaObserver()->OnSetAudioStreamStatus(this, stream_id, "flushed"); | 285 if (GetMediaObserver()) |
| 286 GetMediaObserver()->OnSetAudioStreamStatus(this, stream_id, "flushed"); |
281 } | 287 } |
282 | 288 |
283 void AudioRendererHost::OnCloseStream(int stream_id) { | 289 void AudioRendererHost::OnCloseStream(int stream_id) { |
284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
285 | 291 |
286 GetMediaObserver()->OnSetAudioStreamStatus(this, stream_id, "closed"); | 292 if (GetMediaObserver()) |
| 293 GetMediaObserver()->OnSetAudioStreamStatus(this, stream_id, "closed"); |
287 | 294 |
288 AudioEntry* entry = LookupById(stream_id); | 295 AudioEntry* entry = LookupById(stream_id); |
289 | 296 |
290 if (entry) | 297 if (entry) |
291 CloseAndDeleteStream(entry); | 298 CloseAndDeleteStream(entry); |
292 } | 299 } |
293 | 300 |
294 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { | 301 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { |
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
296 | 303 |
297 AudioEntry* entry = LookupById(stream_id); | 304 AudioEntry* entry = LookupById(stream_id); |
298 if (!entry) { | 305 if (!entry) { |
299 SendErrorMessage(stream_id); | 306 SendErrorMessage(stream_id); |
300 return; | 307 return; |
301 } | 308 } |
302 | 309 |
303 // Make sure the volume is valid. | 310 // Make sure the volume is valid. |
304 if (volume < 0 || volume > 1.0) | 311 if (volume < 0 || volume > 1.0) |
305 return; | 312 return; |
306 entry->controller->SetVolume(volume); | 313 entry->controller->SetVolume(volume); |
307 GetMediaObserver()->OnSetAudioStreamVolume(this, stream_id, volume); | 314 if (GetMediaObserver()) |
| 315 GetMediaObserver()->OnSetAudioStreamVolume(this, stream_id, volume); |
308 } | 316 } |
309 | 317 |
310 void AudioRendererHost::SendErrorMessage(int32 stream_id) { | 318 void AudioRendererHost::SendErrorMessage(int32 stream_id) { |
311 Send(new AudioMsg_NotifyStreamStateChanged(stream_id, kAudioStreamError)); | 319 Send(new AudioMsg_NotifyStreamStateChanged(stream_id, kAudioStreamError)); |
312 } | 320 } |
313 | 321 |
314 void AudioRendererHost::DeleteEntries() { | 322 void AudioRendererHost::DeleteEntries() { |
315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
316 | 324 |
317 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 325 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
(...skipping 23 matching lines...) Expand all Loading... |
341 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { | 349 void AudioRendererHost::DeleteEntry(AudioEntry* entry) { |
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
343 | 351 |
344 // Delete the entry when this method goes out of scope. | 352 // Delete the entry when this method goes out of scope. |
345 scoped_ptr<AudioEntry> entry_deleter(entry); | 353 scoped_ptr<AudioEntry> entry_deleter(entry); |
346 | 354 |
347 // Erase the entry identified by |stream_id| from the map. | 355 // Erase the entry identified by |stream_id| from the map. |
348 audio_entries_.erase(entry->stream_id); | 356 audio_entries_.erase(entry->stream_id); |
349 | 357 |
350 // Notify the media observer. | 358 // Notify the media observer. |
351 GetMediaObserver()->OnDeleteAudioStream(this, entry->stream_id); | 359 if (GetMediaObserver()) |
| 360 GetMediaObserver()->OnDeleteAudioStream(this, entry->stream_id); |
352 } | 361 } |
353 | 362 |
354 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { | 363 void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { |
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
356 | 365 |
357 // Sends the error message first before we close the stream because | 366 // Sends the error message first before we close the stream because |
358 // |entry| is destroyed in DeleteEntry(). | 367 // |entry| is destroyed in DeleteEntry(). |
359 SendErrorMessage(entry->stream_id); | 368 SendErrorMessage(entry->stream_id); |
360 | 369 |
361 GetMediaObserver()->OnSetAudioStreamStatus(this, entry->stream_id, "error"); | 370 if (GetMediaObserver()) |
| 371 GetMediaObserver()->OnSetAudioStreamStatus(this, entry->stream_id, "error"); |
362 CloseAndDeleteStream(entry); | 372 CloseAndDeleteStream(entry); |
363 } | 373 } |
364 | 374 |
365 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 375 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
367 | 377 |
368 AudioEntryMap::iterator i = audio_entries_.find(stream_id); | 378 AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
369 if (i != audio_entries_.end() && !i->second->pending_close) | 379 if (i != audio_entries_.end() && !i->second->pending_close) |
370 return i->second; | 380 return i->second; |
371 return NULL; | 381 return NULL; |
372 } | 382 } |
373 | 383 |
374 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( | 384 AudioRendererHost::AudioEntry* AudioRendererHost::LookupByController( |
375 media::AudioOutputController* controller) { | 385 media::AudioOutputController* controller) { |
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
377 | 387 |
378 // Iterate the map of entries. | 388 // Iterate the map of entries. |
379 // TODO(hclam): Implement a faster look up method. | 389 // TODO(hclam): Implement a faster look up method. |
380 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 390 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
381 i != audio_entries_.end(); ++i) { | 391 i != audio_entries_.end(); ++i) { |
382 if (!i->second->pending_close && controller == i->second->controller.get()) | 392 if (!i->second->pending_close && controller == i->second->controller.get()) |
383 return i->second; | 393 return i->second; |
384 } | 394 } |
385 return NULL; | 395 return NULL; |
386 } | 396 } |
387 | 397 |
388 content::MediaObserver* AudioRendererHost::GetMediaObserver() { | 398 content::MediaObserver* AudioRendererHost::GetMediaObserver() { |
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
390 if (!media_observer_) | 400 if (resource_context_) |
391 media_observer_ = resource_context_->GetMediaObserver(); | 401 return resource_context_->GetMediaObserver(); |
392 return media_observer_; | 402 return NULL; |
393 } | 403 } |
OLD | NEW |