| 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 StreamMixerAlsaInput::Delegate* delegate, | 62 StreamMixerAlsaInput::Delegate* delegate, |
| 63 int input_samples_per_second, | 63 int input_samples_per_second, |
| 64 bool primary, | 64 bool primary, |
| 65 StreamMixerAlsa* mixer) | 65 StreamMixerAlsa* mixer) |
| 66 : delegate_(delegate), | 66 : delegate_(delegate), |
| 67 input_samples_per_second_(input_samples_per_second), | 67 input_samples_per_second_(input_samples_per_second), |
| 68 primary_(primary), | 68 primary_(primary), |
| 69 mixer_(mixer), | 69 mixer_(mixer), |
| 70 mixer_task_runner_(mixer_->task_runner()), | 70 mixer_task_runner_(mixer_->task_runner()), |
| 71 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 71 caller_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 72 resample_ratio_(1.0), |
| 72 state_(kStateUninitialized), | 73 state_(kStateUninitialized), |
| 73 volume_multiplier_(1.0f), | 74 volume_multiplier_(1.0f), |
| 74 queued_frames_(0), | 75 queued_frames_(0), |
| 75 queued_frames_including_resampler_(0), | 76 queued_frames_including_resampler_(0), |
| 76 current_buffer_offset_(0), | 77 current_buffer_offset_(0), |
| 77 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / | 78 max_queued_frames_(kMaxInputQueueUs * input_samples_per_second / |
| 78 base::Time::kMicrosecondsPerSecond), | 79 base::Time::kMicrosecondsPerSecond), |
| 79 fade_frames_remaining_(0), | 80 fade_frames_remaining_(0), |
| 80 fade_out_frames_total_(0), | 81 fade_out_frames_total_(0), |
| 81 zeroed_frames_(0), | 82 zeroed_frames_(0), |
| 82 weak_factory_(this) { | 83 weak_factory_(this) { |
| 84 LOG(INFO) << "Create " << this; |
| 83 DCHECK(delegate_); | 85 DCHECK(delegate_); |
| 84 DCHECK(mixer_); | 86 DCHECK(mixer_); |
| 85 weak_this_ = weak_factory_.GetWeakPtr(); | 87 weak_this_ = weak_factory_.GetWeakPtr(); |
| 86 } | 88 } |
| 87 | 89 |
| 88 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { | 90 StreamMixerAlsaInputImpl::~StreamMixerAlsaInputImpl() { |
| 91 LOG(INFO) << "Destroy " << this; |
| 89 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 92 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 90 } | 93 } |
| 91 | 94 |
| 92 int StreamMixerAlsaInputImpl::input_samples_per_second() const { | 95 int StreamMixerAlsaInputImpl::input_samples_per_second() const { |
| 93 return input_samples_per_second_; | 96 return input_samples_per_second_; |
| 94 } | 97 } |
| 95 | 98 |
| 96 float StreamMixerAlsaInputImpl::volume_multiplier() const { | 99 float StreamMixerAlsaInputImpl::volume_multiplier() const { |
| 97 return volume_multiplier_; | 100 return volume_multiplier_; |
| 98 } | 101 } |
| 99 | 102 |
| 100 bool StreamMixerAlsaInputImpl::primary() const { | 103 bool StreamMixerAlsaInputImpl::primary() const { |
| 101 return primary_; | 104 return primary_; |
| 102 } | 105 } |
| 103 | 106 |
| 104 bool StreamMixerAlsaInputImpl::IsDeleting() const { | 107 bool StreamMixerAlsaInputImpl::IsDeleting() const { |
| 105 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 108 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 106 return (state_ == kStateFinalFade || state_ == kStateDeleted); | 109 return (state_ == kStateFinalFade || state_ == kStateDeleted); |
| 107 } | 110 } |
| 108 | 111 |
| 109 void StreamMixerAlsaInputImpl::Initialize( | 112 void StreamMixerAlsaInputImpl::Initialize( |
| 110 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { | 113 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { |
| 111 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 114 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 112 DCHECK(!IsDeleting()); | 115 DCHECK(!IsDeleting()); |
| 113 if (mixer_->output_samples_per_second() != input_samples_per_second_) { | 116 if (mixer_->output_samples_per_second() != input_samples_per_second_) { |
| 114 double resample_ratio = static_cast<double>(input_samples_per_second_) / | 117 resample_ratio_ = static_cast<double>(input_samples_per_second_) / |
| 115 mixer_->output_samples_per_second(); | 118 mixer_->output_samples_per_second(); |
| 116 resampler_.reset(new ::media::MultiChannelResampler( | 119 resampler_.reset(new ::media::MultiChannelResampler( |
| 117 kNumOutputChannels, resample_ratio, kDefaultReadSize, | 120 kNumOutputChannels, resample_ratio_, kDefaultReadSize, |
| 118 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); | 121 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); |
| 119 resampler_->PrimeWithSilence(); | 122 resampler_->PrimeWithSilence(); |
| 120 } | 123 } |
| 121 mixer_rendering_delay_ = mixer_rendering_delay; | 124 mixer_rendering_delay_ = mixer_rendering_delay; |
| 122 fade_out_frames_total_ = NormalFadeFrames(); | 125 fade_out_frames_total_ = NormalFadeFrames(); |
| 123 fade_frames_remaining_ = NormalFadeFrames(); | 126 fade_frames_remaining_ = NormalFadeFrames(); |
| 124 } | 127 } |
| 125 | 128 |
| 126 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { | 129 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { |
| 127 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 130 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 139 delete_cb_ = delete_cb; | 142 delete_cb_ = delete_cb; |
| 140 if (state_ != kStateNormalPlayback && state_ != kStateFadingOut && | 143 if (state_ != kStateNormalPlayback && state_ != kStateFadingOut && |
| 141 state_ != kStateGotEos) { | 144 state_ != kStateGotEos) { |
| 142 DeleteThis(); | 145 DeleteThis(); |
| 143 return; | 146 return; |
| 144 } | 147 } |
| 145 | 148 |
| 146 { | 149 { |
| 147 base::AutoLock lock(queue_lock_); | 150 base::AutoLock lock(queue_lock_); |
| 148 if (state_ == kStateGotEos) { | 151 if (state_ == kStateGotEos) { |
| 149 fade_out_frames_total_ = queued_frames_including_resampler_; | 152 fade_out_frames_total_ = |
| 150 fade_frames_remaining_ = queued_frames_including_resampler_; | 153 queued_frames_including_resampler_ / resample_ratio_; |
| 154 fade_frames_remaining_ = |
| 155 queued_frames_including_resampler_ / resample_ratio_; |
| 151 } else if (state_ == kStateNormalPlayback) { | 156 } else if (state_ == kStateNormalPlayback) { |
| 152 fade_out_frames_total_ = | 157 fade_out_frames_total_ = |
| 153 std::min(static_cast<int>(queued_frames_including_resampler_), | 158 std::min(static_cast<int>(queued_frames_including_resampler_ / |
| 159 resample_ratio_), |
| 154 NormalFadeFrames()); | 160 NormalFadeFrames()); |
| 155 fade_frames_remaining_ = fade_out_frames_total_; | 161 fade_frames_remaining_ = fade_out_frames_total_; |
| 156 } | 162 } |
| 157 } | 163 } |
| 158 | 164 |
| 159 state_ = kStateFinalFade; | 165 state_ = kStateFinalFade; |
| 160 if (fade_frames_remaining_ == 0) { | 166 if (fade_frames_remaining_ == 0) { |
| 161 DeleteThis(); | 167 DeleteThis(); |
| 162 } else { | 168 } else { |
| 163 // Tell the mixer that some more data might be available (since when fading | 169 // Tell the mixer that some more data might be available (since when fading |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 const MediaPipelineBackendAlsa::RenderingDelay& delay) { | 220 const MediaPipelineBackendAlsa::RenderingDelay& delay) { |
| 215 RUN_ON_CALLER_THREAD(PostPcmCallback, delay); | 221 RUN_ON_CALLER_THREAD(PostPcmCallback, delay); |
| 216 delegate_->OnWritePcmCompletion(MediaPipelineBackendAlsa::kBufferSuccess, | 222 delegate_->OnWritePcmCompletion(MediaPipelineBackendAlsa::kBufferSuccess, |
| 217 delay); | 223 delay); |
| 218 } | 224 } |
| 219 | 225 |
| 220 void StreamMixerAlsaInputImpl::DidQueueData(bool end_of_stream) { | 226 void StreamMixerAlsaInputImpl::DidQueueData(bool end_of_stream) { |
| 221 RUN_ON_MIXER_THREAD(DidQueueData, end_of_stream); | 227 RUN_ON_MIXER_THREAD(DidQueueData, end_of_stream); |
| 222 DCHECK(!IsDeleting()); | 228 DCHECK(!IsDeleting()); |
| 223 if (end_of_stream) { | 229 if (end_of_stream) { |
| 230 LOG(INFO) << "End of stream for " << this; |
| 224 state_ = kStateGotEos; | 231 state_ = kStateGotEos; |
| 225 } else if (state_ == kStateUninitialized) { | 232 } else if (state_ == kStateUninitialized) { |
| 226 state_ = kStateNormalPlayback; | 233 state_ = kStateNormalPlayback; |
| 227 } | 234 } |
| 228 mixer_->OnFramesQueued(); | 235 mixer_->OnFramesQueued(); |
| 229 } | 236 } |
| 230 | 237 |
| 231 void StreamMixerAlsaInputImpl::AfterWriteFrames( | 238 void StreamMixerAlsaInputImpl::AfterWriteFrames( |
| 232 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { | 239 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { |
| 233 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 240 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 234 double resampler_queued_frames = | 241 double resampler_queued_frames = |
| 235 (resampler_ ? resampler_->BufferedFrames() : 0); | 242 (resampler_ ? resampler_->BufferedFrames() : 0); |
| 236 | 243 |
| 237 bool queued_more_data = false; | 244 bool queued_more_data = false; |
| 238 MediaPipelineBackendAlsa::RenderingDelay total_delay; | 245 MediaPipelineBackendAlsa::RenderingDelay total_delay; |
| 239 { | 246 { |
| 240 base::AutoLock lock(queue_lock_); | 247 base::AutoLock lock(queue_lock_); |
| 241 mixer_rendering_delay_ = mixer_rendering_delay; | 248 mixer_rendering_delay_ = mixer_rendering_delay; |
| 242 queued_frames_ = 0; | 249 queued_frames_ = 0; |
| 243 for (const auto& data : queue_) | 250 for (const auto& data : queue_) { |
| 244 queued_frames_ += | 251 queued_frames_ += |
| 245 data->data_size() / (kNumOutputChannels * sizeof(float)); | 252 data->data_size() / (kNumOutputChannels * sizeof(float)); |
| 253 } |
| 246 queued_frames_ -= current_buffer_offset_; | 254 queued_frames_ -= current_buffer_offset_; |
| 247 DCHECK_GE(queued_frames_, 0); | 255 DCHECK_GE(queued_frames_, 0); |
| 248 queued_frames_including_resampler_ = | 256 queued_frames_including_resampler_ = |
| 249 queued_frames_ + resampler_queued_frames; | 257 queued_frames_ + resampler_queued_frames; |
| 250 | 258 |
| 251 if (pending_data_ && queued_frames_ < max_queued_frames_) { | 259 if (pending_data_ && queued_frames_ < max_queued_frames_) { |
| 252 scoped_refptr<DecoderBufferBase> data = pending_data_; | 260 scoped_refptr<DecoderBufferBase> data = pending_data_; |
| 253 pending_data_ = nullptr; | 261 pending_data_ = nullptr; |
| 254 total_delay = QueueData(data); | 262 total_delay = QueueData(data); |
| 255 queued_more_data = true; | 263 queued_more_data = true; |
| 256 if (data->end_of_stream()) | 264 if (data->end_of_stream()) { |
| 265 LOG(INFO) << "End of stream for " << this; |
| 257 state_ = kStateGotEos; | 266 state_ = kStateGotEos; |
| 267 } |
| 258 } | 268 } |
| 259 } | 269 } |
| 260 | 270 |
| 261 if (queued_more_data) | 271 if (queued_more_data) |
| 262 PostPcmCallback(total_delay); | 272 PostPcmCallback(total_delay); |
| 263 } | 273 } |
| 264 | 274 |
| 265 int StreamMixerAlsaInputImpl::MaxReadSize() { | 275 int StreamMixerAlsaInputImpl::MaxReadSize() { |
| 266 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 276 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 267 if (state_ == kStatePaused || state_ == kStateDeleted) | 277 if (state_ == kStatePaused || state_ == kStateDeleted) |
| 268 return kPausedReadSamples; | 278 return kPausedReadSamples; |
| 269 if (state_ == kStateFinalFade) | 279 if (state_ == kStateFinalFade) |
| 270 return fade_frames_remaining_; | 280 return fade_frames_remaining_; |
| 271 | 281 |
| 272 int queued_frames; | 282 int queued_frames; |
| 273 { | 283 { |
| 274 base::AutoLock lock(queue_lock_); | 284 base::AutoLock lock(queue_lock_); |
| 275 if (state_ == kStateGotEos) | 285 if (state_ == kStateGotEos) |
| 276 return std::max(static_cast<int>(queued_frames_including_resampler_), | 286 return std::max(static_cast<int>(queued_frames_including_resampler_ / |
| 287 resample_ratio_), |
| 277 kDefaultReadSize); | 288 kDefaultReadSize); |
| 278 queued_frames = queued_frames_; | 289 queued_frames = queued_frames_; |
| 279 } | 290 } |
| 280 | 291 |
| 281 int available_frames = 0; | 292 int available_frames = 0; |
| 282 if (resampler_) { | 293 if (resampler_) { |
| 283 int num_chunks = queued_frames / kDefaultReadSize; | 294 int num_chunks = queued_frames / kDefaultReadSize; |
| 284 available_frames = resampler_->ChunkSize() * num_chunks; | 295 available_frames = resampler_->ChunkSize() * num_chunks; |
| 285 } else { | 296 } else { |
| 286 available_frames = queued_frames; | 297 available_frames = queued_frames; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 if (buffer) { | 372 if (buffer) { |
| 362 const float* buffer_samples = | 373 const float* buffer_samples = |
| 363 reinterpret_cast<const float*>(buffer->data()); | 374 reinterpret_cast<const float*>(buffer->data()); |
| 364 for (int i = 0; i < kNumOutputChannels; ++i) { | 375 for (int i = 0; i < kNumOutputChannels; ++i) { |
| 365 const float* buffer_channel = buffer_samples + (buffer_frames * i); | 376 const float* buffer_channel = buffer_samples + (buffer_frames * i); |
| 366 memcpy(output->channel(i) + frames_filled, | 377 memcpy(output->channel(i) + frames_filled, |
| 367 buffer_channel + buffer_offset, frames_to_copy * sizeof(float)); | 378 buffer_channel + buffer_offset, frames_to_copy * sizeof(float)); |
| 368 } | 379 } |
| 369 frames_left -= frames_to_copy; | 380 frames_left -= frames_to_copy; |
| 370 frames_filled += frames_to_copy; | 381 frames_filled += frames_to_copy; |
| 371 LOG_IF(WARNING, zeroed_frames_ > 0) << "Filled a total of " | 382 LOG_IF(WARNING, state_ != kStateFinalFade && zeroed_frames_ > 0) |
| 372 << zeroed_frames_ << " frames with 0"; | 383 << "Filled a total of " << zeroed_frames_ << " frames with 0"; |
| 373 zeroed_frames_ = 0; | 384 zeroed_frames_ = 0; |
| 374 } else { | 385 } else { |
| 375 // No data left in queue; fill remaining frames with zeros. | 386 // No data left in queue; fill remaining frames with zeros. |
| 376 LOG_IF(WARNING, zeroed_frames_ == 0) << "Starting to fill frames with 0"; | 387 LOG_IF(WARNING, state_ != kStateFinalFade && zeroed_frames_ == 0) |
| 388 << "Starting to fill frames with 0"; |
| 377 zeroed_frames_ += frames_left; | 389 zeroed_frames_ += frames_left; |
| 378 output->ZeroFramesPartial(frames_filled, frames_left); | 390 output->ZeroFramesPartial(frames_filled, frames_left); |
| 379 frames_filled += frames_left; | 391 frames_filled += frames_left; |
| 380 frames_left = 0; | 392 frames_left = 0; |
| 381 break; | 393 break; |
| 382 } | 394 } |
| 383 } | 395 } |
| 384 | 396 |
| 385 DCHECK_EQ(0, frames_left); | 397 DCHECK_EQ(0, frames_left); |
| 386 DCHECK_EQ(frames, frames_filled); | 398 DCHECK_EQ(frames, frames_filled); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 | 490 |
| 479 if (state_ == kStateFadingOut) { | 491 if (state_ == kStateFadingOut) { |
| 480 // Tell the mixer that some more data might be available (since when fading | 492 // Tell the mixer that some more data might be available (since when fading |
| 481 // out, we can drain the queue completely). | 493 // out, we can drain the queue completely). |
| 482 mixer_->OnFramesQueued(); | 494 mixer_->OnFramesQueued(); |
| 483 } | 495 } |
| 484 } | 496 } |
| 485 | 497 |
| 486 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { | 498 void StreamMixerAlsaInputImpl::SetVolumeMultiplier(float multiplier) { |
| 487 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); | 499 RUN_ON_MIXER_THREAD(SetVolumeMultiplier, multiplier); |
| 500 LOG(INFO) << this << ": stream volume = " << multiplier; |
| 488 DCHECK(!IsDeleting()); | 501 DCHECK(!IsDeleting()); |
| 489 if (multiplier > 1.0f) | 502 if (multiplier > 1.0f) |
| 490 multiplier = 1.0f; | 503 multiplier = 1.0f; |
| 491 if (multiplier < 0.0f) | 504 if (multiplier < 0.0f) |
| 492 multiplier = 0.0f; | 505 multiplier = 0.0f; |
| 493 volume_multiplier_ = multiplier; | 506 volume_multiplier_ = multiplier; |
| 494 } | 507 } |
| 495 | 508 |
| 496 } // namespace media | 509 } // namespace media |
| 497 } // namespace chromecast | 510 } // namespace chromecast |
| OLD | NEW |