Index: services/media/audio/audio_output_manager.h |
diff --git a/services/media/audio/audio_output_manager.h b/services/media/audio/audio_output_manager.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2599ee57ef01b351ce0178e6ca8f074d8f2209d2 |
--- /dev/null |
+++ b/services/media/audio/audio_output_manager.h |
@@ -0,0 +1,109 @@ |
+// 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. |
+ |
+#ifndef SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_MANAGER_H_ |
+#define SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_MANAGER_H_ |
+ |
+#include <set> |
+ |
+#include "base/synchronization/lock.h" |
+#include "base/threading/sequenced_worker_pool.h" |
+#include "mojo/services/media/common/interfaces/media_common.mojom.h" |
+#include "mojo/services/media/common/interfaces/media_pipe.mojom.h" |
+#include "services/media/audio/audio_output.h" |
+#include "services/media/audio/fwd_decls.h" |
+ |
+namespace mojo { |
+namespace media { |
+namespace audio { |
+ |
+class AudioOutputManager { |
+ public: |
+ explicit AudioOutputManager(AudioServerImpl* server); |
+ ~AudioOutputManager(); |
+ |
+ // Initialize the output manager. Called from the service implementation, |
+ // once, at startup time. Should... |
+ // |
+ // 1) Initialize the mixing thread pool. |
+ // 2) Instantiate all of the built-in audio output devices. |
+ // 3) Being monitoring for plug/unplug events for pluggable audio output |
+ // devices. |
+ MediaResult Init(); |
+ |
+ // Blocking call. Called by the service, once, when it is time to shutdown |
+ // the service implementation. While this function is blocking, it must never |
+ // block for long. Our process is going away; this is our last chance to |
+ // perform a clean shutdown. If an unclean shutdown must be performed in |
+ // order to implode in a timely fashion, so be it. |
+ // |
+ // Shutdown must be idempotent, and safe to call from the output manager's |
+ // destructor, although it should never be necessary to do so. If the |
+ // shutdown called from the destructor has to do real work, something has gone |
+ // Very Seriously Wrong. |
jeffbrown
2015/11/04 23:43:33
Instead of this comment, maybe just make it blow u
johngro
2015/11/06 02:20:25
I already have some DCHECK protection for the idem
|
+ void Shutdown(); |
+ |
+ // Select the initial set of outputs for a track which has just been |
+ // configured. |
+ void SelectOutputsForTrack(AudioTrackImplPtr track); |
+ |
+ // Schedule a closure to run on our encapsulating server's main message loop. |
+ void ScheduleMessageLoopTask(const tracked_objects::Location& from_here, |
+ const base::Closure& task); |
+ |
+ // Shutdown the specified audio output and remove it from the set of active |
+ // outputs. |
+ void ShutdownOutput(AudioOutputPtr output); |
+ |
+ private: |
+ // TODO(johngro): A SequencedWorkerPool currently seems to be as close to what |
+ // we want which we can currently get using the chrome/mojo framework. Things |
+ // which are missing and will eventually need to be addressed include... |
+ // |
+ // 1) Threads are created on the fly, as needed. We really want to be able to |
+ // spin up the proper number of threads at pool creation time. Audio |
+ // mixing is very timing sensitive... If we are in a situation where we |
+ // have not hit the max number of threads in the pool, and we need to spin |
+ // up a thread in order to mix, we *really* do not want to have to wait to |
+ // create the thread at the OS level before we can mix some audio. The |
+ // thread needs to already be ready to go. |
+ // 2) Threads in the pool are created with default priority. Audio mixing |
+ // threads will need to be created with elevated priority. |
+ // 3) It is currently unclear if explicitly scheduling tasks with delays will |
+ // be sufficient for the audio mixer. We really would like to be able to |
+ // have tasks fire when some handle abstraction becomes signalled. This |
+ // will let us implement mixing not only with open loop timing, but also |
+ // with events which can come from device drivers. Note: this seems to be |
+ // an issue with the TaskRunner architecture in general, not the |
+ // SequencedWorkerPool in specific. |
+ // 4) The resolution of posted delayed tasks may hinder the low latency goals |
+ // of the system. Being able to know the underlying achievable resolution |
+ // of dispatching delayed tasks is a minimum requirement. From that, we |
+ // can compute our worst case overhead which can be communicated to the |
+ // user and will have an effect on overall latency. Hitting something on |
+ // the order of 10s of microseconds is what we really should be shooting |
+ // for here. Single milliseconds is probably too coarse. |
+ // 5) Not a requirement, but a sure-would-be-nice-to-have... Scheduling |
+ // delayed tasks using absolute times. Having to schedule using delta |
+ // times from now means that we need to take the time it takes to schedule |
+ // the task (along with its jitter) into account when scheduling. This can |
+ // lead to additional, undesirable, latency. |
+ scoped_refptr<base::SequencedWorkerPool> thread_pool_; |
jeffbrown
2015/11/04 23:43:33
Alternately if the number of audio outputs is smal
johngro
2015/11/06 02:20:24
Acknowledged.
We may end up at this point. Per-ou
|
+ |
+ // A pointer to the server which encapsulates us. It is not possible for this |
+ // pointer to be bad while we still exist. |
+ AudioServerImpl* server_; |
+ |
+ // Our set of currently active audio output instances. |
+ // |
+ // Contents of the output set must only be manipulated on the main message |
+ // loop thread, so no synchronization should be needed. |
+ AudioOutputSet outputs_; |
+}; |
+ |
+} // namespace audio |
+} // namespace media |
+} // namespace mojo |
+ |
+#endif // SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_MANAGER_H_ |