Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1178)

Unified Diff: content/browser/renderer_host/media/audio_renderer_host.cc

Issue 2289543003: IPC->mojo of audio_renderer_host (Closed)
Patch Set: New interface. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 a3ca23926826d8df32370f319ff0b3309dfe1617..baeb46edcd55bf27a1f2af29d70e6b0209385470 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -23,7 +23,6 @@
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/media/audio_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/media_observer.h"
@@ -33,6 +32,11 @@
#include "media/audio/audio_streams_tracker.h"
#include "media/base/audio_bus.h"
#include "media/base/limits.h"
+#include "media/mojo/interfaces/audio_output.mojom-shared.h"
+#include "media/mojo/interfaces/audio_output.mojom.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/platform_handle.h"
using media::AudioBus;
using media::AudioManager;
@@ -47,7 +51,7 @@ base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker =
LAZY_INSTANCE_INITIALIZER;
std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData(
- int stream_id,
+ int32_t stream_id,
bool authorized,
const std::string& device_unique_id) {
return std::make_pair(stream_id,
@@ -132,10 +136,11 @@ void ValidateRenderFrameId(int render_process_id,
} // namespace
class AudioRendererHost::AudioEntry
- : public media::AudioOutputController::EventHandler {
+ : public media::AudioOutputController::EventHandler,
+ private media::mojom::AudioOutputStream {
public:
AudioEntry(AudioRendererHost* host,
- int stream_id,
+ int32_t stream_id,
int render_frame_id,
const media::AudioParameters& params,
const std::string& output_device_id,
@@ -143,9 +148,7 @@ class AudioRendererHost::AudioEntry
std::unique_ptr<media::AudioOutputController::SyncReader> reader);
~AudioEntry() override;
- int stream_id() const {
- return stream_id_;
- }
+ int32_t stream_id() const { return stream_id_; }
int render_frame_id() const { return render_frame_id_; }
@@ -162,6 +165,14 @@ class AudioRendererHost::AudioEntry
bool playing() const { return playing_; }
void set_playing(bool playing) { playing_ = playing; }
+ // media::mojom::AudioOutputStream implementation
+ void Play() override;
+ void Pause() override;
+ void SetVolume(double volume) override;
+
+ void OnConnectionError();
+ void BindRequest(media::mojom::AudioOutputStreamRequest);
+
private:
// media::AudioOutputController::EventHandler implementation.
void OnCreated() override;
@@ -170,7 +181,7 @@ class AudioRendererHost::AudioEntry
void OnError() override;
AudioRendererHost* const host_;
- const int stream_id_;
+ const int32_t stream_id_;
// The routing ID of the source RenderFrame.
const int render_frame_id_;
@@ -184,12 +195,18 @@ class AudioRendererHost::AudioEntry
// The AudioOutputController that manages the audio stream.
const scoped_refptr<media::AudioOutputController> controller_;
+ // Binds |this| to an AudioOutputStreamPtr that is passed to the
+ // AudioOutputStreamClient (AudioOutputIPC in the renderer process).
+ std::unique_ptr<mojo::Binding<media::mojom::AudioOutputStream>> binding_;
+
bool playing_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioEntry);
};
AudioRendererHost::AudioEntry::AudioEntry(
AudioRendererHost* host,
- int stream_id,
+ int32_t stream_id,
int render_frame_id,
const media::AudioParameters& params,
const std::string& output_device_id,
@@ -205,8 +222,49 @@ AudioRendererHost::AudioEntry::AudioEntry(
params,
output_device_id,
reader_.get())),
+ callback_(callback),
playing_(false) {
DCHECK(controller_.get());
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::OnCloseStream, host_, stream_id_));
+}
+
+void AudioRendererHost::AudioEntry::Play() {
+ controller_->Play();
+ host_->audio_log_->OnStarted(stream_id_);
+}
+
+void AudioRendererHost::AudioEntry::Pause() {
+ controller_->Pause();
+ host_->audio_log_->OnStopped(stream_id_);
+}
+
+void AudioRendererHost::AudioEntry::SetVolume(double volume) {
+ if (volume < 0 || volume > 1.0)
+ return;
+
+ controller_->SetVolume(volume);
+ host_->audio_log_->OnSetVolume(stream_id_, volume);
+}
+
+void AudioRendererHost::AudioEntry::OnConnectionError() {
+ binding_.reset();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::CloseStream, host_, stream_id_));
+}
+
+void AudioRendererHost::AudioEntry::BindRequest(
+ media::mojom::AudioOutputStreamRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ binding_.reset(new mojo::Binding<media::mojom::AudioOutputStream>(
+ this, std::move(request)));
+ binding_->set_connection_error_handler(
+ base::Bind(&AudioEntry::OnConnectionError, base::Unretained(this)));
}
AudioRendererHost::AudioEntry::~AudioEntry() {}
@@ -220,8 +278,7 @@ AudioRendererHost::AudioRendererHost(int render_process_id,
MediaInternals* media_internals,
MediaStreamManager* media_stream_manager,
const std::string& salt)
- : BrowserMessageFilter(AudioMsgStart),
- render_process_id_(render_process_id),
+ : render_process_id_(render_process_id),
audio_manager_(audio_manager),
mirroring_manager_(mirroring_manager),
audio_log_(media_internals->CreateAudioLog(
@@ -229,6 +286,7 @@ AudioRendererHost::AudioRendererHost(int render_process_id,
media_stream_manager_(media_stream_manager),
num_playing_streams_(0),
salt_(salt),
+ next_stream_id_(0),
#if DCHECK_IS_ON()
validate_render_frame_id_function_(&ValidateRenderFrameId),
#endif // DCHECK_IS_ON()
@@ -263,99 +321,77 @@ void AudioRendererHost::GetOutputControllers(
base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback);
}
-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);
- }
-
- // Remove any authorizations for streams that were not yet created
- authorizations_.clear();
-}
-
-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_));
+ // TODO: make sure it's safe to capture |this| in the callback.
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::DoCompleteCreation,
+ host_, this, stream_id_, callback_));
}
void AudioRendererHost::AudioEntry::OnPlaying() {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
- host_,
- stream_id_,
- true));
}
void AudioRendererHost::AudioEntry::OnPaused() {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
- host_,
- stream_id_,
- false));
}
void AudioRendererHost::AudioEntry::OnError() {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::OnCloseStream, host_, stream_id_));
}
-void AudioRendererHost::DoCompleteCreation(int stream_id) {
+void AudioRendererHost::DoCompleteCreation(AudioEntry* entry,
+ int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!PeerHandle()) {
- DLOG(WARNING) << "Renderer process handle is invalid.";
- ReportErrorAndClose(stream_id);
- return;
- }
-
- AudioEntry* const entry = LookupById(stream_id);
- if (!entry) {
- ReportErrorAndClose(stream_id);
- return;
- }
-
- // Once the audio stream is created then complete the creation process by
- // mapping shared memory and sharing with the renderer process.
- base::SharedMemoryHandle foreign_memory_handle;
- if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
- &foreign_memory_handle)) {
- // If we failed to map and share the shared memory then close the audio
- // stream and send an error message.
- ReportErrorAndClose(entry->stream_id());
- return;
- }
+ media::mojom::AudioOutputStreamPtr stream_ptr;
+ entry->BindRequest(mojo::GetProxy(&stream_ptr));
AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
-
- base::SyncSocket::TransitDescriptor socket_descriptor;
-
- // If we failed to prepare the sync socket for the renderer then we fail
- // the construction of audio stream.
- if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) {
- ReportErrorAndClose(entry->stream_id());
- return;
- }
-
- Send(new AudioMsg_NotifyStreamCreated(
- entry->stream_id(), foreign_memory_handle, socket_descriptor,
- entry->shared_memory()->requested_size()));
-}
-
-void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
+ base::PlatformFile socket_fd = reader->GetSyncSocket();
+ mojo::ScopedHandle socket_handle = mojo::WrapPlatformFile(socket_fd);
+ DCHECK(socket_handle.is_valid());
+
+ base::SharedMemoryHandle shared_memory_handle =
+ base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle());
+ if (!base::SharedMemory::IsHandleValid(shared_memory_handle)) {
+ // TODO: When can this happen?
+ LOG(FATAL) << "Invalid shared mem handle";
+ return ReportErrorAndClose(stream_id);
+ }
+ mojo::ScopedSharedBufferHandle shared_buffer_handle =
+ mojo::WrapSharedMemoryHandle(shared_memory_handle,
+ entry->shared_memory()->requested_size(),
+ false);
+ DCHECK(shared_buffer_handle.is_valid());
+
+ /*mojo::ScopedSharedBufferHandle shared_buffer_handle =
+ mojo::WrapSharedMemoryHandle(shared_memory_handle,
+ entry->shared_memory()->requested_size(),
+ false);*/
+
+ /* TODO: read comment.
+ // The socket sent from the browser to the renderer is a ForeignSocket, which
+ // is a part of AudioSyncReader that is owned by AudioEntry. The socket handle
+ // is closed when the owning AudioEntry destructs. With mojo, the ownership of
+ // the handle is transferred to the target process. The handle is no longer
+ // valid in the sending process, and cannot be closed there. If the socket
+ // handle is closed when the AudioEntry is deleted, an error occurs. To WAR
+ // this error, duplicate the socket and send the duplicate to the renderer.
+ #if defined(OS_WIN)
+ mojo::ScopedHandle socket_handle =
+ mojo::WrapPlatformFile(socket_descriptor);
+ #else
+ mojo::ScopedHandle socket_handle =
+ mojo::WrapPlatformFile(socket_descriptor.fd);
+ #endif
+ */
+
+ callback.Run(std::move(stream_ptr), std::move(shared_buffer_handle),
+ std::move(socket_handle));
+}
+
+/*void AudioRendererHost::DoNotifyStreamStateChanged(int32_t stream_id,
bool is_playing) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -363,10 +399,9 @@ void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
if (!entry)
return;
- Send(new AudioMsg_NotifyStreamStateChanged(
- stream_id,
- is_playing ? media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING
- : media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED));
+ entry->SendStreamStateResponse(
+ is_playing ? media::mojom::AudioOutputStreamState::PLAYING
+ : media::mojom::AudioOutputStreamState::PAUSED);
if (is_playing) {
AudioStreamMonitor::StartMonitoringStream(
@@ -380,7 +415,7 @@ void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
render_process_id_, entry->render_frame_id(), entry->stream_id());
}
UpdateNumPlayingStreams(entry, is_playing);
-}
+}*/
RenderProcessHost::AudioOutputControllerList
AudioRendererHost::DoGetOutputControllers() const {
@@ -396,91 +431,13 @@ AudioRendererHost::DoGetOutputControllers() const {
return controllers;
}
-///////////////////////////////////////////////////////////////////////////////
-// IPC Messages handler
-bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
- IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization,
- OnRequestDeviceAuthorization)
- IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
- IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void AudioRendererHost::OnRequestDeviceAuthorization(
- int stream_id,
- int render_frame_id,
- int session_id,
+void AudioRendererHost::OnDeviceAuthorized(
+ int32_t stream_id,
+ RequestDeviceAuthorizationCallback callback,
const std::string& device_id,
- const url::Origin& security_origin) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const base::TimeTicks auth_start_time = base::TimeTicks::Now();
-
- DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
- << "(stream_id=" << stream_id
- << ", render_frame_id=" << render_frame_id
- << ", session_id=" << session_id << ", device_id=" << device_id
- << ", security_origin=" << security_origin << ")";
-
- if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
- return;
-
- if (!IsValidDeviceId(device_id)) {
- UMALogDeviceAuthorizationTime(auth_start_time);
- Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
- media::AudioParameters::UnavailableDeviceParams(), std::string()));
- return;
- }
-
- // 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)) {
- const StreamDeviceInfo* info =
- media_stream_manager_->audio_input_device_manager()
- ->GetOpenedDeviceInfoById(session_id);
- if (info) {
- media::AudioParameters output_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- static_cast<media::ChannelLayout>(
- info->device.matched_output.channel_layout),
- info->device.matched_output.sample_rate, 16,
- info->device.matched_output.frames_per_buffer);
- output_params.set_effects(info->device.matched_output.effects);
- authorizations_.insert(MakeAuthorizationData(
- stream_id, true, info->device.matched_output_device_id));
- MaybeFixAudioParameters(&output_params);
- UMALogDeviceAuthorizationTime(auth_start_time);
- // Hash matched device id and pass it to the renderer
- Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
- GetHMACForMediaDeviceID(salt_, security_origin,
- info->device.matched_output_device_id)));
- return;
- }
- }
-
- authorizations_.insert(
- MakeAuthorizationData(stream_id, false, std::string()));
- CheckOutputDeviceAccess(
- render_frame_id, device_id, security_origin,
- base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id,
- device_id, security_origin, auth_start_time));
-}
-
-void AudioRendererHost::OnDeviceAuthorized(int stream_id,
- const std::string& device_id,
- const url::Origin& security_origin,
- base::TimeTicks auth_start_time,
- bool have_access) {
+ const url::Origin& security_origin,
+ base::TimeTicks auth_start_time,
+ bool have_access) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const auto& auth_data = authorizations_.find(stream_id);
@@ -493,9 +450,9 @@ void AudioRendererHost::OnDeviceAuthorized(int stream_id,
if (!have_access) {
authorizations_.erase(auth_data);
UMALogDeviceAuthorizationTime(auth_start_time);
- Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
- media::AudioParameters::UnavailableDeviceParams(), std::string()));
+ SendAuthorizationMessage(
+ callback, stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
+ media::AudioParameters::UnavailableDeviceParams(), std::string());
return;
}
@@ -510,19 +467,20 @@ void AudioRendererHost::OnDeviceAuthorized(int stream_id,
audio_manager_->GetTaskRunner(), FROM_HERE,
base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_),
base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id,
- auth_start_time, true));
+ auth_start_time, callback, true));
} else {
media_stream_manager_->audio_output_device_enumerator()->Enumerate(
base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id,
security_origin,
base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this,
- stream_id, auth_start_time)));
+ stream_id, auth_start_time, callback)));
}
}
void AudioRendererHost::OnDeviceIDTranslated(
- int stream_id,
+ int32_t stream_id,
base::TimeTicks auth_start_time,
+ RequestDeviceAuthorizationCallback callback,
bool device_found,
const AudioOutputDeviceInfo& device_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -537,9 +495,9 @@ void AudioRendererHost::OnDeviceIDTranslated(
if (!device_found) {
authorizations_.erase(auth_data);
UMALogDeviceAuthorizationTime(auth_start_time);
- Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
- media::AudioParameters::UnavailableDeviceParams(), std::string()));
+ SendAuthorizationMessage(
+ callback, stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
+ media::AudioParameters::UnavailableDeviceParams(), std::string());
return;
}
@@ -549,45 +507,11 @@ void AudioRendererHost::OnDeviceIDTranslated(
media::AudioParameters output_params = device_info.output_params;
MaybeFixAudioParameters(&output_params);
UMALogDeviceAuthorizationTime(auth_start_time);
- Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string()));
-}
-
-void AudioRendererHost::OnCreateStream(int stream_id,
- int render_frame_id,
- const media::AudioParameters& params) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
- << "(stream_id=" << stream_id << ")";
-
- // Determine whether to use the device_unique_id from an authorization, or an
- // empty string (i.e., when no previous authorization was requested, assume
- // default device).
- std::string device_unique_id;
- const auto& auth_data = authorizations_.find(stream_id);
- if (auth_data != authorizations_.end()) {
- CHECK(auth_data->second.first);
- device_unique_id.swap(auth_data->second.second);
- authorizations_.erase(auth_data);
- }
-
-#if DCHECK_IS_ON()
- // When DCHECKs are turned on, hop over to the UI thread to validate the
- // |render_frame_id|, then continue stream creation on the IO thread. See
- // comment at top of DoCreateStream() for further details.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(validate_render_frame_id_function_, render_process_id_,
- render_frame_id,
- base::Bind(&AudioRendererHost::DoCreateStream, this, stream_id,
- render_frame_id, params, device_unique_id)));
-#else
- DoCreateStream(stream_id, render_frame_id, params, device_unique_id,
- render_frame_id > 0);
-#endif // DCHECK_IS_ON()
+ SendAuthorizationMessage(callback, stream_id, media::OUTPUT_DEVICE_STATUS_OK,
+ output_params, std::string());
}
-void AudioRendererHost::DoCreateStream(int stream_id,
+void AudioRendererHost::DoCreateStream(int32_t stream_id,
int render_frame_id,
const media::AudioParameters& params,
const std::string& device_unique_id,
@@ -619,6 +543,7 @@ void AudioRendererHost::DoCreateStream(int stream_id,
AudioBus::CalculateMemorySize(params);
std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
+ // client->OnStreamStateChange(media::mojom::AudioOutputStreamState::ERROR);
SendErrorMessage(stream_id);
return;
}
@@ -635,9 +560,9 @@ void AudioRendererHost::DoCreateStream(int stream_id,
if (media_observer)
media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
- std::unique_ptr<AudioEntry> entry(
- new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id,
- std::move(shared_memory), std::move(reader)));
+ std::unique_ptr<AudioEntry> entry(new AudioEntry(
+ this, callback, stream_id, render_frame_id, params, device_unique_id,
+ std::move(shared_memory), std::move(reader)));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
render_process_id_, entry->render_frame_id(), entry->controller());
@@ -653,7 +578,7 @@ void AudioRendererHost::DoCreateStream(int stream_id,
max_simultaneous_streams_ = audio_entries_.size();
}
-void AudioRendererHost::OnPlayStream(int stream_id) {
+void AudioRendererHost::OnPlayStream(int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntry* entry = LookupById(stream_id);
@@ -666,7 +591,7 @@ void AudioRendererHost::OnPlayStream(int stream_id) {
audio_log_->OnStarted(stream_id);
}
-void AudioRendererHost::OnPauseStream(int stream_id) {
+void AudioRendererHost::OnPauseStream(int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntry* entry = LookupById(stream_id);
@@ -679,7 +604,7 @@ void AudioRendererHost::OnPauseStream(int stream_id) {
audio_log_->OnStopped(stream_id);
}
-void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
+void AudioRendererHost::OnSetVolume(int32_t stream_id, double volume) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntry* entry = LookupById(stream_id);
@@ -695,12 +620,11 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
audio_log_->OnSetVolume(stream_id, volume);
}
-void AudioRendererHost::SendErrorMessage(int stream_id) {
- Send(new AudioMsg_NotifyStreamStateChanged(
- stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR));
+void AudioRendererHost::SendErrorMessage(int32_t stream_id) {
+ // TODO
}
-void AudioRendererHost::OnCloseStream(int stream_id) {
+void AudioRendererHost::OnCloseStream(int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
authorizations_.erase(stream_id);
@@ -735,7 +659,7 @@ void AudioRendererHost::DeleteEntry(std::unique_ptr<AudioEntry> entry) {
UpdateNumPlayingStreams(entry.get(), false);
}
-void AudioRendererHost::ReportErrorAndClose(int stream_id) {
+void AudioRendererHost::ReportErrorAndClose(int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Make sure this isn't a stray callback executing after the stream has been
@@ -750,7 +674,8 @@ void AudioRendererHost::ReportErrorAndClose(int stream_id) {
OnCloseStream(stream_id);
}
-AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
+AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(
+ int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
@@ -791,6 +716,128 @@ bool AudioRendererHost::HasActiveAudio() {
return !base::AtomicRefCountIsZero(&num_playing_streams_);
}
+void AudioRendererHost::BindRequest(media::mojom::AudioOutputRequest request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ binding_.reset(
+ new mojo::Binding<media::mojom::AudioOutput>(this, std::move(request)));
+}
+
+// media::mojom::AudioOutput implementation
+void AudioRendererHost::RequestDeviceAuthorization(
+ int64_t render_frame_id,
+ int64_t session_id,
+ const mojo::String& device_id,
+ const url::Origin& origin,
+ const RequestDeviceAuthorizationCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const base::TimeTicks auth_start_time = base::TimeTicks::Now();
+ int32_t stream_id = next_stream_id++;
+
+ DVLOG(1) << "AudioRendererHost@" << this << "::RequestDeviceAuthorization"
+ << "(stream_id=" << stream_id
+ << ", render_frame_id=" << render_frame_id
+ << ", session_id=" << session_id << ", device_id=" << device_id
+ << ", origin=" << origin << ")";
+
+ if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
+ return;
+
+ if (!IsValidDeviceId(device_id)) {
+ UMALogDeviceAuthorizationTime(auth_start_time);
+ SendAuthorizationMessage(
+ callback, stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
+ media::AudioParameters::UnavailableDeviceParams(), std::string());
+ return;
+ }
+
+ // 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)) {
+ const StreamDeviceInfo* info =
+ media_stream_manager_->audio_input_device_manager()
+ ->GetOpenedDeviceInfoById(session_id);
+ if (info) {
+ media::AudioParameters output_params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ static_cast<media::ChannelLayout>(
+ info->device.matched_output.channel_layout),
+ info->device.matched_output.sample_rate, 16,
+ info->device.matched_output.frames_per_buffer);
+ output_params.set_effects(info->device.matched_output.effects);
+ authorizations_.insert(MakeAuthorizationData(
+ stream_id, true, info->device.matched_output_device_id));
+ MaybeFixAudioParameters(&output_params);
+ UMALogDeviceAuthorizationTime(auth_start_time);
+ // Hash matched device id and pass it to the renderer
+ SendAuthorizationMessage(
+ callback, stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
+ GetHMACForMediaDeviceID(salt_, origin,
+ info->device.matched_output_device_id));
+ return;
+ }
+ }
+
+ authorizations_.insert(
+ MakeAuthorizationData(stream_id, false, std::string()));
+ CheckOutputDeviceAccess(
+ render_frame_id, device_id, origin,
+ base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id,
+ callback, device_id, origin, auth_start_time));
+}
+
+void AudioRendererHost::CreateStream(int32_t stream_id,
+ int render_frame_id,
+ const media::AudioParameters& params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(1) << "AudioRendererHost@" << this << "::CreateStream"
+ << "(stream_id=" << stream_id << ")";
+
+ // Determine whether to use the device_unique_id from an authorization, or an
+ // empty string (i.e., when no previous authorization was requested, assume
+ // default device).
+ std::string device_unique_id;
+ const auto& auth_data = authorizations_.find(stream_id);
+ if (auth_data != authorizations_.end()) {
+ CHECK(auth_data->second.first);
+ device_unique_id.swap(auth_data->second.second);
+ authorizations_.erase(auth_data);
+ }
+
+#if DCHECK_IS_ON()
+ // When DCHECKs are turned on, hop over to the UI thread to validate the
+ // |render_frame_id|, then continue stream creation on the IO thread. See
+ // comment at top of DoCreateStream() for further details.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(validate_render_frame_id_function_, render_process_id_,
+ render_frame_id,
+ base::Bind(&AudioRendererHost::DoCreateStream, this, stream_id,
+ render_frame_id, params, device_unique_id)));
+#else
+ DoCreateStream(stream_id, render_frame_id, params, device_unique_id,
+ render_frame_id > 0);
+#endif // DCHECK_IS_ON()
+}
+
+void AudioRendererHost::CloseStream(int32_t stream_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ OnCloseStream(stream_id);
+}
+
+void AudioRendererHost::SendAuthorizationMessage(
+ RequestDeviceAuthorizationCallback callback,
+ int32_t stream_id,
+ media::OutputDeviceStatus status,
+ const media::AudioParameters& params,
+ const std::string& matched_device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ callback.Run(status, params, matched_device_id);
+}
+
void AudioRendererHost::CheckOutputDeviceAccess(
int render_frame_id,
const std::string& device_id,
@@ -803,8 +850,8 @@ void AudioRendererHost::CheckOutputDeviceAccess(
if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
!MediaStreamManager::IsOriginAllowed(render_process_id_,
security_origin)) {
- content::bad_message::ReceivedBadMessage(this,
- bad_message::ARH_UNAUTHORIZED_URL);
+ // content::bad_message::ReceivedBadMessage(this,
+ // bad_message::ARH_UNAUTHORIZED_URL);
return;
}
@@ -861,7 +908,7 @@ void AudioRendererHost::TranslateDeviceID(
callback.Run(false, device_info);
}
-bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
+bool AudioRendererHost::IsAuthorizationStarted(int32_t stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const auto& i = authorizations_.find(stream_id);
return i != authorizations_.end();

Powered by Google App Engine
This is Rietveld 408576698