| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include <limits> | 5 #include <limits> |
| 6 #include <set> | 6 #include <set> |
| 7 | 7 |
| 8 #include "mojo/services/media/common/cpp/local_time.h" | 8 #include "mojo/services/media/common/cpp/local_time.h" |
| 9 #include "services/media/audio/platform/linux/alsa_output.h" | 9 #include "services/media/audio/platform/linux/alsa_output.h" |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 // If we could own the output entirely and bypass the mixer to achieve lower | 42 // If we could own the output entirely and bypass the mixer to achieve lower |
| 43 // latency, that would be even better. | 43 // latency, that would be even better. |
| 44 AudioOutputPtr audio_out(audio::AlsaOutput::New(manager)); | 44 AudioOutputPtr audio_out(audio::AlsaOutput::New(manager)); |
| 45 if (!audio_out) { return nullptr; } | 45 if (!audio_out) { return nullptr; } |
| 46 | 46 |
| 47 AlsaOutput* alsa_out = static_cast<AlsaOutput*>(audio_out.get()); | 47 AlsaOutput* alsa_out = static_cast<AlsaOutput*>(audio_out.get()); |
| 48 DCHECK(alsa_out); | 48 DCHECK(alsa_out); |
| 49 | 49 |
| 50 LpcmMediaTypeDetailsPtr config(LpcmMediaTypeDetails::New()); | 50 LpcmMediaTypeDetailsPtr config(LpcmMediaTypeDetails::New()); |
| 51 config->frames_per_second = 48000; | 51 config->frames_per_second = 48000; |
| 52 config->samples_per_frame = 2; | 52 config->channels = 2; |
| 53 config->sample_format = LpcmSampleFormat::SIGNED_16; | 53 config->sample_format = LpcmSampleFormat::SIGNED_16; |
| 54 | 54 |
| 55 if (alsa_out->Configure(config.Pass()) != MediaResult::OK) { | 55 if (alsa_out->Configure(config.Pass()) != MediaResult::OK) { |
| 56 return nullptr; | 56 return nullptr; |
| 57 } | 57 } |
| 58 | 58 |
| 59 return audio_out; | 59 return audio_out; |
| 60 } | 60 } |
| 61 | 61 |
| 62 AlsaOutput::AlsaOutput(AudioOutputManager* manager) | 62 AlsaOutput::AlsaOutput(AudioOutputManager* manager) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 case LpcmSampleFormat::SIGNED_24_IN_32: | 94 case LpcmSampleFormat::SIGNED_24_IN_32: |
| 95 default: | 95 default: |
| 96 return MediaResult::UNSUPPORTED_CONFIG; | 96 return MediaResult::UNSUPPORTED_CONFIG; |
| 97 } | 97 } |
| 98 | 98 |
| 99 if (SUPPORTED_SAMPLE_RATES.find(config->frames_per_second) == | 99 if (SUPPORTED_SAMPLE_RATES.find(config->frames_per_second) == |
| 100 SUPPORTED_SAMPLE_RATES.end()) { | 100 SUPPORTED_SAMPLE_RATES.end()) { |
| 101 return MediaResult::UNSUPPORTED_CONFIG; | 101 return MediaResult::UNSUPPORTED_CONFIG; |
| 102 } | 102 } |
| 103 | 103 |
| 104 if (SUPPORTED_CHANNEL_COUNTS.find(config->samples_per_frame) == | 104 if (SUPPORTED_CHANNEL_COUNTS.find(config->channels) == |
| 105 SUPPORTED_CHANNEL_COUNTS.end()) { | 105 SUPPORTED_CHANNEL_COUNTS.end()) { |
| 106 return MediaResult::UNSUPPORTED_CONFIG; | 106 return MediaResult::UNSUPPORTED_CONFIG; |
| 107 } | 107 } |
| 108 | 108 |
| 109 // Compute the ratio between frames and local time ticks. | 109 // Compute the ratio between frames and local time ticks. |
| 110 LinearTransform::Ratio sec_per_tick(LocalDuration::period::num, | 110 LinearTransform::Ratio sec_per_tick(LocalDuration::period::num, |
| 111 LocalDuration::period::den); | 111 LocalDuration::period::den); |
| 112 LinearTransform::Ratio frames_per_sec(config->frames_per_second, 1); | 112 LinearTransform::Ratio frames_per_sec(config->frames_per_second, 1); |
| 113 bool is_precise = LinearTransform::Ratio::Compose(frames_per_sec, | 113 bool is_precise = LinearTransform::Ratio::Compose(frames_per_sec, |
| 114 sec_per_tick, | 114 sec_per_tick, |
| 115 &frames_per_tick_); | 115 &frames_per_tick_); |
| 116 DCHECK(is_precise); | 116 DCHECK(is_precise); |
| 117 | 117 |
| 118 // Figure out how many bytes there are per frame. | 118 // Figure out how many bytes there are per frame. |
| 119 output_bytes_per_frame_ = bytes_per_sample * config->samples_per_frame; | 119 output_bytes_per_frame_ = bytes_per_sample * config->channels; |
| 120 | 120 |
| 121 // Success | 121 // Success |
| 122 output_format_ = config.Pass(); | 122 output_format_ = config.Pass(); |
| 123 return MediaResult::OK; | 123 return MediaResult::OK; |
| 124 } | 124 } |
| 125 | 125 |
| 126 MediaResult AlsaOutput::Init() { | 126 MediaResult AlsaOutput::Init() { |
| 127 static const char* kAlsaDevice = "default"; | 127 static const char* kAlsaDevice = "default"; |
| 128 | 128 |
| 129 if (!output_format_) { return MediaResult::BAD_STATE; } | 129 if (!output_format_) { return MediaResult::BAD_STATE; } |
| 130 if (alsa_device_) { return MediaResult::BAD_STATE; } | 130 if (alsa_device_) { return MediaResult::BAD_STATE; } |
| 131 | 131 |
| 132 snd_pcm_sframes_t res; | 132 snd_pcm_sframes_t res; |
| 133 res = snd_pcm_open(&alsa_device_, | 133 res = snd_pcm_open(&alsa_device_, |
| 134 kAlsaDevice, | 134 kAlsaDevice, |
| 135 SND_PCM_STREAM_PLAYBACK, | 135 SND_PCM_STREAM_PLAYBACK, |
| 136 SND_PCM_NONBLOCK); | 136 SND_PCM_NONBLOCK); |
| 137 if (res != 0) { | 137 if (res != 0) { |
| 138 LOG(ERROR) << "Failed to open ALSA device \"" << kAlsaDevice << "\"."; | 138 LOG(ERROR) << "Failed to open ALSA device \"" << kAlsaDevice << "\"."; |
| 139 return MediaResult::INTERNAL_ERROR; | 139 return MediaResult::INTERNAL_ERROR; |
| 140 } | 140 } |
| 141 | 141 |
| 142 res = snd_pcm_set_params(alsa_device_, | 142 res = snd_pcm_set_params(alsa_device_, |
| 143 alsa_format_, | 143 alsa_format_, |
| 144 SND_PCM_ACCESS_RW_INTERLEAVED, | 144 SND_PCM_ACCESS_RW_INTERLEAVED, |
| 145 output_format_->samples_per_frame, | 145 output_format_->channels, |
| 146 output_format_->frames_per_second, | 146 output_format_->frames_per_second, |
| 147 0, // do not allow ALSA resample | 147 0, // do not allow ALSA resample |
| 148 local_time::to_usec<unsigned int>(TARGET_LATENCY)); | 148 local_time::to_usec<unsigned int>(TARGET_LATENCY)); |
| 149 if (res) { | 149 if (res) { |
| 150 LOG(ERROR) << "Failed to configure ALSA device \"" << kAlsaDevice << "\" " | 150 LOG(ERROR) << "Failed to configure ALSA device \"" << kAlsaDevice << "\" " |
| 151 << "(res = " << res << ")"; | 151 << "(res = " << res << ")"; |
| 152 LOG(ERROR) << "Requested samples per frame: " | 152 LOG(ERROR) << "Requested samples per frame: " |
| 153 << output_format_->samples_per_frame; | 153 << output_format_->channels; |
| 154 LOG(ERROR) << "Requested frames per second: " | 154 LOG(ERROR) << "Requested frames per second: " |
| 155 << output_format_->frames_per_second; | 155 << output_format_->frames_per_second; |
| 156 LOG(ERROR) << "Requested ALSA format : " << alsa_format_; | 156 LOG(ERROR) << "Requested ALSA format : " << alsa_format_; |
| 157 Cleanup(); | 157 Cleanup(); |
| 158 return MediaResult::INTERNAL_ERROR; | 158 return MediaResult::INTERNAL_ERROR; |
| 159 } | 159 } |
| 160 | 160 |
| 161 // Figure out how big our mixing buffer needs to be, then allocate it. | 161 // Figure out how big our mixing buffer needs to be, then allocate it. |
| 162 res = snd_pcm_avail_update(alsa_device_); | 162 res = snd_pcm_avail_update(alsa_device_); |
| 163 if (res <= 0) { | 163 if (res <= 0) { |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 if (code == -EPIPE) { | 390 if (code == -EPIPE) { |
| 391 HandleAsUnderflow(); | 391 HandleAsUnderflow(); |
| 392 } else { | 392 } else { |
| 393 HandleAsError(code); | 393 HandleAsError(code); |
| 394 } | 394 } |
| 395 } | 395 } |
| 396 | 396 |
| 397 } // namespace audio | 397 } // namespace audio |
| 398 } // namespace media | 398 } // namespace media |
| 399 } // namespace mojo | 399 } // namespace mojo |
| 400 | |
| OLD | NEW |