OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_MANAGER_H_ |
| 6 #define SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_MANAGER_H_ |
| 7 |
| 8 #include <set> |
| 9 |
| 10 #include "base/synchronization/lock.h" |
| 11 #include "base/threading/sequenced_worker_pool.h" |
| 12 #include "mojo/services/media/common/interfaces/media_common.mojom.h" |
| 13 #include "mojo/services/media/common/interfaces/media_pipe.mojom.h" |
| 14 #include "services/media/audio/audio_output.h" |
| 15 #include "services/media/audio/fwd_decls.h" |
| 16 |
| 17 namespace mojo { |
| 18 namespace media { |
| 19 namespace audio { |
| 20 |
| 21 class AudioOutputManager { |
| 22 public: |
| 23 explicit AudioOutputManager(AudioServerImpl* server); |
| 24 ~AudioOutputManager(); |
| 25 |
| 26 // Initialize the output manager. Called from the service implementation, |
| 27 // once, at startup time. Should... |
| 28 // |
| 29 // 1) Initialize the mixing thread pool. |
| 30 // 2) Instantiate all of the built-in audio output devices. |
| 31 // 3) Being monitoring for plug/unplug events for pluggable audio output |
| 32 // devices. |
| 33 MediaResult Init(); |
| 34 |
| 35 // Blocking call. Called by the service, once, when it is time to shutdown |
| 36 // the service implementation. While this function is blocking, it must never |
| 37 // block for long. Our process is going away; this is our last chance to |
| 38 // perform a clean shutdown. If an unclean shutdown must be performed in |
| 39 // order to implode in a timely fashion, so be it. |
| 40 // |
| 41 // Shutdown must be idempotent, and safe to call from the output manager's |
| 42 // destructor, although it should never be necessary to do so. If the |
| 43 // shutdown called from the destructor has to do real work, something has gone |
| 44 // Very Seriously Wrong. |
| 45 void Shutdown(); |
| 46 |
| 47 // Select the initial set of outputs for a track which has just been |
| 48 // configured. |
| 49 void SelectOutputsForTrack(AudioTrackImplPtr track); |
| 50 |
| 51 // Schedule a closure to run on our encapsulating server's main message loop. |
| 52 void ScheduleMessageLoopTask(const tracked_objects::Location& from_here, |
| 53 const base::Closure& task); |
| 54 |
| 55 // Shutdown the specified audio output and remove it from the set of active |
| 56 // outputs. |
| 57 void ShutdownOutput(AudioOutputPtr output); |
| 58 |
| 59 private: |
| 60 // TODO(johngro): A SequencedWorkerPool currently seems to be as close to what |
| 61 // we want which we can currently get using the chrome/mojo framework. Things |
| 62 // which are missing and will eventually need to be addressed include... |
| 63 // |
| 64 // 1) Threads are created on the fly, as needed. We really want to be able to |
| 65 // spin up the proper number of threads at pool creation time. Audio |
| 66 // mixing is very timing sensitive... If we are in a situation where we |
| 67 // have not hit the max number of threads in the pool, and we need to spin |
| 68 // up a thread in order to mix, we *really* do not want to have to wait to |
| 69 // create the thread at the OS level before we can mix some audio. The |
| 70 // thread needs to already be ready to go. |
| 71 // 2) Threads in the pool are created with default priority. Audio mixing |
| 72 // threads will need to be created with elevated priority. |
| 73 // 3) It is currently unclear if explicitly scheduling tasks with delays will |
| 74 // be sufficient for the audio mixer. We really would like to be able to |
| 75 // have tasks fire when some handle abstraction becomes signalled. This |
| 76 // will let us implement mixing not only with open loop timing, but also |
| 77 // with events which can come from device drivers. Note: this seems to be |
| 78 // an issue with the TaskRunner architecture in general, not the |
| 79 // SequencedWorkerPool in specific. |
| 80 // 4) The resolution of posted delayed tasks may hinder the low latency goals |
| 81 // of the system. Being able to know the underlying achievable resolution |
| 82 // of dispatching delayed tasks is a minimum requirement. From that, we |
| 83 // can compute our worst case overhead which can be communicated to the |
| 84 // user and will have an effect on overall latency. Hitting something on |
| 85 // the order of 10s of microseconds is what we really should be shooting |
| 86 // for here. Single milliseconds is probably too coarse. |
| 87 // 5) Not a requirement, but a sure-would-be-nice-to-have... Scheduling |
| 88 // delayed tasks using absolute times. Having to schedule using delta |
| 89 // times from now means that we need to take the time it takes to schedule |
| 90 // the task (along with its jitter) into account when scheduling. This can |
| 91 // lead to additional, undesirable, latency. |
| 92 scoped_refptr<base::SequencedWorkerPool> thread_pool_; |
| 93 |
| 94 // A pointer to the server which encapsulates us. It is not possible for this |
| 95 // pointer to be bad while we still exist. |
| 96 AudioServerImpl* server_; |
| 97 |
| 98 // Our set of currently active audio output instances. |
| 99 // |
| 100 // Contents of the output set must only be manipulated on the main message |
| 101 // loop thread, so no synchronization should be needed. |
| 102 AudioOutputSet outputs_; |
| 103 }; |
| 104 |
| 105 } // namespace audio |
| 106 } // namespace media |
| 107 } // namespace mojo |
| 108 |
| 109 #endif // SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_MANAGER_H_ |
OLD | NEW |