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 |