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 |