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_H_ |
| 6 #define SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_H_ |
| 7 |
| 8 #include <deque> |
| 9 #include <memory> |
| 10 #include <set> |
| 11 |
| 12 #include "base/callback.h" |
| 13 #include "base/synchronization/lock.h" |
| 14 #include "base/threading/sequenced_worker_pool.h" |
| 15 #include "mojo/services/media/common/cpp/local_time.h" |
| 16 #include "services/media/audio/audio_pipe.h" |
| 17 #include "services/media/audio/audio_track_impl.h" |
| 18 #include "services/media/audio/fwd_decls.h" |
| 19 |
| 20 namespace mojo { |
| 21 namespace media { |
| 22 namespace audio { |
| 23 |
| 24 class AudioOutput { |
| 25 public: |
| 26 virtual ~AudioOutput(); |
| 27 |
| 28 // AddTrack/RemoveTrack |
| 29 // |
| 30 // Adds or removes a track to/from the set of current set of tracks serviced |
| 31 // by this output. Called only from the main message loop. Obtains the |
| 32 // processing_lock and may block for the time it takes the derived class to |
| 33 // run its processing task if the task is in progress when the method was |
| 34 // called. |
| 35 MediaResult AddTrackLink(AudioTrackToOutputLinkPtr link); |
| 36 MediaResult RemoveTrackLink(const AudioTrackToOutputLinkPtr& link); |
| 37 |
| 38 protected: |
| 39 explicit AudioOutput(AudioOutputManager* manager); |
| 40 |
| 41 ////////////////////////////////////////////////////////////////////////////// |
| 42 // |
| 43 // Methods which may be implemented by derived classes to customize behavior. |
| 44 // |
| 45 ////////////////////////////////////////////////////////////////////////////// |
| 46 |
| 47 // Init |
| 48 // |
| 49 // Called during startup on the AudioServer's main message loop thread. No |
| 50 // locks are being held at this point. Derived classes should allocate their |
| 51 // hardware resources and initialize any internal state. Return |
| 52 // MediaResult::OK if everything is good and the output is ready to do work. |
| 53 virtual MediaResult Init(); |
| 54 |
| 55 // Cleanup |
| 56 // |
| 57 // Called at shutdown on the AudioServer's main message loop thread to allow |
| 58 // derived classes to clean up any allocated resources. All pending |
| 59 // processing callbacks have either been nerfed or run till completion. All |
| 60 // AudioTrack tracks have been disconnected. No locks are being held. |
| 61 virtual void Cleanup(); |
| 62 |
| 63 // Process |
| 64 // |
| 65 // Called from within the context of the processing lock any time a scheduled |
| 66 // processing callback fires. One callback will be automatically scheduled at |
| 67 // the end of initialization. After that, derived classes are responsible for |
| 68 // scheduling all subsequent callbacks to keep the engine running. |
| 69 // |
| 70 // Note: Process callbacks execute on one of the threads from the |
| 71 // AudioOutputManager's base::SequencedWorkerPool. While successive callbacks |
| 72 // may not execute on the same thread, they are guaranteed to execute in a |
| 73 // serialized fashion. |
| 74 virtual void Process() = 0; |
| 75 |
| 76 // InitializeLink |
| 77 // |
| 78 // Called on the AudioServer's main message loop any time a track is being |
| 79 // added to this output. Outputs should allocate and initialize any |
| 80 // bookkeeping they will need to perform mixing on behalf of the newly added |
| 81 // track. |
| 82 // |
| 83 // @return MediaResult::OK if initialization succeeded, or an appropriate |
| 84 // error code otherwise. |
| 85 virtual MediaResult InitializeLink(const AudioTrackToOutputLinkPtr& link); |
| 86 |
| 87 ////////////////////////////////////////////////////////////////////////////// |
| 88 // |
| 89 // Methods which may used by derived classes from within the context of a |
| 90 // processing callback. Note; since these methods are intended to be called |
| 91 // from the within a process callback, the processing_lock will always be held |
| 92 // when they are called. |
| 93 // |
| 94 |
| 95 // ScheduleCallback |
| 96 // |
| 97 // Schedule a processing callback at the specified absolute time on the local |
| 98 // clock. |
| 99 void ScheduleCallback(LocalTime when); |
| 100 |
| 101 // ShutdownSelf |
| 102 // |
| 103 // Kick off the process of shooting ourselves in the head. Note, after this |
| 104 // method has been called, no new callbacks may be scheduled. As soon as the |
| 105 // main message loop finds out about our shutdown request, it will complete |
| 106 // the process of shutting us down, unlinking us from our tracks and calling |
| 107 // the Cleanup method. |
| 108 void ShutdownSelf(); |
| 109 |
| 110 // shutting_down |
| 111 // |
| 112 // Check the shutting down flag. Only the base class may modify the flag, but |
| 113 // derived classes are free to check it at any time. |
| 114 inline bool shutting_down() const { return shutting_down_; } |
| 115 |
| 116 // TODO(johngro): Order this by priority. Figure out how we are going to be |
| 117 // able to quickly find a track with a specific priority in order to optimize |
| 118 // changes of priority. Perhaps uniquify the priorities by assigning a |
| 119 // sequence number to the lower bits (avoiding collisions when assigning new |
| 120 // priorities will be the trick). |
| 121 // |
| 122 // Right now, we have no priorities, so this is just a set of track/output |
| 123 // links. |
| 124 AudioTrackToOutputLinkSet links_; |
| 125 AudioOutputManager* manager_; |
| 126 |
| 127 private: |
| 128 // It's always nice when you manager is also your friend. Seriously though, |
| 129 // the AudioOutputManager gets to call Init and Shutown, no one else |
| 130 // (including derived classes) should be able to. |
| 131 friend class AudioOutputManager; |
| 132 |
| 133 // Thunk used to schedule delayed processing tasks on our task_runner. |
| 134 static void ProcessThunk(AudioOutputWeakPtr weak_output); |
| 135 |
| 136 // Called from the AudioOutputManager after an output has been created. |
| 137 // Gives derived classes a chance to set up hardware, then sets up the |
| 138 // machinery needed for scheduling processing tasks and schedules the first |
| 139 // processing callback immediately in order to get the process running. |
| 140 MediaResult Init(const AudioOutputPtr& self, |
| 141 scoped_refptr<base::SequencedTaskRunner> task_runner); |
| 142 |
| 143 // Called from Shutdown (main message loop) and ShutdowSelf (processing |
| 144 // context). Starts the process of shutdown, preventing new processing tasks |
| 145 // from being scheduled, and nerfing any tasks in flight. |
| 146 // |
| 147 // @return true if this call just kicked off the process of shutting down, |
| 148 // false otherwise. |
| 149 bool BeginShutdown(); |
| 150 |
| 151 // Called from the AudioOutputManager on the main message loop |
| 152 // thread. Makes certain that the process of shutdown has started, |
| 153 // synchronizes with any processing tasks which were executing at the time, |
| 154 // then finishes the shutdown process by unlinking from all tracks and |
| 155 // cleaning up all resources. |
| 156 void Shutdown(); |
| 157 |
| 158 base::Lock processing_lock_; |
| 159 base::Lock shutdown_lock_; |
| 160 scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| 161 AudioOutputWeakPtr weak_self_; |
| 162 |
| 163 // TODO(johngro): Eliminate the shutting down flag and just use the |
| 164 // task_runner_'s nullness for this test? |
| 165 volatile bool shutting_down_ = false; |
| 166 volatile bool shut_down_ = false; |
| 167 }; |
| 168 |
| 169 } // namespace audio |
| 170 } // namespace media |
| 171 } // namespace mojo |
| 172 |
| 173 #endif // SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_H_ |
| 174 |
OLD | NEW |