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, |
68 StreamMixerAlsa* mixer) | 69 StreamMixerAlsa* mixer) |
69 : delegate_(delegate), | 70 : delegate_(delegate), |
70 input_samples_per_second_(input_samples_per_second), | 71 input_samples_per_second_(input_samples_per_second), |
71 primary_(primary), | 72 primary_(primary), |
| 73 device_id_(device_id), |
72 mixer_(mixer), | 74 mixer_(mixer), |
| 75 filter_group_(nullptr), |
73 mixer_task_runner_(mixer_->task_runner()), | 76 mixer_task_runner_(mixer_->task_runner()), |
74 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 77 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
75 resample_ratio_(1.0), | 78 resample_ratio_(1.0), |
76 state_(kStateUninitialized), | 79 state_(kStateUninitialized), |
77 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs), | 80 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs), |
78 queued_frames_(0), | 81 queued_frames_(0), |
79 queued_frames_including_resampler_(0), | 82 queued_frames_including_resampler_(0), |
80 current_buffer_offset_(0), | 83 current_buffer_offset_(0), |
81 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / | 84 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / |
82 base::Time::kMicrosecondsPerSecond), | 85 base::Time::kMicrosecondsPerSecond), |
83 fade_frames_remaining_(0), | 86 fade_frames_remaining_(0), |
84 fade_out_frames_total_(0), | 87 fade_out_frames_total_(0), |
85 zeroed_frames_(0), | 88 zeroed_frames_(0), |
86 is_underflowing_(false), | 89 is_underflowing_(false), |
87 weak_factory_(this) { | 90 weak_factory_(this) { |
88 LOG(INFO) << "Create " << this; | 91 LOG(INFO) << "Create " << device_id_ << " (" << this << ")"; |
89 DCHECK(delegate_); | 92 DCHECK(delegate_); |
90 DCHECK(mixer_); | 93 DCHECK(mixer_); |
91 weak_this_ = weak_factory_.GetWeakPtr(); | 94 weak_this_ = weak_factory_.GetWeakPtr(); |
92 } | 95 } |
93 | 96 |
94 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { | 97 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { |
95 LOG(INFO) << "Destroy " << this; | 98 LOG(INFO) << "Destroy " << device_id_ << " (" << this << ")"; |
96 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 99 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
97 } | 100 } |
98 | 101 |
99 int StreamMixerAlsaInputImpl::input_samples_per_second() const { | 102 int StreamMixerAlsaInputImpl::input_samples_per_second() const { |
100 return input_samples_per_second_; | 103 return input_samples_per_second_; |
101 } | 104 } |
102 | 105 |
103 bool StreamMixerAlsaInputImpl::primary() const { | 106 bool StreamMixerAlsaInputImpl::primary() const { |
104 return primary_; | 107 return primary_; |
105 } | 108 } |
106 | 109 |
| 110 std::string StreamMixerAlsaInputImpl::device_id() const { |
| 111 return device_id_; |
| 112 } |
| 113 |
107 bool StreamMixerAlsaInputImpl::IsDeleting() const { | 114 bool StreamMixerAlsaInputImpl::IsDeleting() const { |
108 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 115 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
109 return (state_ == kStateFinalFade || state_ == kStateDeleted); | 116 return (state_ == kStateFinalFade || state_ == kStateDeleted); |
110 } | 117 } |
111 | 118 |
112 void StreamMixerAlsaInputImpl::Initialize( | 119 void StreamMixerAlsaInputImpl::Initialize( |
113 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { | 120 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { |
114 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 121 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
115 DCHECK(!IsDeleting()); | 122 DCHECK(!IsDeleting()); |
116 if (mixer_->output_samples_per_second() != input_samples_per_second_) { | 123 if (mixer_->output_samples_per_second() != input_samples_per_second_) { |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 int StreamMixerAlsaInputImpl::NormalFadeFrames() { | 426 int StreamMixerAlsaInputImpl::NormalFadeFrames() { |
420 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 427 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
421 int frames = (mixer_->output_samples_per_second() * kFadeMs / | 428 int frames = (mixer_->output_samples_per_second() * kFadeMs / |
422 base::Time::kMillisecondsPerSecond) - | 429 base::Time::kMillisecondsPerSecond) - |
423 1; | 430 1; |
424 return std::max(frames, 0); | 431 return std::max(frames, 0); |
425 } | 432 } |
426 | 433 |
427 void StreamMixerAlsaInputImpl::FadeIn(::media::AudioBus* dest, int frames) { | 434 void StreamMixerAlsaInputImpl::FadeIn(::media::AudioBus* dest, int frames) { |
428 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 435 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
429 LOG(INFO) << "Fading in, " << fade_frames_remaining_ << " frames remaining"; | |
430 float fade_in_frames = mixer_->output_samples_per_second() * kFadeMs / | 436 float fade_in_frames = mixer_->output_samples_per_second() * kFadeMs / |
431 base::Time::kMillisecondsPerSecond; | 437 base::Time::kMillisecondsPerSecond; |
432 for (int f = 0; f < frames && fade_frames_remaining_; ++f) { | 438 for (int f = 0; f < frames && fade_frames_remaining_; ++f) { |
433 float fade_multiplier = 1.0 - fade_frames_remaining_ / fade_in_frames; | 439 float fade_multiplier = 1.0 - fade_frames_remaining_ / fade_in_frames; |
434 for (int c = 0; c < kNumOutputChannels; ++c) | 440 for (int c = 0; c < kNumOutputChannels; ++c) |
435 dest->channel(c)[f] *= fade_multiplier; | 441 dest->channel(c)[f] *= fade_multiplier; |
436 --fade_frames_remaining_; | 442 --fade_frames_remaining_; |
437 } | 443 } |
438 } | 444 } |
439 | 445 |
440 void StreamMixerAlsaInputImpl::FadeOut(::media::AudioBus* dest, int frames) { | 446 void StreamMixerAlsaInputImpl::FadeOut(::media::AudioBus* dest, int frames) { |
441 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 447 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
442 LOG(INFO) << "Fading out, " << fade_frames_remaining_ << " frames remaining"; | |
443 int f = 0; | 448 int f = 0; |
444 for (; f < frames && fade_frames_remaining_; ++f) { | 449 for (; f < frames && fade_frames_remaining_; ++f) { |
445 float fade_multiplier = | 450 float fade_multiplier = |
446 fade_frames_remaining_ / static_cast<float>(fade_out_frames_total_); | 451 fade_frames_remaining_ / static_cast<float>(fade_out_frames_total_); |
447 for (int c = 0; c < kNumOutputChannels; ++c) | 452 for (int c = 0; c < kNumOutputChannels; ++c) |
448 dest->channel(c)[f] *= fade_multiplier; | 453 dest->channel(c)[f] *= fade_multiplier; |
449 --fade_frames_remaining_; | 454 --fade_frames_remaining_; |
450 } | 455 } |
451 // Zero remaining frames | 456 // Zero remaining frames |
452 for (; f < frames; ++f) { | 457 for (; f < frames; ++f) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 | 513 |
509 if (state_ == kStateFadingOut) { | 514 if (state_ == kStateFadingOut) { |
510 // Tell the mixer that some more data might be available (since when fading | 515 // Tell the mixer that some more data might be available (since when fading |
511 // out, we can drain the queue completely). | 516 // out, we can drain the queue completely). |
512 mixer_->OnFramesQueued(); | 517 mixer_->OnFramesQueued(); |
513 } | 518 } |
514 } | 519 } |
515 | 520 |
516 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { | 521 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { |
517 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); | 522 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); |
518 LOG(INFO) << this << ": stream volume = " << multiplier; | 523 LOG(INFO) << device_id_ << "(" << this << "): stream volume = " << multiplier; |
519 DCHECK(!IsDeleting()); | 524 DCHECK(!IsDeleting()); |
520 if (multiplier > 1.0f) | 525 if (multiplier > 1.0f) |
521 multiplier = 1.0f; | 526 multiplier = 1.0f; |
522 if (multiplier < 0.0f) | 527 if (multiplier < 0.0f) |
523 multiplier = 0.0f; | 528 multiplier = 0.0f; |
524 slew_volume_.SetVolume(multiplier); | 529 slew_volume_.SetVolume(multiplier); |
525 } | 530 } |
526 | 531 |
527 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition, | 532 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition, |
528 const float* src, | 533 const float* src, |
529 int frames, | 534 int frames, |
530 float* dest) { | 535 float* dest) { |
531 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest); | 536 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest); |
532 } | 537 } |
533 | 538 |
534 } // namespace media | 539 } // namespace media |
535 } // namespace chromecast | 540 } // namespace chromecast |
OLD | NEW |