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

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

Issue 637223011: Redesign the copresence audio handlers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git/+/master
Patch Set: Created 6 years, 2 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
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_manager_impl.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 "base/strings/string_util.h"
15 #include "components/copresence/mediums/audio/audio_player_impl.h"
16 #include "components/copresence/mediums/audio/audio_recorder_impl.h"
17 #include "components/copresence/public/copresence_constants.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "media/audio/audio_manager.h"
20 #include "media/audio/audio_manager_base.h"
21 #include "media/base/audio_bus.h"
22
23 namespace copresence {
24
25 namespace {
26
27 // UrlSafe is defined as:
28 // '/' represented by a '_' and '+' represented by a '-'
29 // TODO(rkc): Move this processing to the whispernet wrapper.
30 std::string FromUrlSafe(std::string token) {
31 base::ReplaceChars(token, "-", "+", &token);
32 base::ReplaceChars(token, "_", "/", &token);
33 return token;
34 }
35
36 const int kSampleExpiryTimeMs = 60 * 60 * 1000; // 60 minutes.
37 const int kMaxSamples = 10000;
38
39 } // namespace
40
41 // Public methods.
42
43 AudioManagerImpl::AudioManagerImpl() : recorder_(NULL) {
44 // TODO(rkc): Move all of these into initializer lists once it is allowed.
45 playing_[AUDIBLE] = false;
46 playing_[INAUDIBLE] = false;
47 recording_[AUDIBLE] = false;
48 recording_[INAUDIBLE] = false;
49
50 player_[AUDIBLE] = NULL;
51 player_[INAUDIBLE] = NULL;
52
53 samples_cache_.resize(2);
54 samples_cache_[AUDIBLE] = new SamplesMap(
55 base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs), kMaxSamples);
56 samples_cache_[INAUDIBLE] = new SamplesMap(
57 base::TimeDelta::FromMilliseconds(kSampleExpiryTimeMs), kMaxSamples);
58 }
59
60 void AudioManagerImpl::Initialize(const DecodeSamplesCallback& decode_cb,
61 const EncodeTokenCallback& encode_cb) {
62 decode_cb_ = decode_cb;
63 encode_cb_ = encode_cb;
64
65 if (!player_[AUDIBLE])
66 player_[AUDIBLE] = new AudioPlayerImpl();
67 player_[AUDIBLE]->Initialize();
68
69 if (!player_[INAUDIBLE])
70 player_[INAUDIBLE] = new AudioPlayerImpl();
71 player_[INAUDIBLE]->Initialize();
72
73 decode_cancelable_cb_.Reset(base::Bind(
74 &AudioManagerImpl::DecodeSamplesConnector, base::Unretained(this)));
75 if (!recorder_)
76 recorder_ = new AudioRecorderImpl();
77 recorder_->Initialize(decode_cancelable_cb_.callback());
78 }
79
80 AudioManagerImpl::~AudioManagerImpl() {
81 if (player_[AUDIBLE])
82 player_[AUDIBLE]->Finalize();
83 if (player_[INAUDIBLE])
84 player_[INAUDIBLE]->Finalize();
85 if (recorder_)
86 recorder_->Finalize();
87 }
88
89 void AudioManagerImpl::StartPlaying(AudioType type) {
90 DCHECK(type == AUDIBLE || type == INAUDIBLE);
91 playing_[type] = true;
92 // If we don't have our token encoded yet, this check will be false, for now.
93 // Once our token is encoded, OnTokenEncoded will call UpdateToken, which
94 // will call this code again (if we're still supposed to be playing).
95 if (samples_cache_[type]->HasKey(token_[type]) &&
96 !player_[type]->IsPlaying()) {
97 DCHECK_GT(token_[type].size(), 0u);
Daniel Erat 2014/10/22 16:34:35 nit: DCHECK(!token_[type].empty());
rkc 2014/10/22 18:21:47 Done.
98 player_[type]->Play(samples_cache_[type]->GetValue(token_[type]));
99 }
100 }
101
102 void AudioManagerImpl::StopPlaying(AudioType type) {
103 DCHECK(type == AUDIBLE || type == INAUDIBLE);
104 playing_[type] = false;
105 if (player_[type]->IsPlaying())
106 player_[type]->Stop();
107 }
108
109 void AudioManagerImpl::StartRecording(AudioType type) {
110 DCHECK(type == AUDIBLE || type == INAUDIBLE);
111 recording_[type] = true;
112 if (!recorder_->IsRecording())
113 recorder_->Record();
114 }
115
116 void AudioManagerImpl::StopRecording(AudioType type) {
117 DCHECK(type == AUDIBLE || type == INAUDIBLE);
118 recording_[type] = false;
119 if (recorder_->IsRecording())
120 recorder_->Stop();
121 }
122
123 void AudioManagerImpl::SetToken(AudioType type,
124 const std::string& url_unsafe_token) {
125 DCHECK(type == AUDIBLE || type == INAUDIBLE);
126 std::string token = FromUrlSafe(url_unsafe_token);
127 if (!samples_cache_[type]->HasKey(token)) {
128 // We're destructed by the destruction chain of
129 // RpcHandler->DirectiveHandler->AudioDirectiveHandler. The RpcHandler
130 // unsets any callbacks that were set on the Whispernet client before it
131 // destructs, unsetting this callback too - making unretained safe to use.
132 encode_cb_.Run(
133 token,
134 type,
135 base::Bind(&AudioManagerImpl::OnTokenEncoded, base::Unretained(this)));
136 } else {
137 UpdateToken(type, token);
138 }
139 }
140
141 const std::string& AudioManagerImpl::GetToken(AudioType type) {
142 return token_[type];
143 }
144
145 bool AudioManagerImpl::IsRecording(AudioType type) {
146 return recording_[type];
147 }
148
149 bool AudioManagerImpl::IsPlaying(AudioType type) {
150 return playing_[type];
151 }
152
153 // Private methods.
154
155 void AudioManagerImpl::OnTokenEncoded(
156 const std::string& token,
157 AudioType type,
158 const scoped_refptr<media::AudioBusRefCounted>& samples) {
159 samples_cache_[type]->Add(token, samples);
160 UpdateToken(type, token);
161 }
162
163 void AudioManagerImpl::UpdateToken(AudioType type, const std::string& token) {
164 DCHECK(type == AUDIBLE || type == INAUDIBLE);
165 if (token_[type] == token)
166 return;
167
168 // Update token.
169 token_[type] = token;
170
171 // If we are supposed to be playing this token type at this moment, switch
172 // out playback with the new samples.
173 if (playing_[type]) {
174 if (player_[type]->IsPlaying())
175 player_[type]->Stop();
176 StartPlaying(type);
177 }
178 }
179
180 void AudioManagerImpl::DecodeSamplesConnector(const std::string& samples) {
181 AudioType decode_type = UNKNOWN;
182
183 if (recording_[AUDIBLE] && recording_[INAUDIBLE])
184 decode_type = BOTH;
185 else if (recording_[AUDIBLE])
186 decode_type = AUDIBLE;
187 else if (recording_[INAUDIBLE])
188 decode_type = INAUDIBLE;
189
190 decode_cb_.Run(decode_type, samples);
191 }
192
193 } // namespace copresence
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698