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

Side by Side Diff: components/copresence/mediums/audio/audio_player.cc

Issue 419073002: Add the copresence DirectiveHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/copresence/mediums/audio/audio_player.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/logging.h"
13 #include "base/run_loop.h"
14 #include "components/copresence/common/copresence_constants.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "media/audio/audio_manager.h"
17 #include "media/audio/audio_parameters.h"
18 #include "media/base/audio_bus.h"
19
20 namespace {
21
22 const int kDefaultFrameCount = 1024;
23 const double kOutputVolumePercent = 1.0;
24 }
xiyuan 2014/07/25 21:02:10 nit: insert an empty line before and add " // nam
rkc 2014/07/28 21:02:02 Done.
25
26 namespace copresence {
27
28 // Public methods.
29
30 AudioPlayer::AudioPlayer()
31 : stream_(NULL),
32 frame_index_(0),
33 is_playing_(false),
34 output_stream_for_testing_(NULL) {
35 media::AudioManager::Get()->GetTaskRunner()->PostTask(
36 FROM_HERE,
37 base::Bind(&AudioPlayer::InitializeOnAudioThread,
38 base::Unretained(this)));
39 }
40
41 AudioPlayer::~AudioPlayer() {
Daniel Erat 2014/07/28 21:18:18 please use the same order in the .cc file as in th
rkc 2014/07/29 00:33:35 Done.
42 }
43
44 AudioPlayer::AudioPlayer(media::AudioOutputStream* output_stream_for_testing)
45 : stream_(NULL),
46 frame_index_(0),
47 is_playing_(false),
48 output_stream_for_testing_(output_stream_for_testing) {
49 media::AudioManager::Get()->GetTaskRunner()->PostTask(
50 FROM_HERE,
51 base::Bind(&AudioPlayer::InitializeOnAudioThread,
Daniel Erat 2014/07/28 21:18:17 how about adding a separate Init() method that doe
rkc 2014/07/29 00:33:35 Done.
52 base::Unretained(this)));
53 }
54
55 void AudioPlayer::Play(
56 const scoped_refptr<media::AudioBusRefCounted>& samples) {
57 media::AudioManager::Get()->GetTaskRunner()->PostTask(
58 FROM_HERE,
59 base::Bind(
60 &AudioPlayer::PlayOnAudioThread, base::Unretained(this), samples));
61 }
62
63 void AudioPlayer::Stop() {
64 media::AudioManager::Get()->GetTaskRunner()->PostTask(
65 FROM_HERE,
66 base::Bind(&AudioPlayer::StopOnAudioThread, base::Unretained(this)));
67 }
68
69 void AudioPlayer::Finalize() {
70 media::AudioManager::Get()->GetTaskRunner()->PostTask(
71 FROM_HERE,
72 base::Bind(&AudioPlayer::FinalizeOnAudioThread, base::Unretained(this)));
73 }
74
75 // Private methods.
76
77 void AudioPlayer::InitializeOnAudioThread() {
78 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
79 stream_ = output_stream_for_testing_
80 ? output_stream_for_testing_
81 : media::AudioManager::Get()->MakeAudioOutputStreamProxy(
82 media::AudioParameters(
83 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
84 media::CHANNEL_LAYOUT_MONO,
85 kDefaultSampleRate,
86 kDefaultBitsPerSample,
87 kDefaultFrameCount),
88 std::string());
89
90 if (!stream_ || !stream_->Open()) {
91 LOG(ERROR) << "Failed to open an output stream.";
92 if (stream_) {
93 stream_->Close();
94 stream_ = NULL;
95 }
96 return;
97 }
98 stream_->SetVolume(kOutputVolumePercent);
99 }
100
101 void AudioPlayer::PlayOnAudioThread(
102 const scoped_refptr<media::AudioBusRefCounted>& samples) {
103 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
104 if (!stream_)
105 return;
106
107 {
108 base::AutoLock al(state_lock_);
109
110 samples_ = samples;
111 frame_index_ = 0;
112
113 if (is_playing_)
114 return;
115 }
116
117 DVLOG(2) << "Playing Audio.";
118 is_playing_ = true;
Daniel Erat 2014/07/28 21:18:17 the header has a comment saying that all members a
rkc 2014/07/29 00:33:35 All the methods that must run on certain threads h
119 stream_->Start(this);
120 }
121
122 void AudioPlayer::StopOnAudioThread() {
123 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
124 if (!stream_)
125 return;
126
127 stream_->Stop();
128 is_playing_ = false;
129 }
130
131 void AudioPlayer::StopAndCloseOnAudioThread() {
132 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
133 if (!stream_)
134 return;
135
136 if (is_playing_)
137 stream_->Stop();
138 stream_->Close();
139 stream_ = NULL;
140
141 is_playing_ = false;
142 }
143
144 void AudioPlayer::FinalizeOnAudioThread() {
145 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
146 StopAndCloseOnAudioThread();
147 delete this;
148 }
149
150 int AudioPlayer::OnMoreData(media::AudioBus* dest,
151 media::AudioBuffersState /* state */) {
152 base::AutoLock al(state_lock_);
153 DCHECK(is_playing_);
154
155 // Continuously play our samples till explicitly told to stop.
156 const int leftover_frames = samples_->frames() - frame_index_;
157 const int frames_to_copy = std::min(dest->frames(), leftover_frames);
158
159 samples_->CopyPartialFramesTo(frame_index_, frames_to_copy, 0, dest);
160 frame_index_ += frames_to_copy;
161
162 // If we didn't fill the destination audio bus, wrap around and fill the rest.
163 if (leftover_frames <= dest->frames()) {
164 samples_->CopyPartialFramesTo(
165 0, dest->frames() - frames_to_copy, frames_to_copy, dest);
166 frame_index_ = dest->frames() - frames_to_copy;
167 }
168
169 return dest->frames();
170 }
171
172 void AudioPlayer::OnError(media::AudioOutputStream* /* stream */) {
173 LOG(ERROR) << "Error during system sound reproduction.";
174 media::AudioManager::Get()->GetTaskRunner()->PostTask(
175 FROM_HERE,
176 base::Bind(&AudioPlayer::StopAndCloseOnAudioThread,
177 base::Unretained(this)));
178 }
179
180 void AudioPlayer::FlushAudioLoop() {
181 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread())
182 return;
183
184 // All this does is flush the tasks on the audio thread.
185 base::RunLoop rl;
DaleCurtis 2014/07/25 20:41:29 This isn't allowed in production code. See base/r
rkc 2014/07/28 21:02:02 Done.
186 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply(
187 FROM_HERE,
188 base::Bind(base::IgnoreResult(&AudioPlayer::IsPlaying),
189 base::Unretained(this)),
190 rl.QuitClosure());
191 rl.Run();
192 }
193
194 bool AudioPlayer::IsPlaying() {
195 FlushAudioLoop();
196 return is_playing_;
197 }
198
199 } // namespace copresence
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698