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

Side by Side Diff: media/audio/sounds/audio_stream_handler.cc

Issue 348843004: Fix potential deadlock situation for ChromeOS sounds. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove suppressions. Created 6 years, 6 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
« no previous file with comments | « base/debug/tsan_suppressions.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/sounds/audio_stream_handler.h" 5 #include "media/audio/sounds/audio_stream_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/cancelable_callback.h" 9 #include "base/cancelable_callback.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 19 matching lines...) Expand all
30 30
31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; 31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL;
32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; 32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL;
33 33
34 } // namespace 34 } // namespace
35 35
36 class AudioStreamHandler::AudioStreamContainer 36 class AudioStreamHandler::AudioStreamContainer
37 : public AudioOutputStream::AudioSourceCallback { 37 : public AudioOutputStream::AudioSourceCallback {
38 public: 38 public:
39 AudioStreamContainer(const WavAudioHandler& wav_audio) 39 AudioStreamContainer(const WavAudioHandler& wav_audio)
40 : stream_(NULL), 40 : started_(false),
41 wav_audio_(wav_audio), 41 stream_(NULL),
42 cursor_(0), 42 cursor_(0),
43 started_(false), 43 delayed_stop_posted_(false),
44 delayed_stop_posted_(false) { 44 wav_audio_(wav_audio) {}
45 }
46 45
47 virtual ~AudioStreamContainer() { 46 virtual ~AudioStreamContainer() {
48 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 47 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
49 } 48 }
50 49
51 void Play() { 50 void Play() {
52 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 51 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
53 52
54 if (!stream_) { 53 if (!stream_) {
55 const AudioParameters& p = wav_audio_.params(); 54 const AudioParameters& p = wav_audio_.params();
56 const AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, 55 const AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
57 p.channel_layout(), 56 p.channel_layout(),
58 p.sample_rate(), 57 p.sample_rate(),
59 p.bits_per_sample(), 58 p.bits_per_sample(),
60 kDefaultFrameCount); 59 kDefaultFrameCount);
61 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy( 60 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params,
62 params, std::string()); 61 std::string());
63 if (!stream_ || !stream_->Open()) { 62 if (!stream_ || !stream_->Open()) {
64 LOG(ERROR) << "Failed to open an output stream."; 63 LOG(ERROR) << "Failed to open an output stream.";
65 return; 64 return;
66 } 65 }
67 stream_->SetVolume(kOutputVolumePercent); 66 stream_->SetVolume(kOutputVolumePercent);
68 } 67 }
69 68
70 { 69 {
71 base::AutoLock al(state_lock_); 70 base::AutoLock al(state_lock_);
72 71
73 delayed_stop_posted_ = false; 72 delayed_stop_posted_ = false;
74 stop_closure_.Reset(base::Bind( 73 stop_closure_.Reset(base::Bind(&AudioStreamContainer::StopStream,
75 &AudioStreamContainer::StopStream, base::Unretained(this))); 74 base::Unretained(this)));
76 75
77 if (started_) { 76 if (started_) {
78 if (wav_audio_.AtEnd(cursor_)) 77 if (wav_audio_.AtEnd(cursor_))
79 cursor_ = 0; 78 cursor_ = 0;
80 return; 79 return;
81 } 80 }
82 81
83 cursor_ = 0; 82 cursor_ = 0;
84 started_ = true;
85 } 83 }
86 84
85 started_ = true;
87 if (g_audio_source_for_testing) 86 if (g_audio_source_for_testing)
88 stream_->Start(g_audio_source_for_testing); 87 stream_->Start(g_audio_source_for_testing);
89 else 88 else
90 stream_->Start(this); 89 stream_->Start(this);
91 90
92 if (g_observer_for_testing) 91 if (g_observer_for_testing)
93 g_observer_for_testing->OnPlay(); 92 g_observer_for_testing->OnPlay();
94 } 93 }
95 94
96 void Stop() { 95 void Stop() {
97 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 96 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
98 StopStream(); 97 StopStream();
99 if (stream_) 98 if (stream_)
100 stream_->Close(); 99 stream_->Close();
101 stream_ = NULL; 100 stream_ = NULL;
101 stop_closure_.Cancel();
102 } 102 }
103 103
104 private: 104 private:
105 // AudioOutputStream::AudioSourceCallback overrides: 105 // AudioOutputStream::AudioSourceCallback overrides:
106 // Following methods could be called from *ANY* thread. 106 // Following methods could be called from *ANY* thread.
107 virtual int OnMoreData(AudioBus* dest, 107 virtual int OnMoreData(AudioBus* dest,
108 AudioBuffersState /* state */) OVERRIDE { 108 AudioBuffersState /* state */) OVERRIDE {
109 base::AutoLock al(state_lock_); 109 base::AutoLock al(state_lock_);
110 size_t bytes_written = 0; 110 size_t bytes_written = 0;
111 111
(...skipping 12 matching lines...) Expand all
124 return dest->frames(); 124 return dest->frames();
125 } 125 }
126 126
127 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE { 127 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE {
128 LOG(ERROR) << "Error during system sound reproduction."; 128 LOG(ERROR) << "Error during system sound reproduction.";
129 } 129 }
130 130
131 void StopStream() { 131 void StopStream() {
132 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 132 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
133 133
134 base::AutoLock al(state_lock_);
135
136 if (stream_ && started_) { 134 if (stream_ && started_) {
135 // Do not hold the |state_lock_| while stopping the output stream.
137 stream_->Stop(); 136 stream_->Stop();
138 if (g_observer_for_testing) 137 if (g_observer_for_testing)
139 g_observer_for_testing->OnStop(cursor_); 138 g_observer_for_testing->OnStop(cursor_);
140 } 139 }
140
141 started_ = false; 141 started_ = false;
142 } 142 }
143 143
144 // Must only be accessed on the AudioManager::GetTaskRunner() thread.
145 bool started_;
144 AudioOutputStream* stream_; 146 AudioOutputStream* stream_;
145 147
146 const WavAudioHandler wav_audio_; 148 // All variables below must be accessed under |state_lock_| when |started_|.
147
148 base::Lock state_lock_; 149 base::Lock state_lock_;
149 size_t cursor_; 150 size_t cursor_;
150 bool started_;
151 bool delayed_stop_posted_; 151 bool delayed_stop_posted_;
152 const WavAudioHandler wav_audio_;
152 base::CancelableClosure stop_closure_; 153 base::CancelableClosure stop_closure_;
153 154
154 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); 155 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
155 }; 156 };
156 157
157 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) 158 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data)
158 : wav_audio_(wav_data), 159 : wav_audio_(wav_data),
159 initialized_(false) { 160 initialized_(false) {
160 AudioManager* manager = AudioManager::Get(); 161 AudioManager* manager = AudioManager::Get();
161 if (!manager) { 162 if (!manager) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 g_observer_for_testing = observer; 210 g_observer_for_testing = observer;
210 } 211 }
211 212
212 // static 213 // static
213 void AudioStreamHandler::SetAudioSourceForTesting( 214 void AudioStreamHandler::SetAudioSourceForTesting(
214 AudioOutputStream::AudioSourceCallback* source) { 215 AudioOutputStream::AudioSourceCallback* source) {
215 g_audio_source_for_testing = source; 216 g_audio_source_for_testing = source;
216 } 217 }
217 218
218 } // namespace media 219 } // namespace media
OLDNEW
« no previous file with comments | « base/debug/tsan_suppressions.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698