| 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_input_impl.h" | 5 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 const int kNumOutputChannels = 2; | 49 const int kNumOutputChannels = 2; |
| 50 const int64_t kMaxInputQueueUs = 90000; | 50 const int64_t kMaxInputQueueUs = 90000; |
| 51 const int64_t kFadeMs = 15; | 51 const int64_t kFadeMs = 15; |
| 52 // Number of samples to report as readable when paused. When paused, the mixer | 52 // Number of samples to report as readable when paused. When paused, the mixer |
| 53 // will still pull this many frames each time it tries to write frames, but we | 53 // will still pull this many frames each time it tries to write frames, but we |
| 54 // fill the frames with silence. | 54 // fill the frames with silence. |
| 55 const int kPausedReadSamples = 512; | 55 const int kPausedReadSamples = 512; |
| 56 const int kDefaultReadSize = ::media::SincResampler::kDefaultRequestSize; | 56 const int kDefaultReadSize = ::media::SincResampler::kDefaultRequestSize; |
| 57 const int64_t kNoTimestamp = std::numeric_limits<int64_t>::min(); | 57 const int64_t kNoTimestamp = std::numeric_limits<int64_t>::min(); |
| 58 | 58 |
| 59 const int kMaxSlewTimeUpMs = 100; |
| 60 const int kMaxSlewTimeDownMs = 100; |
| 61 |
| 59 } // namespace | 62 } // namespace |
| 60 | 63 |
| 61 StreamMixerAlsaInputImpl::StreamMixerAlsaInputImpl( | 64 StreamMixerAlsaInputImpl::StreamMixerAlsaInputImpl( |
| 62 StreamMixerAlsaInput::Delegate* delegate, | 65 StreamMixerAlsaInput::Delegate* delegate, |
| 63 int input_samples_per_second, | 66 int input_samples_per_second, |
| 64 bool primary, | 67 bool primary, |
| 65 StreamMixerAlsa* mixer) | 68 StreamMixerAlsa* mixer) |
| 66 : delegate_(delegate), | 69 : delegate_(delegate), |
| 67 input_samples_per_second_(input_samples_per_second), | 70 input_samples_per_second_(input_samples_per_second), |
| 68 primary_(primary), | 71 primary_(primary), |
| 69 mixer_(mixer), | 72 mixer_(mixer), |
| 70 mixer_task_runner_(mixer_->task_runner()), | 73 mixer_task_runner_(mixer_->task_runner()), |
| 71 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 74 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 72 resample_ratio_(1.0), | 75 resample_ratio_(1.0), |
| 73 state_(kStateUninitialized), | 76 state_(kStateUninitialized), |
| 74 volume_multiplier_(1.0f), | 77 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs), |
| 75 queued_frames_(0), | 78 queued_frames_(0), |
| 76 queued_frames_including_resampler_(0), | 79 queued_frames_including_resampler_(0), |
| 77 current_buffer_offset_(0), | 80 current_buffer_offset_(0), |
| 78 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / | 81 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / |
| 79 base::Time::kMicrosecondsPerSecond), | 82 base::Time::kMicrosecondsPerSecond), |
| 80 fade_frames_remaining_(0), | 83 fade_frames_remaining_(0), |
| 81 fade_out_frames_total_(0), | 84 fade_out_frames_total_(0), |
| 82 zeroed_frames_(0), | 85 zeroed_frames_(0), |
| 83 weak_factory_(this) { | 86 weak_factory_(this) { |
| 84 LOG(INFO) << "Create " << this; | 87 LOG(INFO) << "Create " << this; |
| 85 DCHECK(delegate_); | 88 DCHECK(delegate_); |
| 86 DCHECK(mixer_); | 89 DCHECK(mixer_); |
| 87 weak_this_ = weak_factory_.GetWeakPtr(); | 90 weak_this_ = weak_factory_.GetWeakPtr(); |
| 88 } | 91 } |
| 89 | 92 |
| 90 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { | 93 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { |
| 91 LOG(INFO) << "Destroy " << this; | 94 LOG(INFO) << "Destroy " << this; |
| 92 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 95 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 93 } | 96 } |
| 94 | 97 |
| 95 int StreamMixerAlsaInputImpl::input_samples_per_second() const { | 98 int StreamMixerAlsaInputImpl::input_samples_per_second() const { |
| 96 return input_samples_per_second_; | 99 return input_samples_per_second_; |
| 97 } | 100 } |
| 98 | 101 |
| 99 float StreamMixerAlsaInputImpl::volume_multiplier() const { | |
| 100 return volume_multiplier_; | |
| 101 } | |
| 102 | |
| 103 bool StreamMixerAlsaInputImpl::primary() const { | 102 bool StreamMixerAlsaInputImpl::primary() const { |
| 104 return primary_; | 103 return primary_; |
| 105 } | 104 } |
| 106 | 105 |
| 107 bool StreamMixerAlsaInputImpl::IsDeleting() const { | 106 bool StreamMixerAlsaInputImpl::IsDeleting() const { |
| 108 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 107 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 109 return (state_ == kStateFinalFade || state_ == kStateDeleted); | 108 return (state_ == kStateFinalFade || state_ == kStateDeleted); |
| 110 } | 109 } |
| 111 | 110 |
| 112 void StreamMixerAlsaInputImpl::Initialize( | 111 void StreamMixerAlsaInputImpl::Initialize( |
| 113 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { | 112 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { |
| 114 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 113 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 115 DCHECK(!IsDeleting()); | 114 DCHECK(!IsDeleting()); |
| 116 if (mixer_->output_samples_per_second() != input_samples_per_second_) { | 115 if (mixer_->output_samples_per_second() != input_samples_per_second_) { |
| 117 resample_ratio_ = static_cast<double>(input_samples_per_second_) / | 116 resample_ratio_ = static_cast<double>(input_samples_per_second_) / |
| 118 mixer_->output_samples_per_second(); | 117 mixer_->output_samples_per_second(); |
| 119 resampler_.reset(new ::media::MultiChannelResampler( | 118 resampler_.reset(new ::media::MultiChannelResampler( |
| 120 kNumOutputChannels, resample_ratio_, kDefaultReadSize, | 119 kNumOutputChannels, resample_ratio_, kDefaultReadSize, |
| 121 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); | 120 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); |
| 122 resampler_->PrimeWithSilence(); | 121 resampler_->PrimeWithSilence(); |
| 123 } | 122 } |
| 123 slew_volume_.SetSampleRate(mixer_->output_samples_per_second()); |
| 124 mixer_rendering_delay_ = mixer_rendering_delay; | 124 mixer_rendering_delay_ = mixer_rendering_delay; |
| 125 fade_out_frames_total_ = NormalFadeFrames(); | 125 fade_out_frames_total_ = NormalFadeFrames(); |
| 126 fade_frames_remaining_ = NormalFadeFrames(); | 126 fade_frames_remaining_ = NormalFadeFrames(); |
| 127 } | 127 } |
| 128 | 128 |
| 129 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { | 129 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { |
| 130 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 130 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 131 weak_factory_.InvalidateWeakPtrs(); | 131 weak_factory_.InvalidateWeakPtrs(); |
| 132 | 132 |
| 133 base::AutoLock lock(queue_lock_); | 133 base::AutoLock lock(queue_lock_); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 } | 496 } |
| 497 | 497 |
| 498 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { | 498 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { |
| 499 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); | 499 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); |
| 500 LOG(INFO) << this << ": stream volume = " << multiplier; | 500 LOG(INFO) << this << ": stream volume = " << multiplier; |
| 501 DCHECK(!IsDeleting()); | 501 DCHECK(!IsDeleting()); |
| 502 if (multiplier > 1.0f) | 502 if (multiplier > 1.0f) |
| 503 multiplier = 1.0f; | 503 multiplier = 1.0f; |
| 504 if (multiplier < 0.0f) | 504 if (multiplier < 0.0f) |
| 505 multiplier = 0.0f; | 505 multiplier = 0.0f; |
| 506 volume_multiplier_ = multiplier; | 506 slew_volume_.SetVolume(multiplier); |
| 507 } |
| 508 |
| 509 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition, |
| 510 const float* src, |
| 511 int frames, |
| 512 float* dest) { |
| 513 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest); |
| 507 } | 514 } |
| 508 | 515 |
| 509 } // namespace media | 516 } // namespace media |
| 510 } // namespace chromecast | 517 } // namespace chromecast |
| OLD | NEW |