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

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

Issue 115693004: Added volume adjust sound behind the flag. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix. Created 6 years, 11 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 | « chromeos/chromeos_switches.cc ('k') | media/audio/sounds/audio_stream_handler_unittest.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 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/logging.h" 10 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h" 11 #include "base/single_thread_task_runner.h"
12 #include "base/synchronization/lock.h"
13 #include "base/time/time.h"
11 #include "media/audio/audio_manager.h" 14 #include "media/audio/audio_manager.h"
12 #include "media/audio/audio_manager_base.h" 15 #include "media/audio/audio_manager_base.h"
13 #include "media/base/channel_layout.h" 16 #include "media/base/channel_layout.h"
14 17
15 namespace media { 18 namespace media {
16 19
17 namespace { 20 namespace {
18 21
19 // Volume percent. 22 // Volume percent.
20 const double kOutputVolumePercent = 0.8; 23 const double kOutputVolumePercent = 0.8;
21 24
22 // The number of frames each OnMoreData() call will request. 25 // The number of frames each OnMoreData() call will request.
23 const int kDefaultFrameCount = 1024; 26 const int kDefaultFrameCount = 1024;
24 27
28 // Keep alive timeout for audio stream.
29 const int kKeepAliveMs = 1500;
30
25 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; 31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL;
26 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; 32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL;
27 33
28 } // namespace 34 } // namespace
29 35
30 class AudioStreamHandler::AudioStreamContainer 36 class AudioStreamHandler::AudioStreamContainer
31 : public AudioOutputStream::AudioSourceCallback { 37 : public AudioOutputStream::AudioSourceCallback {
32 public: 38 public:
33 AudioStreamContainer(const WavAudioHandler& wav_audio, 39 AudioStreamContainer(const WavAudioHandler& wav_audio)
34 const AudioParameters& params)
35 : stream_(NULL), 40 : stream_(NULL),
36 wav_audio_(wav_audio), 41 wav_audio_(wav_audio),
37 params_(params), 42 cursor_(0),
38 cursor_(0) { 43 started_(false),
44 delayed_stop_posted_(false) {
39 } 45 }
40 46
41 virtual ~AudioStreamContainer() { 47 virtual ~AudioStreamContainer() {
42 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 48 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
43 } 49 }
44 50
45 void Play() { 51 void Play() {
46 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 52 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
47 53
48 if (!stream_) { 54 if (!stream_) {
49 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params_, 55 const AudioParameters& p = wav_audio_.params();
50 std::string(), 56 const AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
51 std::string()); 57 p.channel_layout(),
58 p.sample_rate(),
59 p.bits_per_sample(),
60 kDefaultFrameCount);
61 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(
62 params, std::string(), std::string());
52 if (!stream_ || !stream_->Open()) { 63 if (!stream_ || !stream_->Open()) {
53 LOG(ERROR) << "Failed to open an output stream."; 64 LOG(ERROR) << "Failed to open an output stream.";
54 return; 65 return;
55 } 66 }
56 stream_->SetVolume(kOutputVolumePercent); 67 stream_->SetVolume(kOutputVolumePercent);
57 } else {
58 // TODO (ygorshenin@): implement smart stream rewind.
59 stream_->Stop();
60 } 68 }
61 69
62 cursor_ = 0; 70 {
71 base::AutoLock al(state_lock_);
72
73 delayed_stop_posted_ = false;
74 stop_closure_.Reset(base::Bind(
75 &AudioStreamContainer::StopStream, base::Unretained(this)));
76
77 if (started_) {
DaleCurtis 2014/01/13 18:12:31 This will drop the the playback request if playbac
ygorshenin1 2014/01/13 18:30:51 Done.
78 if (wav_audio_.AtEnd(cursor_))
79 cursor_ = 0;
80 return;
81 }
82
83 cursor_ = 0;
84 started_ = true;
85 }
86
63 if (g_audio_source_for_testing) 87 if (g_audio_source_for_testing)
64 stream_->Start(g_audio_source_for_testing); 88 stream_->Start(g_audio_source_for_testing);
65 else 89 else
66 stream_->Start(this); 90 stream_->Start(this);
67 91
68 if (g_observer_for_testing) 92 if (g_observer_for_testing)
69 g_observer_for_testing->OnPlay(); 93 g_observer_for_testing->OnPlay();
70 } 94 }
71 95
72 void Stop() { 96 void Stop() {
73 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 97 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
74 if (!stream_) 98 StopStream();
75 return; 99 if (stream_)
76 stream_->Stop(); 100 stream_->Close();
77 stream_->Close();
78 stream_ = NULL; 101 stream_ = NULL;
79
80 if (g_observer_for_testing)
81 g_observer_for_testing->OnStop(cursor_);
82 } 102 }
83 103
84 private: 104 private:
85 // AudioOutputStream::AudioSourceCallback overrides: 105 // AudioOutputStream::AudioSourceCallback overrides:
86 // Following methods could be called from *ANY* thread. 106 // Following methods could be called from *ANY* thread.
87 virtual int OnMoreData(AudioBus* dest, 107 virtual int OnMoreData(AudioBus* dest,
88 AudioBuffersState /* state */) OVERRIDE { 108 AudioBuffersState /* state */) OVERRIDE {
109 base::AutoLock al(state_lock_);
89 size_t bytes_written = 0; 110 size_t bytes_written = 0;
111
90 if (wav_audio_.AtEnd(cursor_) || 112 if (wav_audio_.AtEnd(cursor_) ||
91 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { 113 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) {
92 AudioManager::Get()->GetTaskRunner()->PostTask( 114 if (delayed_stop_posted_)
115 return 0;
116 delayed_stop_posted_ = true;
117 AudioManager::Get()->GetTaskRunner()->PostDelayedTask(
93 FROM_HERE, 118 FROM_HERE,
94 base::Bind(&AudioStreamContainer::Stop, base::Unretained(this))); 119 stop_closure_.callback(),
120 base::TimeDelta::FromMilliseconds(kKeepAliveMs));
95 return 0; 121 return 0;
96 } 122 }
97 cursor_ += bytes_written; 123 cursor_ += bytes_written;
98
99 return dest->frames(); 124 return dest->frames();
100 } 125 }
101 126
102 virtual int OnMoreIOData(AudioBus* /* source */, 127 virtual int OnMoreIOData(AudioBus* /* source */,
103 AudioBus* dest, 128 AudioBus* dest,
104 AudioBuffersState state) OVERRIDE { 129 AudioBuffersState state) OVERRIDE {
105 return OnMoreData(dest, state); 130 return OnMoreData(dest, state);
106 } 131 }
107 132
108 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE { 133 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE {
109 LOG(ERROR) << "Error during system sound reproduction."; 134 LOG(ERROR) << "Error during system sound reproduction.";
110 } 135 }
111 136
137 void StopStream() {
138 base::AutoLock al(state_lock_);
DaleCurtis 2014/01/13 18:12:31 Add a DCHECK(AudioManager::Get()->GetTaskRunner()-
ygorshenin1 2014/01/13 18:30:51 Done.
139
140 if (stream_ && started_) {
141 stream_->Stop();
142 if (g_observer_for_testing)
143 g_observer_for_testing->OnStop(cursor_);
144 }
145 started_ = false;
146 }
147
112 AudioOutputStream* stream_; 148 AudioOutputStream* stream_;
113 149
114 const WavAudioHandler wav_audio_; 150 const WavAudioHandler wav_audio_;
115 const AudioParameters params_;
116 151
152 base::Lock state_lock_;
117 size_t cursor_; 153 size_t cursor_;
154 bool started_;
155 bool delayed_stop_posted_;
156 base::CancelableClosure stop_closure_;
118 157
119 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); 158 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
120 }; 159 };
121 160
122 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) 161 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data)
123 : wav_audio_(wav_data), 162 : wav_audio_(wav_data),
124 initialized_(false) { 163 initialized_(false) {
125 AudioManager* manager = AudioManager::Get(); 164 AudioManager* manager = AudioManager::Get();
126 if (!manager) { 165 if (!manager) {
127 LOG(ERROR) << "Can't get access to audio manager."; 166 LOG(ERROR) << "Can't get access to audio manager.";
128 return; 167 return;
129 } 168 }
130 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, 169 if (!wav_audio_.params().IsValid()) {
131 GuessChannelLayout(wav_audio_.num_channels()),
132 wav_audio_.sample_rate(),
133 wav_audio_.bits_per_sample(),
134 kDefaultFrameCount);
135 if (!params.IsValid()) {
136 LOG(ERROR) << "Audio params are invalid."; 170 LOG(ERROR) << "Audio params are invalid.";
137 return; 171 return;
138 } 172 }
139 stream_.reset(new AudioStreamContainer(wav_audio_, params)); 173 stream_.reset(new AudioStreamContainer(wav_audio_));
140 initialized_ = true; 174 initialized_ = true;
141 } 175 }
142 176
143 AudioStreamHandler::~AudioStreamHandler() { 177 AudioStreamHandler::~AudioStreamHandler() {
144 DCHECK(CalledOnValidThread()); 178 DCHECK(CalledOnValidThread());
145 AudioManager::Get()->GetTaskRunner()->PostTask( 179 AudioManager::Get()->GetTaskRunner()->PostTask(
146 FROM_HERE, 180 FROM_HERE,
147 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 181 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
148 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, 182 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE,
149 stream_.release()); 183 stream_.release());
150 } 184 }
151 185
152 bool AudioStreamHandler::IsInitialized() const { 186 bool AudioStreamHandler::IsInitialized() const {
153 DCHECK(CalledOnValidThread()); 187 DCHECK(CalledOnValidThread());
154 return initialized_; 188 return initialized_;
155 } 189 }
156 190
157 bool AudioStreamHandler::Play() { 191 bool AudioStreamHandler::Play() {
158 DCHECK(CalledOnValidThread()); 192 DCHECK(CalledOnValidThread());
159 193
(...skipping 19 matching lines...) Expand all
179 g_observer_for_testing = observer; 213 g_observer_for_testing = observer;
180 } 214 }
181 215
182 // static 216 // static
183 void AudioStreamHandler::SetAudioSourceForTesting( 217 void AudioStreamHandler::SetAudioSourceForTesting(
184 AudioOutputStream::AudioSourceCallback* source) { 218 AudioOutputStream::AudioSourceCallback* source) {
185 g_audio_source_for_testing = source; 219 g_audio_source_for_testing = source;
186 } 220 }
187 221
188 } // namespace media 222 } // namespace media
OLDNEW
« no previous file with comments | « chromeos/chromeos_switches.cc ('k') | media/audio/sounds/audio_stream_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698