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

Side by Side Diff: chromecast/media/audio/cast_audio_output_stream.cc

Issue 1913973003: [chromecast] Simplify CastAudioOutputStream. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cleanup Created 4 years, 7 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "chromecast/media/audio/cast_audio_output_stream.h" 5 #include "chromecast/media/audio/cast_audio_output_stream.h"
6 6
7 #include <stdint.h>
8
9 #include "base/bind.h" 7 #include "base/bind.h"
10 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
11 #include "base/macros.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread_checker.h"
14 #include "chromecast/base/metrics/cast_metrics_helper.h" 9 #include "chromecast/base/metrics/cast_metrics_helper.h"
15 #include "chromecast/base/task_runner_impl.h" 10 #include "chromecast/base/task_runner_impl.h"
16 #include "chromecast/media/audio/cast_audio_manager.h" 11 #include "chromecast/media/audio/cast_audio_manager.h"
17 #include "chromecast/media/base/media_message_loop.h"
18 #include "chromecast/media/cma/base/decoder_buffer_adapter.h" 12 #include "chromecast/media/cma/base/decoder_buffer_adapter.h"
19 #include "chromecast/public/media/decoder_config.h" 13 #include "chromecast/public/media/decoder_config.h"
20 #include "chromecast/public/media/decrypt_context.h"
21 #include "chromecast/public/media/media_pipeline_backend.h" 14 #include "chromecast/public/media/media_pipeline_backend.h"
22 #include "chromecast/public/media/media_pipeline_device_params.h" 15 #include "chromecast/public/media/media_pipeline_device_params.h"
23 #include "media/base/bind_to_current_loop.h"
24 #include "media/base/decoder_buffer.h" 16 #include "media/base/decoder_buffer.h"
25 17
18 namespace {
19 const int kMaxQueuedDataMs = 1000;
20 } // namespace
21
26 namespace chromecast { 22 namespace chromecast {
27 namespace media { 23 namespace media {
28 namespace {
29 24
30 const int kMaxQueuedDataMs = 1000; 25 // Backend represents a MediaPipelineBackend adapter.
31 26 // It can be created and destroyed on any thread,
32 MediaPipelineBackend::AudioDecoder* InitializeBackend( 27 // but all other member functions must be called on a single thread.
33 const ::media::AudioParameters& audio_params,
34 MediaPipelineBackend* backend,
35 MediaPipelineBackend::Decoder::Delegate* delegate) {
36 DCHECK(backend);
37 DCHECK(delegate);
38
39 MediaPipelineBackend::AudioDecoder* decoder = backend->CreateAudioDecoder();
40 if (!decoder)
41 return nullptr;
42 decoder->SetDelegate(delegate);
43
44 AudioConfig audio_config;
45 audio_config.codec = kCodecPCM;
46 audio_config.sample_format = kSampleFormatS16;
47 audio_config.bytes_per_channel = audio_params.bits_per_sample() / 8;
48 audio_config.channel_number = audio_params.channels();
49 audio_config.samples_per_second = audio_params.sample_rate();
50
51 if (!decoder->SetConfig(audio_config))
52 return nullptr;
53
54 if (!backend->Initialize())
55 return nullptr;
56
57 return decoder;
58 }
59
60 } // namespace
61
62 // Backend represents a MediaPipelineBackend adapter that runs on cast
63 // media thread (media::MediaMessageLoop::GetTaskRunner).
64 // It can be created and destroyed on any thread, but all other member functions
65 // must be called on a single thread.
66 class CastAudioOutputStream::Backend 28 class CastAudioOutputStream::Backend
67 : public MediaPipelineBackend::Decoder::Delegate { 29 : public MediaPipelineBackend::Decoder::Delegate {
68 public: 30 public:
69 using PushBufferCompletionCallback = base::Callback<void(bool)>; 31 using PushBufferCompletionCallback = base::Callback<void(bool)>;
70 32
71 Backend(const ::media::AudioParameters& audio_params) 33 Backend() : decoder_(nullptr), first_start_(true), error_(false) {
72 : audio_params_(audio_params),
73 decoder_(nullptr),
74 first_start_(true),
75 error_(false),
76 weak_factory_(this) {
77 thread_checker_.DetachFromThread(); 34 thread_checker_.DetachFromThread();
78 } 35 }
79 ~Backend() override {} 36 ~Backend() override {}
80 37
81 void Open(CastAudioManager* audio_manager, 38 bool Open(const ::media::AudioParameters& audio_params,
82 bool* success, 39 CastAudioManager* audio_manager) {
83 base::WaitableEvent* completion_event) {
84 DCHECK(thread_checker_.CalledOnValidThread()); 40 DCHECK(thread_checker_.CalledOnValidThread());
41 DCHECK(audio_manager);
85 DCHECK(backend_ == nullptr); 42 DCHECK(backend_ == nullptr);
86 DCHECK(audio_manager);
87 DCHECK(success);
88 DCHECK(completion_event);
89 43
90 backend_task_runner_.reset(new TaskRunnerImpl()); 44 backend_task_runner_.reset(new TaskRunnerImpl());
91 MediaPipelineDeviceParams device_params( 45 MediaPipelineDeviceParams device_params(
92 MediaPipelineDeviceParams::kModeIgnorePts, 46 MediaPipelineDeviceParams::kModeIgnorePts,
93 MediaPipelineDeviceParams::kAudioStreamSoundEffects, 47 MediaPipelineDeviceParams::kAudioStreamSoundEffects,
94 backend_task_runner_.get()); 48 backend_task_runner_.get());
95 backend_ = audio_manager->CreateMediaPipelineBackend(device_params); 49 backend_ = audio_manager->CreateMediaPipelineBackend(device_params);
96 if (backend_) 50 if (!backend_)
97 decoder_ = InitializeBackend(audio_params_, backend_.get(), this); 51 return false;
98 *success = decoder_ != nullptr; 52
99 completion_event->Signal(); 53 decoder_ = backend_->CreateAudioDecoder();
54 if (!decoder_)
55 return false;
56 decoder_->SetDelegate(this);
57
58 AudioConfig audio_config;
59 audio_config.codec = kCodecPCM;
60 audio_config.sample_format = kSampleFormatS16;
61 audio_config.bytes_per_channel = audio_params.bits_per_sample() / 8;
62 audio_config.channel_number = audio_params.channels();
63 audio_config.samples_per_second = audio_params.sample_rate();
64 if (!decoder_->SetConfig(audio_config))
65 return false;
66
67 return backend_->Initialize();
100 } 68 }
101 69
102 void Close() { 70 void Close() {
103 DCHECK(thread_checker_.CalledOnValidThread()); 71 DCHECK(thread_checker_.CalledOnValidThread());
104 72
105 if (backend_ && !first_start_) // Only stop the backend if it was started. 73 if (backend_ && !first_start_) // Only stop the backend if it was started.
106 backend_->Stop(); 74 backend_->Stop();
107 backend_.reset(); 75 backend_.reset();
108 backend_task_runner_.reset(); 76 backend_task_runner_.reset();
109 } 77 }
(...skipping 22 matching lines...) Expand all
132 DCHECK(thread_checker_.CalledOnValidThread()); 100 DCHECK(thread_checker_.CalledOnValidThread());
133 DCHECK(decoder_); 101 DCHECK(decoder_);
134 DCHECK(!completion_cb.is_null()); 102 DCHECK(!completion_cb.is_null());
135 DCHECK(completion_cb_.is_null()); 103 DCHECK(completion_cb_.is_null());
136 if (error_) { 104 if (error_) {
137 completion_cb.Run(false); 105 completion_cb.Run(false);
138 return; 106 return;
139 } 107 }
140 108
141 backend_buffer_ = decoder_buffer; 109 backend_buffer_ = decoder_buffer;
142
143 completion_cb_ = completion_cb; 110 completion_cb_ = completion_cb;
144 BufferStatus status = decoder_->PushBuffer(backend_buffer_.get()); 111 BufferStatus status = decoder_->PushBuffer(backend_buffer_.get());
145 if (status != MediaPipelineBackend::kBufferPending) 112 if (status != MediaPipelineBackend::kBufferPending)
146 OnPushBufferComplete(status); 113 OnPushBufferComplete(status);
147 } 114 }
148 115
149 void SetVolume(double volume) { 116 void SetVolume(double volume) {
150 DCHECK(thread_checker_.CalledOnValidThread()); 117 DCHECK(thread_checker_.CalledOnValidThread());
151 DCHECK(decoder_); 118 DCHECK(decoder_);
152 decoder_->SetVolume(volume); 119 decoder_->SetVolume(volume);
153 } 120 }
154 121
122 private:
155 // MediaPipelineBackend::Decoder::Delegate implementation 123 // MediaPipelineBackend::Decoder::Delegate implementation
156 void OnPushBufferComplete(BufferStatus status) override { 124 void OnPushBufferComplete(BufferStatus status) override {
157 DCHECK(thread_checker_.CalledOnValidThread()); 125 DCHECK(thread_checker_.CalledOnValidThread());
158 DCHECK_NE(status, MediaPipelineBackend::kBufferPending); 126 DCHECK_NE(status, MediaPipelineBackend::kBufferPending);
159 127
160 // |completion_cb_| may be null if OnDecoderError was called. 128 // |completion_cb_| may be null if OnDecoderError was called.
161 if (completion_cb_.is_null()) 129 if (completion_cb_.is_null())
162 return; 130 return;
163 131
164 base::ResetAndReturn(&completion_cb_) 132 base::ResetAndReturn(&completion_cb_)
165 .Run(status == MediaPipelineBackend::kBufferSuccess); 133 .Run(status == MediaPipelineBackend::kBufferSuccess);
166 } 134 }
167 135
168 void OnEndOfStream() override {} 136 void OnEndOfStream() override {}
169 137
170 void OnDecoderError() override { 138 void OnDecoderError() override {
139 DCHECK(thread_checker_.CalledOnValidThread());
171 error_ = true; 140 error_ = true;
172 if (!completion_cb_.is_null()) 141 if (!completion_cb_.is_null())
173 OnPushBufferComplete(MediaPipelineBackend::kBufferFailed); 142 OnPushBufferComplete(MediaPipelineBackend::kBufferFailed);
174 } 143 }
175 144
176 void OnKeyStatusChanged(const std::string& key_id, 145 void OnKeyStatusChanged(const std::string& key_id,
177 CastKeyStatus key_status, 146 CastKeyStatus key_status,
178 uint32_t system_code) override {} 147 uint32_t system_code) override {}
179 148
180 void OnVideoResolutionChanged(const Size& size) override {} 149 void OnVideoResolutionChanged(const Size& size) override {}
181 150
182 base::WeakPtr<CastAudioOutputStream::Backend> GetWeakPtr() {
183 return weak_factory_.GetWeakPtr();
184 }
185
186 private:
187 const ::media::AudioParameters audio_params_;
188 std::unique_ptr<MediaPipelineBackend> backend_; 151 std::unique_ptr<MediaPipelineBackend> backend_;
189 std::unique_ptr<TaskRunnerImpl> backend_task_runner_; 152 std::unique_ptr<TaskRunnerImpl> backend_task_runner_;
190 MediaPipelineBackend::AudioDecoder* decoder_; 153 MediaPipelineBackend::AudioDecoder* decoder_;
191 PushBufferCompletionCallback completion_cb_; 154 PushBufferCompletionCallback completion_cb_;
192 bool first_start_; 155 bool first_start_;
193 bool error_; 156 bool error_;
194 scoped_refptr<DecoderBufferBase> backend_buffer_; 157 scoped_refptr<DecoderBufferBase> backend_buffer_;
195 base::ThreadChecker thread_checker_; 158 base::ThreadChecker thread_checker_;
196 base::WeakPtrFactory<CastAudioOutputStream::Backend> weak_factory_;
197 159
198 DISALLOW_COPY_AND_ASSIGN(Backend); 160 DISALLOW_COPY_AND_ASSIGN(Backend);
199 }; 161 };
200 162
201 // CastAudioOutputStream runs on audio thread (AudioManager::GetTaskRunner). 163 // CastAudioOutputStream runs on audio thread (AudioManager::GetTaskRunner).
202 CastAudioOutputStream::CastAudioOutputStream( 164 CastAudioOutputStream::CastAudioOutputStream(
203 const ::media::AudioParameters& audio_params, 165 const ::media::AudioParameters& audio_params,
204 CastAudioManager* audio_manager) 166 CastAudioManager* audio_manager)
205 : audio_params_(audio_params), 167 : audio_params_(audio_params),
206 audio_manager_(audio_manager), 168 audio_manager_(audio_manager),
207 volume_(1.0), 169 volume_(1.0),
208 source_callback_(nullptr), 170 source_callback_(nullptr),
209 backend_(new Backend(audio_params)), 171 backend_(new Backend()),
210 buffer_duration_(audio_params.GetBufferDuration()), 172 buffer_duration_(audio_params.GetBufferDuration()),
211 push_in_progress_(false), 173 push_in_progress_(false),
212 audio_task_runner_(audio_manager->GetTaskRunner()),
213 backend_task_runner_(media::MediaMessageLoop::GetTaskRunner()),
214 weak_factory_(this) { 174 weak_factory_(this) {
215 VLOG(1) << "CastAudioOutputStream " << this << " created with " 175 VLOG(1) << "CastAudioOutputStream " << this << " created with "
216 << audio_params_.AsHumanReadableString(); 176 << audio_params_.AsHumanReadableString();
217 } 177 }
218 178
219 CastAudioOutputStream::~CastAudioOutputStream() { 179 CastAudioOutputStream::~CastAudioOutputStream() {
220 backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
221 } 180 }
222 181
223 bool CastAudioOutputStream::Open() { 182 bool CastAudioOutputStream::Open() {
224 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 183 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
225 184
226 ::media::AudioParameters::Format format = audio_params_.format(); 185 ::media::AudioParameters::Format format = audio_params_.format();
227 DCHECK((format == ::media::AudioParameters::AUDIO_PCM_LINEAR) || 186 DCHECK((format == ::media::AudioParameters::AUDIO_PCM_LINEAR) ||
228 (format == ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY)); 187 (format == ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY));
229 188
230 ::media::ChannelLayout channel_layout = audio_params_.channel_layout(); 189 ::media::ChannelLayout channel_layout = audio_params_.channel_layout();
231 if ((channel_layout != ::media::CHANNEL_LAYOUT_MONO) && 190 if ((channel_layout != ::media::CHANNEL_LAYOUT_MONO) &&
232 (channel_layout != ::media::CHANNEL_LAYOUT_STEREO)) { 191 (channel_layout != ::media::CHANNEL_LAYOUT_STEREO)) {
233 LOG(WARNING) << "Unsupported channel layout: " << channel_layout; 192 LOG(WARNING) << "Unsupported channel layout: " << channel_layout;
234 return false; 193 return false;
235 } 194 }
236 DCHECK_GE(audio_params_.channels(), 1); 195 DCHECK_GE(audio_params_.channels(), 1);
237 DCHECK_LE(audio_params_.channels(), 2); 196 DCHECK_LE(audio_params_.channels(), 2);
238 197
239 { 198 if (!backend_->Open(audio_params_, audio_manager_)) {
240 // Wait until the backend has initialized so that the outcome can be 199 LOG(WARNING) << "Failed to create media pipeline backend.";
241 // communicated to the client. 200 return false;
242 bool success = false; 201 }
243 base::WaitableEvent completion_event(false, false);
244 backend_task_runner_->PostTask(
245 FROM_HERE, base::Bind(&Backend::Open, backend_->GetWeakPtr(),
246 audio_manager_, &success, &completion_event));
247 completion_event.Wait();
248 202
249 if (!success) {
250 LOG(WARNING) << "Failed to create media pipeline backend.";
251 return false;
252 }
253 }
254 audio_bus_ = ::media::AudioBus::Create(audio_params_); 203 audio_bus_ = ::media::AudioBus::Create(audio_params_);
255 decoder_buffer_ = new DecoderBufferAdapter( 204 decoder_buffer_ = new DecoderBufferAdapter(
256 new ::media::DecoderBuffer(audio_params_.GetBytesPerBuffer())); 205 new ::media::DecoderBuffer(audio_params_.GetBytesPerBuffer()));
257 206
258 VLOG(1) << __FUNCTION__ << " : " << this; 207 VLOG(1) << __FUNCTION__ << " : " << this;
259 return true; 208 return true;
260 } 209 }
261 210
262 void CastAudioOutputStream::Close() { 211 void CastAudioOutputStream::Close() {
263 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 212 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
213 VLOG(1) << __FUNCTION__ << " : " << this;
264 214
265 VLOG(1) << __FUNCTION__ << " : " << this; 215 backend_->Close();
266 backend_task_runner_->PostTaskAndReply( 216 // Signal to the manager that we're closed and can be removed.
267 FROM_HERE, base::Bind(&Backend::Close, backend_->GetWeakPtr()), 217 // This should be the last call in the function as it deletes "this".
268 base::Bind(&CastAudioOutputStream::OnClosed, base::Unretained(this))); 218 audio_manager_->ReleaseOutputStream(this);
269 } 219 }
270 220
271 void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) { 221 void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) {
272 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 222 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
273 DCHECK(source_callback); 223 DCHECK(source_callback);
274 224
275 source_callback_ = source_callback; 225 source_callback_ = source_callback;
276 backend_task_runner_->PostTask( 226 backend_->Start();
277 FROM_HERE, base::Bind(&Backend::Start, backend_->GetWeakPtr()));
278 227
279 next_push_time_ = base::TimeTicks::Now(); 228 next_push_time_ = base::TimeTicks::Now();
280 if (!push_in_progress_) { 229 if (!push_in_progress_) {
281 audio_task_runner_->PostTask(FROM_HERE, 230 audio_manager_->GetTaskRunner()->PostTask(
282 base::Bind(&CastAudioOutputStream::PushBuffer, 231 FROM_HERE, base::Bind(&CastAudioOutputStream::PushBuffer,
283 weak_factory_.GetWeakPtr())); 232 weak_factory_.GetWeakPtr()));
284 push_in_progress_ = true; 233 push_in_progress_ = true;
285 } 234 }
286 235
287 metrics::CastMetricsHelper::GetInstance()->LogTimeToFirstAudio(); 236 metrics::CastMetricsHelper::GetInstance()->LogTimeToFirstAudio();
288 } 237 }
289 238
290 void CastAudioOutputStream::Stop() { 239 void CastAudioOutputStream::Stop() {
291 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 240 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
292 241
293 source_callback_ = nullptr; 242 source_callback_ = nullptr;
294 backend_task_runner_->PostTask( 243 backend_->Stop();
295 FROM_HERE, base::Bind(&Backend::Stop, backend_->GetWeakPtr()));
296 } 244 }
297 245
298 void CastAudioOutputStream::SetVolume(double volume) { 246 void CastAudioOutputStream::SetVolume(double volume) {
299 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 247 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
300 248
301 volume_ = volume; 249 volume_ = volume;
302 backend_task_runner_->PostTask( 250 backend_->SetVolume(volume);
303 FROM_HERE, base::Bind(&Backend::SetVolume,
304 backend_->GetWeakPtr(), volume));
305 } 251 }
306 252
307 void CastAudioOutputStream::GetVolume(double* volume) { 253 void CastAudioOutputStream::GetVolume(double* volume) {
308 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 254 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
309 255
310 *volume = volume_; 256 *volume = volume_;
311 } 257 }
312 258
313 void CastAudioOutputStream::OnClosed() {
314 DCHECK(audio_task_runner_->BelongsToCurrentThread());
315
316 VLOG(1) << __FUNCTION__ << " : " << this;
317 // Signal to the manager that we're closed and can be removed.
318 // This should be the last call in the function as it deletes "this".
319 audio_manager_->ReleaseOutputStream(this);
320 }
321
322 void CastAudioOutputStream::PushBuffer() { 259 void CastAudioOutputStream::PushBuffer() {
323 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 260 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
324 DCHECK(push_in_progress_); 261 DCHECK(push_in_progress_);
325 262
326 if (!source_callback_) { 263 if (!source_callback_) {
327 push_in_progress_ = false; 264 push_in_progress_ = false;
328 return; 265 return;
329 } 266 }
330 267
331 const base::TimeTicks now = base::TimeTicks::Now(); 268 const base::TimeTicks now = base::TimeTicks::Now();
332 base::TimeDelta queue_delay = 269 base::TimeDelta queue_delay =
333 std::max(base::TimeDelta(), next_push_time_ - now); 270 std::max(base::TimeDelta(), next_push_time_ - now);
334 uint32_t bytes_delay = queue_delay.InMicroseconds() * 271 uint32_t bytes_delay = queue_delay.InMicroseconds() *
335 audio_params_.GetBytesPerSecond() / 1000000; 272 audio_params_.GetBytesPerSecond() / 1000000;
336 int frame_count = 273 int frame_count =
337 source_callback_->OnMoreData(audio_bus_.get(), bytes_delay, 0); 274 source_callback_->OnMoreData(audio_bus_.get(), bytes_delay, 0);
338 VLOG(3) << "frames_filled=" << frame_count << " with latency=" << bytes_delay; 275 VLOG(3) << "frames_filled=" << frame_count << " with latency=" << bytes_delay;
339 276
340 DCHECK_EQ(frame_count, audio_bus_->frames()); 277 DCHECK_EQ(frame_count, audio_bus_->frames());
341 DCHECK_EQ(static_cast<int>(decoder_buffer_->data_size()), 278 DCHECK_EQ(static_cast<int>(decoder_buffer_->data_size()),
342 frame_count * audio_params_.GetBytesPerFrame()); 279 frame_count * audio_params_.GetBytesPerFrame());
343 audio_bus_->ToInterleaved(frame_count, audio_params_.bits_per_sample() / 8, 280 audio_bus_->ToInterleaved(frame_count, audio_params_.bits_per_sample() / 8,
344 decoder_buffer_->writable_data()); 281 decoder_buffer_->writable_data());
345 282
346 auto completion_cb = ::media::BindToCurrentLoop( 283 auto completion_cb = base::Bind(&CastAudioOutputStream::OnPushBufferComplete,
347 base::Bind(&CastAudioOutputStream::OnPushBufferComplete, 284 weak_factory_.GetWeakPtr());
348 weak_factory_.GetWeakPtr())); 285 backend_->PushBuffer(decoder_buffer_, completion_cb);
349 backend_task_runner_->PostTask(FROM_HERE,
350 base::Bind(&Backend::PushBuffer,
351 backend_->GetWeakPtr(),
352 decoder_buffer_,
353 completion_cb));
354 } 286 }
355 287
356 void CastAudioOutputStream::OnPushBufferComplete(bool success) { 288 void CastAudioOutputStream::OnPushBufferComplete(bool success) {
357 DCHECK(audio_task_runner_->BelongsToCurrentThread()); 289 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
358 DCHECK(push_in_progress_); 290 DCHECK(push_in_progress_);
359 291
360 push_in_progress_ = false; 292 push_in_progress_ = false;
361 293
362 if (!source_callback_) 294 if (!source_callback_)
363 return; 295 return;
364 if (!success) { 296 if (!success) {
365 source_callback_->OnError(this); 297 source_callback_->OnError(this);
366 return; 298 return;
367 } 299 }
368 300
369 // Schedule next push buffer. We don't want to allow more than 301 // Schedule next push buffer. We don't want to allow more than
370 // kMaxQueuedDataMs of queued audio. 302 // kMaxQueuedDataMs of queued audio.
371 const base::TimeTicks now = base::TimeTicks::Now(); 303 const base::TimeTicks now = base::TimeTicks::Now();
372 next_push_time_ = std::max(now, next_push_time_ + buffer_duration_); 304 next_push_time_ = std::max(now, next_push_time_ + buffer_duration_);
373 305
374 base::TimeDelta delay = (next_push_time_ - now) - 306 base::TimeDelta delay = (next_push_time_ - now) -
375 base::TimeDelta::FromMilliseconds(kMaxQueuedDataMs); 307 base::TimeDelta::FromMilliseconds(kMaxQueuedDataMs);
376 delay = std::max(delay, base::TimeDelta()); 308 delay = std::max(delay, base::TimeDelta());
377 309
378 audio_task_runner_->PostDelayedTask( 310 audio_manager_->GetTaskRunner()->PostDelayedTask(
379 FROM_HERE, 311 FROM_HERE, base::Bind(&CastAudioOutputStream::PushBuffer,
380 base::Bind(&CastAudioOutputStream::PushBuffer, 312 weak_factory_.GetWeakPtr()),
381 weak_factory_.GetWeakPtr()),
382 delay); 313 delay);
383 push_in_progress_ = true; 314 push_in_progress_ = true;
384 } 315 }
385 316
386 } // namespace media 317 } // namespace media
387 } // namespace chromecast 318 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/media/audio/cast_audio_output_stream.h ('k') | chromecast/media/audio/cast_audio_output_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698