Chromium Code Reviews| 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 outputs. Called only from the main message loop. Obtains the | |
|
jeffbrown
2015/11/04 23:43:32
outputs -> output
johngro
2015/11/06 02:20:24
Done.
| |
| 32 // processing_lock and may block for the time it takes the derrived class to | |
|
jeffbrown
2015/11/04 23:43:33
derrived -> derived
johngro
2015/11/06 02:20:24
Done.
| |
| 33 // run its processing task if the task is in progress when the method was | |
| 34 // called. | |
|
jeffbrown
2015/11/04 23:43:32
In general it's safer to avoid immediately calling
johngro
2015/11/06 02:20:24
I'm not sure that I understand the question. As t
| |
| 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(); | |
|
jeffbrown
2015/11/04 23:43:32
Consider using a convention such as OnInit() to di
johngro
2015/11/06 02:20:24
If I had not intended for the method to be overrid
| |
| 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 | |
|
jeffbrown
2015/11/04 23:43:32
Technically you don't need a lock to guarantee ser
johngro
2015/11/06 02:20:24
The lock is not being used to guarantee serializat
| |
| 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 virtual void Process() = 0; | |
| 70 | |
| 71 // InitializeLink | |
| 72 // | |
| 73 // Called on the AudioServer's main message loop any time a track is being | |
| 74 // added to this output. Outputs should allocate and initialize any | |
| 75 // bookkeeping they will need to perform mixing on behalf of the newly added | |
| 76 // track. | |
| 77 // | |
| 78 // @return MediaResult::OK if initialization succeeded, or an appropriate | |
| 79 // error code otherwise. | |
| 80 virtual MediaResult InitializeLink(const AudioTrackToOutputLinkPtr& link); | |
| 81 | |
| 82 ////////////////////////////////////////////////////////////////////////////// | |
| 83 // | |
| 84 // Methods which may used by derived classes from within the context of a | |
| 85 // processing callback. Note; since these methods are intended to be called | |
| 86 // from the within a processing callback, the processing_lock will always be | |
|
jeffbrown
2015/11/04 23:43:32
This here suggests that these methods should be pr
johngro
2015/11/06 02:20:24
I don't understand. The context, in this case, is
| |
| 87 // held when they are called. | |
| 88 // | |
| 89 | |
| 90 // ScheduleCallback | |
| 91 // | |
| 92 // Schedule a processing callback at the specified absolute time on the local | |
| 93 // clock. | |
| 94 void ScheduleCallback(LocalTime when); | |
| 95 | |
| 96 // ShutdownSelf | |
| 97 // | |
| 98 // Kick off the process of shooting ourselves in the head. Note, after this | |
| 99 // method has been called, no new callbacks may be scheduled. As soon as the | |
| 100 // main message loop finds out about our shutdown request, it will complete | |
| 101 // the process of shutting us down, unlinking us from our tracks and calling | |
| 102 // the Cleanup method. | |
| 103 void ShutdownSelf(); | |
| 104 | |
| 105 // shutting_down | |
| 106 // | |
| 107 // Check the shutting down flag. Only the base class may modify the flag, but | |
| 108 // derived classes are free to check it at any time. | |
| 109 inline bool shutting_down() const { return shutting_down_; } | |
| 110 | |
| 111 // TODO(johngro): Order this by priority. Figure out how we are going to be | |
| 112 // able to quickly find a track with a specific priority in order to optimize | |
| 113 // changes of priority. Perhaps uniquify the priorities by assigning a | |
| 114 // sequence number to the lower bits (avoiding collisions when assigning new | |
| 115 // priorities will be the trick). | |
|
jeffbrown
2015/11/04 23:43:33
Could just use a heap.
johngro
2015/11/06 02:20:24
sure, I pretty much already am; right now I am usi
| |
| 116 // | |
| 117 // Right now, we have no priorities, so this is just a set of track/output | |
| 118 // links. | |
| 119 AudioTrackToOutputLinkSet links_; | |
| 120 AudioOutputManager* manager_; | |
| 121 | |
| 122 private: | |
| 123 // It's always nice when you manager is also your friend. Seriously though, | |
| 124 // the AudioOutputManager gets to call Init and Shutown, no one else | |
| 125 // (including derived classes) should be able to. | |
| 126 friend class AudioOutputManager; | |
| 127 | |
| 128 // Thunk used to schedule delayed processing tasks on our task_runner. | |
| 129 static void ProcessThunk(AudioOutputWeakPtr weak_output); | |
| 130 | |
| 131 // Called from the AudioOutputManager after an output has been created. | |
| 132 // Gives derived classes a chance to set up hardware, then sets up the | |
| 133 // machinery needed for scheduling processing tasks and schedules the first | |
| 134 // processing callback immediately in order to get the process running. | |
| 135 MediaResult Init(const AudioOutputPtr& self, | |
| 136 scoped_refptr<base::SequencedTaskRunner> task_runner); | |
| 137 | |
| 138 // Called from Shutdown (main message loop) and ShutdowSelf (processing | |
|
jeffbrown
2015/11/04 23:43:32
I think it's a little weird for there to be two di
johngro
2015/11/06 02:20:24
That is how things handled now. Shutdown self pos
| |
| 139 // context). Starts the process of shutdown, preventing new processing tasks | |
| 140 // from being scheduled, and nerfing any tasks in flight. | |
| 141 // | |
| 142 // @return true if this call just kicked off the process of shutting down, | |
| 143 // false otherwise. | |
| 144 bool BeginShutdown(); | |
| 145 | |
| 146 // Called from the AudioOutputManager on the main message loop | |
| 147 // thread. Makes certain that the process of shutdown has started, | |
| 148 // synchronizes with any processing tasks which were executing at the time, | |
| 149 // then finishes the shutdown process by unlinking from all tracks and | |
| 150 // cleaning up all resources. | |
| 151 void Shutdown(); | |
| 152 | |
| 153 base::Lock processing_lock_; | |
|
jeffbrown
2015/11/04 23:43:33
We won't need this lock if the processing state is
johngro
2015/11/06 02:20:24
I disagree. See my comments regarding synchroniza
| |
| 154 base::Lock shutdown_lock_; | |
|
jeffbrown
2015/11/04 23:43:32
We won't need this lock is shutdown is always init
johngro
2015/11/06 02:20:24
Unfortunately, I think it is an important requirem
| |
| 155 scoped_refptr<base::SequencedTaskRunner> task_runner_; | |
| 156 AudioOutputWeakPtr weak_self_; | |
| 157 | |
| 158 // TODO(johngro): Eliminate the shutting down flag and just use the | |
| 159 // task_runner_'s nullness for this test? | |
| 160 volatile bool shutting_down_ = false; | |
| 161 volatile bool shut_down_ = false; | |
| 162 }; | |
| 163 | |
| 164 } // namespace audio | |
| 165 } // namespace media | |
| 166 } // namespace mojo | |
| 167 | |
| 168 #endif // SERVICES_MEDIA_AUDIO_AUDIO_OUTPUT_H_ | |
| 169 | |
| OLD | NEW |