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

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: 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
« no previous file with comments | « media/audio/audio_manager_base.h ('k') | media/audio/mac/audio_manager_mac.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 = 15;
tommi (sloooow) - chröme 2012/03/13 11:06:48 16?
no longer working on chromium 2012/03/13 14:08:59 Done.
20 20
21 // Default maximum number of input streams that can be open simultaneously
22 // for all platforms.
23 static const int kDefaultMaxInputStreams = 10;
tommi (sloooow) - chröme 2012/03/13 11:06:48 16?
no longer working on chromium 2012/03/13 14:08:59 Done.
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(params);
74 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { 89 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
75 num_output_streams_++; 90 ++num_output_streams_;
tommi (sloooow) - chröme 2012/03/13 10:50:28 I think I made a comment on this in an earlier rev
no longer working on chromium 2012/03/13 14:08:59 Done.
76 stream = MakeLinearOutputStream(params); 91 stream = MakeLinearOutputStream(params);
77 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { 92 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) {
78 num_output_streams_++; 93 ++num_output_streams_;
79 stream = MakeLowLatencyOutputStream(params); 94 stream = MakeLowLatencyOutputStream(params);
80 } 95 }
81 96
82 return stream; 97 return stream;
83 } 98 }
84 99
85 AudioInputStream* AudioManagerBase::MakeAudioInputStream( 100 AudioInputStream* AudioManagerBase::MakeAudioInputStream(
86 const AudioParameters& params, const std::string& device_id) { 101 const AudioParameters& params, const std::string& device_id) {
87 if (!params.IsValid() || (params.channels > kMaxInputChannels) || 102 if (!params.IsValid() || (params.channels > kMaxInputChannels) ||
88 device_id.empty()) { 103 device_id.empty()) {
89 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id; 104 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id;
90 return NULL; 105 return NULL;
91 } 106 }
92 107
108 if (num_input_streams_ >= max_num_input_streams_) {
tommi (sloooow) - chröme 2012/03/13 10:50:28 this change seems unrelated to the bug. Do on a se
tommi (sloooow) - chröme 2012/03/13 11:06:48 as discussed offline, this is OK with me.
no longer working on chromium 2012/03/13 14:08:59 Done.
109 DLOG(ERROR) << "Number of opened input audio streams "
110 << num_input_streams_
111 << " exceed the max allowed number " << max_num_input_streams_;
112 return NULL;
113 }
114
93 AudioInputStream* stream = NULL; 115 AudioInputStream* stream = NULL;
94 if (params.format == AudioParameters::AUDIO_MOCK) { 116 if (params.format == AudioParameters::AUDIO_MOCK) {
95 stream = FakeAudioInputStream::MakeFakeStream(params); 117 stream = FakeAudioInputStream::MakeFakeStream(params);
96 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { 118 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) {
119 ++num_input_streams_;
tommi (sloooow) - chröme 2012/03/13 10:50:28 same comment as for the output stream.
no longer working on chromium 2012/03/13 14:08:59 Done.
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) {
122 ++num_input_streams_;
99 stream = MakeLowLatencyInputStream(params, device_id); 123 stream = MakeLowLatencyInputStream(params, device_id);
100 } 124 }
101 125
102 return stream; 126 return stream;
103 } 127 }
104 128
105 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( 129 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
106 const AudioParameters& params) { 130 const AudioParameters& params) {
107 DCHECK(GetMessageLoop()->BelongsToCurrentThread()); 131 DCHECK(GetMessageLoop()->BelongsToCurrentThread());
108 132
(...skipping 21 matching lines...) Expand all
130 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. 154 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
131 // For example, pass the ownership to AudioManager so it can delete the 155 // For example, pass the ownership to AudioManager so it can delete the
132 // streams. 156 // streams.
133 num_output_streams_--; 157 num_output_streams_--;
134 delete stream; 158 delete stream;
135 } 159 }
136 160
137 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { 161 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
138 DCHECK(stream); 162 DCHECK(stream);
139 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. 163 // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
164 num_input_streams_--;
140 delete stream; 165 delete stream;
141 } 166 }
142 167
143 void AudioManagerBase::IncreaseActiveInputStreamCount() { 168 void AudioManagerBase::IncreaseActiveInputStreamCount() {
144 base::AtomicRefCountInc(&num_active_input_streams_); 169 base::AtomicRefCountInc(&num_active_input_streams_);
145 } 170 }
146 171
147 void AudioManagerBase::DecreaseActiveInputStreamCount() { 172 void AudioManagerBase::DecreaseActiveInputStreamCount() {
148 DCHECK(IsRecordingInProcess()); 173 DCHECK(IsRecordingInProcess());
149 base::AtomicRefCountDec(&num_active_input_streams_); 174 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 217 // 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. 218 // well as the message loop of the audio thread that will soon go away.
194 // So, better crash now than later. 219 // So, better crash now than later.
195 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; 220 CHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive";
196 dispatcher = NULL; 221 dispatcher = NULL;
197 } 222 }
198 } 223 }
199 224
200 output_dispatchers_.clear(); 225 output_dispatchers_.clear();
201 } 226 }
OLDNEW
« no previous file with comments | « media/audio/audio_manager_base.h ('k') | media/audio/mac/audio_manager_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698