Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc

Issue 2738873002: [Chromecast] Implement new volume control API (Closed)
Patch Set: slan comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 = 15; 59 const int kMaxSlewTimeUpMs = 15;
60 const int kMaxSlewTimeDownMs = 15; 60 const int kMaxSlewTimeDownMs = 15;
61 61
62 std::string AudioContentTypeToString(media::AudioContentType type) {
63 switch (type) {
64 case media::AudioContentType::kAlarm:
65 return "alarm";
66 case media::AudioContentType::kCommunication:
67 return "communication";
68 default:
69 return "media";
70 }
71 }
72
62 } // namespace 73 } // namespace
63 74
64 StreamMixerAlsaInputImpl::StreamMixerAlsaInputImpl( 75 StreamMixerAlsaInputImpl::StreamMixerAlsaInputImpl(
65 StreamMixerAlsaInput::Delegate* delegate, 76 StreamMixerAlsaInput::Delegate* delegate,
66 int input_samples_per_second, 77 int input_samples_per_second,
67 bool primary, 78 bool primary,
68 const std::string& device_id, 79 const std::string& device_id,
80 AudioContentType content_type,
69 StreamMixerAlsa* mixer) 81 StreamMixerAlsa* mixer)
70 : delegate_(delegate), 82 : delegate_(delegate),
71 input_samples_per_second_(input_samples_per_second), 83 input_samples_per_second_(input_samples_per_second),
72 primary_(primary), 84 primary_(primary),
73 device_id_(device_id), 85 device_id_(device_id),
86 content_type_(content_type),
74 mixer_(mixer), 87 mixer_(mixer),
75 filter_group_(nullptr), 88 filter_group_(nullptr),
76 mixer_task_runner_(mixer_->task_runner()), 89 mixer_task_runner_(mixer_->task_runner()),
77 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), 90 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
78 resample_ratio_(1.0), 91 resample_ratio_(1.0),
79 state_(kStateUninitialized), 92 state_(kStateUninitialized),
93 stream_volume_multiplier_(1.0f),
94 type_volume_multiplier_(1.0f),
95 mute_volume_multiplier_(1.0f),
80 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs), 96 slew_volume_(kMaxSlewTimeUpMs, kMaxSlewTimeDownMs),
81 queued_frames_(0), 97 queued_frames_(0),
82 queued_frames_including_resampler_(0), 98 queued_frames_including_resampler_(0),
83 current_buffer_offset_(0), 99 current_buffer_offset_(0),
84 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / 100 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second /
85 base::Time::kMicrosecondsPerSecond), 101 base::Time::kMicrosecondsPerSecond),
86 fade_frames_remaining_(0), 102 fade_frames_remaining_(0),
87 fade_out_frames_total_(0), 103 fade_out_frames_total_(0),
88 zeroed_frames_(0), 104 zeroed_frames_(0),
89 is_underflowing_(false), 105 is_underflowing_(false),
90 weak_factory_(this) { 106 weak_factory_(this) {
91 LOG(INFO) << "Create " << device_id_ << " (" << this << ")"; 107 LOG(INFO) << "Create " << device_id_ << " (" << this
108 << "), content type = " << AudioContentTypeToString(content_type_);
92 DCHECK(delegate_); 109 DCHECK(delegate_);
93 DCHECK(mixer_); 110 DCHECK(mixer_);
94 weak_this_ = weak_factory_.GetWeakPtr(); 111 weak_this_ = weak_factory_.GetWeakPtr();
95 } 112 }
96 113
97 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { 114 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() {
98 LOG(INFO) << "Destroy " << device_id_ << " (" << this << ")"; 115 LOG(INFO) << "Destroy " << device_id_ << " (" << this << ")";
99 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 116 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
100 } 117 }
101 118
102 int StreamMixerAlsaInputImpl::input_samples_per_second() const { 119 int StreamMixerAlsaInputImpl::input_samples_per_second() const {
103 return input_samples_per_second_; 120 return input_samples_per_second_;
104 } 121 }
105 122
106 bool StreamMixerAlsaInputImpl::primary() const { 123 bool StreamMixerAlsaInputImpl::primary() const {
107 return primary_; 124 return primary_;
108 } 125 }
109 126
110 std::string StreamMixerAlsaInputImpl::device_id() const { 127 std::string StreamMixerAlsaInputImpl::device_id() const {
111 return device_id_; 128 return device_id_;
112 } 129 }
113 130
131 AudioContentType StreamMixerAlsaInputImpl::content_type() const {
132 return content_type_;
133 }
134
114 bool StreamMixerAlsaInputImpl::IsDeleting() const { 135 bool StreamMixerAlsaInputImpl::IsDeleting() const {
115 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 136 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
116 return (state_ == kStateFinalFade || state_ == kStateDeleted); 137 return (state_ == kStateFinalFade || state_ == kStateDeleted);
117 } 138 }
118 139
119 void StreamMixerAlsaInputImpl::Initialize( 140 void StreamMixerAlsaInputImpl::Initialize(
120 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { 141 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) {
121 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 142 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
122 DCHECK(!IsDeleting()); 143 DCHECK(!IsDeleting());
123 if (mixer_->output_samples_per_second() != input_samples_per_second_) { 144 if (mixer_->output_samples_per_second() != input_samples_per_second_) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 void StreamMixerAlsaInputImpl::OnSkipped() { 279 void StreamMixerAlsaInputImpl::OnSkipped() {
259 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 280 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
260 if (!is_underflowing_) { 281 if (!is_underflowing_) {
261 LOG(WARNING) << "Underflow for " << this; 282 LOG(WARNING) << "Underflow for " << this;
262 is_underflowing_ = true; 283 is_underflowing_ = true;
263 } 284 }
264 if (state_ == kStateNormalPlayback) { 285 if (state_ == kStateNormalPlayback) {
265 // Fade in once this input starts providing data again. 286 // Fade in once this input starts providing data again.
266 fade_frames_remaining_ = NormalFadeFrames(); 287 fade_frames_remaining_ = NormalFadeFrames();
267 } 288 }
289 slew_volume_.Interrupted();
268 } 290 }
269 291
270 void StreamMixerAlsaInputImpl::AfterWriteFrames( 292 void StreamMixerAlsaInputImpl::AfterWriteFrames(
271 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { 293 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) {
272 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); 294 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
273 double resampler_queued_frames = 295 double resampler_queued_frames =
274 (resampler_ ? resampler_->BufferedFrames() : 0); 296 (resampler_ ? resampler_->BufferedFrames() : 0);
275 297
276 bool queued_more_data = false; 298 bool queued_more_data = false;
277 MediaPipelineBackendAlsa::RenderingDelay total_delay; 299 MediaPipelineBackendAlsa::RenderingDelay total_delay;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 543
522 if (state_ == kStateFadingOut) { 544 if (state_ == kStateFadingOut) {
523 // Tell the mixer that some more data might be available (since when fading 545 // Tell the mixer that some more data might be available (since when fading
524 // out, we can drain the queue completely). 546 // out, we can drain the queue completely).
525 mixer_->OnFramesQueued(); 547 mixer_->OnFramesQueued();
526 } 548 }
527 } 549 }
528 550
529 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { 551 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) {
530 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); 552 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier);
531 LOG(INFO) << device_id_ << "(" << this << "): stream volume = " << multiplier;
532 DCHECK(!IsDeleting()); 553 DCHECK(!IsDeleting());
533 if (multiplier > 1.0f) 554 stream_volume_multiplier_ = std::max(0.0f, std::min(multiplier, 1.0f));
534 multiplier = 1.0f; 555 float effective_volume = stream_volume_multiplier_ * type_volume_multiplier_ *
535 if (multiplier < 0.0f) 556 mute_volume_multiplier_;
536 multiplier = 0.0f; 557 LOG(INFO) << device_id_ << "(" << this
537 slew_volume_.SetVolume(multiplier); 558 << "): stream volume = " << stream_volume_multiplier_
559 << ", effective multiplier = " << effective_volume;
560 slew_volume_.SetVolume(effective_volume);
561 }
562
563 void StreamMixerAlsaInputImpl::SetContentTypeVolume(float volume) {
564 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
565 type_volume_multiplier_ = std::max(0.0f, std::min(volume, 1.0f));
566 float effective_volume = stream_volume_multiplier_ * type_volume_multiplier_ *
567 mute_volume_multiplier_;
568 LOG(INFO) << device_id_ << "(" << this
569 << "): type volume = " << type_volume_multiplier_
570 << ", effective multiplier = " << effective_volume;
571 slew_volume_.SetVolume(effective_volume);
572 }
573
574 void StreamMixerAlsaInputImpl::SetMuted(bool muted) {
575 DCHECK(mixer_task_runner_->BelongsToCurrentThread());
576 mute_volume_multiplier_ = muted ? 0.0f : 1.0f;
577 float effective_volume = stream_volume_multiplier_ * type_volume_multiplier_ *
578 mute_volume_multiplier_;
579 LOG(INFO) << device_id_ << "(" << this
580 << "): mute volume = " << mute_volume_multiplier_
581 << ", effective multiplier = " << effective_volume;
582 slew_volume_.SetVolume(effective_volume);
538 } 583 }
539 584
540 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition, 585 void StreamMixerAlsaInputImpl::VolumeScaleAccumulate(bool repeat_transition,
541 const float* src, 586 const float* src,
542 int frames, 587 int frames,
543 float* dest) { 588 float* dest) {
544 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest); 589 slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest);
545 } 590 }
546 591
547 } // namespace media 592 } // namespace media
548 } // namespace chromecast 593 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698