Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: media/base/audio_renderer_mixer.cc

Issue 2067863003: Mixing audio with different latency requirements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixing bot redness Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "media/base/audio_renderer_mixer.h" 5 #include "media/base/audio_renderer_mixer.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/metrics/histogram_macros.h"
13 14
14 namespace media { 15 namespace media {
15 16
16 enum { kPauseDelaySeconds = 10 }; 17 enum { kPauseDelaySeconds = 10 };
17 18
19 // Tracks the maximum value of a counter and logs it into a UMA histogram upon
20 // each increase of the maximum. NOT thread-safe, make sure it is used under
21 // lock.
22 class AudioRendererMixer::UMAMaxValueTracker {
23 public:
24 UMAMaxValueTracker(const UmaLogCallback& log_callback)
25 : log_callback_(log_callback), count_(0), max_count_(0) {}
26
27 ~UMAMaxValueTracker() {}
28
29 // Increments the counter, updates the maximum.
30 void Increment() {
31 ++count_;
32 if (max_count_ < count_) {
33 max_count_ = count_;
34 log_callback_.Run(max_count_);
35 }
36 }
37
38 // Decrements the counter.
39 void Decrement() { --count_; }
40
41 private:
42 const UmaLogCallback log_callback_;
43 int count_;
44 int max_count_;
45 DISALLOW_COPY_AND_ASSIGN(UMAMaxValueTracker);
46 };
47
18 AudioRendererMixer::AudioRendererMixer(const AudioParameters& output_params, 48 AudioRendererMixer::AudioRendererMixer(const AudioParameters& output_params,
19 scoped_refptr<AudioRendererSink> sink) 49 scoped_refptr<AudioRendererSink> sink,
50 const UmaLogCallback& log_callback)
20 : output_params_(output_params), 51 : output_params_(output_params),
21 audio_sink_(std::move(sink)), 52 audio_sink_(std::move(sink)),
22 master_converter_(output_params, output_params, true), 53 master_converter_(output_params, output_params, true),
23 pause_delay_(base::TimeDelta::FromSeconds(kPauseDelaySeconds)), 54 pause_delay_(base::TimeDelta::FromSeconds(kPauseDelaySeconds)),
24 last_play_time_(base::TimeTicks::Now()), 55 last_play_time_(base::TimeTicks::Now()),
25 // Initialize |playing_| to true since Start() results in an auto-play. 56 // Initialize |playing_| to true since Start() results in an auto-play.
26 playing_(true) { 57 playing_(true),
58 input_count_tracker_(new UMAMaxValueTracker(log_callback)) {
27 DCHECK(audio_sink_); 59 DCHECK(audio_sink_);
28 audio_sink_->Initialize(output_params, this); 60 audio_sink_->Initialize(output_params, this);
29 audio_sink_->Start(); 61 audio_sink_->Start();
30 } 62 }
31 63
32 AudioRendererMixer::~AudioRendererMixer() { 64 AudioRendererMixer::~AudioRendererMixer() {
33 // AudioRendererSink must be stopped before mixer is destructed. 65 // AudioRendererSink must be stopped before mixer is destructed.
34 audio_sink_->Stop(); 66 audio_sink_->Stop();
35 67
36 // Ensure that all mixer inputs have removed themselves prior to destruction. 68 // Ensure that all mixer inputs have removed themselves prior to destruction.
(...skipping 26 matching lines...) Expand all
63 // size requests, disabling FIFO. 95 // size requests, disabling FIFO.
64 new LoopbackAudioConverter( 96 new LoopbackAudioConverter(
65 input_params, output_params_, true)))); 97 input_params, output_params_, true))));
66 converter = result.first; 98 converter = result.first;
67 99
68 // Add newly-created resampler as an input to the master mixer. 100 // Add newly-created resampler as an input to the master mixer.
69 master_converter_.AddInput(converter->second.get()); 101 master_converter_.AddInput(converter->second.get());
70 } 102 }
71 converter->second->AddInput(input); 103 converter->second->AddInput(input);
72 } 104 }
105
106 input_count_tracker_->Increment();
73 } 107 }
74 108
75 void AudioRendererMixer::RemoveMixerInput( 109 void AudioRendererMixer::RemoveMixerInput(
76 const AudioParameters& input_params, 110 const AudioParameters& input_params,
77 AudioConverter::InputCallback* input) { 111 AudioConverter::InputCallback* input) {
78 base::AutoLock auto_lock(lock_); 112 base::AutoLock auto_lock(lock_);
79 113
80 int input_sample_rate = input_params.sample_rate(); 114 int input_sample_rate = input_params.sample_rate();
81 if (is_master_sample_rate(input_sample_rate)) { 115 if (is_master_sample_rate(input_sample_rate)) {
82 master_converter_.RemoveInput(input); 116 master_converter_.RemoveInput(input);
83 } else { 117 } else {
84 AudioConvertersMap::iterator converter = 118 AudioConvertersMap::iterator converter =
85 converters_.find(input_sample_rate); 119 converters_.find(input_sample_rate);
86 DCHECK(converter != converters_.end()); 120 DCHECK(converter != converters_.end());
87 converter->second->RemoveInput(input); 121 converter->second->RemoveInput(input);
88 if (converter->second->empty()) { 122 if (converter->second->empty()) {
89 // Remove converter when it's empty. 123 // Remove converter when it's empty.
90 master_converter_.RemoveInput(converter->second.get()); 124 master_converter_.RemoveInput(converter->second.get());
91 converters_.erase(converter); 125 converters_.erase(converter);
92 } 126 }
93 } 127 }
128
129 input_count_tracker_->Decrement();
94 } 130 }
95 131
96 void AudioRendererMixer::AddErrorCallback(const base::Closure& error_cb) { 132 void AudioRendererMixer::AddErrorCallback(const base::Closure& error_cb) {
97 base::AutoLock auto_lock(lock_); 133 base::AutoLock auto_lock(lock_);
98 error_callbacks_.push_back(error_cb); 134 error_callbacks_.push_back(error_cb);
99 } 135 }
100 136
101 void AudioRendererMixer::RemoveErrorCallback(const base::Closure& error_cb) { 137 void AudioRendererMixer::RemoveErrorCallback(const base::Closure& error_cb) {
102 base::AutoLock auto_lock(lock_); 138 base::AutoLock auto_lock(lock_);
103 for (ErrorCallbackList::iterator it = error_callbacks_.begin(); 139 for (ErrorCallbackList::iterator it = error_callbacks_.begin();
(...skipping 11 matching lines...) Expand all
115 151
116 OutputDeviceInfo AudioRendererMixer::GetOutputDeviceInfo() { 152 OutputDeviceInfo AudioRendererMixer::GetOutputDeviceInfo() {
117 DVLOG(1) << __FUNCTION__; 153 DVLOG(1) << __FUNCTION__;
118 return audio_sink_->GetOutputDeviceInfo(); 154 return audio_sink_->GetOutputDeviceInfo();
119 } 155 }
120 156
121 bool AudioRendererMixer::CurrentThreadIsRenderingThread() { 157 bool AudioRendererMixer::CurrentThreadIsRenderingThread() {
122 return audio_sink_->CurrentThreadIsRenderingThread(); 158 return audio_sink_->CurrentThreadIsRenderingThread();
123 } 159 }
124 160
161 void AudioRendererMixer::LogLifetimeUmaStats() {
162 base::AutoLock auto_lock(lock_);
163 input_count_tracker_.reset();
164 };
tommi (sloooow) - chröme 2016/06/29 12:26:52 nit: remove ;
o1ka 2016/06/29 13:57:32 removed the method (not used).
165
125 int AudioRendererMixer::Render(AudioBus* audio_bus, 166 int AudioRendererMixer::Render(AudioBus* audio_bus,
126 uint32_t frames_delayed, 167 uint32_t frames_delayed,
127 uint32_t frames_skipped) { 168 uint32_t frames_skipped) {
128 base::AutoLock auto_lock(lock_); 169 base::AutoLock auto_lock(lock_);
129 170
130 // If there are no mixer inputs and we haven't seen one for a while, pause the 171 // If there are no mixer inputs and we haven't seen one for a while, pause the
131 // sink to avoid wasting resources when media elements are present but remain 172 // sink to avoid wasting resources when media elements are present but remain
132 // in the pause state. 173 // in the pause state.
133 const base::TimeTicks now = base::TimeTicks::Now(); 174 const base::TimeTicks now = base::TimeTicks::Now();
134 if (!master_converter_.empty()) { 175 if (!master_converter_.empty()) {
135 last_play_time_ = now; 176 last_play_time_ = now;
136 } else if (now - last_play_time_ >= pause_delay_ && playing_) { 177 } else if (now - last_play_time_ >= pause_delay_ && playing_) {
137 audio_sink_->Pause(); 178 audio_sink_->Pause();
138 playing_ = false; 179 playing_ = false;
139 } 180 }
140 181
141 master_converter_.ConvertWithDelay(frames_delayed, audio_bus); 182 master_converter_.ConvertWithDelay(frames_delayed, audio_bus);
142 return audio_bus->frames(); 183 return audio_bus->frames();
143 } 184 }
144 185
145 void AudioRendererMixer::OnRenderError() { 186 void AudioRendererMixer::OnRenderError() {
146 // Call each mixer input and signal an error. 187 // Call each mixer input and signal an error.
147 base::AutoLock auto_lock(lock_); 188 base::AutoLock auto_lock(lock_);
148 for (const auto& cb : error_callbacks_) 189 for (const auto& cb : error_callbacks_)
149 cb.Run(); 190 cb.Run();
150 } 191 }
151 192
152 } // namespace media 193 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698