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