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

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: Unit tests, cleanup 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 // the destruciton.
21 class AudioRendererMixer::UMAMaxValueTracker {
22 public:
23 UMAMaxValueTracker(const std::string& histogram_name)
24 : histogram_name_(histogram_name), count_(0), max_count_(0) {}
25
26 ~UMAMaxValueTracker() {
27 if (max_count_ && !histogram_name_.empty())
28 LOCAL_HISTOGRAM_CUSTOM_COUNTS(histogram_name_, max_count_, 1, 100, 100);
tommi (sloooow) - chröme 2016/06/28 14:14:54 see other comment about using a variable here
o1ka 2016/06/29 10:11:26 Done.
29 }
30
31 // Increments the counter, updates the maximum.
32 void Increment() {
tommi (sloooow) - chröme 2016/06/28 14:14:54 thread checks?
o1ka 2016/06/29 10:11:26 Updated a comment. It's used under a lock from mul
33 ++count_;
34 if (max_count_ < count_)
35 max_count_ = count_;
36 }
37
38 // Decrements the counter.
39 void Decrement() { --count_; }
40
41 private:
42 const std::string histogram_name_;
tommi (sloooow) - chröme 2016/06/28 14:14:54 const char*
o1ka 2016/06/29 10:11:26 Acknowledged.
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 std::string& histogram_name)
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(histogram_name)) {
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 } 175 }
140 176
141 void AudioRendererMixer::OnRenderError() { 177 void AudioRendererMixer::OnRenderError() {
142 // Call each mixer input and signal an error. 178 // Call each mixer input and signal an error.
143 base::AutoLock auto_lock(lock_); 179 base::AutoLock auto_lock(lock_);
144 for (const auto& cb : error_callbacks_) 180 for (const auto& cb : error_callbacks_)
145 cb.Run(); 181 cb.Run();
146 } 182 }
147 183
148 } // namespace media 184 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698