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

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: review comments Created 6 years, 4 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.0f;
24
25 } // namespace
26
27 namespace copresence {
28
29 // Public methods.
30
31 AudioPlayer::AudioPlayer()
32 : stream_(NULL),
33 frame_index_(0),
34 is_playing_(false),
35 output_stream_for_testing_(NULL) {
36 media::AudioManager::Get()->GetTaskRunner()->PostTask(
37 FROM_HERE,
38 base::Bind(&AudioPlayer::InitializeOnAudioThread,
39 base::Unretained(this)));
40 }
41
42 AudioPlayer::~AudioPlayer() {
43 }
44
45 AudioPlayer::AudioPlayer(media::AudioOutputStream* output_stream_for_testing)
46 : stream_(NULL),
47 frame_index_(0),
48 is_playing_(false),
49 output_stream_for_testing_(output_stream_for_testing) {
50 media::AudioManager::Get()->GetTaskRunner()->PostTask(
51 FROM_HERE,
52 base::Bind(&AudioPlayer::InitializeOnAudioThread,
53 base::Unretained(this)));
54 }
55
56 void AudioPlayer::Play(
57 const scoped_refptr<media::AudioBusRefCounted>& samples) {
58 media::AudioManager::Get()->GetTaskRunner()->PostTask(
59 FROM_HERE,
60 base::Bind(
61 &AudioPlayer::PlayOnAudioThread, base::Unretained(this), samples));
62 }
63
64 void AudioPlayer::Stop() {
65 media::AudioManager::Get()->GetTaskRunner()->PostTask(
66 FROM_HERE,
67 base::Bind(&AudioPlayer::StopOnAudioThread, base::Unretained(this)));
68 }
69
70 void AudioPlayer::Finalize() {
71 media::AudioManager::Get()->GetTaskRunner()->PostTask(
72 FROM_HERE,
73 base::Bind(&AudioPlayer::FinalizeOnAudioThread, base::Unretained(this)));
74 }
75
76 // Private methods.
77
78 void AudioPlayer::InitializeOnAudioThread() {
79 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
80 stream_ = output_stream_for_testing_
81 ? output_stream_for_testing_
82 : media::AudioManager::Get()->MakeAudioOutputStreamProxy(
83 media::AudioParameters(
84 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
85 media::CHANNEL_LAYOUT_MONO,
86 kDefaultSampleRate,
87 kDefaultBitsPerSample,
88 kDefaultFrameCount),
89 std::string());
90
91 if (!stream_ || !stream_->Open()) {
92 LOG(ERROR) << "Failed to open an output stream.";
93 if (stream_) {
94 stream_->Close();
95 stream_ = NULL;
96 }
97 return;
98 }
99 stream_->SetVolume(kOutputVolumePercent);
100 }
101
102 void AudioPlayer::PlayOnAudioThread(
103 const scoped_refptr<media::AudioBusRefCounted>& samples) {
104 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
105 if (!stream_)
106 return;
107
108 {
109 base::AutoLock al(state_lock_);
110
111 samples_ = samples;
112 frame_index_ = 0;
113
114 if (is_playing_)
115 return;
116 }
117
118 DVLOG(2) << "Playing Audio.";
119 is_playing_ = true;
120 stream_->Start(this);
121 }
122
123 void AudioPlayer::StopOnAudioThread() {
124 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
125 if (!stream_)
126 return;
127
128 stream_->Stop();
129 is_playing_ = false;
130 }
131
132 void AudioPlayer::StopAndCloseOnAudioThread() {
133 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
134 if (!stream_)
135 return;
136
137 if (is_playing_)
138 stream_->Stop();
139 stream_->Close();
140 stream_ = NULL;
141
142 is_playing_ = false;
143 }
144
145 void AudioPlayer::FinalizeOnAudioThread() {
146 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
147 StopAndCloseOnAudioThread();
148 delete this;
149 }
150
151 int AudioPlayer::OnMoreData(media::AudioBus* dest,
152 media::AudioBuffersState /* state */) {
153 base::AutoLock al(state_lock_);
154 DCHECK(is_playing_);
155
156 // Continuously play our samples till explicitly told to stop.
157 const int leftover_frames = samples_->frames() - frame_index_;
158 const int frames_to_copy = std::min(dest->frames(), leftover_frames);
159
160 samples_->CopyPartialFramesTo(frame_index_, frames_to_copy, 0, dest);
161 frame_index_ += frames_to_copy;
162
163 // If we didn't fill the destination audio bus, wrap around and fill the rest.
164 if (leftover_frames <= dest->frames()) {
165 samples_->CopyPartialFramesTo(
166 0, dest->frames() - frames_to_copy, frames_to_copy, dest);
167 frame_index_ = dest->frames() - frames_to_copy;
168 }
169
170 return dest->frames();
171 }
172
173 void AudioPlayer::OnError(media::AudioOutputStream* /* stream */) {
174 LOG(ERROR) << "Error during system sound reproduction.";
175 media::AudioManager::Get()->GetTaskRunner()->PostTask(
176 FROM_HERE,
177 base::Bind(&AudioPlayer::StopAndCloseOnAudioThread,
178 base::Unretained(this)));
179 }
180
181 void AudioPlayer::FlushAudioLoopForTesting() {
182 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread())
183 return;
184
185 // Queue task on the audio thread, when it is executed, that means we've
186 // successfully executed all the tasks before us.
187 base::RunLoop rl;
188 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply(
189 FROM_HERE,
190 base::Bind(base::IgnoreResult(&AudioPlayer::FlushAudioLoopForTesting),
191 base::Unretained(this)),
192 rl.QuitClosure());
193 rl.Run();
194 }
195
196 } // namespace copresence
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698