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