Chromium Code Reviews| 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 |