OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Audio rendering unit utilizing an AudioRendererSink to output data. | 5 // Audio rendering unit utilizing an AudioRendererSink to output data. |
6 // | 6 // |
7 // This class lives inside three threads during it's lifetime, namely: | 7 // This class lives inside three threads during it's lifetime, namely: |
8 // 1. Render thread. | 8 // 1. Render thread. |
9 // This object is created on the render thread. | 9 // This object is created on the render thread. |
10 // 2. Pipeline thread | 10 // 2. Pipeline thread |
11 // Initialize() is called here with the audio format. | 11 // Initialize() is called here with the audio format. |
12 // Play/Pause/Preroll() also happens here. | 12 // Play/Pause/Preroll() also happens here. |
13 // 3. Audio thread created by the AudioRendererSink. | 13 // 3. Audio thread created by the AudioRendererSink. |
14 // Render() is called here where audio data is decoded into raw PCM data. | 14 // Render() is called here where audio data is decoded into raw PCM data. |
15 // | 15 // |
16 // AudioRendererImpl talks to an AudioRendererAlgorithm that takes care of | 16 // AudioRendererImpl talks to an AudioRendererAlgorithm that takes care of |
17 // queueing audio data and stretching/shrinking audio data when playback rate != | 17 // queueing audio data and stretching/shrinking audio data when playback rate != |
18 // 1.0 or 0.0. | 18 // 1.0 or 0.0. |
19 | 19 |
20 #ifndef MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ | 20 #ifndef MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ |
21 #define MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ | 21 #define MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ |
22 | 22 |
23 #include <deque> | 23 #include <deque> |
24 | 24 |
25 #include "base/synchronization/lock.h" | 25 #include "base/synchronization/lock.h" |
26 #include "base/threading/thread_checker.h" | |
26 #include "media/base/audio_decoder.h" | 27 #include "media/base/audio_decoder.h" |
27 #include "media/base/audio_renderer.h" | 28 #include "media/base/audio_renderer.h" |
28 #include "media/base/audio_renderer_sink.h" | 29 #include "media/base/audio_renderer_sink.h" |
29 #include "media/base/buffers.h" | 30 #include "media/base/buffers.h" |
30 #include "media/filters/audio_renderer_algorithm.h" | 31 #include "media/filters/audio_renderer_algorithm.h" |
31 | 32 |
32 namespace media { | 33 namespace media { |
33 | 34 |
34 class MEDIA_EXPORT AudioRendererImpl | 35 class MEDIA_EXPORT AudioRendererImpl |
35 : public AudioRenderer, | 36 : public AudioRenderer, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 | 107 |
107 // Get the playback rate of |algorithm_|. | 108 // Get the playback rate of |algorithm_|. |
108 float GetPlaybackRate(); | 109 float GetPlaybackRate(); |
109 | 110 |
110 // Convert number of bytes to duration of time using information about the | 111 // Convert number of bytes to duration of time using information about the |
111 // number of channels, sample rate and sample bits. | 112 // number of channels, sample rate and sample bits. |
112 base::TimeDelta ConvertToDuration(int bytes); | 113 base::TimeDelta ConvertToDuration(int bytes); |
113 | 114 |
114 // Estimate earliest time when current buffer can stop playing. | 115 // Estimate earliest time when current buffer can stop playing. |
115 void UpdateEarliestEndTime(int bytes_filled, | 116 void UpdateEarliestEndTime(int bytes_filled, |
117 float playback_rate, | |
116 base::TimeDelta request_delay, | 118 base::TimeDelta request_delay, |
117 base::Time time_now); | 119 base::Time time_now); |
118 | 120 |
119 // Methods called on pipeline thread ---------------------------------------- | 121 // Methods called on pipeline thread ---------------------------------------- |
120 void DoPlay(); | 122 void DoPlay(); |
121 void DoPause(); | 123 void DoPause(); |
122 | 124 |
123 // media::AudioRendererSink::RenderCallback implementation. | 125 // media::AudioRendererSink::RenderCallback implementation. Called on the |
126 // AudioDevice thread. | |
124 virtual int Render(AudioBus* audio_bus, | 127 virtual int Render(AudioBus* audio_bus, |
125 int audio_delay_milliseconds) OVERRIDE; | 128 int audio_delay_milliseconds) OVERRIDE; |
126 virtual void OnRenderError() OVERRIDE; | 129 virtual void OnRenderError() OVERRIDE; |
127 | 130 |
128 // Helper method that schedules an asynchronous read from the decoder and | 131 // Helper method that schedules an asynchronous read from the decoder and |
129 // increments |pending_reads_|. | 132 // increments |pending_reads_|. |
130 // | 133 // |
131 // Safe to call from any thread. | 134 // Safe to call from any thread. |
132 void ScheduleRead_Locked(); | 135 void ScheduleRead_Locked(); |
133 | 136 |
(...skipping 10 matching lines...) Expand all Loading... | |
144 // Called when |decoder_| initialization completes. | 147 // Called when |decoder_| initialization completes. |
145 // |demuxer_stream| & |decoders| are used if initialization failed and | 148 // |demuxer_stream| & |decoders| are used if initialization failed and |
146 // InitializeNextDecoder() needs to be called again. | 149 // InitializeNextDecoder() needs to be called again. |
147 void OnDecoderInitDone(const scoped_refptr<DemuxerStream>& demuxer_stream, | 150 void OnDecoderInitDone(const scoped_refptr<DemuxerStream>& demuxer_stream, |
148 scoped_ptr<AudioDecoderList> decoders, | 151 scoped_ptr<AudioDecoderList> decoders, |
149 PipelineStatus status); | 152 PipelineStatus status); |
150 | 153 |
151 // Audio decoder. | 154 // Audio decoder. |
152 scoped_refptr<AudioDecoder> decoder_; | 155 scoped_refptr<AudioDecoder> decoder_; |
153 | 156 |
154 // Algorithm for scaling audio. | 157 // The sink (destination) for rendered audio. |sink_| must only be accessed |
158 // on the pipeline thread (verify with |pipeline_thread_checker_|). |sink_| | |
159 // must never be called under |lock_| or the 3-way thread bridge between the | |
160 // audio, pipeline, and decoder threads may dead lock. | |
Ami GONE FROM CHROMIUM
2012/11/03 00:11:45
deadlock is one word.
DaleCurtis
2012/11/03 01:32:47
Done.
| |
161 scoped_refptr<media::AudioRendererSink> sink_; | |
162 | |
163 // Ensures certain methods are always called on the pipeline thread. | |
164 base::ThreadChecker pipeline_thread_checker_; | |
165 | |
166 // AudioParameters constructed during Initialize() based on |decoder_|. | |
167 AudioParameters audio_parameters_; | |
168 | |
169 // Callbacks provided during Initialize(). | |
170 PipelineStatusCB init_cb_; | |
171 StatisticsCB statistics_cb_; | |
172 base::Closure underflow_cb_; | |
173 TimeCB time_cb_; | |
174 base::Closure ended_cb_; | |
175 base::Closure disabled_cb_; | |
176 PipelineStatusCB error_cb_; | |
177 | |
178 // Callback provided to Pause(...). | |
Ami GONE FROM CHROMIUM
2012/11/03 00:11:45
ellipses here and below aren't useful
DaleCurtis
2012/11/03 01:32:47
Done.
| |
179 base::Closure pause_cb_; | |
180 | |
181 // Callback provided to Preroll(...). | |
182 PipelineStatusCB preroll_cb_; | |
183 | |
184 // After Initialize() has completed, all variables below must be accessed | |
185 // under |lock_|. ------------------------------------------------------------ | |
186 base::Lock lock_; | |
187 | |
188 // Algorithm for scaling audio. Access must be guarded by |lock_| if not on | |
189 // the pipeline thread. | |
Ami GONE FROM CHROMIUM
2012/11/03 00:11:45
this is a very codesmelly comment.
Why is it OK to
DaleCurtis
2012/11/03 01:32:47
Removed.
| |
155 scoped_ptr<AudioRendererAlgorithm> algorithm_; | 190 scoped_ptr<AudioRendererAlgorithm> algorithm_; |
156 | 191 |
157 base::Lock lock_; | |
158 | |
159 // Simple state tracking variable. | 192 // Simple state tracking variable. |
160 enum State { | 193 enum State { |
161 kUninitialized, | 194 kUninitialized, |
162 kPaused, | 195 kPaused, |
163 kPrerolling, | 196 kPrerolling, |
164 kPlaying, | 197 kPlaying, |
165 kStopped, | 198 kStopped, |
166 kUnderflow, | 199 kUnderflow, |
167 kRebuffering, | 200 kRebuffering, |
168 }; | 201 }; |
202 | |
203 // |state_| access must always be guarded by |lock_| | |
Ami GONE FROM CHROMIUM
2012/11/03 00:11:45
redundant to l.184?
DaleCurtis
2012/11/03 01:32:47
Done.
| |
169 State state_; | 204 State state_; |
170 | 205 |
171 // Keep track of our outstanding read to |decoder_|. | 206 // Keep track of our outstanding read to |decoder_|. |
172 bool pending_read_; | 207 bool pending_read_; |
173 | 208 |
174 // Keeps track of whether we received and rendered the end of stream buffer. | 209 // Keeps track of whether we received and rendered the end of stream buffer. |
175 bool received_end_of_stream_; | 210 bool received_end_of_stream_; |
176 bool rendered_end_of_stream_; | 211 bool rendered_end_of_stream_; |
177 | 212 |
178 // The timestamp of the last frame (i.e. furthest in the future) buffered as | 213 // The timestamp of the last frame (i.e. furthest in the future) buffered as |
179 // well as the current time that takes current playback delay into account. | 214 // well as the current time that takes current playback delay into account. |
180 base::TimeDelta audio_time_buffered_; | 215 base::TimeDelta audio_time_buffered_; |
181 base::TimeDelta current_time_; | 216 base::TimeDelta current_time_; |
182 | 217 |
183 PipelineStatusCB init_cb_; | |
184 StatisticsCB statistics_cb_; | |
185 | |
186 // Filter callbacks. | |
187 base::Closure pause_cb_; | |
188 PipelineStatusCB preroll_cb_; | |
189 | |
190 base::Closure underflow_cb_; | |
191 TimeCB time_cb_; | |
192 base::Closure ended_cb_; | |
193 base::Closure disabled_cb_; | |
194 PipelineStatusCB error_cb_; | |
195 | |
196 base::TimeDelta preroll_timestamp_; | 218 base::TimeDelta preroll_timestamp_; |
197 | 219 |
198 uint32 bytes_per_frame_; | |
199 | |
200 // A flag that indicates this filter is called to stop. | |
201 bool stopped_; | |
202 | |
203 // The sink (destination) for rendered audio. | |
204 scoped_refptr<media::AudioRendererSink> sink_; | |
205 | |
206 // We're supposed to know amount of audio data OS or hardware buffered, but | 220 // We're supposed to know amount of audio data OS or hardware buffered, but |
207 // that is not always so -- on my Linux box | 221 // that is not always so -- on my Linux box |
208 // AudioBuffersState::hardware_delay_bytes never reaches 0. | 222 // AudioBuffersState::hardware_delay_bytes never reaches 0. |
209 // | 223 // |
210 // As a result we cannot use it to find when stream ends. If we just ignore | 224 // As a result we cannot use it to find when stream ends. If we just ignore |
211 // buffered data we will notify host that stream ended before it is actually | 225 // buffered data we will notify host that stream ended before it is actually |
212 // did so, I've seen it done ~140ms too early when playing ~150ms file. | 226 // did so, I've seen it done ~140ms too early when playing ~150ms file. |
213 // | 227 // |
214 // Instead of trying to invent OS-specific solution for each and every OS we | 228 // Instead of trying to invent OS-specific solution for each and every OS we |
215 // are supporting, use simple workaround: every time we fill the buffer we | 229 // are supporting, use simple workaround: every time we fill the buffer we |
216 // remember when it should stop playing, and do not assume that buffer is | 230 // remember when it should stop playing, and do not assume that buffer is |
217 // empty till that time. Workaround is not bulletproof, as we don't exactly | 231 // empty till that time. Workaround is not bulletproof, as we don't exactly |
218 // know when that particular data would start playing, but it is much better | 232 // know when that particular data would start playing, but it is much better |
219 // than nothing. | 233 // than nothing. |
220 base::Time earliest_end_time_; | 234 base::Time earliest_end_time_; |
221 | 235 |
222 AudioParameters audio_parameters_; | |
223 | |
224 bool underflow_disabled_; | 236 bool underflow_disabled_; |
225 | 237 |
226 // True if the renderer receives a buffer with kAborted status during preroll, | 238 // True if the renderer receives a buffer with kAborted status during preroll, |
227 // false otherwise. This flag is cleared on the next Preroll() call. | 239 // false otherwise. This flag is cleared on the next Preroll() call. |
228 bool preroll_aborted_; | 240 bool preroll_aborted_; |
229 | 241 |
242 // End variables which must be accessed under |lock_|. ---------------------- | |
243 | |
230 DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); | 244 DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); |
231 }; | 245 }; |
232 | 246 |
233 } // namespace media | 247 } // namespace media |
234 | 248 |
235 #endif // MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ | 249 #endif // MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ |
OLD | NEW |