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