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

Unified Diff: services/media/audio/audio_output_manager.cc

Issue 1424933002: Add an initial revision of an audio server. (Closed) Base URL: https://github.com/domokit/mojo.git@change4
Patch Set: fix issues discovered with initial preflight Created 5 years, 1 month 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
« no previous file with comments | « services/media/audio/audio_output_manager.h ('k') | services/media/audio/audio_pipe.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: services/media/audio/audio_output_manager.cc
diff --git a/services/media/audio/audio_output_manager.cc b/services/media/audio/audio_output_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..59e4ff38a2052c2a748e307355851b6f87412eb3
--- /dev/null
+++ b/services/media/audio/audio_output_manager.cc
@@ -0,0 +1,150 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "services/media/audio/audio_output.h"
+#include "services/media/audio/audio_output_manager.h"
+#include "services/media/audio/audio_server_impl.h"
+#include "services/media/audio/audio_track_to_output_link.h"
+#include "services/media/audio/platform/generic/throttle_output.h"
+
+namespace mojo {
+namespace media {
+namespace audio {
+
+static constexpr size_t THREAD_POOL_SZ = 2;
+static const std::string THREAD_PREFIX("AudioMixer");
+
+AudioOutputManager::AudioOutputManager(AudioServerImpl* server)
+ : server_(server) {
+}
+
+AudioOutputManager::~AudioOutputManager() {
+ Shutdown();
+ DCHECK_EQ(outputs_.size(), 0u);
+ DCHECK(!thread_pool_);
+}
+
+MediaResult AudioOutputManager::Init() {
+ // Step #1: Initialize the mixing thread pool.
+ //
+ // TODO(johngro): make the thread pool size proportional to the maximum
+ // number of cores available in the system.
+ //
+ // TODO(johngro): make sure that the threads are executed at an elevated
+ // priority, not the default priority.
+ thread_pool_ = new base::SequencedWorkerPool(THREAD_POOL_SZ, THREAD_PREFIX);
+
+ // Step #2: Instantiate all of the built-in audio output devices.
+ //
+ // TODO(johngro): Come up with a better way of doing this based on our
+ // platform. Right now, we just create some hardcoded default outputs and
+ // leave it at that.
+ outputs_.emplace(audio::ThrottleOutput::New(this));
+
+ // Step #3: Being monitoring for plug/unplug events for pluggable audio
+ // output devices.
+ //
+ // TODO(johngro): Implement step #3. Right now, the details are behind
+ // hot-plug monitoring are TBD, so the feature is not implemented.
+
+ // Step #4: Attempt to initialize each of the audio outputs we have created,
+ // then kick off the callback engine for each of them.
+ for (auto iter = outputs_.begin(); iter != outputs_.end(); ) {
+ const AudioOutputPtr& output = *iter;
+ auto tmp = iter++;
+ DCHECK(output);
+
+ // Create a sequenced task runner for this output. It will be used by the
+ // output to schedule jobs (such as mixing) on the thread pool.
+ scoped_refptr<base::SequencedTaskRunner> task_runner =
+ thread_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
+ thread_pool_->GetSequenceToken(),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+
+ MediaResult res = output->Init(output, task_runner);
+ if (res != MediaResult::OK) {
+ // TODO(johngro): Probably should log something about this, assuming that
+ // the output has not already.
+ outputs_.erase(tmp);
+ }
+ }
+
+ return MediaResult::OK;
+}
+
+void AudioOutputManager::Shutdown() {
+ // Are we already shutdown (or were we never successfully initialized?)
+ if (thread_pool_ == nullptr) {
+ DCHECK_EQ(outputs_.size(), 0u);
+ return;
+ }
+
+ // Step #1: Stop monitoringing plug/unplug events. We are shutting down and
+ // no longer care about outputs coming and going.
+ //
+ // TODO(johngro): Implement step #1. Right now, the details are behind
+ // hot-plug monitoring are TBD, so the feature is not implemented.
+
+ // Step #2: Shut down each currently active output in the system. It is
+ // possible for this to take a bit of time as outputs release their hardware,
+ // but it should not take long.
+ for (const auto& output_ptr : outputs_) {
+ output_ptr->Shutdown();
+ }
+ outputs_.clear();
+
+ // Step #3: Shutdown and release our thread pool. Since we have shut down all
+ // of our outputs, any pending tasks left in the task runner are now no-ops,
+ // so it does not matter that the task runner is going to cancel them all
+ // (instead of blocking) when we shut it down.
+ thread_pool_->Shutdown();
+ thread_pool_ = nullptr;
+}
+
+void AudioOutputManager::ShutdownOutput(AudioOutputPtr output) {
+ // No one should be calling this method if we have been shut down (or never
+ // successfully started).
+ DCHECK(thread_pool_);
+
+ auto iter = outputs_.find(output);
+ if (iter != outputs_.end()) {
+ output->Shutdown();
+ outputs_.erase(iter);
+ }
+}
+
+void AudioOutputManager::SelectOutputsForTrack(AudioTrackImplPtr track) {
+ // TODO(johngro): Someday, base this on policy. For now, every track gets
+ // assigned to every output in the system.
+ DCHECK(track);
+
+ // TODO(johngro): Add some way to assert that we are executing on the main
+ // message loop thread.
+
+ for (auto output : outputs_) {
+ auto link = AudioTrackToOutputLink::New(track, output);
+ DCHECK(output);
+ DCHECK(link);
+
+ // If we cannot add this link to the output, it's because the output is in
+ // the process of shutting down (we didn't want to hang out with that guy
+ // anyway)
+ if (output->AddTrackLink(link) == MediaResult::OK) {
+ track->AddOutput(link);
+ }
+ }
+}
+
+void AudioOutputManager::ScheduleMessageLoopTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ DCHECK(server_);
+ server_->ScheduleMessageLoopTask(from_here, task);
+}
+
+} // namespace audio
+} // namespace media
+} // namespace mojo
« no previous file with comments | « services/media/audio/audio_output_manager.h ('k') | services/media/audio/audio_pipe.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698