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

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

Issue 9692038: stopping the audio thread before destroying the AudioManager<Platform> (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased and fixed the speech recognition unittest Created 8 years, 9 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 (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/audio/audio_manager_base.h" 5 #include "media/audio/audio_manager_base.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop_proxy.h" 8 #include "base/message_loop_proxy.h"
9 #include "base/threading/thread.h" 9 #include "base/threading/thread.h"
10 #include "media/audio/audio_output_dispatcher.h" 10 #include "media/audio/audio_output_dispatcher.h"
11 #include "media/audio/audio_output_proxy.h" 11 #include "media/audio/audio_output_proxy.h"
12 #include "media/audio/fake_audio_input_stream.h" 12 #include "media/audio/fake_audio_input_stream.h"
13 #include "media/audio/fake_audio_output_stream.h" 13 #include "media/audio/fake_audio_output_stream.h"
14 14
15 static const int kStreamCloseDelaySeconds = 5; 15 static const int kStreamCloseDelaySeconds = 5;
16 16
17 // Default maximum number of output streams that can be open simultaneously 17 // Default maximum number of output streams that can be open simultaneously
18 // for all platforms. 18 // for all platforms.
19 static const int kDefaultMaxOutputStreams = 15; 19 static const int kDefaultMaxOutputStreams = 16;
20
21 // Default maximum number of input streams that can be open simultaneously
22 // for all platforms.
23 static const int kDefaultMaxInputStreams = 16;
20 24
21 static const int kMaxInputChannels = 2; 25 static const int kMaxInputChannels = 2;
22 26
23 const char AudioManagerBase::kDefaultDeviceName[] = "Default"; 27 const char AudioManagerBase::kDefaultDeviceName[] = "Default";
24 const char AudioManagerBase::kDefaultDeviceId[] = "default"; 28 const char AudioManagerBase::kDefaultDeviceId[] = "default";
25 29
26 AudioManagerBase::AudioManagerBase() 30 AudioManagerBase::AudioManagerBase()
27 : num_active_input_streams_(0), 31 : num_active_input_streams_(0),
28 max_num_output_streams_(kDefaultMaxOutputStreams), 32 max_num_output_streams_(kDefaultMaxOutputStreams),
29 num_output_streams_(0) { 33 max_num_input_streams_(kDefaultMaxInputStreams),
34 num_output_streams_(0),
35 num_input_streams_(0) {
30 } 36 }
31 37
32 AudioManagerBase::~AudioManagerBase() { 38 AudioManagerBase::~AudioManagerBase() {
33 Shutdown(); 39 // The platform specific AudioManager implementation must have already
40 // stopped the audio thread. Otherwise, we may destroy audio streams before
41 // stopping the thread, resulting an unexpected behavior.
42 // This way we make sure activities of the audio streams are all stopped
43 // before we destroy them.
44 CHECK(!audio_thread_.get());
34 // All the output streams should have been deleted. 45 // All the output streams should have been deleted.
35 DCHECK_EQ(0, num_output_streams_); 46 DCHECK_EQ(0, num_output_streams_);
47 // All the input streams should have been deleted.
48 DCHECK_EQ(0, num_input_streams_);
36 } 49 }
37 50
38 void AudioManagerBase::Init() { 51 void AudioManagerBase::Init() {
39 base::AutoLock lock(audio_thread_lock_); 52 base::AutoLock lock(audio_thread_lock_);
40 DCHECK(!audio_thread_.get()); 53 DCHECK(!audio_thread_.get());
41 audio_thread_.reset(new base::Thread("AudioThread")); 54 audio_thread_.reset(new base::Thread("AudioThread"));
42 CHECK(audio_thread_->Start()); 55 CHECK(audio_thread_->Start());
43 } 56 }
44 57
45 string16 AudioManagerBase::GetAudioInputDeviceModel() { 58 string16 AudioManagerBase::GetAudioInputDeviceModel() {
(...skipping 10 matching lines...) Expand all
56 if (!params.IsValid()) { 69 if (!params.IsValid()) {
57 DLOG(ERROR) << "Audio parameters are invalid"; 70 DLOG(ERROR) << "Audio parameters are invalid";
58 return NULL; 71 return NULL;
59 } 72 }
60 73
61 // Limit the number of audio streams opened. This is to prevent using 74 // Limit the number of audio streams opened. This is to prevent using
62 // excessive resources for a large number of audio streams. More 75 // excessive resources for a large number of audio streams. More
63 // importantly it prevents instability on certain systems. 76 // importantly it prevents instability on certain systems.
64 // See bug: http://crbug.com/30242. 77 // See bug: http://crbug.com/30242.
65 if (num_output_streams_ >= max_num_output_streams_) { 78 if (num_output_streams_ >= max_num_output_streams_) {
66 DLOG(ERROR) << "Number of opened audio streams " << num_output_streams_ 79 DLOG(ERROR) << "Number of opened output audio streams "
67 << " exceed the max allowed number " << max_num_output_streams_; 80 << num_output_streams_
81 << " exceed the max allowed number "
82 << max_num_output_streams_;
68 return NULL; 83 return NULL;
69 } 84 }
70 85
71 AudioOutputStream* stream = NULL; 86 AudioOutputStream* stream = NULL;
72 if (params.format == AudioParameters::AUDIO_MOCK) { 87 if (params.format == AudioParameters::AUDIO_MOCK) {
73 stream = FakeAudioOutputStream::MakeFakeStream(params); 88 stream = FakeAudioOutputStream::MakeFakeStream(this, params);
74 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { 89 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
75 num_output_streams_++;
76 stream = MakeLinearOutputStream(params); 90 stream = MakeLinearOutputStream(params);
77 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { 91 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
78 num_output_streams_++;
79 stream = MakeLowLatencyOutputStream(params); 92 stream = MakeLowLatencyOutputStream(params);
80 } 93 }
81 94
95 if (stream)
96 ++num_output_streams_;
97
82 return stream; 98 return stream;
83 } 99 }
84 100
85 AudioInputStream* AudioManagerBase::MakeAudioInputStream( 101 AudioInputStream* AudioManagerBase::MakeAudioInputStream(
86 const AudioParameters& params, const std::string& device_id) { 102 const AudioParameters& params, const std::string& device_id) {
87 if (!params.IsValid() || (params.channels > kMaxInputChannels) || 103 if (!params.IsValid() || (params.channels > kMaxInputChannels) ||
88 device_id.empty()) { 104 device_id.empty()) {
89 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; 105 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id;
90 return NULL; 106 return NULL;
91 } 107 }
92 108
109 if (num_input_streams_ >= max_num_input_streams_) {
110 DLOG(ERROR) << "Number of opened input audio streams "
111 << num_input_streams_
112 << " exceed the max allowed number " << max_num_input_streams_;
113 return NULL;
114 }
115
93 AudioInputStream* stream = NULL; 116 AudioInputStream* stream = NULL;
94 if (params.format == AudioParameters::AUDIO_MOCK) { 117 if (params.format == AudioParameters::AUDIO_MOCK) {
95 stream = FakeAudioInputStream::MakeFakeStream(params); 118 stream = FakeAudioInputStream::MakeFakeStream(this, params);
96 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { 119 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
97 stream = MakeLinearInputStream(params, device_id); 120 stream = MakeLinearInputStream(params, device_id);
98 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { 121 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
99 stream = MakeLowLatencyInputStream(params, device_id); 122 stream = MakeLowLatencyInputStream(params, device_id);
100 } 123 }
101 124
125 if (stream)
126 ++num_input_streams_;
127
102 return stream; 128 return stream;
103 } 129 }
104 130
105 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( 131 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
106 const AudioParameters& params) { 132 const AudioParameters& params) {
107 DCHECK(GetMessageLoop()->BelongsToCurrentThread()); 133 DCHECK(GetMessageLoop()->BelongsToCurrentThread());
108 134
109 scoped_refptr<AudioOutputDispatcher>& dispatcher = 135 scoped_refptr<AudioOutputDispatcher>& dispatcher =
110 output_dispatchers_[params]; 136 output_dispatchers_[params];
111 if (!dispatcher) 137 if (!dispatcher)
(...skipping 18 matching lines...) Expand all
130 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. 156 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
131 // For example, pass the ownership to AudioManager so it can delete the 157 // For example, pass the ownership to AudioManager so it can delete the
132 // streams. 158 // streams.
133 num_output_streams_--; 159 num_output_streams_--;
134 delete stream; 160 delete stream;
135 } 161 }
136 162
137 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { 163 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
138 DCHECK(stream); 164 DCHECK(stream);
139 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. 165 // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
166 num_input_streams_--;
140 delete stream; 167 delete stream;
141 } 168 }
142 169
143 void AudioManagerBase::IncreaseActiveInputStreamCount() { 170 void AudioManagerBase::IncreaseActiveInputStreamCount() {
144 base::AtomicRefCountInc(&num_active_input_streams_); 171 base::AtomicRefCountInc(&num_active_input_streams_);
145 } 172 }
146 173
147 void AudioManagerBase::DecreaseActiveInputStreamCount() { 174 void AudioManagerBase::DecreaseActiveInputStreamCount() {
148 DCHECK(IsRecordingInProcess()); 175 DCHECK(IsRecordingInProcess());
149 base::AtomicRefCountDec(&num_active_input_streams_); 176 base::AtomicRefCountDec(&num_active_input_streams_);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 // both physical audio stream objects that belong to the dispatcher as 219 // both physical audio stream objects that belong to the dispatcher as
193 // well as the message loop of the audio thread that will soon go away. 220 // well as the message loop of the audio thread that will soon go away.
194 // So, better crash now than later. 221 // So, better crash now than later.
195 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; 222 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive";
196 dispatcher = NULL; 223 dispatcher = NULL;
197 } 224 }
198 } 225 }
199 226
200 output_dispatchers_.clear(); 227 output_dispatchers_.clear();
201 } 228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698