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 "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h" | 5 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 #include <utility> | 10 #include <utility> |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 // A list of supported sample rates. | 76 // A list of supported sample rates. |
77 // TODO(jyw): move this up into chromecast/public for 1) documentation and | 77 // TODO(jyw): move this up into chromecast/public for 1) documentation and |
78 // 2) to help when implementing IsSampleRateSupported() | 78 // 2) to help when implementing IsSampleRateSupported() |
79 // clang-format off | 79 // clang-format off |
80 const int kSupportedSampleRates[] = | 80 const int kSupportedSampleRates[] = |
81 { 8000, 11025, 12000, | 81 { 8000, 11025, 12000, |
82 16000, 22050, 24000, | 82 16000, 22050, 24000, |
83 32000, 44100, 48000, | 83 32000, 44100, 48000, |
84 64000, 88200, 96000}; | 84 64000, 88200, 96000}; |
85 // clang-format on | 85 // clang-format on |
| 86 const int kInvalidSampleRate = 0; |
86 | 87 |
87 // Arbitrary sample rate in Hz to mix all audio to when a new primary input has | 88 // Arbitrary sample rate in Hz to mix all audio to when a new primary input has |
88 // a sample rate that is not directly supported, and a better fallback sample | 89 // a sample rate that is not directly supported, and a better fallback sample |
89 // rate cannot be determined. 48000 is the highest supported non-hi-res sample | 90 // rate cannot be determined. 48000 is the highest supported non-hi-res sample |
90 // rate. 96000 is the highest supported hi-res sample rate. | 91 // rate. 96000 is the highest supported hi-res sample rate. |
91 const unsigned int kFallbackSampleRate = 48000; | 92 const unsigned int kFallbackSampleRate = 48000; |
92 const unsigned int kFallbackSampleRateHiRes = 96000; | 93 const unsigned int kFallbackSampleRateHiRes = 96000; |
93 | 94 |
| 95 // Resample all audio below this frequency. |
| 96 const unsigned int kLowSampleRateCutoff = 32000; |
| 97 |
94 // The snd_pcm_(hw|sw)_params_set_*_near families of functions will report what | 98 // The snd_pcm_(hw|sw)_params_set_*_near families of functions will report what |
95 // direction they adjusted the requested parameter in, but since we read the | 99 // direction they adjusted the requested parameter in, but since we read the |
96 // output param and then log the information, this module doesn't need to get | 100 // output param and then log the information, this module doesn't need to get |
97 // the direction explicitly. | 101 // the direction explicitly. |
98 static int* kAlsaDirDontCare = nullptr; | 102 static int* kAlsaDirDontCare = nullptr; |
99 | 103 |
100 // These sample formats will be tried in order. 32 bit samples is ideal, but | 104 // These sample formats will be tried in order. 32 bit samples is ideal, but |
101 // some devices do not support 32 bit samples. | 105 // some devices do not support 32 bit samples. |
102 const snd_pcm_format_t kPreferredSampleFormats[] = {SND_PCM_FORMAT_S32, | 106 const snd_pcm_format_t kPreferredSampleFormats[] = {SND_PCM_FORMAT_S32, |
103 SND_PCM_FORMAT_S16}; | 107 SND_PCM_FORMAT_S16}; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 166 |
163 // static | 167 // static |
164 void StreamMixerAlsa::MakeSingleThreadedForTest() { | 168 void StreamMixerAlsa::MakeSingleThreadedForTest() { |
165 single_threaded_for_test_ = true; | 169 single_threaded_for_test_ = true; |
166 StreamMixerAlsa::Get()->ResetTaskRunnerForTest(); | 170 StreamMixerAlsa::Get()->ResetTaskRunnerForTest(); |
167 } | 171 } |
168 | 172 |
169 StreamMixerAlsa::StreamMixerAlsa() | 173 StreamMixerAlsa::StreamMixerAlsa() |
170 : mixer_thread_(new base::Thread("ALSA CMA mixer thread")), | 174 : mixer_thread_(new base::Thread("ALSA CMA mixer thread")), |
171 mixer_task_runner_(nullptr), | 175 mixer_task_runner_(nullptr), |
172 requested_output_samples_per_second_(0), | 176 requested_output_samples_per_second_(kInvalidSampleRate), |
173 output_samples_per_second_(0), | 177 output_samples_per_second_(kInvalidSampleRate), |
174 pcm_(nullptr), | 178 pcm_(nullptr), |
175 pcm_hw_params_(nullptr), | 179 pcm_hw_params_(nullptr), |
176 pcm_status_(nullptr), | 180 pcm_status_(nullptr), |
177 pcm_format_(SND_PCM_FORMAT_UNKNOWN), | 181 pcm_format_(SND_PCM_FORMAT_UNKNOWN), |
178 alsa_buffer_size_(0), | 182 alsa_buffer_size_(0), |
179 alsa_period_explicitly_set(false), | 183 alsa_period_explicitly_set(false), |
180 alsa_period_size_(0), | 184 alsa_period_size_(0), |
181 alsa_start_threshold_(0), | 185 alsa_start_threshold_(0), |
182 alsa_avail_min_(0), | 186 alsa_avail_min_(0), |
183 state_(kStateUninitialized), | 187 state_(kStateUninitialized), |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 // doesn't always choose a rate that's actually near the given input sample | 303 // doesn't always choose a rate that's actually near the given input sample |
300 // rate when the input sample rate is not supported. | 304 // rate when the input sample rate is not supported. |
301 const int* kSupportedSampleRatesEnd = | 305 const int* kSupportedSampleRatesEnd = |
302 kSupportedSampleRates + arraysize(kSupportedSampleRates); | 306 kSupportedSampleRates + arraysize(kSupportedSampleRates); |
303 auto nearest_sample_rate = | 307 auto nearest_sample_rate = |
304 std::min_element(kSupportedSampleRates, kSupportedSampleRatesEnd, | 308 std::min_element(kSupportedSampleRates, kSupportedSampleRatesEnd, |
305 [this](int r1, int r2) -> bool { | 309 [this](int r1, int r2) -> bool { |
306 return abs(requested_output_samples_per_second_ - r1) < | 310 return abs(requested_output_samples_per_second_ - r1) < |
307 abs(requested_output_samples_per_second_ - r2); | 311 abs(requested_output_samples_per_second_ - r2); |
308 }); | 312 }); |
| 313 // Resample audio with sample rates deemed to be too low (i.e. below 32kHz) |
| 314 // because some common AV receivers don't support optical out at these |
| 315 // frequencies. See b/26385501 |
| 316 unsigned int first_choice_sample_rate = requested_rate; |
| 317 if (requested_rate < kLowSampleRateCutoff) { |
| 318 first_choice_sample_rate = output_samples_per_second_ != kInvalidSampleRate |
| 319 ? output_samples_per_second_ |
| 320 : kFallbackSampleRate; |
| 321 } |
309 const unsigned int preferred_sample_rates[] = { | 322 const unsigned int preferred_sample_rates[] = { |
310 requested_rate, | 323 first_choice_sample_rate, |
311 static_cast<unsigned int>(*nearest_sample_rate), | 324 static_cast<unsigned int>(*nearest_sample_rate), |
312 kFallbackSampleRateHiRes, | 325 kFallbackSampleRateHiRes, |
313 kFallbackSampleRate}; | 326 kFallbackSampleRate}; |
314 for (const auto& sample_rate : preferred_sample_rates) { | 327 for (const auto& sample_rate : preferred_sample_rates) { |
315 err = alsa_->PcmHwParamsTestRate(pcm_, pcm_hw_params_, sample_rate, | 328 err = alsa_->PcmHwParamsTestRate(pcm_, pcm_hw_params_, sample_rate, |
316 0 /* try exact rate */); | 329 0 /* try exact rate */); |
317 if (err == 0) { | 330 if (err == 0) { |
318 unsigned_output_samples_per_second = sample_rate; | 331 unsigned_output_samples_per_second = sample_rate; |
319 break; | 332 break; |
320 } | 333 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 | 470 |
458 state_ = kStateNormalPlayback; | 471 state_ = kStateNormalPlayback; |
459 } | 472 } |
460 | 473 |
461 void StreamMixerAlsa::Stop() { | 474 void StreamMixerAlsa::Stop() { |
462 alsa_->PcmStatusFree(pcm_status_); | 475 alsa_->PcmStatusFree(pcm_status_); |
463 pcm_status_ = nullptr; | 476 pcm_status_ = nullptr; |
464 alsa_->PcmHwParamsFree(pcm_hw_params_); | 477 alsa_->PcmHwParamsFree(pcm_hw_params_); |
465 pcm_hw_params_ = nullptr; | 478 pcm_hw_params_ = nullptr; |
466 state_ = kStateUninitialized; | 479 state_ = kStateUninitialized; |
| 480 output_samples_per_second_ = kInvalidSampleRate; |
467 | 481 |
468 if (!pcm_) | 482 if (!pcm_) |
469 return; | 483 return; |
470 | 484 |
471 // If |pcm_| is RUNNING, drain all pending data. | 485 // If |pcm_| is RUNNING, drain all pending data. |
472 if (alsa_->PcmState(pcm_) == SND_PCM_STATE_RUNNING) { | 486 if (alsa_->PcmState(pcm_) == SND_PCM_STATE_RUNNING) { |
473 int err = alsa_->PcmDrain(pcm_); | 487 int err = alsa_->PcmDrain(pcm_); |
474 if (err < 0) | 488 if (err < 0) |
475 LOG(ERROR) << "snd_pcm_drain error: " << alsa_->StrError(err); | 489 LOG(ERROR) << "snd_pcm_drain error: " << alsa_->StrError(err); |
476 } else { | 490 } else { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 input_ptr->Initialize(rendering_delay_); | 555 input_ptr->Initialize(rendering_delay_); |
542 } else { | 556 } else { |
543 input_ptr->SignalError(); | 557 input_ptr->SignalError(); |
544 } | 558 } |
545 } | 559 } |
546 | 560 |
547 void StreamMixerAlsa::CheckChangeOutputRate(int input_samples_per_second) { | 561 void StreamMixerAlsa::CheckChangeOutputRate(int input_samples_per_second) { |
548 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 562 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
549 if (!pcm_ || | 563 if (!pcm_ || |
550 input_samples_per_second == requested_output_samples_per_second_ || | 564 input_samples_per_second == requested_output_samples_per_second_ || |
551 input_samples_per_second == output_samples_per_second_) | 565 input_samples_per_second == output_samples_per_second_ || |
| 566 input_samples_per_second < static_cast<int>(kLowSampleRateCutoff)) |
552 return; | 567 return; |
553 for (InputQueue* input : inputs_) { | 568 for (InputQueue* input : inputs_) { |
554 if (input->primary() && !input->IsDeleting()) | 569 if (input->primary() && !input->IsDeleting()) |
555 return; | 570 return; |
556 } | 571 } |
557 | 572 |
558 // Move all current inputs to the ignored list | 573 // Move all current inputs to the ignored list |
559 for (InputQueue* input : inputs_) { | 574 for (InputQueue* input : inputs_) { |
560 LOG(INFO) << "Mixer input " << input | 575 LOG(INFO) << "Mixer input " << input |
561 << " now being ignored due to output sample rate change from " | 576 << " now being ignored due to output sample rate change from " |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 rendering_delay_.timestamp_microseconds = | 758 rendering_delay_.timestamp_microseconds = |
744 TimespecToMicroseconds(status_timestamp); | 759 TimespecToMicroseconds(status_timestamp); |
745 snd_pcm_sframes_t delay_frames = alsa_->PcmStatusGetDelay(pcm_status_); | 760 snd_pcm_sframes_t delay_frames = alsa_->PcmStatusGetDelay(pcm_status_); |
746 rendering_delay_.delay_microseconds = static_cast<int64_t>(delay_frames) * | 761 rendering_delay_.delay_microseconds = static_cast<int64_t>(delay_frames) * |
747 base::Time::kMicrosecondsPerSecond / | 762 base::Time::kMicrosecondsPerSecond / |
748 output_samples_per_second_; | 763 output_samples_per_second_; |
749 } | 764 } |
750 | 765 |
751 } // namespace media | 766 } // namespace media |
752 } // namespace chromecast | 767 } // namespace chromecast |
OLD | NEW |