| 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 |