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 |