1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/base/audio_renderer_mixer.h"
6 
7 #include <cmath>
8 
9 #include "base/check_op.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/time/time.h"
12 #include "base/trace_event/trace_event.h"
13 #include "media/base/audio_renderer_mixer_input.h"
14 #include "media/base/audio_timestamp_helper.h"
15 
16 namespace media {
17 
18 constexpr base::TimeDelta kPauseDelay = base::TimeDelta::FromSeconds(10);
19 
AudioRendererMixer(const AudioParameters & output_params,scoped_refptr<AudioRendererSink> sink)20 AudioRendererMixer::AudioRendererMixer(const AudioParameters& output_params,
21                                        scoped_refptr<AudioRendererSink> sink)
22     : output_params_(output_params),
23       audio_sink_(std::move(sink)),
24       master_converter_(output_params, output_params, true),
25       pause_delay_(kPauseDelay),
26       last_play_time_(base::TimeTicks::Now()),
27       // Initialize |playing_| to true since Start() results in an auto-play.
28       playing_(true) {
29   DCHECK(audio_sink_);
30 
31   // If enabled we will disable the real audio output stream for muted/silent
32   // playbacks after some time elapses.
33   RenderCallback* callback = this;
34   audio_sink_->Initialize(output_params, callback);
35   audio_sink_->Start();
36 }
37 
~AudioRendererMixer()38 AudioRendererMixer::~AudioRendererMixer() {
39   // AudioRendererSink must be stopped before mixer is destructed.
40   audio_sink_->Stop();
41 
42   // Ensure that all mixer inputs have removed themselves prior to destruction.
43   DCHECK(master_converter_.empty());
44   DCHECK(converters_.empty());
45   DCHECK(error_callbacks_.empty());
46 }
47 
AddMixerInput(const AudioParameters & input_params,AudioConverter::InputCallback * input)48 void AudioRendererMixer::AddMixerInput(const AudioParameters& input_params,
49                                        AudioConverter::InputCallback* input) {
50   base::AutoLock auto_lock(lock_);
51   if (!playing_) {
52     playing_ = true;
53     last_play_time_ = base::TimeTicks::Now();
54     audio_sink_->Play();
55   }
56 
57   int input_sample_rate = input_params.sample_rate();
58   if (is_master_sample_rate(input_sample_rate)) {
59     master_converter_.AddInput(input);
60   } else {
61     auto converter = converters_.find(input_sample_rate);
62     if (converter == converters_.end()) {
63       std::pair<AudioConvertersMap::iterator, bool> result =
64           converters_.insert(std::make_pair(
65               input_sample_rate, std::make_unique<LoopbackAudioConverter>(
66                                      // We expect all InputCallbacks to be
67                                      // capable of handling arbitrary buffer
68                                      // size requests, disabling FIFO.
69                                      input_params, output_params_, true)));
70       converter = result.first;
71 
72       // Add newly-created resampler as an input to the master mixer.
73       master_converter_.AddInput(converter->second.get());
74     }
75     converter->second->AddInput(input);
76   }
77 }
78 
RemoveMixerInput(const AudioParameters & input_params,AudioConverter::InputCallback * input)79 void AudioRendererMixer::RemoveMixerInput(
80     const AudioParameters& input_params,
81     AudioConverter::InputCallback* input) {
82   base::AutoLock auto_lock(lock_);
83 
84   int input_sample_rate = input_params.sample_rate();
85   if (is_master_sample_rate(input_sample_rate)) {
86     master_converter_.RemoveInput(input);
87   } else {
88     auto converter = converters_.find(input_sample_rate);
89     DCHECK(converter != converters_.end());
90     converter->second->RemoveInput(input);
91     if (converter->second->empty()) {
92       // Remove converter when it's empty.
93       master_converter_.RemoveInput(converter->second.get());
94       converters_.erase(converter);
95     }
96   }
97 }
98 
AddErrorCallback(AudioRendererMixerInput * input)99 void AudioRendererMixer::AddErrorCallback(AudioRendererMixerInput* input) {
100   base::AutoLock auto_lock(lock_);
101   error_callbacks_.insert(input);
102 }
103 
RemoveErrorCallback(AudioRendererMixerInput * input)104 void AudioRendererMixer::RemoveErrorCallback(AudioRendererMixerInput* input) {
105   base::AutoLock auto_lock(lock_);
106   error_callbacks_.erase(input);
107 }
108 
CurrentThreadIsRenderingThread()109 bool AudioRendererMixer::CurrentThreadIsRenderingThread() {
110   return audio_sink_->CurrentThreadIsRenderingThread();
111 }
112 
SetPauseDelayForTesting(base::TimeDelta delay)113 void AudioRendererMixer::SetPauseDelayForTesting(base::TimeDelta delay) {
114   base::AutoLock auto_lock(lock_);
115   pause_delay_ = delay;
116 }
117 
Render(base::TimeDelta delay,base::TimeTicks delay_timestamp,int prior_frames_skipped,AudioBus * audio_bus)118 int AudioRendererMixer::Render(base::TimeDelta delay,
119                                base::TimeTicks delay_timestamp,
120                                int prior_frames_skipped,
121                                AudioBus* audio_bus) {
122   TRACE_EVENT0("audio", "AudioRendererMixer::Render");
123   base::AutoLock auto_lock(lock_);
124 
125   // If there are no mixer inputs and we haven't seen one for a while, pause the
126   // sink to avoid wasting resources when media elements are present but remain
127   // in the pause state.
128   const base::TimeTicks now = base::TimeTicks::Now();
129   if (!master_converter_.empty()) {
130     last_play_time_ = now;
131   } else if (now - last_play_time_ >= pause_delay_ && playing_) {
132     audio_sink_->Pause();
133     playing_ = false;
134   }
135 
136   // Since AudioConverter uses uint32_t for delay calculations, we must drop
137   // negative delay values (which are incorrect anyways).
138   if (delay < base::TimeDelta())
139     delay = base::TimeDelta();
140 
141   uint32_t frames_delayed =
142       AudioTimestampHelper::TimeToFrames(delay, output_params_.sample_rate());
143   master_converter_.ConvertWithDelay(frames_delayed, audio_bus);
144   return audio_bus->frames();
145 }
146 
OnRenderError()147 void AudioRendererMixer::OnRenderError() {
148   // Call each mixer input and signal an error.
149   base::AutoLock auto_lock(lock_);
150   for (auto* input : error_callbacks_)
151     input->OnRenderError();
152 }
153 
154 }  // namespace media
155