OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // THREAD SAFETY | 5 // THREAD SAFETY |
6 // | 6 // |
7 // The AlsaPcmOutputStream object's internal state is accessed by two threads: | 7 // The AlsaPcmOutputStream object's internal state is accessed by two threads: |
8 // | 8 // |
9 // client thread - creates the object and calls the public APIs. | 9 // client thread - creates the object and calls the public APIs. |
10 // message loop thread - executes all the internal tasks including querying | 10 // message loop thread - executes all the internal tasks including querying |
11 // the data source for more data, writing to the alsa device, and closing | 11 // the data source for more data, writing to the alsa device, and closing |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 static const uint32 kSleepErrorMilliseconds = 20; | 98 static const uint32 kSleepErrorMilliseconds = 20; |
99 | 99 |
100 // Set to 0 during debugging if you want error messages due to underrun | 100 // Set to 0 during debugging if you want error messages due to underrun |
101 // events or other recoverable errors. | 101 // events or other recoverable errors. |
102 #if defined(NDEBUG) | 102 #if defined(NDEBUG) |
103 static const int kPcmRecoverIsSilent = 1; | 103 static const int kPcmRecoverIsSilent = 1; |
104 #else | 104 #else |
105 static const int kPcmRecoverIsSilent = 0; | 105 static const int kPcmRecoverIsSilent = 0; |
106 #endif | 106 #endif |
107 | 107 |
108 const char AlsaPcmOutputStream::kDefaultDevice[] = "default"; | |
109 const char AlsaPcmOutputStream::kAutoSelectDevice[] = ""; | |
110 const char AlsaPcmOutputStream::kPlugPrefix[] = "plug:"; | |
111 | |
112 // Since we expect to only be able to wake up with a resolution of | |
113 // kSleepErrorMilliseconds, double that for our minimum required latency. | |
114 const uint32 AlsaPcmOutputStream::kMinLatencyMicros = | |
115 kSleepErrorMilliseconds * 2 * 1000; | |
116 | |
117 namespace { | |
118 | |
119 // ALSA is currently limited to 48Khz. | 108 // ALSA is currently limited to 48Khz. |
120 // TODO(fbarchard): Resample audio from higher frequency to 48000. | 109 // TODO(fbarchard): Resample audio from higher frequency to 48000. |
121 const int kAlsaMaxSampleRate = 48000; | 110 static const int kAlsaMaxSampleRate = 48000; |
122 | 111 |
123 // While the "default" device may support multi-channel audio, in Alsa, only | 112 // While the "default" device may support multi-channel audio, in Alsa, only |
124 // the device names surround40, surround41, surround50, etc, have a defined | 113 // the device names surround40, surround41, surround50, etc, have a defined |
125 // channel mapping according to Lennart: | 114 // channel mapping according to Lennart: |
126 // | 115 // |
127 // http://0pointer.de/blog/projects/guide-to-sound-apis.html | 116 // http://0pointer.de/blog/projects/guide-to-sound-apis.html |
128 // | 117 // |
129 // This function makes a best guess at the specific > 2 channel device name | 118 // This function makes a best guess at the specific > 2 channel device name |
130 // based on the number of channels requested. NULL is returned if no device | 119 // based on the number of channels requested. NULL is returned if no device |
131 // can be found to match the channel numbers. In this case, using | 120 // can be found to match the channel numbers. In this case, using |
132 // kDefaultDevice is probably the best bet. | 121 // kDefaultDevice is probably the best bet. |
133 // | 122 // |
134 // A five channel source is assumed to be surround50 instead of surround41 | 123 // A five channel source is assumed to be surround50 instead of surround41 |
135 // (which is also 5 channels). | 124 // (which is also 5 channels). |
136 // | 125 // |
137 // TODO(ajwong): The source data should have enough info to tell us if we want | 126 // TODO(ajwong): The source data should have enough info to tell us if we want |
138 // surround41 versus surround51, etc., instead of needing us to guess base don | 127 // surround41 versus surround51, etc., instead of needing us to guess base don |
139 // channel number. Fix API to pass that data down. | 128 // channel number. Fix API to pass that data down. |
140 const char* GuessSpecificDeviceName(uint32 channels) { | 129 static const char* GuessSpecificDeviceName(uint32 channels) { |
141 switch (channels) { | 130 switch (channels) { |
142 case 8: | 131 case 8: |
143 return "surround71"; | 132 return "surround71"; |
144 | 133 |
145 case 7: | 134 case 7: |
146 return "surround70"; | 135 return "surround70"; |
147 | 136 |
148 case 6: | 137 case 6: |
149 return "surround51"; | 138 return "surround51"; |
150 | 139 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 memcpy(aac, b, sizeof(aac)); | 172 memcpy(aac, b, sizeof(aac)); |
184 b[0] = aac[1]; // L | 173 b[0] = aac[1]; // L |
185 b[1] = aac[2]; // R | 174 b[1] = aac[2]; // R |
186 b[2] = aac[3]; // Ls | 175 b[2] = aac[3]; // Ls |
187 b[3] = aac[4]; // Rs | 176 b[3] = aac[4]; // Rs |
188 b[4] = aac[0]; // C | 177 b[4] = aac[0]; // C |
189 b[5] = aac[5]; // LFE | 178 b[5] = aac[5]; // LFE |
190 } | 179 } |
191 } | 180 } |
192 | 181 |
193 } // namespace | |
194 | |
195 // Not in an anonymous namespace so that it can be a friend to | |
196 // AlsaPcmOutputStream. | |
197 std::ostream& operator<<(std::ostream& os, | 182 std::ostream& operator<<(std::ostream& os, |
198 AlsaPcmOutputStream::InternalState state) { | 183 AlsaPcmOutputStream::InternalState state) { |
199 switch (state) { | 184 switch (state) { |
200 case AlsaPcmOutputStream::kInError: | 185 case AlsaPcmOutputStream::kInError: |
201 os << "kInError"; | 186 os << "kInError"; |
202 break; | 187 break; |
203 case AlsaPcmOutputStream::kCreated: | 188 case AlsaPcmOutputStream::kCreated: |
204 os << "kCreated"; | 189 os << "kCreated"; |
205 break; | 190 break; |
206 case AlsaPcmOutputStream::kIsOpened: | 191 case AlsaPcmOutputStream::kIsOpened: |
207 os << "kIsOpened"; | 192 os << "kIsOpened"; |
208 break; | 193 break; |
209 case AlsaPcmOutputStream::kIsPlaying: | 194 case AlsaPcmOutputStream::kIsPlaying: |
210 os << "kIsPlaying"; | 195 os << "kIsPlaying"; |
211 break; | 196 break; |
212 case AlsaPcmOutputStream::kIsStopped: | 197 case AlsaPcmOutputStream::kIsStopped: |
213 os << "kIsStopped"; | 198 os << "kIsStopped"; |
214 break; | 199 break; |
215 case AlsaPcmOutputStream::kIsClosed: | 200 case AlsaPcmOutputStream::kIsClosed: |
216 os << "kIsClosed"; | 201 os << "kIsClosed"; |
217 break; | 202 break; |
218 }; | 203 }; |
219 return os; | 204 return os; |
220 } | 205 } |
221 | 206 |
| 207 const char AlsaPcmOutputStream::kDefaultDevice[] = "default"; |
| 208 const char AlsaPcmOutputStream::kAutoSelectDevice[] = ""; |
| 209 const char AlsaPcmOutputStream::kPlugPrefix[] = "plug:"; |
| 210 |
| 211 // Since we expect to only be able to wake up with a resolution of |
| 212 // kSleepErrorMilliseconds, double that for our minimum required latency. |
| 213 const uint32 AlsaPcmOutputStream::kMinLatencyMicros = |
| 214 kSleepErrorMilliseconds * 2 * 1000; |
| 215 |
222 AlsaPcmOutputStream::AlsaPcmOutputStream(const std::string& device_name, | 216 AlsaPcmOutputStream::AlsaPcmOutputStream(const std::string& device_name, |
223 AudioParameters params, | 217 AudioParameters params, |
224 AlsaWrapper* wrapper, | 218 AlsaWrapper* wrapper, |
225 AudioManagerLinux* manager, | 219 AudioManagerLinux* manager, |
226 MessageLoop* message_loop) | 220 MessageLoop* message_loop) |
227 : shared_data_(MessageLoop::current()), | 221 : shared_data_(MessageLoop::current()), |
228 requested_device_name_(device_name), | 222 requested_device_name_(device_name), |
229 pcm_format_(alsa_util::BitsToFormat(params.bits_per_sample)), | 223 pcm_format_(alsa_util::BitsToFormat(params.bits_per_sample)), |
230 channels_(params.channels), | 224 channels_(params.channels), |
231 sample_rate_(params.sample_rate), | 225 sample_rate_(params.sample_rate), |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 } | 913 } |
920 | 914 |
921 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to | 915 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to |
922 // release ownership of the currently registered callback. | 916 // release ownership of the currently registered callback. |
923 void AlsaPcmOutputStream::SharedData::set_source_callback( | 917 void AlsaPcmOutputStream::SharedData::set_source_callback( |
924 AudioSourceCallback* callback) { | 918 AudioSourceCallback* callback) { |
925 DCHECK_EQ(MessageLoop::current(), state_transition_loop_); | 919 DCHECK_EQ(MessageLoop::current(), state_transition_loop_); |
926 base::AutoLock l(lock_); | 920 base::AutoLock l(lock_); |
927 source_callback_ = callback; | 921 source_callback_ = callback; |
928 } | 922 } |
OLD | NEW |