Index: content/browser/renderer_host/media/audio_renderer_host.cc |
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc |
index 4486fedb98f76ab6065ef22917d14a8baba4d6e4..9eef0125822249da93a687859f3349e706c659b6 100644 |
--- a/content/browser/renderer_host/media/audio_renderer_host.cc |
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc |
@@ -10,8 +10,6 @@ |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
#include "base/lazy_instance.h" |
-#include "base/memory/ptr_util.h" |
-#include "base/memory/shared_memory.h" |
#include "base/metrics/histogram_macros.h" |
#include "base/process/process.h" |
#include "content/browser/bad_message.h" |
@@ -119,102 +117,6 @@ void ValidateRenderFrameId(int render_process_id, |
} // namespace |
-class AudioRendererHost::AudioEntry |
- : public media::AudioOutputController::EventHandler { |
- public: |
- ~AudioEntry() override; |
- |
- // Returns nullptr on failure. |
- static std::unique_ptr<AudioRendererHost::AudioEntry> Create( |
- AudioRendererHost* host, |
- int stream_id, |
- int render_frame_id, |
- const media::AudioParameters& params, |
- const std::string& output_device_id); |
- |
- int stream_id() const { |
- return stream_id_; |
- } |
- |
- int render_frame_id() const { return render_frame_id_; } |
- |
- media::AudioOutputController* controller() const { return controller_.get(); } |
- |
- AudioSyncReader* reader() const { return reader_.get(); } |
- |
- // Used by ARH to track the number of active streams for UMA stats. |
- bool playing() const { return playing_; } |
- void set_playing(bool playing) { playing_ = playing; } |
- |
- private: |
- AudioEntry(AudioRendererHost* host, |
- int stream_id, |
- int render_frame_id, |
- const media::AudioParameters& params, |
- const std::string& output_device_id, |
- std::unique_ptr<AudioSyncReader> reader); |
- |
- // media::AudioOutputController::EventHandler implementation. |
- void OnCreated() override; |
- void OnPlaying() override; |
- void OnPaused() override; |
- void OnError() override; |
- |
- AudioRendererHost* const host_; |
- const int stream_id_; |
- |
- // The routing ID of the source RenderFrame. |
- const int render_frame_id_; |
- |
- // The synchronous reader to be used by |controller_|. |
- const std::unique_ptr<AudioSyncReader> reader_; |
- |
- // The AudioOutputController that manages the audio stream. |
- const scoped_refptr<media::AudioOutputController> controller_; |
- |
- bool playing_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AudioEntry); |
-}; |
- |
-AudioRendererHost::AudioEntry::AudioEntry( |
- AudioRendererHost* host, |
- int stream_id, |
- int render_frame_id, |
- const media::AudioParameters& params, |
- const std::string& output_device_id, |
- std::unique_ptr<AudioSyncReader> reader) |
- : host_(host), |
- stream_id_(stream_id), |
- render_frame_id_(render_frame_id), |
- reader_(std::move(reader)), |
- controller_(media::AudioOutputController::Create(host->audio_manager_, |
- this, |
- params, |
- output_device_id, |
- reader_.get())), |
- playing_(false) { |
- DCHECK(controller_); |
-} |
- |
-AudioRendererHost::AudioEntry::~AudioEntry() {} |
- |
-// static |
-std::unique_ptr<AudioRendererHost::AudioEntry> |
-AudioRendererHost::AudioEntry::Create(AudioRendererHost* host, |
- int stream_id, |
- int render_frame_id, |
- const media::AudioParameters& params, |
- const std::string& output_device_id) { |
- std::unique_ptr<AudioSyncReader> reader(AudioSyncReader::Create(params)); |
- if (!reader) { |
- return nullptr; |
- } |
- return base::WrapUnique(new AudioEntry(host, stream_id, render_frame_id, |
- params, output_device_id, |
- std::move(reader))); |
-} |
- |
/////////////////////////////////////////////////////////////////////////////// |
// AudioRendererHost implementations. |
@@ -241,7 +143,7 @@ AudioRendererHost::AudioRendererHost(int render_process_id, |
AudioRendererHost::~AudioRendererHost() { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- CHECK(audio_entries_.empty()); |
+ CHECK(delegates_.empty()); |
// If we had any streams, report UMA stats for the maximum number of |
// simultaneous streams for this render process and for the whole browser |
@@ -268,9 +170,9 @@ void AudioRendererHost::GetOutputControllers( |
void AudioRendererHost::OnChannelClosing() { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
// Since the IPC sender is gone, close all requested audio streams. |
- while (!audio_entries_.empty()) { |
- // Note: OnCloseStream() removes the entries from audio_entries_. |
- OnCloseStream(audio_entries_.begin()->first); |
+ while (!delegates_.empty()) { |
+ // Note: OnCloseStream() removes the delegates from delegates_. |
+ OnCloseStream(delegates_[0]->stream_id()); |
} |
// Remove any authorizations for streams that were not yet created |
@@ -281,53 +183,18 @@ void AudioRendererHost::OnDestruct() const { |
BrowserThread::DeleteOnIOThread::Destruct(this); |
} |
-void AudioRendererHost::AudioEntry::OnCreated() { |
- BrowserThread::PostTask( |
- BrowserThread::IO, |
- FROM_HERE, |
- base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); |
-} |
- |
-void AudioRendererHost::AudioEntry::OnPlaying() { |
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
- base::Bind(&AudioRendererHost::StreamStateChanged, |
- host_, stream_id_, true)); |
-} |
- |
-void AudioRendererHost::AudioEntry::OnPaused() { |
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
- base::Bind(&AudioRendererHost::StreamStateChanged, |
- host_, stream_id_, false)); |
-} |
- |
-void AudioRendererHost::AudioEntry::OnError() { |
- BrowserThread::PostTask( |
- BrowserThread::IO, |
- FROM_HERE, |
- base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); |
-} |
- |
-void AudioRendererHost::DoCompleteCreation(int stream_id) { |
+void AudioRendererHost::OnStreamCreated( |
+ int stream_id, |
+ base::SharedMemory* shared_memory, |
+ base::CancelableSyncSocket* foreign_socket) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
if (!PeerHandle()) { |
DLOG(WARNING) << "Renderer process handle is invalid."; |
- ReportErrorAndClose(stream_id); |
+ OnStreamError(stream_id); |
return; |
} |
- AudioEntry* const entry = LookupById(stream_id); |
- if (!entry) { |
- ReportErrorAndClose(stream_id); |
- return; |
- } |
- |
- // Now construction is done and we are ready to send the shared memory and the |
- // sync socket to the renderer. |
- base::SharedMemory* shared_memory = entry->reader()->shared_memory(); |
- base::CancelableSyncSocket* foreign_socket = |
- entry->reader()->foreign_socket(); |
- |
base::SharedMemoryHandle foreign_memory_handle; |
base::SyncSocket::TransitDescriptor socket_descriptor; |
size_t shared_memory_size = shared_memory->requested_size(); |
@@ -336,7 +203,7 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) { |
foreign_socket->PrepareTransitDescriptor(PeerHandle(), |
&socket_descriptor))) { |
// Something went wrong in preparing the IPC handles. |
- ReportErrorAndClose(entry->stream_id()); |
+ OnStreamError(stream_id); |
return; |
} |
@@ -345,35 +212,52 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) { |
base::checked_cast<uint32_t>(shared_memory_size))); |
} |
-void AudioRendererHost::DidValidateRenderFrame(int stream_id, bool is_valid) { |
+void AudioRendererHost::OnStreamStateChanged(bool is_playing) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ if (is_playing) { |
+ base::AtomicRefCountInc(&num_playing_streams_); |
- if (!is_valid) { |
- DLOG(WARNING) << "Render frame for stream (id=" << stream_id |
- << ") no longer exists."; |
- ReportErrorAndClose(stream_id); |
+ // Inform the RenderProcessHost when audio starts playing for the first |
+ // time. |
+ if (base::AtomicRefCountIsOne(&num_playing_streams_)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&NotifyRenderProcessHostThatAudioStateChanged, |
+ render_process_id_)); |
+ } |
+ } else { |
+ // Inform the RenderProcessHost when there is no more audio playing. |
+ if (!base::AtomicRefCountDec(&num_playing_streams_)) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&NotifyRenderProcessHostThatAudioStateChanged, |
+ render_process_id_)); |
+ } |
} |
} |
-void AudioRendererHost::StreamStateChanged(int stream_id, bool is_playing) { |
+void AudioRendererHost::OnStreamError(int stream_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- AudioEntry* const entry = LookupById(stream_id); |
- if (!entry) |
+ // Make sure this isn't a stray callback executing after the stream has been |
+ // closed, so error notifications aren't sent after clients believe the stream |
+ // is closed. |
+ if (!LookupById(stream_id)) |
return; |
- if (is_playing) { |
- AudioStreamMonitor::StartMonitoringStream( |
- render_process_id_, |
- entry->render_frame_id(), |
- entry->stream_id(), |
- base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip, |
- entry->controller())); |
- } else { |
- AudioStreamMonitor::StopMonitoringStream( |
- render_process_id_, entry->render_frame_id(), entry->stream_id()); |
+ SendErrorMessage(stream_id); |
+ |
+ OnCloseStream(stream_id); |
+} |
+ |
+void AudioRendererHost::DidValidateRenderFrame(int stream_id, bool is_valid) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ if (!is_valid) { |
+ DLOG(WARNING) << "Render frame for stream (id=" << stream_id |
+ << ") no longer exists."; |
+ OnStreamError(stream_id); |
} |
- UpdateNumPlayingStreams(entry, is_playing); |
} |
RenderProcessHost::AudioOutputControllerList |
@@ -381,11 +265,8 @@ AudioRendererHost::DoGetOutputControllers() const { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
RenderProcessHost::AudioOutputControllerList controllers; |
- for (AudioEntryMap::const_iterator it = audio_entries_.begin(); |
- it != audio_entries_.end(); |
- ++it) { |
- controllers.push_back(it->second->controller()); |
- } |
+ for (const auto& delegate : delegates_) |
+ controllers.push_back(delegate->controller()); |
return controllers; |
} |
@@ -434,7 +315,7 @@ void AudioRendererHost::OnRequestDeviceAuthorization( |
return; |
} |
- // If |session_id should be used for output device selection and such output |
+ // If |session_id| should be used for output device selection and such output |
// device is found, reuse the input device permissions. |
if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, |
device_id)) { |
@@ -493,8 +374,9 @@ void AudioRendererHost::OnCreateStream(int stream_id, |
} |
// Fail early if either of two sanity-checks fail: |
- // 1. There should not yet exist an AudioEntry for the given |stream_id| |
- // since the renderer may not create two streams with the same ID. |
+ // 1. There should not yet exist an AudioOutputDelegate for the given |
+ // |stream_id| since the renderer may not create two streams with the |
+ // same ID. |
// 2. An out-of-range render frame ID was provided. Renderers must *always* |
// specify a valid render frame ID for each audio output they create, as |
// several browser-level features depend on this (e.g., OOM manager, UI |
@@ -521,64 +403,49 @@ void AudioRendererHost::OnCreateStream(int stream_id, |
base::Bind(&AudioRendererHost::DidValidateRenderFrame, this, |
stream_id))); |
- std::unique_ptr<AudioEntry> entry = AudioEntry::Create( |
- this, stream_id, render_frame_id, params, device_unique_id); |
- if (!entry) { |
- SendErrorMessage(stream_id); |
- return; |
- } |
- |
MediaObserver* const media_observer = |
GetContentClient()->browser()->GetMediaObserver(); |
- if (media_observer) |
- media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); |
+ std::unique_ptr<AudioOutputDelegate> delegate(new AudioOutputDelegate( |
+ this, audio_log_.get(), mirroring_manager_, media_observer, stream_id, |
+ render_frame_id, render_process_id_, params, device_unique_id)); |
- if (mirroring_manager_) { |
- mirroring_manager_->AddDiverter( |
- render_process_id_, entry->render_frame_id(), entry->controller()); |
- } |
- audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
- g_audio_streams_tracker.Get().IncreaseStreamCount(); |
+ delegates_.push_back(std::move(delegate)); |
- audio_log_->OnCreated(stream_id, params, device_unique_id); |
- MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
- stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
+ g_audio_streams_tracker.Get().IncreaseStreamCount(); |
- if (audio_entries_.size() > max_simultaneous_streams_) |
- max_simultaneous_streams_ = audio_entries_.size(); |
+ if (delegates_.size() > max_simultaneous_streams_) |
+ max_simultaneous_streams_ = delegates_.size(); |
} |
void AudioRendererHost::OnPlayStream(int stream_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- AudioEntry* entry = LookupById(stream_id); |
- if (!entry) { |
+ AudioOutputDelegate* delegate = LookupById(stream_id); |
+ if (!delegate) { |
SendErrorMessage(stream_id); |
return; |
} |
- entry->controller()->Play(); |
- audio_log_->OnStarted(stream_id); |
+ delegate->OnPlayStream(); |
} |
void AudioRendererHost::OnPauseStream(int stream_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- AudioEntry* entry = LookupById(stream_id); |
- if (!entry) { |
+ AudioOutputDelegate* delegate = LookupById(stream_id); |
+ if (!delegate) { |
SendErrorMessage(stream_id); |
return; |
} |
- entry->controller()->Pause(); |
- audio_log_->OnStopped(stream_id); |
+ delegate->OnPauseStream(); |
} |
void AudioRendererHost::OnSetVolume(int stream_id, double volume) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- AudioEntry* entry = LookupById(stream_id); |
- if (!entry) { |
+ AudioOutputDelegate* delegate = LookupById(stream_id); |
+ if (!delegate) { |
SendErrorMessage(stream_id); |
return; |
} |
@@ -586,8 +453,7 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) { |
// Make sure the volume is valid. |
if (volume < 0 || volume > 1.0) |
return; |
- entry->controller()->SetVolume(volume); |
- audio_log_->OnSetVolume(stream_id, volume); |
+ delegate->OnSetVolume(volume); |
} |
void AudioRendererHost::SendErrorMessage(int stream_id) { |
@@ -599,86 +465,31 @@ void AudioRendererHost::OnCloseStream(int stream_id) { |
authorizations_.erase(stream_id); |
// Prevent oustanding callbacks from attempting to close/delete the same |
- // AudioEntry twice. |
- AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
- if (i == audio_entries_.end()) |
- return; |
- std::unique_ptr<AudioEntry> entry(i->second); |
- audio_entries_.erase(i); |
- g_audio_streams_tracker.Get().DecreaseStreamCount(); |
- |
- media::AudioOutputController* const controller = entry->controller(); |
- controller->Close( |
- base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry))); |
- audio_log_->OnClosed(stream_id); |
-} |
- |
-void AudioRendererHost::DeleteEntry(std::unique_ptr<AudioEntry> entry) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- |
- // De-register the controller from the AudioMirroringManager now that the |
- // controller has closed the AudioOutputStream and shut itself down. This |
- // ensures that calling RemoveDiverter() here won't trigger the controller to |
- // re-start the default AudioOutputStream and cause a brief audio blip to come |
- // out the user's speakers. http://crbug.com/474432 |
- if (mirroring_manager_) |
- mirroring_manager_->RemoveDiverter(entry->controller()); |
- |
- AudioStreamMonitor::StopMonitoringStream( |
- render_process_id_, entry->render_frame_id(), entry->stream_id()); |
- UpdateNumPlayingStreams(entry.get(), false); |
-} |
- |
-void AudioRendererHost::ReportErrorAndClose(int stream_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- |
- // Make sure this isn't a stray callback executing after the stream has been |
- // closed, so error notifications aren't sent after clients believe the stream |
- // is closed. |
- if (!LookupById(stream_id)) |
+ // AudioOutputDelegate twice. |
+ AudioOutputDelegateList::iterator i; |
+ for (i = delegates_.begin(); |
+ i != delegates_.end() && (*i)->stream_id() != stream_id; ++i) { |
+ } |
+ if (i == delegates_.end()) |
return; |
- SendErrorMessage(stream_id); |
- |
- audio_log_->OnError(stream_id); |
- OnCloseStream(stream_id); |
-} |
+ std::unique_ptr<AudioOutputDelegate> delegate = std::move(*i); |
+ *i = std::move(delegates_.back()); |
+ delegates_.pop_back(); |
-AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ delegate->OnCloseStream(); |
- AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); |
- return i != audio_entries_.end() ? i->second : NULL; |
+ g_audio_streams_tracker.Get().DecreaseStreamCount(); |
} |
-void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, |
- bool is_playing) { |
+AudioOutputDelegate* AudioRendererHost::LookupById(int stream_id) { |
DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- if (entry->playing() == is_playing) |
- return; |
- if (is_playing) { |
- entry->set_playing(true); |
- base::AtomicRefCountInc(&num_playing_streams_); |
- |
- // Inform the RenderProcessHost when audio starts playing for the first |
- // time. |
- if (base::AtomicRefCountIsOne(&num_playing_streams_)) { |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&NotifyRenderProcessHostThatAudioStateChanged, |
- render_process_id_)); |
- } |
- } else { |
- entry->set_playing(false); |
- // Inform the RenderProcessHost when there is no more audio playing. |
- if (!base::AtomicRefCountDec(&num_playing_streams_)) { |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&NotifyRenderProcessHostThatAudioStateChanged, |
- render_process_id_)); |
- } |
+ AudioOutputDelegateList::iterator i; |
+ for (i = delegates_.begin(); |
+ i != delegates_.end() && (*i)->stream_id() != stream_id; ++i) { |
o1ka
2016/10/25 12:32:34
(alternatively you can use std::find_if)
Max Morin
2016/10/26 09:20:17
Done.
|
} |
+ return i != delegates_.end() ? i->get() : nullptr; |
} |
bool AudioRendererHost::HasActiveAudio() { |