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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 | 58 |
59 const int kMaxSlewTimeUpMs = 15; | 59 const int kMaxSlewTimeUpMs = 15; |
60 const int kMaxSlewTimeDownMs = 15; | 60 const int kMaxSlewTimeDownMs = 15; |
61 | 61 |
62 } // namespace | 62 } // namespace |
63 | 63 |
64 StreamMixerAlsaInputImpl::StreamMixerAlsaInputImpl( | 64 StreamMixerAlsaInputImpl::StreamMixerAlsaInputImpl( |
65 StreamMixerAlsaInput::Delegate* delegate, | 65 StreamMixerAlsaInput::Delegate* delegate, |
66 int input_samples_per_second, | 66 int input_samples_per_second, |
67 bool primary, | 67 bool primary, |
68 const std::string& device_id, | |
69 StreamMixerAlsa* mixer) | 68 StreamMixerAlsa* mixer) |
70 : delegate_(delegate), | 69 : delegate_(delegate), |
71 input_samples_per_second_(input_samples_per_second), | 70 input_samples_per_second_(input_samples_per_second), |
72 primary_(primary), | 71 primary_(primary), |
73 device_id_(device_id), | |
74 mixer_(mixer), | 72 mixer_(mixer), |
75 filter_group_(nullptr), | |
76 mixer_task_runner_(mixer_->task_runner()), | 73 mixer_task_runner_(mixer_->task_runner()), |
77 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 74 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
78 resample_ratio_(1.0), | 75 resample_ratio_(1.0), |
79 state_(kStateUninitialized), | 76 state_(kStateUninitialized), |
80 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs), | 77 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs), |
81 queued_frames_(0), | 78 queued_frames_(0), |
82 queued_frames_including_resampler_(0), | 79 queued_frames_including_resampler_(0), |
83 current_buffer_offset_(0), | 80 current_buffer_offset_(0), |
84 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / | 81 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / |
85 base::Time::kMicrosecondsPerSecond), | 82 base::Time::kMicrosecondsPerSecond), |
86 fade_frames_remaining_(0), | 83 fade_frames_remaining_(0), |
87 fade_out_frames_total_(0), | 84 fade_out_frames_total_(0), |
88 zeroed_frames_(0), | 85 zeroed_frames_(0), |
89 is_underflowing_(false), | 86 is_underflowing_(false), |
90 weak_factory_(this) { | 87 weak_factory_(this) { |
91 LOG(INFO) << "Create " << device_id_ << " (" << this << ")"; | 88 LOG(INFO) << "Create " << this; |
92 DCHECK(delegate_); | 89 DCHECK(delegate_); |
93 DCHECK(mixer_); | 90 DCHECK(mixer_); |
94 weak_this_ = weak_factory_.GetWeakPtr(); | 91 weak_this_ = weak_factory_.GetWeakPtr(); |
95 } | 92 } |
96 | 93 |
97 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { | 94 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { |
98 LOG(INFO) << "Destroy " << device_id_ << " (" << this << ")"; | 95 LOG(INFO) << "Destroy " << this; |
99 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 96 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
100 } | 97 } |
101 | 98 |
102 int StreamMixerAlsaInputImpl::input_samples_per_second() const { | 99 int StreamMixerAlsaInputImpl::input_samples_per_second() const { |
103 return input_samples_per_second_; | 100 return input_samples_per_second_; |
104 } | 101 } |
105 | 102 |
106 bool StreamMixerAlsaInputImpl::primary() const { | 103 bool StreamMixerAlsaInputImpl::primary() const { |
107 return primary_; | 104 return primary_; |
108 } | 105 } |
109 | 106 |
110 std::string StreamMixerAlsaInputImpl::device_id() const { | |
111 return device_id_; | |
112 } | |
113 | |
114 bool StreamMixerAlsaInputImpl::IsDeleting() const { | 107 bool StreamMixerAlsaInputImpl::IsDeleting() const { |
115 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 108 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
116 return (state_ == kStateFinalFade || state_ == kStateDeleted); | 109 return (state_ == kStateFinalFade || state_ == kStateDeleted); |
117 } | 110 } |
118 | 111 |
119 void StreamMixerAlsaInputImpl::Initialize( | 112 void StreamMixerAlsaInputImpl::Initialize( |
120 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { | 113 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { |
121 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 114 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
122 DCHECK(!IsDeleting()); | 115 DCHECK(!IsDeleting()); |
123 if (mixer_->output_samples_per_second() != input_samples_per_second_) { | 116 if (mixer_->output_samples_per_second() != input_samples_per_second_) { |
124 resample_ratio_ = static_cast<double>(input_samples_per_second_) / | 117 resample_ratio_ = static_cast<double>(input_samples_per_second_) / |
125 mixer_->output_samples_per_second(); | 118 mixer_->output_samples_per_second(); |
126 resampler_.reset(new ::media::MultiChannelResampler( | 119 resampler_.reset(new ::media::MultiChannelResampler( |
127 kNumOutputChannels, resample_ratio_, kDefaultReadSize, | 120 kNumOutputChannels, resample_ratio_, kDefaultReadSize, |
128 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); | 121 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); |
129 resampler_->PrimeWithSilence(); | 122 resampler_->PrimeWithSilence(); |
130 } | 123 } |
131 slew_volume_.SetSampleRate(mixer_->output_samples_per_second()); | 124 slew_volume_.SetSampleRate(mixer_->output_samples_per_second()); |
132 mixer_rendering_delay_ = mixer_rendering_delay; | 125 mixer_rendering_delay_ = mixer_rendering_delay; |
133 fade_out_frames_total_ = NormalFadeFrames(); | 126 fade_out_frames_total_ = NormalFadeFrames(); |
134 fade_frames_remaining_ = NormalFadeFrames(); | 127 fade_frames_remaining_ = NormalFadeFrames(); |
135 } | 128 } |
136 | 129 |
137 void StreamMixerAlsaInputImpl::set_filter_group(FilterGroup* filter_group) { | |
138 filter_group_ = filter_group; | |
139 } | |
140 | |
141 FilterGroup* StreamMixerAlsaInputImpl::filter_group() { | |
142 return filter_group_; | |
143 } | |
144 | |
145 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { | 130 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { |
146 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 131 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
147 weak_factory_.InvalidateWeakPtrs(); | 132 weak_factory_.InvalidateWeakPtrs(); |
148 | 133 |
149 base::AutoLock lock(queue_lock_); | 134 base::AutoLock lock(queue_lock_); |
150 pending_data_ = nullptr; | 135 pending_data_ = nullptr; |
151 } | 136 } |
152 | 137 |
153 void StreamMixerAlsaInputImpl::PrepareToDelete( | 138 void StreamMixerAlsaInputImpl::PrepareToDelete( |
154 const OnReadyToDeleteCb& delete_cb) { | 139 const OnReadyToDeleteCb& delete_cb) { |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 int StreamMixerAlsaInputImpl::NormalFadeFrames() { | 419 int StreamMixerAlsaInputImpl::NormalFadeFrames() { |
435 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 420 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
436 int frames = (mixer_->output_samples_per_second() * kFadeMs / | 421 int frames = (mixer_->output_samples_per_second() * kFadeMs / |
437 base::Time::kMillisecondsPerSecond) - | 422 base::Time::kMillisecondsPerSecond) - |
438 1; | 423 1; |
439 return std::max(frames, 0); | 424 return std::max(frames, 0); |
440 } | 425 } |
441 | 426 |
442 void StreamMixerAlsaInputImpl::FadeIn(::media::AudioBus* dest, int frames) { | 427 void StreamMixerAlsaInputImpl::FadeIn(::media::AudioBus* dest, int frames) { |
443 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 428 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 429 LOG(INFO) << "Fading in, " << fade_frames_remaining_ << " frames remaining"; |
444 float fade_in_frames = mixer_->output_samples_per_second() * kFadeMs / | 430 float fade_in_frames = mixer_->output_samples_per_second() * kFadeMs / |
445 base::Time::kMillisecondsPerSecond; | 431 base::Time::kMillisecondsPerSecond; |
446 for (int f = 0; f < frames && fade_frames_remaining_; ++f) { | 432 for (int f = 0; f < frames && fade_frames_remaining_; ++f) { |
447 float fade_multiplier = 1.0 - fade_frames_remaining_ / fade_in_frames; | 433 float fade_multiplier = 1.0 - fade_frames_remaining_ / fade_in_frames; |
448 for (int c = 0; c < kNumOutputChannels; ++c) | 434 for (int c = 0; c < kNumOutputChannels; ++c) |
449 dest->channel(c)[f] *= fade_multiplier; | 435 dest->channel(c)[f] *= fade_multiplier; |
450 --fade_frames_remaining_; | 436 --fade_frames_remaining_; |
451 } | 437 } |
452 } | 438 } |
453 | 439 |
454 void StreamMixerAlsaInputImpl::FadeOut(::media::AudioBus* dest, int frames) { | 440 void StreamMixerAlsaInputImpl::FadeOut(::media::AudioBus* dest, int frames) { |
455 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 441 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 442 LOG(INFO) << "Fading out, " << fade_frames_remaining_ << " frames remaining"; |
456 int f = 0; | 443 int f = 0; |
457 for (; f < frames && fade_frames_remaining_; ++f) { | 444 for (; f < frames && fade_frames_remaining_; ++f) { |
458 float fade_multiplier = | 445 float fade_multiplier = |
459 fade_frames_remaining_ / static_cast<float>(fade_out_frames_total_); | 446 fade_frames_remaining_ / static_cast<float>(fade_out_frames_total_); |
460 for (int c = 0; c < kNumOutputChannels; ++c) | 447 for (int c = 0; c < kNumOutputChannels; ++c) |
461 dest->channel(c)[f] *= fade_multiplier; | 448 dest->channel(c)[f] *= fade_multiplier; |
462 --fade_frames_remaining_; | 449 --fade_frames_remaining_; |
463 } | 450 } |
464 // Zero remaining frames | 451 // Zero remaining frames |
465 for (; f < frames; ++f) { | 452 for (; f < frames; ++f) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 | 508 |
522 if (state_ == kStateFadingOut) { | 509 if (state_ == kStateFadingOut) { |
523 // Tell the mixer that some more data might be available (since when fading | 510 // Tell the mixer that some more data might be available (since when fading |
524 // out, we can drain the queue completely). | 511 // out, we can drain the queue completely). |
525 mixer_->OnFramesQueued(); | 512 mixer_->OnFramesQueued(); |
526 } | 513 } |
527 } | 514 } |
528 | 515 |
529 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { | 516 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { |
530 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); | 517 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); |
531 LOG(INFO) << device_id_ << "(" << this << "): stream volume = " << multiplier; | 518 LOG(INFO) << this << ": stream volume = " << multiplier; |
532 DCHECK(!IsDeleting()); | 519 DCHECK(!IsDeleting()); |
533 if (multiplier > 1.0f) | 520 if (multiplier > 1.0f) |
534 multiplier = 1.0f; | 521 multiplier = 1.0f; |
535 if (multiplier < 0.0f) | 522 if (multiplier < 0.0f) |
536 multiplier = 0.0f; | 523 multiplier = 0.0f; |
537 slew_volume_.SetVolume(multiplier); | 524 slew_volume_.SetVolume(multiplier); |
538 } | 525 } |
539 | 526 |
540 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition, | 527 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition, |
541 const float* src, | 528 const float* src, |
542 int frames, | 529 int frames, |
543 float* dest) { | 530 float* dest) { |
544 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest); | 531 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest); |
545 } | 532 } |
546 | 533 |
547 } // namespace media | 534 } // namespace media |
548 } // namespace chromecast | 535 } // namespace chromecast |
OLD | NEW |