15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_renderer_mixer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)enum { kPauseDelaySeconds = 10 }; 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioRendererMixer::AudioRendererMixer( 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioParameters& input_params, const AudioParameters& output_params, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<AudioRendererSink>& sink) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : audio_sink_(sink), 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_converter_(input_params, output_params, true), 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pause_delay_(base::TimeDelta::FromSeconds(kPauseDelaySeconds)), 217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) last_play_time_(base::TimeTicks::Now()), 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Initialize |playing_| to true since Start() results in an auto-play. 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) playing_(true) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_sink_->Initialize(output_params, this); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_sink_->Start(); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioRendererMixer::~AudioRendererMixer() { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioRendererSinks must be stopped before being destructed. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_sink_->Stop(); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Ensure that all mixer inputs have removed themselves prior to destruction. 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(audio_converter_.empty()); 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(error_callbacks_.size(), 0U); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AudioRendererMixer::AddMixerInput(AudioConverter::InputCallback* input) { 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::AutoLock auto_lock(lock_); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!playing_) { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) playing_ = true; 417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) last_play_time_ = base::TimeTicks::Now(); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_sink_->Play(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_converter_.AddInput(input); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererMixer::RemoveMixerInput( 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AudioConverter::InputCallback* input) { 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::AutoLock auto_lock(lock_); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_converter_.RemoveInput(input); 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AudioRendererMixer::AddErrorCallback(const base::Closure& error_cb) { 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::AutoLock auto_lock(lock_); 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callbacks_.push_back(error_cb); 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AudioRendererMixer::RemoveErrorCallback(const base::Closure& error_cb) { 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::AutoLock auto_lock(lock_); 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (ErrorCallbackList::iterator it = error_callbacks_.begin(); 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != error_callbacks_.end(); 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++it) { 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (it->Equals(error_cb)) { 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callbacks_.erase(it); 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // An error callback should always exist when called. 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) NOTREACHED(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AudioRendererMixer::Render(AudioBus* audio_bus, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int audio_delay_milliseconds) { 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::AutoLock auto_lock(lock_); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there are no mixer inputs and we haven't seen one for a while, pause the 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sink to avoid wasting resources when media elements are present but remain 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in the pause state. 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::TimeTicks now = base::TimeTicks::Now(); 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!audio_converter_.empty()) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_play_time_ = now; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (now - last_play_time_ >= pause_delay_ && playing_) { 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_sink_->Pause(); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) playing_ = false; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_converter_.ConvertWithDelay( 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeDelta::FromMilliseconds(audio_delay_milliseconds), audio_bus); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return audio_bus->frames(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioRendererMixer::OnRenderError() { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call each mixer input and signal an error. 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::AutoLock auto_lock(lock_); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (const auto& cb : error_callbacks_) 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cb.Run(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 102