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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 // | 90 // |
90 // If this method returns fewer frames than |requested_frames|, it could | 91 // If this method returns fewer frames than |requested_frames|, it could |
91 // be a sign that the pipeline is stalled or unable to stream the data fast | 92 // be a sign that the pipeline is stalled or unable to stream the data fast |
92 // enough. In such scenarios, the callee should zero out unused portions | 93 // enough. In such scenarios, the callee should zero out unused portions |
93 // of their buffer to playback silence. | 94 // of their buffer to playback silence. |
94 // | 95 // |
95 // FillBuffer() updates the pipeline's playback timestamp. If FillBuffer() is | 96 // FillBuffer() updates the pipeline's playback timestamp. If FillBuffer() is |
96 // not called at the same rate as audio samples are played, then the reported | 97 // not called at the same rate as audio samples are played, then the reported |
97 // timestamp in the pipeline will be ahead of the actual audio playback. In | 98 // timestamp in the pipeline will be ahead of the actual audio playback. In |
98 // this case |playback_delay| should be used to indicate when in the future | 99 // this case |playback_delay| should be used to indicate when in the future |
99 // should the filled buffer be played. If FillBuffer() is called as the audio | 100 // should the filled buffer be played. |
100 // hardware plays the buffer, then |playback_delay| should be zero. | |
101 // | 101 // |
102 // Safe to call on any thread. | 102 // Safe to call on any thread. |
103 uint32 FillBuffer(uint8* dest, | 103 uint32 FillBuffer(uint8* dest, |
104 uint32 requested_frames, | 104 uint32 requested_frames, |
105 const base::TimeDelta& playback_delay); | 105 int audio_delay_milliseconds); |
106 | |
107 // Get the playback rate of |algorithm_|. | |
108 float GetPlaybackRate(); | |
109 | |
110 // Convert number of bytes to duration of time using information about the | |
111 // number of channels, sample rate and sample bits. | |
112 base::TimeDelta ConvertToDuration(int bytes); | |
113 | 106 |
114 // Estimate earliest time when current buffer can stop playing. | 107 // Estimate earliest time when current buffer can stop playing. |
115 void UpdateEarliestEndTime(int bytes_filled, | 108 void UpdateEarliestEndTime_Locked(int frames_filled, |
116 base::TimeDelta request_delay, | 109 float playback_rate, |
117 base::Time time_now); | 110 base::TimeDelta playback_delay, |
| 111 base::Time time_now); |
118 | 112 |
119 // Methods called on pipeline thread ---------------------------------------- | 113 // Methods called on pipeline thread ---------------------------------------- |
120 void DoPlay(); | 114 void DoPlay(); |
121 void DoPause(); | 115 void DoPause(); |
122 | 116 |
123 // media::AudioRendererSink::RenderCallback implementation. | 117 // media::AudioRendererSink::RenderCallback implementation. Called on the |
| 118 // AudioDevice thread. |
124 virtual int Render(AudioBus* audio_bus, | 119 virtual int Render(AudioBus* audio_bus, |
125 int audio_delay_milliseconds) OVERRIDE; | 120 int audio_delay_milliseconds) OVERRIDE; |
126 virtual void OnRenderError() OVERRIDE; | 121 virtual void OnRenderError() OVERRIDE; |
127 | 122 |
128 // Helper method that schedules an asynchronous read from the decoder and | 123 // Helper method that schedules an asynchronous read from the decoder and |
129 // increments |pending_reads_|. | 124 // increments |pending_reads_|. |
130 // | 125 // |
131 // Safe to call from any thread. | 126 // Safe to call from any thread. |
132 void ScheduleRead_Locked(); | 127 void ScheduleRead_Locked(); |
133 | 128 |
(...skipping 10 matching lines...) Expand all Loading... |
144 // Called when |decoder_| initialization completes. | 139 // Called when |decoder_| initialization completes. |
145 // |demuxer_stream| & |decoders| are used if initialization failed and | 140 // |demuxer_stream| & |decoders| are used if initialization failed and |
146 // InitializeNextDecoder() needs to be called again. | 141 // InitializeNextDecoder() needs to be called again. |
147 void OnDecoderInitDone(const scoped_refptr<DemuxerStream>& demuxer_stream, | 142 void OnDecoderInitDone(const scoped_refptr<DemuxerStream>& demuxer_stream, |
148 scoped_ptr<AudioDecoderList> decoders, | 143 scoped_ptr<AudioDecoderList> decoders, |
149 PipelineStatus status); | 144 PipelineStatus status); |
150 | 145 |
151 // Audio decoder. | 146 // Audio decoder. |
152 scoped_refptr<AudioDecoder> decoder_; | 147 scoped_refptr<AudioDecoder> decoder_; |
153 | 148 |
| 149 // The sink (destination) for rendered audio. |sink_| must only be accessed |
| 150 // on the pipeline thread (verify with |pipeline_thread_checker_|). |sink_| |
| 151 // must never be called under |lock_| or the 3-way thread bridge between the |
| 152 // audio, pipeline, and decoder threads may deadlock. |
| 153 scoped_refptr<media::AudioRendererSink> sink_; |
| 154 |
| 155 // Ensures certain methods are always called on the pipeline thread. |
| 156 base::ThreadChecker pipeline_thread_checker_; |
| 157 |
| 158 // AudioParameters constructed during Initialize() based on |decoder_|. |
| 159 AudioParameters audio_parameters_; |
| 160 |
| 161 // Callbacks provided during Initialize(). |
| 162 PipelineStatusCB init_cb_; |
| 163 StatisticsCB statistics_cb_; |
| 164 base::Closure underflow_cb_; |
| 165 TimeCB time_cb_; |
| 166 base::Closure ended_cb_; |
| 167 base::Closure disabled_cb_; |
| 168 PipelineStatusCB error_cb_; |
| 169 |
| 170 // Callback provided to Pause(). |
| 171 base::Closure pause_cb_; |
| 172 |
| 173 // Callback provided to Preroll(). |
| 174 PipelineStatusCB preroll_cb_; |
| 175 |
| 176 // After Initialize() has completed, all variables below must be accessed |
| 177 // under |lock_|. ------------------------------------------------------------ |
| 178 base::Lock lock_; |
| 179 |
154 // Algorithm for scaling audio. | 180 // Algorithm for scaling audio. |
155 scoped_ptr<AudioRendererAlgorithm> algorithm_; | 181 scoped_ptr<AudioRendererAlgorithm> algorithm_; |
156 | 182 |
157 base::Lock lock_; | |
158 | |
159 // Simple state tracking variable. | 183 // Simple state tracking variable. |
160 enum State { | 184 enum State { |
161 kUninitialized, | 185 kUninitialized, |
162 kPaused, | 186 kPaused, |
163 kPrerolling, | 187 kPrerolling, |
164 kPlaying, | 188 kPlaying, |
165 kStopped, | 189 kStopped, |
166 kUnderflow, | 190 kUnderflow, |
167 kRebuffering, | 191 kRebuffering, |
168 }; | 192 }; |
169 State state_; | 193 State state_; |
170 | 194 |
171 // Keep track of our outstanding read to |decoder_|. | 195 // Keep track of our outstanding read to |decoder_|. |
172 bool pending_read_; | 196 bool pending_read_; |
173 | 197 |
174 // Keeps track of whether we received and rendered the end of stream buffer. | 198 // Keeps track of whether we received and rendered the end of stream buffer. |
175 bool received_end_of_stream_; | 199 bool received_end_of_stream_; |
176 bool rendered_end_of_stream_; | 200 bool rendered_end_of_stream_; |
177 | 201 |
178 // The timestamp of the last frame (i.e. furthest in the future) buffered as | 202 // 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. | 203 // well as the current time that takes current playback delay into account. |
180 base::TimeDelta audio_time_buffered_; | 204 base::TimeDelta audio_time_buffered_; |
181 base::TimeDelta current_time_; | 205 base::TimeDelta current_time_; |
182 | 206 |
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_; | 207 base::TimeDelta preroll_timestamp_; |
197 | 208 |
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 | 209 // We're supposed to know amount of audio data OS or hardware buffered, but |
207 // that is not always so -- on my Linux box | 210 // that is not always so -- on my Linux box |
208 // AudioBuffersState::hardware_delay_bytes never reaches 0. | 211 // AudioBuffersState::hardware_delay_bytes never reaches 0. |
209 // | 212 // |
210 // As a result we cannot use it to find when stream ends. If we just ignore | 213 // 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 | 214 // 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. | 215 // did so, I've seen it done ~140ms too early when playing ~150ms file. |
213 // | 216 // |
214 // Instead of trying to invent OS-specific solution for each and every OS we | 217 // 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 | 218 // 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 | 219 // 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 | 220 // 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 | 221 // know when that particular data would start playing, but it is much better |
219 // than nothing. | 222 // than nothing. |
220 base::Time earliest_end_time_; | 223 base::Time earliest_end_time_; |
221 | 224 |
222 AudioParameters audio_parameters_; | |
223 | |
224 bool underflow_disabled_; | 225 bool underflow_disabled_; |
225 | 226 |
226 // True if the renderer receives a buffer with kAborted status during preroll, | 227 // True if the renderer receives a buffer with kAborted status during preroll, |
227 // false otherwise. This flag is cleared on the next Preroll() call. | 228 // false otherwise. This flag is cleared on the next Preroll() call. |
228 bool preroll_aborted_; | 229 bool preroll_aborted_; |
229 | 230 |
| 231 // End variables which must be accessed under |lock_|. ---------------------- |
| 232 |
| 233 // Variables used only on the audio thread. --------------------------------- |
| 234 int actual_frames_per_buffer_; |
| 235 scoped_array<uint8> audio_buffer_; |
| 236 |
230 DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); | 237 DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); |
231 }; | 238 }; |
232 | 239 |
233 } // namespace media | 240 } // namespace media |
234 | 241 |
235 #endif // MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ | 242 #endif // MEDIA_FILTERS_AUDIO_RENDERER_IMPL_H_ |
OLD | NEW |