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

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

Issue 1856673002: Mojofication of the Chrome Audio Rendering Prototype Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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 eadd484b31116d0507282c74ef860ffbc59fad1a..fd604950241b0d1aa78f5e7961df33314cab72ab 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -11,7 +11,6 @@
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
#include "base/process/process.h"
#include "content/browser/bad_message.h"
@@ -31,11 +30,17 @@
#include "content/public/browser/media_observer.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/content_switches.h"
+#include "content/renderer/media/audio_output_client.h"
#include "media/audio/audio_device_name.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_streams_tracker.h"
#include "media/base/audio_bus.h"
#include "media/base/limits.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/public/cpp/system/handle.h"
+#include "base/time/time.h"
+
+#include "content/browser/media/audio_output_impl.h"
using media::AudioBus;
using media::AudioManager;
@@ -122,63 +127,7 @@ void MaybeFixAudioParameters(media::AudioParameters* params) {
} // namespace
-class AudioRendererHost::AudioEntry
- : public media::AudioOutputController::EventHandler {
- public:
- AudioEntry(AudioRendererHost* host,
- int stream_id,
- int render_frame_id,
- const media::AudioParameters& params,
- const std::string& output_device_id,
- scoped_ptr<base::SharedMemory> shared_memory,
- scoped_ptr<media::AudioOutputController::SyncReader> reader);
- ~AudioEntry() override;
-
- int stream_id() const {
- return stream_id_;
- }
-
- int render_frame_id() const { return render_frame_id_; }
-
- media::AudioOutputController* controller() const { return controller_.get(); }
-
- base::SharedMemory* shared_memory() {
- return shared_memory_.get();
- }
-
- media::AudioOutputController::SyncReader* reader() const {
- return reader_.get();
- }
-
- bool playing() const { return playing_; }
- void set_playing(bool playing) { playing_ = playing; }
-
- private:
- // 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_;
-
- // Shared memory for transmission of the audio data. Used by |reader_|.
- const scoped_ptr<base::SharedMemory> shared_memory_;
-
- // The synchronous reader to be used by |controller_|.
- const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
-
- // The AudioOutputController that manages the audio stream.
- const scoped_refptr<media::AudioOutputController> controller_;
-
- bool playing_;
-};
-
-AudioRendererHost::AudioEntry::AudioEntry(
+AudioEntry::AudioEntry(
AudioRendererHost* host,
int stream_id,
int render_frame_id,
@@ -200,7 +149,33 @@ AudioRendererHost::AudioEntry::AudioEntry(
DCHECK(controller_.get());
}
-AudioRendererHost::AudioEntry::~AudioEntry() {}
+AudioEntry::AudioEntry(
+ AudioRendererHost* host,
+ int stream_id,
+ int render_frame_id,
+ const media::AudioParameters& params,
+ const std::string& output_device_id,
+ scoped_ptr<base::SharedMemory> shared_memory,
+ scoped_ptr<media::AudioOutputController::SyncReader> reader,
+ mojom::AudioOutputStreamPtr stream,
+ const mojom::AudioOutput::CreateStreamCallback& callback)
+ : host_(host),
+ stream_id_(stream_id),
+ render_frame_id_(render_frame_id),
+ shared_memory_(std::move(shared_memory)),
+ reader_(std::move(reader)),
+ controller_(media::AudioOutputController::Create(host->audio_manager_,
+ this,
+ params,
+ output_device_id,
+ reader_.get(),
+ std::move(stream),
+ callback)),
+ playing_(false) {
+ DCHECK(controller_.get());
+}
+
+AudioEntry::~AudioEntry() {}
///////////////////////////////////////////////////////////////////////////////
// AudioRendererHost implementations.
@@ -267,14 +242,22 @@ void AudioRendererHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
-void AudioRendererHost::AudioEntry::OnCreated() {
+void AudioEntry::OnCreated() {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
}
-void AudioRendererHost::AudioEntry::OnPlaying() {
+void AudioEntry::OnCreated(
+ mojom::AudioOutputStreamPtr stream,
+ const mojom::AudioOutput::CreateStreamCallback& callback) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioRendererHost::DoCompleteCreationMojo,
+ host_, stream_id_, callback));
+}
+
+void AudioEntry::OnPlaying() {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -284,7 +267,7 @@ void AudioRendererHost::AudioEntry::OnPlaying() {
true));
}
-void AudioRendererHost::AudioEntry::OnPaused() {
+void AudioEntry::OnPaused() {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -294,7 +277,7 @@ void AudioRendererHost::AudioEntry::OnPaused() {
false));
}
-void AudioRendererHost::AudioEntry::OnError() {
+void AudioEntry::OnError() {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -306,13 +289,13 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
if (!PeerHandle()) {
DLOG(WARNING) << "Renderer process handle is invalid.";
- ReportErrorAndClose(stream_id);
+ // ReportErrorAndClose(stream_id);
return;
}
AudioEntry* const entry = LookupById(stream_id);
if (!entry) {
- ReportErrorAndClose(stream_id);
+ // ReportErrorAndClose(stream_id);
return;
}
@@ -323,7 +306,7 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
&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());
+ // ReportErrorAndClose(entry->stream_id());
return;
}
@@ -334,7 +317,7 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
// 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());
+ // ReportErrorAndClose(entry->stream_id());
return;
}
@@ -343,6 +326,99 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
entry->shared_memory()->requested_size()));
}
+void AudioRendererHost::DoCompleteCreationMojo(
+ int stream_id,
+ const mojom::AudioOutput::CreateStreamCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!PeerHandle()) {
+ DLOG(WARNING) << "Renderer process handle is invalid.";
+ ReportErrorAndCloseMojo(stream_id, callback);
+ return;
+ }
+
+ AudioEntry* const entry = LookupById(stream_id);
+ if (!entry) {
+ ReportErrorAndCloseMojo(stream_id, callback);
+ return;
+ }
+
+ scoped_ptr<mojom::AudioOutputStreamPtr> stream_ptr(
+ AudioOutputImpl::CreateStream(entry, stream_id));
+
+ base::SharedMemoryHandle shared_memory_handle =
+ base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle());
+
+ MojoHandle mojo_foreign_memory_handle;
+
+ MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper(
+ shared_memory_handle, entry->shared_memory()->requested_size(), false,
+ &mojo_foreign_memory_handle);
+
+ if (shared_buffer_result != MOJO_RESULT_OK) {
+ LOG(WARNING) << "Failed to wrap transit descriptor. Closing: "
+ << shared_buffer_result;
+ ReportErrorAndCloseMojo(entry->stream_id(), callback);
+ return;
+ }
+
+ 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)) {
+ ReportErrorAndCloseMojo(entry->stream_id(), callback);
+ return;
+ }
+ mojo::ScopedSharedBufferHandle shared_buffer_handle =
+ mojo::ScopedSharedBufferHandle(
+ mojo::SharedBufferHandle(mojo_foreign_memory_handle));
+
+ MojoHandle socket_descriptor_handle;
+ MojoResult platform_handle_result;
+
+#if defined(OS_WIN)
+ platform_handle_result = mojo::edk::CreatePlatformHandleWrapper(
+ mojo::edk::ScopedPlatformHandle(
+ mojo::edk::PlatformHandle(socket_descriptor)),
+ &socket_descriptor_handle);
+#else
+ platform_handle_result = mojo::edk::CreatePlatformHandleWrapper(
+ mojo::edk::ScopedPlatformHandle(
+ mojo::edk::PlatformHandle(socket_descriptor.fd)),
+ &socket_descriptor_handle);
+ LOG(WARNING) << "socket_descriptor.fd" << socket_descriptor.fd;
+ LOG(WARNING) << "socket_descriptor_handle" << socket_descriptor_handle;
+#endif
+
+ if (platform_handle_result != MOJO_RESULT_OK) {
+ LOG(WARNING) << "Failed to wrap platform handle. Closing: "
+ << platform_handle_result;
+ ReportErrorAndCloseMojo(stream_id, callback);
+ return;
+ }
+
+ stream_ptr->get()->set(20);
+ mojo::ScopedHandle socket_handle =
+ mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle));
+
+ LOG(ERROR) << "stream_id" << stream_id;
+ // LOG(ERROR) << "foreign_memory_handle.fd" << foreign_memory_handle.fd;
+ // LOG(ERROR) << "foreign_memory_handle.auto_close" <<
+ // foreign_memory_handle.auto_close;
+ LOG(ERROR) << "socket_descriptor.fd" << socket_descriptor.fd;
+ LOG(ERROR) << "socket_descriptor.auto_close" << socket_descriptor.auto_close;
+ LOG(ERROR) << "entry->shared_memory()->requested_size()"
+ << entry->shared_memory()->requested_size();
+ LOG(ERROR) << "AudioRendererHost::DoCompleteCreationMojo"
+ << base::TimeTicks::Now();
+
+ callback.Run(std::move(*stream_ptr), stream_id,
+ std::move(shared_buffer_handle), std::move(socket_handle));
+}
+
void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
bool is_playing) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -549,6 +625,32 @@ void AudioRendererHost::OnCreateStream(int stream_id,
authorizations_.erase(auth_data);
}
+void AudioRendererHost::OnCreateStreamMojo(
+ int stream_id,
+ int render_frame_id,
+ const media::AudioParameters& params,
+ mojom::AudioOutputStreamPtr stream,
+ const mojom::AudioOutput::CreateStreamCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
+ << "(stream_id=" << stream_id << ")";
+ LOG(ERROR) << "stream_id" << stream_id;
+
+ const auto& auth_data = authorizations_.find(stream_id);
+
+ // If no previous authorization requested, assume default device
+ if (auth_data == authorizations_.end()) {
+ DoCreateStream(stream_id, render_frame_id, params, std::string(),
+ std::move(stream), callback);
+ return;
+ }
+
+ CHECK(auth_data->second.first);
+ DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second,
+ std::move(stream), callback);
+ authorizations_.erase(auth_data);
+}
+
void AudioRendererHost::DoCreateStream(int stream_id,
int render_frame_id,
const media::AudioParameters& params,
@@ -600,6 +702,73 @@ void AudioRendererHost::DoCreateStream(int stream_id,
max_simultaneous_streams_ = audio_entries_.size();
}
+void AudioRendererHost::DoCreateStream(
+ int stream_id,
+ int render_frame_id,
+ const media::AudioParameters& params,
+ const std::string& device_unique_id,
+ mojom::AudioOutputStreamPtr stream,
+ const mojom::AudioOutput::CreateStreamCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // media::AudioParameters is validated in the deserializer.
+ if (LookupById(stream_id) != NULL) {
+ SendErrorMessage(stream_id);
+ return;
+ }
+
+ // Create the shared memory and share with the renderer process.
+ uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) +
+ AudioBus::CalculateMemorySize(params);
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+ if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
+ SendErrorMessage(stream_id);
+ return;
+ }
+
+ scoped_ptr<AudioSyncReader> reader(
+ new AudioSyncReader(shared_memory.get(), params));
+ if (!reader->Init()) {
+ SendErrorMessage(stream_id);
+ return;
+ }
+
+ MediaObserver* const media_observer =
+ GetContentClient()->browser()->GetMediaObserver();
+ if (media_observer)
+ media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
+
+ scoped_ptr<AudioEntry> entry(
+ new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id,
+ std::move(shared_memory), std::move(reader),
+ std::move(stream), callback));
+ 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();
+
+ audio_log_->OnCreated(stream_id, params, device_unique_id);
+ MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry(
+ stream_id, render_process_id_, render_frame_id, audio_log_.get());
+
+ if (audio_entries_.size() > max_simultaneous_streams_)
+ max_simultaneous_streams_ = audio_entries_.size();
+}
+
+void AudioRendererHost::OnPlayEntry(AudioEntry* entry) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!entry) {
+ SendErrorMessage(0);
+ return;
+ }
+
+ entry->controller()->Play();
+ audio_log_->OnStarted(0);
+}
+
void AudioRendererHost::OnPlayStream(int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -648,6 +817,7 @@ void AudioRendererHost::SendErrorMessage(int stream_id) {
}
void AudioRendererHost::OnCloseStream(int stream_id) {
+ DLOG(WARNING) << "OnCloseStream " << stream_id;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
authorizations_.erase(stream_id);
@@ -697,7 +867,29 @@ void AudioRendererHost::ReportErrorAndClose(int stream_id) {
OnCloseStream(stream_id);
}
-AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
+void AudioRendererHost::ReportErrorAndCloseMojo(
+ int stream_id,
+ const mojom::AudioOutput::CreateStreamCallback& callback) {
+ 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))
+ return;
+ mojo::ScopedSharedBufferHandle shared_buffer_handle =
+ mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle());
+
+ mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle());
+
+ callback.Run(mojom::AudioOutputStreamPtr(), stream_id,
+ std::move(shared_buffer_handle), std::move(socket_handle));
+
+ audio_log_->OnError(stream_id);
+ OnCloseStream(stream_id);
+}
+
+AudioEntry* AudioRendererHost::LookupById(int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
« no previous file with comments | « content/browser/renderer_host/media/audio_renderer_host.h ('k') | content/browser/renderer_host/render_process_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698