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

Side by Side Diff: media/audio/audio_power_monitor.cc

Issue 22339024: Crash fix: Remove MessageLoop from AudioPowerMonitor and instead use MessageLoopProxy in AudioOutpu… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/audio/audio_power_monitor.h" 5 #include "media/audio/audio_power_monitor.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/bind.h"
11 #include "base/float_util.h" 10 #include "base/float_util.h"
12 #include "base/logging.h" 11 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h" 12 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
14 #include "base/time/time.h" 13 #include "base/time/time.h"
15 #include "media/base/audio_bus.h" 14 #include "media/base/audio_bus.h"
16 15
17 namespace media { 16 namespace media {
18 17
19 AudioPowerMonitor::AudioPowerMonitor( 18 AudioPowerMonitor::AudioPowerMonitor(
20 int sample_rate, 19 int sample_rate, const base::TimeDelta& time_constant)
21 const base::TimeDelta& time_constant,
22 const base::TimeDelta& measurement_period,
23 base::MessageLoop* message_loop,
24 const PowerMeasurementCallback& callback)
25 : sample_weight_( 20 : sample_weight_(
26 1.0f - expf(-1.0f / (sample_rate * time_constant.InSecondsF()))), 21 1.0f - expf(-1.0f / (sample_rate * time_constant.InSecondsF()))) {
27 num_frames_per_callback_(sample_rate * measurement_period.InSecondsF()), 22 ANNOTATE_BENIGN_RACE(
DaleCurtis 2013/08/12 18:23:29 Annotating only keeps TSAN happy, while the impl i
miu 2013/08/12 19:41:46 Done.
28 message_loop_(message_loop), 23 &average_power_, "only one writer; reader takes samples periodically");
29 power_level_callback_(callback), 24 ANNOTATE_BENIGN_RACE(
30 average_power_(0.0f), 25 &has_clipped_,
31 clipped_since_last_notification_(false), 26 "flag set by one thread, cleared by the other; okay to be out-of-sync");
32 frames_since_last_notification_(0), 27 Reset();
33 last_reported_power_(-1.0f),
34 last_reported_clipped_(false) {
35 DCHECK(message_loop_);
36 DCHECK(!power_level_callback_.is_null());
37 } 28 }
38 29
39 AudioPowerMonitor::~AudioPowerMonitor() { 30 AudioPowerMonitor::~AudioPowerMonitor() {
40 } 31 }
41 32
33 void AudioPowerMonitor::Reset() {
34 average_power_ = 0.0f;
35 has_clipped_ = false;
36 }
37
42 void AudioPowerMonitor::Scan(const AudioBus& buffer, int num_frames) { 38 void AudioPowerMonitor::Scan(const AudioBus& buffer, int num_frames) {
43 DCHECK_LE(num_frames, buffer.frames()); 39 DCHECK_LE(num_frames, buffer.frames());
44 const int num_channels = buffer.channels(); 40 const int num_channels = buffer.channels();
45 if (num_frames <= 0 || num_channels <= 0) 41 if (num_frames <= 0 || num_channels <= 0)
46 return; 42 return;
47 43
48 // Calculate a new average power by applying a first-order low-pass filter 44 // Calculate a new average power by applying a first-order low-pass filter
49 // over the audio samples in |buffer|. 45 // over the audio samples in |buffer|.
50 // 46 //
51 // TODO(miu): Implement optimized SSE/NEON to more efficiently compute the 47 // TODO(miu): Implement optimized SSE/NEON to more efficiently compute the
(...skipping 10 matching lines...) Expand all
62 clipped |= (sample_squared > 1.0f); 58 clipped |= (sample_squared > 1.0f);
63 average_power_this_channel += 59 average_power_this_channel +=
64 (sample_squared - average_power_this_channel) * sample_weight_; 60 (sample_squared - average_power_this_channel) * sample_weight_;
65 } 61 }
66 // If data in audio buffer is garbage, ignore its effect on the result. 62 // If data in audio buffer is garbage, ignore its effect on the result.
67 if (base::IsNaN(average_power_this_channel)) 63 if (base::IsNaN(average_power_this_channel))
68 average_power_this_channel = average_power_; 64 average_power_this_channel = average_power_;
69 sum_power += average_power_this_channel; 65 sum_power += average_power_this_channel;
70 } 66 }
71 67
72 // Update accumulated results. 68 // Update accumulated results.
DaleCurtis 2013/08/12 18:23:29 if (lock.Try()) { average_power_exported_ = aver
miu 2013/08/12 19:41:46 Done.
73 average_power_ = std::max(0.0f, std::min(1.0f, sum_power / num_channels)); 69 average_power_ = std::max(0.0f, std::min(1.0f, sum_power / num_channels));
74 clipped_since_last_notification_ |= clipped; 70 if (clipped)
DaleCurtis 2013/08/12 18:23:29 This is not the same behavior as before and will l
miu 2013/08/12 19:41:46 It looks like the same behavior to me. Can you pr
DaleCurtis 2013/08/12 20:43:56 Ah you're right. The | is clearer to me apparentl
75 frames_since_last_notification_ += num_frames; 71 has_clipped_ = true;
72 }
76 73
77 // Once enough frames have been scanned, report the accumulated results. 74 float AudioPowerMonitor::ReadCurrentPower() const {
78 if (frames_since_last_notification_ >= num_frames_per_callback_) { 75 // Ensure we have a copy of |average_power_| local to this thread so that the
79 // Note: Forgo making redundant callbacks when results remain unchanged. 76 // value will not mutate while evaluating the return expression below.
80 // Part of this is to pin-down the power to zero if it is insignificantly 77 float sampled_power;
81 // small. 78 memcpy(&sampled_power, &average_power_, sizeof(float));
DaleCurtis 2013/08/12 18:23:29 I don't think memcpy provides you any guarantees,
miu 2013/08/12 19:41:46 Removed. Not needed anymore now that we're using
82 const float kInsignificantPower = 1.0e-10f; // -100 dBFS 79
83 const float power = 80 // Return the sampled power level, converted to dBFS units, and pinned-down to
84 (average_power_ < kInsignificantPower) ? 0.0f : average_power_; 81 // zero if it is insignificantly small.
85 if (power != last_reported_power_ || 82 const float kInsignificantPower = 1.0e-10f; // -100 dBFS
86 clipped_since_last_notification_ != last_reported_clipped_) { 83 return sampled_power < kInsignificantPower ? zero_power() :
87 const float power_dbfs = 84 10.0f * log10f(sampled_power);
88 power > 0.0f ? 10.0f * log10f(power) : zero_power(); 85 }
89 // Try to post a task to run the callback with the dBFS result. The 86
90 // posting of the task is guaranteed to be non-blocking, and therefore 87 bool AudioPowerMonitor::TestForClippingAndClear() {
91 // could fail. However, in the common case, failures should be rare (and 88 const bool clipped = has_clipped_;
92 // then the task-post will likely succeed the next time it's attempted). 89 if (clipped)
93 if (!message_loop_->TryPostTask( 90 has_clipped_ = false;
94 FROM_HERE, 91 return clipped;
95 base::Bind(power_level_callback_,
96 power_dbfs, clipped_since_last_notification_))) {
97 DVLOG(2) << "TryPostTask() did not succeed.";
98 return;
99 }
100 last_reported_power_ = power;
101 last_reported_clipped_ = clipped_since_last_notification_;
102 }
103 clipped_since_last_notification_ = false;
104 frames_since_last_notification_ = 0;
105 }
106 } 92 }
107 93
108 } // namespace media 94 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698