OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/renderer/pepper/pepper_platform_audio_output.h" | 5 #include "content/renderer/pepper/pepper_platform_audio_output.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
11 #include "base/threading/thread_task_runner_handle.h" | 11 #include "base/threading/thread_task_runner_handle.h" |
12 #include "base/time/time.h" | |
13 #include "base/timer/timer.h" | |
12 #include "build/build_config.h" | 14 #include "build/build_config.h" |
13 #include "content/child/child_process.h" | 15 #include "content/child/child_process.h" |
16 #include "content/common/content_constants_internal.h" | |
14 #include "content/common/media/audio_messages.h" | 17 #include "content/common/media/audio_messages.h" |
15 #include "content/renderer/media/audio_message_filter.h" | 18 #include "content/renderer/media/audio_message_filter.h" |
16 #include "content/renderer/pepper/audio_helper.h" | 19 #include "content/renderer/pepper/audio_helper.h" |
20 #include "content/renderer/pepper/pepper_audio_output_host.h" | |
21 #include "content/renderer/pepper/pepper_media_device_manager.h" | |
22 #include "content/renderer/render_frame_impl.h" | |
17 #include "content/renderer/render_thread_impl.h" | 23 #include "content/renderer/render_thread_impl.h" |
24 #include "media/audio/audio_device_description.h" | |
18 #include "ppapi/shared_impl/ppb_audio_config_shared.h" | 25 #include "ppapi/shared_impl/ppb_audio_config_shared.h" |
19 | 26 |
20 namespace content { | 27 namespace content { |
21 | 28 |
22 // static | 29 // static |
23 PepperPlatformAudioOutput* PepperPlatformAudioOutput::Create( | 30 PepperPlatformAudioOutput* PepperPlatformAudioOutput::Create( |
24 int sample_rate, | 31 int sample_rate, |
25 int frames_per_buffer, | 32 int frames_per_buffer, |
26 int source_render_frame_id, | 33 int source_render_frame_id, |
27 AudioHelper* client) { | 34 AudioHelper* client) { |
28 scoped_refptr<PepperPlatformAudioOutput> audio_output( | 35 scoped_refptr<PepperPlatformAudioOutput> audio_output( |
29 new PepperPlatformAudioOutput()); | 36 new PepperPlatformAudioOutput()); |
30 if (audio_output->Initialize(sample_rate, | 37 if (audio_output->Initialize(sample_rate, |
31 frames_per_buffer, | 38 frames_per_buffer, |
32 source_render_frame_id, | 39 source_render_frame_id, |
33 client)) { | 40 client)) { |
34 // Balanced by Release invoked in | 41 // Balanced by Release invoked in |
35 // PepperPlatformAudioOutput::ShutDownOnIOThread(). | 42 // PepperPlatformAudioOutput::ShutDownOnIOThread(). |
36 audio_output->AddRef(); | 43 audio_output->AddRef(); |
37 return audio_output.get(); | 44 return audio_output.get(); |
38 } | 45 } |
39 return NULL; | 46 return NULL; |
40 } | 47 } |
41 | 48 |
49 // static | |
50 PepperPlatformAudioOutput* PepperPlatformAudioOutput::Create( | |
51 int render_frame_id, | |
52 const std::string& device_id, | |
53 const GURL& document_url, | |
54 int sample_rate, | |
55 int frames_per_buffer, | |
56 PepperAudioOutputHost* client) { | |
57 scoped_refptr<PepperPlatformAudioOutput> audio_output( | |
58 new PepperPlatformAudioOutput(render_frame_id, device_id, document_url, | |
59 // Set authorization request timeout at 80% of renderer hung timeout, | |
60 // but no more than kMaxAuthorizationTimeout. | |
61 base::TimeDelta::FromMilliseconds( | |
62 std::min(kHungRendererDelayMs * 8 / 10, | |
63 kMaxAuthorizationTimeoutMs)))); | |
64 | |
65 if (audio_output->Initialize(sample_rate, | |
66 frames_per_buffer, | |
67 client)) { | |
68 // Balanced by Release invoked in | |
69 // PepperPlatformAudioOutput::ShutDownOnIOThread(). | |
70 audio_output->AddRef(); | |
71 return audio_output.get(); | |
72 } | |
73 return NULL; | |
74 } | |
75 | |
76 void PepperPlatformAudioOutput::RequestDeviceAuthorization() { | |
77 if (ipc_) { | |
78 io_task_runner_->PostTask( | |
79 FROM_HERE, | |
80 base::Bind( | |
81 &PepperPlatformAudioOutput::RequestDeviceAuthorizationOnIOThread, | |
82 this)); | |
83 } | |
84 } | |
85 | |
42 bool PepperPlatformAudioOutput::StartPlayback() { | 86 bool PepperPlatformAudioOutput::StartPlayback() { |
43 if (ipc_) { | 87 if (ipc_) { |
44 io_task_runner_->PostTask( | 88 io_task_runner_->PostTask( |
45 FROM_HERE, | 89 FROM_HERE, |
46 base::Bind(&PepperPlatformAudioOutput::StartPlaybackOnIOThread, this)); | 90 base::Bind(&PepperPlatformAudioOutput::StartPlaybackOnIOThread, this)); |
47 return true; | 91 return true; |
48 } | 92 } |
49 return false; | 93 return false; |
50 } | 94 } |
51 | 95 |
(...skipping 15 matching lines...) Expand all Loading... | |
67 this, volume)); | 111 this, volume)); |
68 return true; | 112 return true; |
69 } | 113 } |
70 return false; | 114 return false; |
71 } | 115 } |
72 | 116 |
73 void PepperPlatformAudioOutput::ShutDown() { | 117 void PepperPlatformAudioOutput::ShutDown() { |
74 // Called on the main thread to stop all audio callbacks. We must only change | 118 // Called on the main thread to stop all audio callbacks. We must only change |
75 // the client on the main thread, and the delegates from the I/O thread. | 119 // the client on the main thread, and the delegates from the I/O thread. |
76 client_ = NULL; | 120 client_ = NULL; |
121 host_client_ = NULL; | |
77 io_task_runner_->PostTask( | 122 io_task_runner_->PostTask( |
78 FROM_HERE, | 123 FROM_HERE, |
79 base::Bind(&PepperPlatformAudioOutput::ShutDownOnIOThread, this)); | 124 base::Bind(&PepperPlatformAudioOutput::ShutDownOnIOThread, this)); |
80 } | 125 } |
81 | 126 |
82 void PepperPlatformAudioOutput::OnError() {} | 127 void PepperPlatformAudioOutput::OnError() { |
128 DCHECK(io_task_runner_->BelongsToCurrentThread()); | |
129 | |
130 // Do nothing if the stream has been closed. | |
131 if (state_ < CREATING_STREAM) | |
132 return; | |
133 | |
134 DLOG(WARNING) << "PepperPlatformAudioOutput::OnError()"; | |
135 | |
136 main_task_runner_->PostTask(FROM_HERE, | |
137 base::Bind(&PepperPlatformAudioOutput::NotifyStreamCreationFailed, this)); | |
bbudge
2017/03/23 18:05:44
This looks like a change to the behavior of PPB_Au
Xing
2017/03/29 21:14:32
New implementation has been moved to pepper_platfo
| |
138 } | |
83 | 139 |
84 void PepperPlatformAudioOutput::OnDeviceAuthorized( | 140 void PepperPlatformAudioOutput::OnDeviceAuthorized( |
85 media::OutputDeviceStatus device_status, | 141 media::OutputDeviceStatus device_status, |
86 const media::AudioParameters& output_params, | 142 const media::AudioParameters& output_params, |
87 const std::string& matched_device_id) { | 143 const std::string& matched_device_id) { |
88 NOTREACHED(); | 144 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
145 | |
146 auth_timeout_action_.reset(); | |
147 | |
148 // Do nothing if late authorization is received after timeout. | |
149 if (state_ == IPC_CLOSED) | |
150 return; | |
151 | |
152 LOG_IF(WARNING, device_status == media::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT) | |
153 << "Output device authorization timed out"; | |
154 | |
155 DCHECK_EQ(state_, AUTHORIZING); | |
156 | |
157 // It may happen that a second authorization is received as a result to a | |
158 // call to StartPlayback() after Shutdown(). If the status for the second | |
159 // authorization differs from the first, it will not be reflected in | |
160 // |device_status_| to avoid a race. | |
161 // This scenario is unlikely. If it occurs, the new value will be | |
162 // different from OUTPUT_DEVICE_STATUS_OK, so the PepperPlatformAudioOutput | |
163 // will enter the IPC_CLOSED state anyway, which is the safe thing to do. | |
164 // This is preferable to holding a lock. | |
165 if (!did_receive_auth_.IsSignaled()) | |
166 device_status_ = device_status; | |
167 | |
168 if (device_status == media::OUTPUT_DEVICE_STATUS_OK) { | |
169 state_ = AUTHORIZED; | |
170 if (!did_receive_auth_.IsSignaled()) { | |
171 output_params_ = output_params; | |
172 | |
173 // It's possible to not have a matched device obtained via session id. It | |
174 // means matching output device through |session_id_| failed and the | |
175 // default device is used. | |
176 DCHECK(media::AudioDeviceDescription::UseSessionIdToSelectDevice( | |
177 session_id_, | |
178 device_id_) || | |
179 matched_device_id_.empty()); | |
180 matched_device_id_ = matched_device_id; | |
181 | |
182 DVLOG(1) << "PepperPlatformAudioOutput authorized, session_id: " | |
183 << session_id_ << ", device_id: " << device_id_ | |
184 << ", matched_device_id: " << matched_device_id_; | |
185 | |
186 did_receive_auth_.Signal(); | |
187 } | |
188 if (start_on_authorized_) | |
189 CreateStreamOnIOThread(params_); | |
190 } | |
191 else { | |
192 // Closing IPC forces a Signal(), so no clients are locked waiting | |
193 // indefinitely after this method returns. | |
194 ipc_->CloseStream(); | |
195 OnIPCClosed(); | |
196 main_task_runner_->PostTask(FROM_HERE, | |
197 base::Bind(&PepperPlatformAudioOutput::NotifyStreamCreationFailed, | |
198 this)); | |
199 } | |
89 } | 200 } |
90 | 201 |
91 void PepperPlatformAudioOutput::OnStreamCreated( | 202 void PepperPlatformAudioOutput::OnStreamCreated( |
92 base::SharedMemoryHandle handle, | 203 base::SharedMemoryHandle handle, |
93 base::SyncSocket::Handle socket_handle, | 204 base::SyncSocket::Handle socket_handle, |
94 int length) { | 205 int length) { |
95 #if defined(OS_WIN) | 206 #if defined(OS_WIN) |
96 DCHECK(handle.IsValid()); | 207 DCHECK(handle.IsValid()); |
97 DCHECK(socket_handle); | 208 DCHECK(socket_handle); |
98 #else | 209 #else |
99 DCHECK(base::SharedMemory::IsHandleValid(handle)); | 210 DCHECK(base::SharedMemory::IsHandleValid(handle)); |
100 DCHECK_NE(-1, socket_handle); | 211 DCHECK_NE(-1, socket_handle); |
101 #endif | 212 #endif |
102 DCHECK(length); | 213 DCHECK(length); |
103 | 214 |
104 if (base::ThreadTaskRunnerHandle::Get().get() == main_task_runner_.get()) { | 215 if (base::ThreadTaskRunnerHandle::Get().get() == main_task_runner_.get()) { |
105 // Must dereference the client only on the main thread. Shutdown may have | 216 // Must dereference the client only on the main thread. Shutdown may have |
106 // occurred while the request was in-flight, so we need to NULL check. | 217 // occurred while the request was in-flight, so we need to NULL check. |
107 if (client_) | 218 if (client_) |
108 client_->StreamCreated(handle, length, socket_handle); | 219 client_->StreamCreated(handle, length, socket_handle); |
220 else if (host_client_) | |
221 host_client_->StreamCreated(handle, length, socket_handle); | |
109 } else { | 222 } else { |
110 main_task_runner_->PostTask( | 223 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
111 FROM_HERE, base::Bind(&PepperPlatformAudioOutput::OnStreamCreated, this, | 224 if (state_ != CREATING_STREAM) |
112 handle, socket_handle, length)); | 225 return; |
226 | |
227 state_ = PAUSED; | |
228 if (play_on_start_) | |
229 StartPlaybackOnIOThread(); | |
230 | |
231 main_task_runner_->PostTask(FROM_HERE, | |
232 base::Bind(&PepperPlatformAudioOutput::OnStreamCreated, this, | |
233 handle, socket_handle, length)); | |
113 } | 234 } |
114 } | 235 } |
115 | 236 |
116 void PepperPlatformAudioOutput::OnIPCClosed() { ipc_.reset(); } | 237 void PepperPlatformAudioOutput::OnIPCClosed() { |
238 DCHECK(io_task_runner_->BelongsToCurrentThread()); | |
239 state_ = IPC_CLOSED; | |
240 ipc_.reset(); | |
241 | |
242 // Signal to unblock any blocked threads waiting for parameters | |
243 did_receive_auth_.Signal(); | |
244 } | |
117 | 245 |
118 PepperPlatformAudioOutput::~PepperPlatformAudioOutput() { | 246 PepperPlatformAudioOutput::~PepperPlatformAudioOutput() { |
119 // Make sure we have been shut down. Warning: this will usually happen on | 247 // Make sure we have been shut down. Warning: this will usually happen on |
120 // the I/O thread! | 248 // the I/O thread! |
121 DCHECK(!ipc_); | 249 DCHECK(!ipc_); |
122 DCHECK(!client_); | 250 DCHECK(!client_); |
251 DCHECK(!host_client_); | |
123 } | 252 } |
124 | 253 |
125 PepperPlatformAudioOutput::PepperPlatformAudioOutput() | 254 PepperPlatformAudioOutput::PepperPlatformAudioOutput() |
126 : client_(NULL), | 255 : client_(NULL), |
256 host_client_(NULL), | |
127 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 257 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
128 io_task_runner_(ChildProcess::current()->io_task_runner()) { | 258 io_task_runner_(ChildProcess::current()->io_task_runner()), |
259 render_frame_id_(MSG_ROUTING_NONE), | |
260 state_(IDLE), | |
261 start_on_authorized_(true), | |
262 play_on_start_(false), | |
263 session_id_(0), | |
264 did_receive_auth_(base::WaitableEvent::ResetPolicy::MANUAL, | |
265 base::WaitableEvent::InitialState::NOT_SIGNALED), | |
266 device_status_(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL) { | |
267 } | |
268 | |
269 PepperPlatformAudioOutput::PepperPlatformAudioOutput(int render_frame_id, | |
270 const std::string& device_id, | |
271 const GURL& document_url, | |
272 base::TimeDelta authorization_timeout) | |
273 : client_(NULL), | |
274 host_client_(NULL), | |
275 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
276 io_task_runner_(ChildProcess::current()->io_task_runner()), | |
277 render_frame_id_(render_frame_id), | |
278 state_(IDLE), | |
279 start_on_authorized_(true), | |
280 play_on_start_(false), | |
281 session_id_(0), | |
282 device_id_(device_id), | |
283 security_origin_(document_url), | |
284 did_receive_auth_(base::WaitableEvent::ResetPolicy::MANUAL, | |
285 base::WaitableEvent::InitialState::NOT_SIGNALED), | |
286 device_status_(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL), | |
287 auth_timeout_(authorization_timeout) { | |
129 } | 288 } |
130 | 289 |
131 bool PepperPlatformAudioOutput::Initialize(int sample_rate, | 290 bool PepperPlatformAudioOutput::Initialize(int sample_rate, |
132 int frames_per_buffer, | 291 int frames_per_buffer, |
133 int source_render_frame_id, | 292 int source_render_frame_id, |
134 AudioHelper* client) { | 293 AudioHelper* client) { |
135 DCHECK(client); | 294 DCHECK(client); |
136 client_ = client; | 295 client_ = client; |
137 | 296 |
138 RenderThreadImpl* const render_thread = RenderThreadImpl::current(); | 297 RenderThreadImpl* const render_thread = RenderThreadImpl::current(); |
139 ipc_ = render_thread->audio_message_filter()->CreateAudioOutputIPC( | 298 ipc_ = render_thread->audio_message_filter()->CreateAudioOutputIPC( |
140 source_render_frame_id); | 299 source_render_frame_id); |
141 CHECK(ipc_); | 300 CHECK(ipc_); |
142 | 301 |
143 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 302 params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
144 media::CHANNEL_LAYOUT_STEREO, | 303 media::CHANNEL_LAYOUT_STEREO, |
145 sample_rate, | 304 sample_rate, |
146 ppapi::kBitsPerAudioOutputSample, | 305 ppapi::kBitsPerAudioOutputSample, |
147 frames_per_buffer); | 306 frames_per_buffer); |
148 | 307 |
149 io_task_runner_->PostTask( | 308 io_task_runner_->PostTask( |
150 FROM_HERE, base::Bind(&PepperPlatformAudioOutput::InitializeOnIOThread, | 309 FROM_HERE, base::Bind(&PepperPlatformAudioOutput::InitializeOnIOThread, |
151 this, params)); | 310 this, params_)); |
311 | |
152 return true; | 312 return true; |
153 } | 313 } |
154 | 314 |
315 bool PepperPlatformAudioOutput::Initialize(int sample_rate, | |
316 int frames_per_buffer, | |
317 PepperAudioOutputHost* client) { | |
318 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
319 | |
320 RenderFrameImpl* const render_frame = | |
321 RenderFrameImpl::FromRoutingID(render_frame_id_); | |
322 if (!render_frame || !client) | |
323 return false; | |
324 | |
325 host_client_ = client; | |
326 | |
327 RenderThreadImpl* const render_thread = RenderThreadImpl::current(); | |
328 ipc_ = render_thread->audio_message_filter()->CreateAudioOutputIPC( | |
329 render_frame_id_); | |
330 CHECK(ipc_); | |
331 | |
332 params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
333 media::CHANNEL_LAYOUT_STEREO, | |
334 sample_rate, | |
335 ppapi::kBitsPerAudioOutputSample, | |
336 frames_per_buffer); | |
337 | |
338 io_task_runner_->PostTask( | |
339 FROM_HERE, base::Bind(&PepperPlatformAudioOutput::CreateStreamOnIOThread, | |
340 this, params_)); | |
341 | |
342 return true; | |
343 } | |
344 | |
345 void PepperPlatformAudioOutput::RequestDeviceAuthorizationOnIOThread() { | |
346 DCHECK(io_task_runner_->BelongsToCurrentThread()); | |
347 DCHECK_EQ(state_, IDLE); | |
348 | |
349 if (!ipc_) | |
350 return; | |
351 | |
352 state_ = AUTHORIZING; | |
353 ipc_->RequestDeviceAuthorization( | |
354 this, session_id_, device_id_, security_origin_); | |
355 | |
356 if (auth_timeout_ > base::TimeDelta()) { | |
357 // Create the timer on the thread it's used on. It's guaranteed to be | |
358 // deleted on the same thread since users must call ShutDown() before | |
359 // deleting PepperPlatformAudioOutput; see ShutDownOnIOThread(). | |
360 auth_timeout_action_.reset(new base::OneShotTimer()); | |
361 auth_timeout_action_->Start( | |
362 FROM_HERE, auth_timeout_, | |
363 base::Bind(&PepperPlatformAudioOutput::OnDeviceAuthorized, this, | |
364 media::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT, | |
365 media::AudioParameters(), std::string())); | |
366 } | |
367 } | |
368 | |
369 void PepperPlatformAudioOutput::CreateStreamOnIOThread( | |
370 const media::AudioParameters& params) { | |
371 DCHECK(io_task_runner_->BelongsToCurrentThread()); | |
372 switch (state_) { | |
373 case IPC_CLOSED: | |
374 main_task_runner_->PostTask(FROM_HERE, | |
375 base::Bind(&PepperPlatformAudioOutput::NotifyStreamCreationFailed, | |
376 this)); | |
377 break; | |
378 | |
379 case IDLE: | |
380 if (did_receive_auth_.IsSignaled() && device_id_.empty() && | |
381 security_origin_.unique()) { | |
382 state_ = CREATING_STREAM; | |
383 ipc_->CreateStream(this, params); | |
384 } | |
385 else { | |
386 RequestDeviceAuthorizationOnIOThread(); | |
387 start_on_authorized_ = true; | |
388 } | |
389 break; | |
390 | |
391 case AUTHORIZING: | |
392 start_on_authorized_ = true; | |
393 break; | |
394 | |
395 case AUTHORIZED: | |
396 state_ = CREATING_STREAM; | |
397 ipc_->CreateStream(this, params); | |
398 start_on_authorized_ = false; | |
399 break; | |
400 | |
401 case CREATING_STREAM: | |
402 case PAUSED: | |
403 case PLAYING: | |
404 NOTREACHED(); | |
405 break; | |
406 } | |
407 } | |
408 | |
155 void PepperPlatformAudioOutput::InitializeOnIOThread( | 409 void PepperPlatformAudioOutput::InitializeOnIOThread( |
156 const media::AudioParameters& params) { | 410 const media::AudioParameters& params) { |
157 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 411 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
158 if (ipc_) | 412 if (ipc_) { |
413 // To maintain the compatibility of the old Pepper audio interface, | |
414 // We bypass the device autherization process, and try to create audio | |
415 // stream directly. | |
416 state_ = CREATING_STREAM; | |
159 ipc_->CreateStream(this, params); | 417 ipc_->CreateStream(this, params); |
418 } | |
160 } | 419 } |
161 | 420 |
162 void PepperPlatformAudioOutput::StartPlaybackOnIOThread() { | 421 void PepperPlatformAudioOutput::StartPlaybackOnIOThread() { |
163 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 422 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
164 if (ipc_) | 423 if (!ipc_) |
424 return; | |
425 | |
426 if (state_ == PAUSED) { | |
165 ipc_->PlayStream(); | 427 ipc_->PlayStream(); |
428 state_ = PLAYING; | |
429 play_on_start_ = false; | |
430 } | |
431 else { | |
432 if (state_ < CREATING_STREAM) | |
433 CreateStreamOnIOThread(params_); | |
434 | |
435 play_on_start_ = true; | |
436 } | |
437 } | |
438 | |
439 void PepperPlatformAudioOutput::StopPlaybackOnIOThread() { | |
440 DCHECK(io_task_runner_->BelongsToCurrentThread()); | |
441 if (!ipc_) | |
442 return; | |
443 | |
444 if (state_ == PLAYING) { | |
445 ipc_->PauseStream(); | |
446 state_ = PAUSED; | |
447 } | |
448 play_on_start_ = false; | |
166 } | 449 } |
167 | 450 |
168 void PepperPlatformAudioOutput::SetVolumeOnIOThread(double volume) { | 451 void PepperPlatformAudioOutput::SetVolumeOnIOThread(double volume) { |
169 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 452 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
170 if (ipc_) | 453 if (!ipc_) |
171 ipc_->SetVolume(volume); | 454 return; |
172 } | |
173 | 455 |
174 void PepperPlatformAudioOutput::StopPlaybackOnIOThread() { | 456 if (state_ >= CREATING_STREAM) |
175 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 457 ipc_->SetVolume(volume); |
176 if (ipc_) | |
177 ipc_->PauseStream(); | |
178 } | 458 } |
179 | 459 |
180 void PepperPlatformAudioOutput::ShutDownOnIOThread() { | 460 void PepperPlatformAudioOutput::ShutDownOnIOThread() { |
181 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 461 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
182 | 462 |
183 // Make sure we don't call shutdown more than once. | 463 // Make sure we don't call shutdown more than once. |
184 if (!ipc_) | 464 if (!ipc_) |
185 return; | 465 return; |
186 | 466 |
187 ipc_->CloseStream(); | 467 // Close the stream, if we haven't already. |
188 ipc_.reset(); | 468 if (state_ >= AUTHORIZING) { |
469 ipc_->CloseStream(); | |
470 ipc_.reset(); | |
471 state_ = IDLE; | |
472 } | |
473 start_on_authorized_ = false; | |
189 | 474 |
190 Release(); // Release for the delegate, balances out the reference taken in | 475 // Destoy the timer on the thread it's used on. |
191 // PepperPlatformAudioOutput::Create. | 476 auth_timeout_action_.reset(); |
477 | |
478 // Release for the delegate, balances out the reference taken in | |
479 // PepperPlatformAudioOutput::Create. | |
480 Release(); | |
481 } | |
482 | |
483 void PepperPlatformAudioOutput::NotifyStreamCreationFailed() { | |
484 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
485 | |
486 if (host_client_) | |
487 host_client_->StreamCreationFailed(); | |
192 } | 488 } |
193 | 489 |
194 } // namespace content | 490 } // namespace content |
OLD | NEW |