| 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 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 | 38 |
| 39 #define POST_TASK_TO_CALLER_THREAD(task, ...) \ | 39 #define POST_TASK_TO_CALLER_THREAD(task, ...) \ |
| 40 caller_task_runner_->PostTask(FROM_HERE, \ | 40 caller_task_runner_->PostTask(FROM_HERE, \ |
| 41 base::Bind(task, weak_this_, ##__VA_ARGS__)); | 41 base::Bind(task, weak_this_, ##__VA_ARGS__)); |
| 42 | 42 |
| 43 namespace chromecast { | 43 namespace chromecast { |
| 44 namespace media { | 44 namespace media { |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 const int kNumOutputChannels = 2; |
| 48 const int64_t kMaxInputQueueUs = 90000; | 49 const int64_t kMaxInputQueueUs = 90000; |
| 49 const int64_t kFadeMs = 15; | 50 const int64_t kFadeMs = 15; |
| 50 // Number of samples to report as readable when paused. When paused, the mixer | 51 // Number of samples to report as readable when paused. When paused, the mixer |
| 51 // will still pull this many frames each time it tries to write frames, but we | 52 // will still pull this many frames each time it tries to write frames, but we |
| 52 // fill the frames with silence. | 53 // fill the frames with silence. |
| 53 const int kPausedReadSamples = 512; | 54 const int kPausedReadSamples = 512; |
| 54 const int kDefaultReadSize = ::media::SincResampler::kDefaultRequestSize; | 55 const int kDefaultReadSize = ::media::SincResampler::kDefaultRequestSize; |
| 55 | 56 |
| 56 } // namespace | 57 } // namespace |
| 57 | 58 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 105 } |
| 105 | 106 |
| 106 void StreamMixerAlsaInputImpl::Initialize( | 107 void StreamMixerAlsaInputImpl::Initialize( |
| 107 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { | 108 const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) { |
| 108 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 109 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 109 DCHECK(!IsDeleting()); | 110 DCHECK(!IsDeleting()); |
| 110 if (mixer_->output_samples_per_second() != input_samples_per_second_) { | 111 if (mixer_->output_samples_per_second() != input_samples_per_second_) { |
| 111 double resample_ratio = static_cast<double>(input_samples_per_second_) / | 112 double resample_ratio = static_cast<double>(input_samples_per_second_) / |
| 112 mixer_->output_samples_per_second(); | 113 mixer_->output_samples_per_second(); |
| 113 resampler_.reset(new ::media::MultiChannelResampler( | 114 resampler_.reset(new ::media::MultiChannelResampler( |
| 114 mixer_->num_output_channels(), resample_ratio, kDefaultReadSize, | 115 kNumOutputChannels, resample_ratio, kDefaultReadSize, |
| 115 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); | 116 base::Bind(&StreamMixerAlsaInputImpl::ReadCB, base::Unretained(this)))); |
| 116 resampler_->PrimeWithSilence(); | 117 resampler_->PrimeWithSilence(); |
| 117 } | 118 } |
| 118 mixer_rendering_delay_ = mixer_rendering_delay; | 119 mixer_rendering_delay_ = mixer_rendering_delay; |
| 119 fade_out_frames_total_ = NormalFadeFrames(); | 120 fade_out_frames_total_ = NormalFadeFrames(); |
| 120 fade_frames_remaining_ = NormalFadeFrames(); | 121 fade_frames_remaining_ = NormalFadeFrames(); |
| 121 } | 122 } |
| 122 | 123 |
| 123 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { | 124 void StreamMixerAlsaInputImpl::PreventDelegateCalls() { |
| 124 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 125 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // Alert the |mixer_| on the mixer thread. | 186 // Alert the |mixer_| on the mixer thread. |
| 186 DidQueueData(data->end_of_stream()); | 187 DidQueueData(data->end_of_stream()); |
| 187 PostPcmCallback(delay); | 188 PostPcmCallback(delay); |
| 188 } | 189 } |
| 189 | 190 |
| 190 // Must only be called when queue_lock_ is locked. | 191 // Must only be called when queue_lock_ is locked. |
| 191 MediaPipelineBackendAlsa::RenderingDelay StreamMixerAlsaInputImpl::QueueData( | 192 MediaPipelineBackendAlsa::RenderingDelay StreamMixerAlsaInputImpl::QueueData( |
| 192 const scoped_refptr<DecoderBufferBase>& data) { | 193 const scoped_refptr<DecoderBufferBase>& data) { |
| 193 queue_lock_.AssertAcquired(); | 194 queue_lock_.AssertAcquired(); |
| 194 if (!data->end_of_stream()) { | 195 if (!data->end_of_stream()) { |
| 195 int frames = | 196 int frames = data->data_size() / (kNumOutputChannels * sizeof(float)); |
| 196 data->data_size() / (mixer_->num_output_channels() * sizeof(float)); | |
| 197 queue_.push_back(data); | 197 queue_.push_back(data); |
| 198 queued_frames_ += frames; | 198 queued_frames_ += frames; |
| 199 queued_frames_including_resampler_ += frames; | 199 queued_frames_including_resampler_ += frames; |
| 200 } | 200 } |
| 201 | 201 |
| 202 MediaPipelineBackendAlsa::RenderingDelay delay = mixer_rendering_delay_; | 202 MediaPipelineBackendAlsa::RenderingDelay delay = mixer_rendering_delay_; |
| 203 delay.delay_microseconds += static_cast<int64_t>( | 203 delay.delay_microseconds += static_cast<int64_t>( |
| 204 queued_frames_including_resampler_ * base::Time::kMicrosecondsPerSecond / | 204 queued_frames_including_resampler_ * base::Time::kMicrosecondsPerSecond / |
| 205 input_samples_per_second_); | 205 input_samples_per_second_); |
| 206 return delay; | 206 return delay; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 231 (resampler_ ? resampler_->BufferedFrames() : 0); | 231 (resampler_ ? resampler_->BufferedFrames() : 0); |
| 232 | 232 |
| 233 bool queued_more_data = false; | 233 bool queued_more_data = false; |
| 234 MediaPipelineBackendAlsa::RenderingDelay total_delay; | 234 MediaPipelineBackendAlsa::RenderingDelay total_delay; |
| 235 { | 235 { |
| 236 base::AutoLock lock(queue_lock_); | 236 base::AutoLock lock(queue_lock_); |
| 237 mixer_rendering_delay_ = mixer_rendering_delay; | 237 mixer_rendering_delay_ = mixer_rendering_delay; |
| 238 queued_frames_ = 0; | 238 queued_frames_ = 0; |
| 239 for (const auto& data : queue_) | 239 for (const auto& data : queue_) |
| 240 queued_frames_ += | 240 queued_frames_ += |
| 241 data->data_size() / (mixer_->num_output_channels() * sizeof(float)); | 241 data->data_size() / (kNumOutputChannels * sizeof(float)); |
| 242 queued_frames_ -= current_buffer_offset_; | 242 queued_frames_ -= current_buffer_offset_; |
| 243 DCHECK_GE(queued_frames_, 0); | 243 DCHECK_GE(queued_frames_, 0); |
| 244 queued_frames_including_resampler_ = | 244 queued_frames_including_resampler_ = |
| 245 queued_frames_ + resampler_queued_frames; | 245 queued_frames_ + resampler_queued_frames; |
| 246 | 246 |
| 247 if (pending_data_ && queued_frames_ < max_queued_frames_) { | 247 if (pending_data_ && queued_frames_ < max_queued_frames_) { |
| 248 scoped_refptr<DecoderBufferBase> data = pending_data_; | 248 scoped_refptr<DecoderBufferBase> data = pending_data_; |
| 249 pending_data_ = nullptr; | 249 pending_data_ = nullptr; |
| 250 total_delay = QueueData(data); | 250 total_delay = QueueData(data); |
| 251 queued_more_data = true; | 251 queued_more_data = true; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 | 284 |
| 285 if (state_ == kStateFadingOut) | 285 if (state_ == kStateFadingOut) |
| 286 return std::min(available_frames, fade_frames_remaining_); | 286 return std::min(available_frames, fade_frames_remaining_); |
| 287 return std::max(0, available_frames - NormalFadeFrames()); | 287 return std::max(0, available_frames - NormalFadeFrames()); |
| 288 } | 288 } |
| 289 | 289 |
| 290 void StreamMixerAlsaInputImpl::GetResampledData(::media::AudioBus* dest, | 290 void StreamMixerAlsaInputImpl::GetResampledData(::media::AudioBus* dest, |
| 291 int frames) { | 291 int frames) { |
| 292 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 292 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 293 DCHECK(dest); | 293 DCHECK(dest); |
| 294 DCHECK_EQ(mixer_->num_output_channels(), dest->channels()); | 294 DCHECK_EQ(kNumOutputChannels, dest->channels()); |
| 295 DCHECK_GE(dest->frames(), frames); | 295 DCHECK_GE(dest->frames(), frames); |
| 296 | 296 |
| 297 if (state_ == kStatePaused || state_ == kStateDeleted) { | 297 if (state_ == kStatePaused || state_ == kStateDeleted) { |
| 298 dest->ZeroFramesPartial(0, frames); | 298 dest->ZeroFramesPartial(0, frames); |
| 299 return; | 299 return; |
| 300 } | 300 } |
| 301 | 301 |
| 302 if (resampler_) { | 302 if (resampler_) { |
| 303 resampler_->Resample(frames, dest); | 303 resampler_->Resample(frames, dest); |
| 304 } else { | 304 } else { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 332 while (frames_left) { | 332 while (frames_left) { |
| 333 scoped_refptr<DecoderBufferBase> buffer; | 333 scoped_refptr<DecoderBufferBase> buffer; |
| 334 int buffer_frames; | 334 int buffer_frames; |
| 335 int frames_to_copy; | 335 int frames_to_copy; |
| 336 int buffer_offset = current_buffer_offset_; | 336 int buffer_offset = current_buffer_offset_; |
| 337 | 337 |
| 338 { | 338 { |
| 339 base::AutoLock lock(queue_lock_); | 339 base::AutoLock lock(queue_lock_); |
| 340 if (!queue_.empty()) { | 340 if (!queue_.empty()) { |
| 341 buffer = queue_.front(); | 341 buffer = queue_.front(); |
| 342 buffer_frames = buffer->data_size() / | 342 buffer_frames = |
| 343 (mixer_->num_output_channels() * sizeof(float)); | 343 buffer->data_size() / (kNumOutputChannels * sizeof(float)); |
| 344 frames_to_copy = | 344 frames_to_copy = |
| 345 std::min(frames_left, buffer_frames - current_buffer_offset_); | 345 std::min(frames_left, buffer_frames - current_buffer_offset_); |
| 346 // Note that queued_frames_ is not updated until AfterWriteFrames(). | 346 // Note that queued_frames_ is not updated until AfterWriteFrames(). |
| 347 // This is done so that the rendering delay is always correct from the | 347 // This is done so that the rendering delay is always correct from the |
| 348 // perspective of the calling thread. | 348 // perspective of the calling thread. |
| 349 current_buffer_offset_ += frames_to_copy; | 349 current_buffer_offset_ += frames_to_copy; |
| 350 if (current_buffer_offset_ == buffer_frames) { | 350 if (current_buffer_offset_ == buffer_frames) { |
| 351 queue_.pop_front(); | 351 queue_.pop_front(); |
| 352 current_buffer_offset_ = 0; | 352 current_buffer_offset_ = 0; |
| 353 } | 353 } |
| 354 } | 354 } |
| 355 } | 355 } |
| 356 | 356 |
| 357 if (buffer) { | 357 if (buffer) { |
| 358 const float* buffer_samples = | 358 const float* buffer_samples = |
| 359 reinterpret_cast<const float*>(buffer->data()); | 359 reinterpret_cast<const float*>(buffer->data()); |
| 360 for (int i = 0; i < mixer_->num_output_channels(); ++i) { | 360 for (int i = 0; i < kNumOutputChannels; ++i) { |
| 361 const float* buffer_channel = buffer_samples + (buffer_frames * i); | 361 const float* buffer_channel = buffer_samples + (buffer_frames * i); |
| 362 memcpy(output->channel(i) + frames_filled, | 362 memcpy(output->channel(i) + frames_filled, |
| 363 buffer_channel + buffer_offset, frames_to_copy * sizeof(float)); | 363 buffer_channel + buffer_offset, frames_to_copy * sizeof(float)); |
| 364 } | 364 } |
| 365 frames_left -= frames_to_copy; | 365 frames_left -= frames_to_copy; |
| 366 frames_filled += frames_to_copy; | 366 frames_filled += frames_to_copy; |
| 367 LOG_IF(WARNING, zeroed_frames_ > 0) << "Filled a total of " | 367 LOG_IF(WARNING, zeroed_frames_ > 0) << "Filled a total of " |
| 368 << zeroed_frames_ << " frames with 0"; | 368 << zeroed_frames_ << " frames with 0"; |
| 369 zeroed_frames_ = 0; | 369 zeroed_frames_ = 0; |
| 370 } else { | 370 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 390 return std::max(frames, 0); | 390 return std::max(frames, 0); |
| 391 } | 391 } |
| 392 | 392 |
| 393 void StreamMixerAlsaInputImpl::FadeIn(::media::AudioBus* dest, int frames) { | 393 void StreamMixerAlsaInputImpl::FadeIn(::media::AudioBus* dest, int frames) { |
| 394 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 394 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 395 LOG(INFO) << "Fading in, " << fade_frames_remaining_ << " frames remaining"; | 395 LOG(INFO) << "Fading in, " << fade_frames_remaining_ << " frames remaining"; |
| 396 float fade_in_frames = mixer_->output_samples_per_second() * kFadeMs / | 396 float fade_in_frames = mixer_->output_samples_per_second() * kFadeMs / |
| 397 base::Time::kMillisecondsPerSecond; | 397 base::Time::kMillisecondsPerSecond; |
| 398 for (int f = 0; f < frames && fade_frames_remaining_; ++f) { | 398 for (int f = 0; f < frames && fade_frames_remaining_; ++f) { |
| 399 float fade_multiplier = 1.0 - fade_frames_remaining_ / fade_in_frames; | 399 float fade_multiplier = 1.0 - fade_frames_remaining_ / fade_in_frames; |
| 400 for (int c = 0; c < mixer_->num_output_channels(); ++c) | 400 for (int c = 0; c < kNumOutputChannels; ++c) |
| 401 dest->channel(c)[f] *= fade_multiplier; | 401 dest->channel(c)[f] *= fade_multiplier; |
| 402 --fade_frames_remaining_; | 402 --fade_frames_remaining_; |
| 403 } | 403 } |
| 404 } | 404 } |
| 405 | 405 |
| 406 void StreamMixerAlsaInputImpl::FadeOut(::media::AudioBus* dest, int frames) { | 406 void StreamMixerAlsaInputImpl::FadeOut(::media::AudioBus* dest, int frames) { |
| 407 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); | 407 DCHECK(mixer_task_runner_->BelongsToCurrentThread()); |
| 408 LOG(INFO) << "Fading out, " << fade_frames_remaining_ << " frames remaining"; | 408 LOG(INFO) << "Fading out, " << fade_frames_remaining_ << " frames remaining"; |
| 409 int f = 0; | 409 int f = 0; |
| 410 for (; f < frames && fade_frames_remaining_; ++f) { | 410 for (; f < frames && fade_frames_remaining_; ++f) { |
| 411 float fade_multiplier = | 411 float fade_multiplier = |
| 412 fade_frames_remaining_ / static_cast<float>(fade_out_frames_total_); | 412 fade_frames_remaining_ / static_cast<float>(fade_out_frames_total_); |
| 413 for (int c = 0; c < mixer_->num_output_channels(); ++c) | 413 for (int c = 0; c < kNumOutputChannels; ++c) |
| 414 dest->channel(c)[f] *= fade_multiplier; | 414 dest->channel(c)[f] *= fade_multiplier; |
| 415 --fade_frames_remaining_; | 415 --fade_frames_remaining_; |
| 416 } | 416 } |
| 417 // Zero remaining frames | 417 // Zero remaining frames |
| 418 for (; f < frames; ++f) { | 418 for (; f < frames; ++f) { |
| 419 for (int c = 0; c < mixer_->num_output_channels(); ++c) | 419 for (int c = 0; c < kNumOutputChannels; ++c) |
| 420 dest->channel(c)[f] = 0.0f; | 420 dest->channel(c)[f] = 0.0f; |
| 421 } | 421 } |
| 422 | 422 |
| 423 if (fade_frames_remaining_ == 0) { | 423 if (fade_frames_remaining_ == 0) { |
| 424 if (state_ == kStateFinalFade) { | 424 if (state_ == kStateFinalFade) { |
| 425 DeleteThis(); | 425 DeleteThis(); |
| 426 } else { | 426 } else { |
| 427 state_ = kStatePaused; | 427 state_ = kStatePaused; |
| 428 } | 428 } |
| 429 } | 429 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 DCHECK(!IsDeleting()); | 484 DCHECK(!IsDeleting()); |
| 485 if (multiplier > 1.0f) | 485 if (multiplier > 1.0f) |
| 486 multiplier = 1.0f; | 486 multiplier = 1.0f; |
| 487 if (multiplier < 0.0f) | 487 if (multiplier < 0.0f) |
| 488 multiplier = 0.0f; | 488 multiplier = 0.0f; |
| 489 volume_multiplier_ = multiplier; | 489 volume_multiplier_ = multiplier; |
| 490 } | 490 } |
| 491 | 491 |
| 492 } // namespace media | 492 } // namespace media |
| 493 } // namespace chromecast | 493 } // namespace chromecast |
| OLD | NEW |