diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-17 22:51:16 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-17 22:51:16 +0000 |
commit | 7307035b2c12088ba241dc49098204d4beff52d4 (patch) | |
tree | 9511385010f72b15bf355f0e3c0a841257a87077 /chrome/browser/renderer_host/audio_renderer_host.cc | |
parent | 8e4040197b15b7af9d1510e47a7fea1d72ec6a06 (diff) | |
download | chromium_src-7307035b2c12088ba241dc49098204d4beff52d4.zip chromium_src-7307035b2c12088ba241dc49098204d4beff52d4.tar.gz chromium_src-7307035b2c12088ba241dc49098204d4beff52d4.tar.bz2 |
Make AudioOutputController.Close() truly asynchronous.
Added closed_task parameter in this method. This parameter is used to
notify the caller when the stream is actually closed. Callbacks may
be called until closed_task is executed.
BUG=55755
TEST=Unittests, audio still works, doesn't crash
Review URL: http://codereview.chromium.org/3415007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59869 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host/audio_renderer_host.cc')
-rw-r--r-- | chrome/browser/renderer_host/audio_renderer_host.cc | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc index 3219333..b4ba6ba 100644 --- a/chrome/browser/renderer_host/audio_renderer_host.cc +++ b/chrome/browser/renderer_host/audio_renderer_host.cc @@ -335,7 +335,14 @@ void AudioRendererHost::OnCreateStream( } scoped_ptr<AudioEntry> entry(new AudioEntry()); - scoped_refptr<media::AudioOutputController> controller = NULL; + // Create the shared memory and share with the renderer process. + if (!entry->shared_memory.Create(L"", false, false, hardware_packet_size) || + !entry->shared_memory.Map(entry->shared_memory.max_size())) { + // If creation of shared memory failed then send an error message. + SendErrorMessage(msg.routing_id(), stream_id); + return; + } + if (low_latency) { // If this is the low latency mode, we need to construct a SyncReader first. scoped_ptr<AudioSyncReader> reader( @@ -350,44 +357,32 @@ void AudioRendererHost::OnCreateStream( // If we have successfully created the SyncReader then assign it to the // entry and construct an AudioOutputController. entry->reader.reset(reader.release()); - controller = + entry->controller = media::AudioOutputController::CreateLowLatency( this, params.params, hardware_packet_size, entry->reader.get()); } else { // The choice of buffer capacity is based on experiment. - controller = + entry->controller = media::AudioOutputController::Create(this, params.params, hardware_packet_size, 3 * hardware_packet_size); } - if (!controller) { + if (!entry->controller) { SendErrorMessage(msg.routing_id(), stream_id); return; } // If we have created the controller successfully create a entry and add it // to the map. - entry->controller = controller; entry->render_view_id = msg.routing_id(); entry->stream_id = stream_id; - // Create the shared memory and share with the renderer process. - if (!entry->shared_memory.Create(L"", false, false, hardware_packet_size) || - !entry->shared_memory.Map(entry->shared_memory.max_size())) { - // If creation of shared memory failed then close the controller and - // sends an error message. - controller->Close(); - SendErrorMessage(msg.routing_id(), stream_id); - return; - } - - // If everything is successful then add it to the map. - audio_entries_.insert(std::make_pair( - AudioEntryId(msg.routing_id(), stream_id), - entry.release())); + audio_entries_.insert(std::make_pair( + AudioEntryId(msg.routing_id(), stream_id), + entry.release())); } void AudioRendererHost::OnPlayStream(const IPC::Message& msg, int stream_id) { @@ -431,10 +426,8 @@ void AudioRendererHost::OnCloseStream(const IPC::Message& msg, int stream_id) { AudioEntry* entry = LookupById(msg.routing_id(), stream_id); - // Note that closing an audio stream is a blocking operation. This call may - // block the IO thread for up to 100ms. if (entry) - DeleteEntry(entry); + CloseAndDeleteStream(entry); } void AudioRendererHost::OnSetVolume(const IPC::Message& msg, int stream_id, @@ -519,10 +512,25 @@ void AudioRendererHost::SendErrorMessage(int32 render_view_id, void AudioRendererHost::DeleteEntries() { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); - while (!audio_entries_.empty()) { - DeleteEntry(audio_entries_.begin()->second); + for (AudioEntryMap::iterator i = audio_entries_.begin(); + i != audio_entries_.end(); ++i) { + CloseAndDeleteStream(i->second); } - DCHECK(audio_entries_.empty()); +} + +void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) { + if (!entry->pending_close) { + entry->controller->Close( + NewRunnableMethod(this, &AudioRendererHost::OnStreamClosed, entry)); + entry->pending_close = true; + } +} + +void AudioRendererHost::OnStreamClosed(AudioEntry* entry) { + // Delete the entry after we've closed the stream. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod(this, &AudioRendererHost::DeleteEntry, entry)); } void AudioRendererHost::DeleteEntry(AudioEntry* entry) { @@ -531,10 +539,7 @@ void AudioRendererHost::DeleteEntry(AudioEntry* entry) { // Delete the entry when this method goes out of scope. scoped_ptr<AudioEntry> entry_deleter(entry); - // Close the audio stream then remove the entry. - entry->controller->Close(); - - // Entry the entry from the map. + // Erase the entry from the map. audio_entries_.erase( AudioEntryId(entry->render_view_id, entry->stream_id)); } @@ -545,7 +550,7 @@ void AudioRendererHost::DeleteEntryOnError(AudioEntry* entry) { // Sends the error message first before we close the stream because // |entry| is destroyed in DeleteEntry(). SendErrorMessage(entry->render_view_id, entry->stream_id); - DeleteEntry(entry); + CloseAndDeleteStream(entry); } AudioRendererHost::AudioEntry* AudioRendererHost::LookupById( |